Skip to content

Commit eb80cdd

Browse files
committed
[RangeInfo] Report declared and referenced decls in a given range.
1 parent e3809e0 commit eb80cdd

File tree

3 files changed

+92
-10
lines changed

3 files changed

+92
-10
lines changed

include/swift/IDE/Utils.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -209,9 +209,15 @@ struct ResolvedRangeInfo {
209209
RangeKind Kind;
210210
Type Ty;
211211
StringRef Content;
212-
ResolvedRangeInfo(RangeKind Kind, Type Ty, StringRef Content): Kind(Kind),
213-
Ty(Ty), Content(Content) {}
214-
ResolvedRangeInfo(): ResolvedRangeInfo(RangeKind::Invalid, Type(), StringRef()) {}
212+
ArrayRef<ValueDecl*> DeclaredDecls;
213+
ArrayRef<ValueDecl*> ReferencedDecls;
214+
ResolvedRangeInfo(RangeKind Kind, Type Ty, StringRef Content,
215+
ArrayRef<ValueDecl*> DeclaredDecls,
216+
ArrayRef<ValueDecl*> ReferencedDecls): Kind(Kind),
217+
Ty(Ty), Content(Content), DeclaredDecls(DeclaredDecls),
218+
ReferencedDecls(ReferencedDecls) {}
219+
ResolvedRangeInfo() :
220+
ResolvedRangeInfo(RangeKind::Invalid, Type(), StringRef(), {}, {}) {}
215221
void print(llvm::raw_ostream &OS);
216222
};
217223

@@ -224,6 +230,8 @@ class RangeResolver : public SourceEntityWalker {
224230
bool walkToStmtPost(Stmt *S) override;
225231
bool walkToDeclPre(Decl *D, CharSourceRange Range) override;
226232
bool walkToDeclPost(Decl *D) override;
233+
bool visitDeclReference(ValueDecl *D, CharSourceRange Range,
234+
TypeDecl *CtorTyRef, Type T) override;
227235
public:
228236
RangeResolver(SourceFile &File, SourceLoc Start, SourceLoc End);
229237
RangeResolver(SourceFile &File, unsigned Offset, unsigned Length);

lib/IDE/SwiftSourceDocInfo.cpp

Lines changed: 62 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -204,10 +204,19 @@ void ResolvedRangeInfo::print(llvm::raw_ostream &OS) {
204204
Ty->print(OS);
205205
OS << "</Type>\n";
206206
}
207+
for (auto *VD : DeclaredDecls) {
208+
OS << "<Declared>" << VD->getNameStr() << "</Declared>\n";
209+
}
210+
for (auto *VD : ReferencedDecls) {
211+
OS << "<Referenced>" << VD->getNameStr() << "</Referenced>\n";
212+
}
213+
OS << "<end>\n";
207214
}
208215

