[RangeInfo] When reporting referenced decls, also report the types of these references.

This commit is contained in:
Xi Ge
2016-12-19 17:16:12 -08:00
parent 87a4b8a07e
commit ba930deff2
3 changed files with 81 additions and 20 deletions

View File

@@ -205,15 +205,23 @@ enum class RangeKind : int8_t{
MultiStatement,
};
struct ReferencedDecl {
ValueDecl *VD;
Type Ty;
ReferencedDecl(ValueDecl* VD, Type Ty) : VD(VD), Ty(Ty) {}
ReferencedDecl() : ReferencedDecl(nullptr, Type()) {}
bool operator==(const ReferencedDecl& other);
};
struct ResolvedRangeInfo {
RangeKind Kind;
Type Ty;
StringRef Content;
ArrayRef<ValueDecl*> DeclaredDecls;
ArrayRef<ValueDecl*> ReferencedDecls;
ArrayRef<ReferencedDecl> ReferencedDecls;
ResolvedRangeInfo(RangeKind Kind, Type Ty, StringRef Content,
ArrayRef<ValueDecl*> DeclaredDecls,
ArrayRef<ValueDecl*> ReferencedDecls): Kind(Kind),
ArrayRef<ReferencedDecl> ReferencedDecls): Kind(Kind),
Ty(Ty), Content(Content), DeclaredDecls(DeclaredDecls),
ReferencedDecls(ReferencedDecls) {}
ResolvedRangeInfo() :

View File

