Skip to content

Commit 5e8d8da

Browse files
committed
[Test] Add range-info test driver to swift-ide-test. NFC
1 parent 6a9298c commit 5e8d8da

File tree

5 files changed

+209
-78
lines changed

5 files changed

+209
-78
lines changed

include/swift/IDE/Utils.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,13 +209,15 @@ struct ResolvedRangeInfo {
209209
RangeKind Kind;
210210
Type Ty;
211211
StringRef Content;
212-
ResolvedRangeInfo(RangeKind Kind, Type Ty, StringRef Content) : Kind(Kind),
212+
ResolvedRangeInfo(RangeKind Kind, Type Ty, StringRef Content): Kind(Kind),
213213
Ty(Ty), Content(Content) {}
214+
ResolvedRangeInfo(): ResolvedRangeInfo(RangeKind::Invalid, Type(), StringRef()) {}
215+
void print(llvm::raw_ostream &OS);
214216
};
215217

216218
class RangeResolver : public SourceEntityWalker {
217219
struct Implementation;
218-
Implementation &Impl;
220+
Implementation *Impl;
219221
bool walkToExprPre(Expr *E) override;
220222
bool walkToExprPost(Expr *E) override;
221223
bool walkToStmtPre(Stmt *S) override;
@@ -224,6 +226,7 @@ class RangeResolver : public SourceEntityWalker {
224226
bool walkToDeclPost(Decl *D) override;
225227
public:
226228
RangeResolver(SourceFile &File, SourceLoc Start, SourceLoc End);
229+
RangeResolver(SourceFile &File, unsigned Offset, unsigned Length);
227230
ResolvedRangeInfo resolve();
228231
~RangeResolver();
229232
};

lib/IDE/SwiftSourceDocInfo.cpp

Lines changed: 107 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "clang/Basic/Module.h"
1414
#include "clang/Index/USRGeneration.h"
1515
#include "clang/Lex/Lexer.h"
16+
#include "clang/Basic/CharInfo.h"
1617

1718
#include "llvm/Support/MemoryBuffer.h"
1819

@@ -174,6 +175,25 @@ bool SemaLocResolver::visitModuleReference(ModuleEntity Mod,
174175
return !tryResolve(Mod, Range.getStart());
175176
}
176177

178+
void ResolvedRangeInfo::print(llvm::raw_ostream &OS) {
179+
OS << "<Kind>";
180+
switch (Kind) {
181+
case RangeKind::SingleExpression: OS << "SingleExpression"; break;
182+
case RangeKind::SingleDecl: OS << "SingleDecl"; break;
183+
case RangeKind::MultiStatement: OS << "MultiStatement"; break;
184+
case RangeKind::SingleStatement: OS << "SingleStatement"; break;
185+
case RangeKind::Invalid: OS << "Invalid"; break;
186+
}
187+
OS << "</Kind>\n";
188+
189+
OS << "<Content>" << Content << "</Content>\n";
190+
if (Ty) {
191+
OS << "<Type>";
192+
Ty->print(OS);
193+
OS << "</Type>\n";
194+
}
195+
}
196+
177197
struct RangeResolver::Implementation {
178198
SourceFile &File;
179199
private:
@@ -214,16 +234,77 @@ struct RangeResolver::Implementation {
214234
}
215235
}
216236

217-
public:
237+
static SourceLoc getNonwhitespaceLocBefore(SourceManager &SM,
238+
unsigned BufferID,
239+
unsigned Offset) {
240+
CharSourceRange entireRange = SM.getRangeForBuffer(BufferID);
241+
StringRef Buffer = SM.extractText(entireRange);
242+
243+
const char *BufStart = Buffer.data();
244+
if (Offset >= Buffer.size())
245+
return SourceLoc();
246+
247+
for (unsigned Off = Offset; Off != 0; Off --) {
248+
if (!clang::isWhitespace(*(BufStart + Off))) {
249+
return SM.getLocForOffset(BufferID, Off);
250+
}
251+
}
252+
return clang::isWhitespace(*BufStart) ? SourceLoc() :
253+
SM.getLocForOffset(BufferID, 0);
254+
}
255+
256+
static SourceLoc getNonwhitespaceLocAfter(SourceManager &SM,
257+
unsigned BufferID,
258+
unsigned Offset) {
259+
CharSourceRange entireRange = SM.getRangeForBuffer(BufferID);
260+
StringRef Buffer = SM.extractText(entireRange);
261+
262+
const char *BufStart = Buffer.data();
263+
if (Offset >= Buffer.size())
264+
return SourceLoc();
265+
266+
for (unsigned Off = Offset; Off < Buffer.size(); Off ++) {
267+
if (!clang::isWhitespace(*(BufStart + Off))) {
268+
return SM.getLocForOffset(BufferID, Off);
269+
}
270+
}
271+
return SourceLoc();
272+
}
273+
218274
Implementation(SourceFile &File, SourceLoc Start, SourceLoc End) :
219275
File(File), Start(Start), End(End), Content(getContent()) {}
276+
277+
public:
220278
bool hasResult() { return Result.hasValue(); }
221279
void enter(ASTNode Node) { ContextStack.emplace_back(Node); }
222280
void leave(ASTNode Node) {
223281
assert(ContextStack.back().Parent.getOpaqueValue() == Node.getOpaqueValue());
224282
ContextStack.pop_back();
225283
}
226284

285+
static Implementation *createInstance(SourceFile &File, unsigned StartOff,
286+
unsigned Length) {
287+
SourceManager &SM = File.getASTContext().SourceMgr;
288+
unsigned BufferId = File.getBufferID().getValue();
289+
SourceLoc StartLoc = Implementation::getNonwhitespaceLocAfter(SM, BufferId,
290+
StartOff);
291+
SourceLoc EndLoc = Implementation::getNonwhitespaceLocBefore(SM, BufferId,
292+
StartOff + Length - 1);
293+
StartLoc = Lexer::getLocForStartOfToken(SM, StartLoc);
294+
EndLoc = Lexer::getLocForStartOfToken(SM, EndLoc);
295+
return StartLoc.isInvalid() || EndLoc.isInvalid() ? nullptr :
296+
new Implementation(File, StartLoc, EndLoc);
297+
}
298+
299+
static Implementation *createInstance(SourceFile &File, SourceLoc Start,
300+
SourceLoc End) {
301+
SourceManager &SM = File.getASTContext().SourceMgr;
302+
unsigned BufferId = File.getBufferID().getValue();
303+
unsigned StartOff = SM.getLocOffsetInBuffer(Start, BufferId);
304+
unsigned EndOff = SM.getLocOffsetInBuffer(End, BufferId);
305+
return createInstance(File, StartOff, EndOff - StartOff);
306+
}
307+
227308
void analyze(ASTNode Node) {
228309
auto &DCInfo = getCurrentDC();
229310
switch (getRangeMatchKind(Node.getSourceRange())) {
@@ -283,53 +364,58 @@ struct RangeResolver::Implementation {
283364
};
284365

285366
RangeResolver::RangeResolver(SourceFile &File, SourceLoc Start, SourceLoc End) :
286-
Impl(*new Implementation(File, Start, End)) {}
367+
Impl(Implementation::createInstance(File, Start, End)) {}
368+
369+
RangeResolver::RangeResolver(SourceFile &File, unsigned Offset, unsigned Length) :
370+
Impl(Implementation::createInstance(File, Offset, Length)) {}
287371

288-
RangeResolver::~RangeResolver() { delete &Impl; }
372+
RangeResolver::~RangeResolver() { if (Impl) delete Impl; }
289373

290374
bool RangeResolver::walkToExprPre(Expr *E) {
291-
if (!Impl.shouldEnter(E))
375+
if (!Impl->shouldEnter(E))
292376
return false;
293-
Impl.analyze(E);
294-
Impl.enter(E);
377+
Impl->analyze(E);
378+
Impl->enter(E);
295379
return true;
296380
}
297381

298382
bool RangeResolver::walkToStmtPre(Stmt *S) {
299-
if (!Impl.shouldEnter(S))
383+
if (!Impl->shouldEnter(S))
300384
return false;
301-
Impl.analyze(S);
302-
Impl.enter(S);
385+
Impl->analyze(S);
386+
Impl->enter(S);
303387
return true;
304388
};
305389

306390
bool RangeResolver::walkToDeclPre(Decl *D, CharSourceRange Range) {
307-
if (!Impl.shouldEnter(D))
391+
if (!Impl->shouldEnter(D))
308392
return false;
309-
Impl.analyze(D);
310-
Impl.enter(D);
393+
Impl->analyze(D);
394+
Impl->enter(D);
311395
return true;
312396
}
313397

314398
bool RangeResolver::walkToExprPost(Expr *E) {
315-
Impl.leave(E);
316-
return !Impl.hasResult();
399+
Impl->leave(E);
400+
return !Impl->hasResult();
317401
}
318402

319403
bool RangeResolver::walkToStmtPost(Stmt *S) {
320-
Impl.leave(S);
321-
return !Impl.hasResult();
404+
Impl->leave(S);
405+
return !Impl->hasResult();
322406
};
323407

324408
bool RangeResolver::walkToDeclPost(Decl *D) {
325-
Impl.leave(D);
326-
return !Impl.hasResult();
409+
Impl->leave(D);
410+
return !Impl->hasResult();
327411
}
328412

329413
ResolvedRangeInfo RangeResolver::resolve() {
330-
Impl.enter(ASTNode());
331-
walk(Impl.File);
332-
return Impl.getResult();
414+
if (!Impl)
415+
return ResolvedRangeInfo();
416+
Impl->enter(ASTNode());
417+
walk(Impl->File);
418+
return Impl->getResult();
333419
}
334420

335421
void swift::ide::getLocationInfoForClangNode(ClangNode ClangNode,

test/IDE/range_info_basics.swift

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
func foo() -> Int{
2+
var aaa = 1 + 2
3+
aaa = aaa + 3
4+
if aaa == 3 { aaa = 4 }
5+
return aaa
6+
}
7+
8+
func foo1() -> Int { return 0 }
9+
class C { func foo() {} }
10+
struct S { func foo() {} }
11+
12+
13+
// RUN: %target-swift-ide-test -range -pos=8:1 -end-pos 8:32 -source-filename %s | %FileCheck %s -check-prefix=CHECK1
14+
// RUN: %target-swift-ide-test -range -pos=9:1 -end-pos 9:26 -source-filename %s | %FileCheck %s -check-prefix=CHECK2
15+
// RUN: %target-swift-ide-test -range -pos=10:1 -end-pos 10:27 -source-filename %s | %FileCheck %s -check-prefix=CHECK3
16+
// RUN: %target-swift-ide-test -range -pos=3:1 -end-pos=4:26 -source-filename %s | %FileCheck %s -check-prefix=CHECK4
17+
// RUN: %target-swift-ide-test -range -pos=3:1 -end-pos=5:13 -source-filename %s | %FileCheck %s -check-prefix=CHECK5
18+
// RUN: %target-swift-ide-test -range -pos=4:1 -end-pos=5:13 -source-filename %s | %FileCheck %s -check-prefix=CHECK6
19+
20+
// CHECK1: <Kind>SingleDecl</Kind>
21+
// CHECK1-NEXT: <Content>func foo1() -> Int { return 0 }</Content>
22+
23+
// CHECK2: <Kind>SingleDecl</Kind>
24+
// CHECK2-NEXT: <Content>class C { func foo() {} }</Content>
25+
26+
// CHECK3: <Kind>SingleDecl</Kind>
27+
// CHECK3-NEXT: <Content>struct S { func foo() {} }</Content>
28+
29+
// CHECK4: <Kind>MultiStatement</Kind>
30+
// CHECK4-NEXT: <Content>aaa = aaa + 3
31+
// CHECK4-NEXT: if aaa == 3 { aaa = 4 }</Content>
32+
33+
// CHECK5: <Kind>MultiStatement</Kind>
34+
// CHECK5-NEXT: <Content>aaa = aaa + 3
35+
// CHECK5-NEXT: if aaa == 3 { aaa = 4 }
36+
// CHECK5-NEXT: return aaa</Content>
37+
38+
// CHECK6: <Kind>MultiStatement</Kind>
39+
// CHECK6-NEXT: if aaa == 3 { aaa = 4 }
40+
// CHECK6-NEXT: return aaa</Content>

tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp

Lines changed: 3 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,7 @@ static StringRef getSourceToken(unsigned Offset,
493493
return L.getTokenAt(Loc).getText();
494494
}
495495

496-
static llvm::Optional<unsigned>
496+
static llvm::Optional<unsigned>
497497
mapOffsetToOlderSnapshot(unsigned Offset,
498498
ImmutableTextSnapshotRef NewSnap,
499499
ImmutableTextSnapshotRef OldSnap) {
@@ -519,7 +519,7 @@ mapOffsetToOlderSnapshot(unsigned Offset,
519519
return Offset;
520520
}
521521

522-
static llvm::Optional<unsigned>
522+
static llvm::Optional<unsigned>
523523
mapOffsetToNewerSnapshot(unsigned Offset,
524524
ImmutableTextSnapshotRef OldSnap,
525525
ImmutableTextSnapshotRef NewSnap) {
@@ -1023,43 +1023,6 @@ static void resolveRange(SwiftLangSupport &Lang,
10231023
unsigned Length;
10241024
std::function<void(const RangeInfo&)> Receiver;
10251025

1026-
static SourceLoc getNonwhitespaceLocBefore(SourceManager &SM,
1027-
unsigned BufferID,
1028-
unsigned Offset) {
1029-
CharSourceRange entireRange = SM.getRangeForBuffer(BufferID);
1030-
StringRef Buffer = SM.extractText(entireRange);
1031-
1032-
const char *BufStart = Buffer.data();
1033-
if (Offset >= Buffer.size())
1034-
return SourceLoc();
1035-
1036-
for (unsigned Off = Offset; Off != 0; Off --) {
1037-
if (!clang::isWhitespace(*(BufStart + Off))) {
1038-
return SM.getLocForOffset(BufferID, Off);
1039-
}
1040-
}
1041-
return clang::isWhitespace(*BufStart) ? SourceLoc() :
1042-
SM.getLocForOffset(BufferID, 0);
1043-
}
1044-
1045-
static SourceLoc getNonwhitespaceLocAfter(SourceManager &SM,
1046-
unsigned BufferID,
1047-
unsigned Offset) {
1048-
CharSourceRange entireRange = SM.getRangeForBuffer(BufferID);
1049-
StringRef Buffer = SM.extractText(entireRange);
1050-
1051-
const char *BufStart = Buffer.data();
1052-
if (Offset >= Buffer.size())
1053-
return SourceLoc();
1054-
1055-
for (unsigned Off = Offset; Off < Buffer.size(); Off ++) {
1056-
if (!clang::isWhitespace(*(BufStart + Off))) {
1057-
return SM.getLocForOffset(BufferID, Off);
1058-
}
1059-
}
1060-
return SourceLoc();
1061-
}
1062-
10631026
public:
10641027
RangeInfoConsumer(StringRef InputFile, unsigned Offset, unsigned Length,
10651028
SwiftLangSupport &Lang, SwiftInvocationRef ASTInvok,
@@ -1070,25 +1033,10 @@ static void resolveRange(SwiftLangSupport &Lang,
10701033

10711034
void handlePrimaryAST(ASTUnitRef AstUnit) override {
10721035
auto &CompIns = AstUnit->getCompilerInstance();
1073-
1074-
unsigned BufferID = AstUnit->getPrimarySourceFile().getBufferID().getValue();
1075-
SourceManager &SM = CompIns.getSourceMgr();
1076-
SourceLoc StartLoc = getNonwhitespaceLocAfter(SM, BufferID, Offset);
1077-
SourceLoc EndLoc = getNonwhitespaceLocBefore(SM, BufferID,
1078-
Offset + Length - 1);
1079-
1080-
StartLoc = Lexer::getLocForStartOfToken(SM, StartLoc);
1081-
EndLoc = Lexer::getLocForStartOfToken(SM, EndLoc);
1082-
1083-
if (StartLoc.isInvalid() || EndLoc.isInvalid()) {
1084-
Receiver({});
1085-
return;
1086-
}
1087-
10881036
if (trace::enabled()) {
10891037
// FIXME: Implement tracing
10901038
}
1091-
RangeResolver Resolver(AstUnit->getPrimarySourceFile(), StartLoc, EndLoc);
1039+
RangeResolver Resolver(AstUnit->getPrimarySourceFile(), Offset, Length);
10921040
ResolvedRangeInfo Info = Resolver.resolve();
10931041

10941042
CompilerInvocation CompInvok;

0 commit comments

Comments
 (0)