209216
struct RangeResolver::Implementation {
210217
SourceFile &File;
218+
ASTContext &Ctx;
219+
SourceManager &SM;
211220
private:
212221
enum class RangeMatchKind : int8_t {
213222
NoneMatch,
@@ -233,19 +242,40 @@ struct RangeResolver::Implementation {
233242
return ContextStack.back();
234243
}
235244

245+
std::vector<ValueDecl*> DeclaredDecls;
246+
std::vector<ValueDecl*> ReferencedDecls;
247+
248+
void pushBackDeclUniquely(std::vector<ValueDecl*> &Bag, ValueDecl* VD) {
249+
if (std::find(Bag.begin(), Bag.end(), VD) == Bag.end()) {
250+
Bag.push_back(VD);
251+
}
252+
}
253+
236254
ResolvedRangeInfo getSingleNodeKind(ASTNode Node) {
237255
assert(!Node.isNull());
238256
if (Node.is<Expr*>())
239257
return ResolvedRangeInfo(RangeKind::SingleExpression,
240-
Node.get<Expr*>()->getType(), Content);
258+
Node.get<Expr*>()->getType(), Content,
259+
llvm::makeArrayRef(DeclaredDecls),
260+
llvm::makeArrayRef(ReferencedDecls));
241261
else if (Node.is<Stmt*>())
242-
return ResolvedRangeInfo(RangeKind::SingleStatement, Type(), Content);
262+
return ResolvedRangeInfo(RangeKind::SingleStatement, Type(), Content,
263+
DeclaredDecls, ReferencedDecls);
243264
else {
244265
assert(Node.is<Decl*>());
245-
return ResolvedRangeInfo(RangeKind::SingleDecl, Type(), Content);
266+
return ResolvedRangeInfo(RangeKind::SingleDecl, Type(), Content,
267+
DeclaredDecls, ReferencedDecls);
246268
}
247269
}
248270

271+
bool isContainedInSelection(CharSourceRange Range) {
272+
if (SM.isBeforeInBuffer(Range.getStart(), Start))
273+
return false;
274+
if (SM.isBeforeInBuffer(End, Range.getEnd()))
275+
return false;
276+
return true;
277+
}
278+
249279
static SourceLoc getNonwhitespaceLocBefore(SourceManager &SM,
250280
unsigned BufferID,
251281
unsigned Offset) {
@@ -284,7 +314,8 @@ struct RangeResolver::Implementation {
284314
}
285315

286316
Implementation(SourceFile &File, SourceLoc Start, SourceLoc End) :
287-
File(File), Start(Start), End(End), Content(getContent()) {}
317+
File(File), Ctx(File.getASTContext()), SM(Ctx.SourceMgr), Start(Start),
318+
End(End), Content(getContent()) {}
288319

289320
public:
290321
bool hasResult() { return Result.hasValue(); }
@@ -318,6 +349,13 @@ struct RangeResolver::Implementation {
318349
}
319350

320351
void analyze(ASTNode Node) {
352+
// Collect declared decls in the range.
353+
if (Node.is<Decl*>()) {
354+
if (auto *VD = dyn_cast<ValueDecl>(Node.get<Decl*>())) {
355+
pushBackDeclUniquely(DeclaredDecls, VD);
356+
}
357+
}
358+
321359
auto &DCInfo = getCurrentDC();
322360
switch (getRangeMatchKind(Node.getSourceRange())) {
323361
case RangeMatchKind::NoneMatch:
@@ -332,14 +370,16 @@ struct RangeResolver::Implementation {
332370
DCInfo.EndMatches.emplace_back(Node);
333371
break;
334372
}
373+
335374
if (!DCInfo.StartMatches.empty() && !DCInfo.EndMatches.empty()) {
336-
Result = {RangeKind::MultiStatement, Type(), Content};
375+
Result = {RangeKind::MultiStatement, Type(), Content,
376+
llvm::makeArrayRef(DeclaredDecls),
377+
llvm::makeArrayRef(ReferencedDecls)};
337378
return;
338379
}
339380
}
340381

341382
bool shouldEnter(ASTNode Node) {
342-
SourceManager &SM = File.getASTContext().SourceMgr;
343383
if (hasResult())
344384
return false;
345385
if (SM.isBeforeInBuffer(End, Node.getSourceRange().Start))
@@ -352,7 +392,14 @@ struct RangeResolver::Implementation {
352392
ResolvedRangeInfo getResult() {
353393
if (Result.hasValue())
354394
return Result.getValue();
355-
return ResolvedRangeInfo(RangeKind::Invalid, Type(), getContent());
395+
return ResolvedRangeInfo();
396+
}
397+
398+
void analyzeDeclRef(ValueDecl *VD, CharSourceRange Range) {
399+
if (!isContainedInSelection(Range))
400+
return;
401+
// Collect referenced decls in the range.
402+
pushBackDeclUniquely(ReferencedDecls, VD);
356403
}
357404

358405
private:
@@ -422,6 +469,14 @@ bool RangeResolver::walkToDeclPost(Decl *D) {
422469
return !Impl->hasResult();
423470
}
424471

472+
473+
bool RangeResolver::
474+
visitDeclReference(ValueDecl *D, CharSourceRange Range, TypeDecl *CtorTyRef,
475+
Type T) {
476+
Impl->analyzeDeclRef(D, Range);
477+
return true;
478+
}
479+
425480
ResolvedRangeInfo RangeResolver::resolve() {
426481
if (!Impl)
427482
return ResolvedRangeInfo();

test/IDE/range_info_basics.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,22 +19,41 @@ struct S { func foo() {} }
1919

2020
// CHECK1: <Kind>SingleDecl</Kind>
2121
// CHECK1-NEXT: <Content>func foo1() -> Int { return 0 }</Content>
22+
// CHECK1-NEXT: <Declared>foo1</Declared>
23+
// CHECK1-NEXT: <end>
2224

2325
// CHECK2: <Kind>SingleDecl</Kind>
2426
// CHECK2-NEXT: <Content>class C { func foo() {} }</Content>
27+
// CHECK2-NEXT: <Declared>C</Declared>
28+
// CHECK2-NEXT: <end>
2529

2630
// CHECK3: <Kind>SingleDecl</Kind>
2731
// CHECK3-NEXT: <Content>struct S { func foo() {} }</Content>
32+
// CHECK3-NEXT: <Declared>S</Declared>
33+
// CHECK3-NEXT: <end>
2834

2935
// CHECK4: <Kind>MultiStatement</Kind>
3036
// CHECK4-NEXT: <Content>aaa = aaa + 3
3137
// CHECK4-NEXT: if aaa == 3 { aaa = 4 }</Content>
38+
// CHECK4-NEXT: <Declared>foo</Declared>
39+
// CHECK4-NEXT: <Referenced>aaa</Referenced>
40+
// CHECK4-NEXT: <Referenced>+</Referenced>
41+
// CHECK4-NEXT: <end>
3242

3343
// CHECK5: <Kind>MultiStatement</Kind>
3444
// CHECK5-NEXT: <Content>aaa = aaa + 3
3545
// CHECK5-NEXT: if aaa == 3 { aaa = 4 }
3646
// CHECK5-NEXT: return aaa</Content>
47+
// CHECK5-NEXT: <Declared>foo</Declared>
48+
// CHECK5-NEXT: <Referenced>aaa</Referenced>
49+
// CHECK5-NEXT: <Referenced>+</Referenced>
50+
// CHECK5-NEXT: <Referenced>==</Referenced>
51+
// CHECK5-NEXT: <end>
3752

3853
// CHECK6: <Kind>MultiStatement</Kind>
3954
// CHECK6-NEXT: if aaa == 3 { aaa = 4 }
4055
// CHECK6-NEXT: return aaa</Content>
56+
// CHECK6-NEXT: <Declared>foo</Declared>
57+
// CHECK6-NEXT: <Referenced>aaa</Referenced>
58+
// CHECK6-NEXT: <Referenced>==</Referenced>
59+
// CHECK6-NEXT: <end>

0 commit comments

Comments
 (0)