@@ -207,12 +207,19 @@ void ResolvedRangeInfo::print(llvm::raw_ostream &OS) {
for (auto *VD : DeclaredDecls) {
OS << "<Declared>" << VD->getNameStr() << "</Declared>\n";
}
for (auto *VD : ReferencedDecls) {
OS << "<Referenced>" << VD->getNameStr() << "</Referenced>\n";
for (auto &RD : ReferencedDecls) {
OS << "<Referenced>" << RD.VD->getNameStr() << "</Referenced>";
OS << "<Type>";
RD.Ty->print(OS);
OS << "</Type>\n";
}
OS << "<end>\n";
}
bool ReferencedDecl::operator==(const ReferencedDecl& Other) {
return VD == Other.VD && Ty.getPointer() == Other.Ty.getPointer();
}
struct RangeResolver::Implementation {
SourceFile &File;
ASTContext &Ctx;
@@ -243,13 +250,7 @@ private:
}
std::vector<ValueDecl*> DeclaredDecls;
std::vector<ValueDecl*> ReferencedDecls;
void pushBackDeclUniquely(std::vector<ValueDecl*> &Bag, ValueDecl* VD) {
if (std::find(Bag.begin(), Bag.end(), VD) == Bag.end()) {
Bag.push_back(VD);
}
}
std::vector<ReferencedDecl> ReferencedDecls;
ResolvedRangeInfo getSingleNodeKind(ASTNode Node) {
assert(!Node.isNull());
@@ -341,6 +342,8 @@ public:
static Implementation *createInstance(SourceFile &File, SourceLoc Start,
SourceLoc End) {
if (Start.isInvalid() || End.isInvalid())
return nullptr;
SourceManager &SM = File.getASTContext().SourceMgr;
unsigned BufferId = File.getBufferID().getValue();
unsigned StartOff = SM.getLocOffsetInBuffer(Start, BufferId);
@@ -355,7 +358,7 @@ public:
if (auto *VD = dyn_cast_or_null<ValueDecl>(D)) {
if (isContainedInSelection(CharSourceRange(SM, VD->getStartLoc(),
VD->getEndLoc())))
pushBackDeclUniquely(DeclaredDecls, VD);
DeclaredDecls.push_back(VD);
}
auto &DCInfo = getCurrentDC();
@@ -400,7 +403,7 @@ public:
return ResolvedRangeInfo();
}
void analyzeDeclRef(ValueDecl *VD, CharSourceRange Range) {
void analyzeDeclRef(ValueDecl *VD, CharSourceRange Range, Type Ty) {
if (!isContainedInSelection(Range))
return;
@@ -409,7 +412,10 @@ public:
return;
// Collect referenced decls in the range.
pushBackDeclUniquely(ReferencedDecls, VD);
ReferencedDecl RD(VD, Ty);
if (std::find(ReferencedDecls.begin(), ReferencedDecls.end(), RD) ==
ReferencedDecls.end())
ReferencedDecls.push_back(RD);
}
private:
@@ -483,7 +489,7 @@ bool RangeResolver::walkToDeclPost(Decl *D) {
bool RangeResolver::
visitDeclReference(ValueDecl *D, CharSourceRange Range, TypeDecl *CtorTyRef,
Type T) {
Impl->analyzeDeclRef(D, Range);
Impl->analyzeDeclRef(D, Range, T);
return true;
}

View File

@@ -17,6 +17,28 @@ func foo2() {
print(b + c)
}
struct S1 {
var a = 3
func foo() -> Int { return 0 }
mutating func increment() -> S1 {
a = a + 1
return self
}
}
func foo3(s: inout S1) -> Int {
let b = s.a
let c = s.foo() + b
s = s.increment()
return c + b
}
func foo4(s: S1) -> Int {
let b = s.a
let c = s.foo() + b
return c + b
}
// RUN: %target-swift-ide-test -range -pos=8:1 -end-pos 8:32 -source-filename %s | %FileCheck %s -check-prefix=CHECK1
// RUN: %target-swift-ide-test -range -pos=9:1 -end-pos 9:26 -source-filename %s | %FileCheck %s -check-prefix=CHECK2
// RUN: %target-swift-ide-test -range -pos=10:1 -end-pos 10:27 -source-filename %s | %FileCheck %s -check-prefix=CHECK3
@@ -24,6 +46,8 @@ func foo2() {
// RUN: %target-swift-ide-test -range -pos=3:1 -end-pos=5:13 -source-filename %s | %FileCheck %s -check-prefix=CHECK5
// RUN: %target-swift-ide-test -range -pos=4:1 -end-pos=5:13 -source-filename %s | %FileCheck %s -check-prefix=CHECK6
// RUN: %target-swift-ide-test -range -pos=14:1 -end-pos=17:15 -source-filename %s | %FileCheck %s -check-prefix=CHECK7
// RUN: %target-swift-ide-test -range -pos=31:1 -end-pos=33:15 -source-filename %s | %FileCheck %s -check-prefix=CHECK8
// RUN: %target-swift-ide-test -range -pos=37:1 -end-pos=39:15 -source-filename %s | %FileCheck %s -check-prefix=CHECK9
// CHECK1: <Kind>SingleDecl</Kind>
// CHECK1-NEXT: <Content>func foo1() -> Int { return 0 }</Content>
@@ -43,20 +67,20 @@ func foo2() {
// CHECK4: <Kind>MultiStatement</Kind>
// CHECK4-NEXT: <Content>aaa = aaa + 3
// CHECK4-NEXT: if aaa == 3 { aaa = 4 }</Content>
// CHECK4-NEXT: <Referenced>aaa</Referenced>
// CHECK4-NEXT: <Referenced>aaa</Referenced><Type>@lvalue Int</Type>
// CHECK4-NEXT: <end>
// CHECK5: <Kind>MultiStatement</Kind>
// CHECK5-NEXT: <Content>aaa = aaa + 3
// CHECK5-NEXT: if aaa == 3 { aaa = 4 }
// CHECK5-NEXT: return aaa</Content>
// CHECK5-NEXT: <Referenced>aaa</Referenced>
// CHECK5-NEXT: <Referenced>aaa</Referenced><Type>@lvalue Int</Type>
// CHECK5-NEXT: <end>
// CHECK6: <Kind>MultiStatement</Kind>
// CHECK6-NEXT: if aaa == 3 { aaa = 4 }
// CHECK6-NEXT: return aaa</Content>
// CHECK6-NEXT: <Referenced>aaa</Referenced>
// CHECK6-NEXT: <Referenced>aaa</Referenced><Type>@lvalue Int</Type>
// CHECK6-NEXT: <end>
// CHECK7: <Kind>MultiStatement</Kind>
@@ -66,6 +90,29 @@ func foo2() {
// CHECK7-NEXT: print(b + c)</Content>
// CHECK7-NEXT: <Declared>b</Declared>
// CHECK7-NEXT: <Declared>c</Declared>
// CHECK7-NEXT: <Referenced>a</Referenced>
// CHECK7-NEXT: <Referenced>b</Referenced>
// CHECK7-NEXT: <Referenced>a</Referenced><Type>Int</Type>
// CHECK7-NEXT: <Referenced>b</Referenced><Type>@lvalue Int</Type>
// CHECK7-NEXT: <end>
// CHECK8: <Kind>MultiStatement</Kind>
// CHECK8-NEXT: <Content>let c = s.foo() + b
// CHECK8-NEXT: s = s.increment()
// CHECK8-NEXT: return c + b</Content>
// CHECK8-NEXT: <Declared>c</Declared>
// CHECK8-NEXT: <Referenced>s</Referenced><Type>@lvalue S1</Type>
// CHECK8-NEXT: <Referenced>foo</Referenced><Type>(S1) -> () -> Int</Type>
// CHECK8-NEXT: <Referenced>b</Referenced><Type>Int</Type>
// CHECK8-NEXT: <Referenced>increment</Referenced><Type>(inout S1) -> () -> S1</Type>
// CHECK8-NEXT: <end>
// CHECK9: <Kind>MultiStatement</Kind>
// CHECK9-NEXT: <Content>let b = s.a
// CHECK9-NEXT: let c = s.foo() + b
// CHECK9-NEXT: return c + b</Content>
// CHECK9-NEXT: <Declared>b</Declared>
// CHECK9-NEXT: <Declared>c</Declared>
// CHECK9-NEXT: <Referenced>s</Referenced><Type>S1</Type>
// CHECK9-NEXT: <Referenced>a</Referenced><Type>Int</Type>
// CHECK9-NEXT: <Referenced>foo</Referenced><Type>(S1) -> () -> Int</Type>
// CHECK9-NEXT: <Referenced>b</Referenced><Type>Int</Type>
// CHECK9-NEXT: <end>