[RangeInfo] Report the innermost decl context for the range under selection. (#6448)

This commit is contained in:
Xi Ge
2016-12-21 16:50:39 -08:00
committed by GitHub
parent 5cff812195
commit 94851e25d7
7 changed files with 148 additions and 4 deletions

View File

@@ -24,6 +24,7 @@ namespace swift {
class Expr;
class Stmt;
class Decl;
class DeclContext;
class SourceLoc;
class SourceRange;
class ASTWalker;
@@ -42,6 +43,10 @@ namespace swift {
void walk(ASTWalker &Walker);
void walk(ASTWalker &&walker) { walk(walker); }
/// \brief get the underlying entity as a decl context if it is one,
/// otherwise, return nullptr;
DeclContext *getAsDeclContext() const;
};
} // namespace swift

View File

@@ -296,6 +296,7 @@ public:
bool shouldPrint(const Decl *D, PrintOptions &Options);
bool shouldPrintPattern(const Pattern *P, PrintOptions &Options);
void printContext(raw_ostream &os, DeclContext *dc);
} // namespace swift
#endif // LLVM_SWIFT_AST_ASTPRINTER_H

View File

@@ -220,13 +220,16 @@ struct ResolvedRangeInfo {
StringRef Content;
ArrayRef<ValueDecl*> DeclaredDecls;
ArrayRef<ReferencedDecl> ReferencedDecls;
DeclContext* RangeContext;
ResolvedRangeInfo(RangeKind Kind, Type Ty, StringRef Content,
DeclContext* RangeContext,
ArrayRef<ValueDecl*> DeclaredDecls,
ArrayRef<ReferencedDecl> ReferencedDecls): Kind(Kind),
Ty(Ty), Content(Content), DeclaredDecls(DeclaredDecls),
ReferencedDecls(ReferencedDecls) {}
ReferencedDecls(ReferencedDecls),
RangeContext(RangeContext) {}
ResolvedRangeInfo() :
ResolvedRangeInfo(RangeKind::Invalid, Type(), StringRef(), {}, {}) {}
ResolvedRangeInfo(RangeKind::Invalid, Type(), StringRef(), nullptr, {}, {}) {}
void print(llvm::raw_ostream &OS);
};

View File

@@ -1048,7 +1048,7 @@ void Decl::dump(raw_ostream &OS, unsigned Indent) const {
}
/// Print the given declaration context (with its parents).
static void printContext(raw_ostream &os, DeclContext *dc) {
void swift::printContext(raw_ostream &os, DeclContext *dc) {
if (auto parent = dc->getParent()) {
printContext(os, parent);
os << '.';

View File

@@ -42,6 +42,20 @@ SourceLoc ASTNode::getEndLoc() const {
return getSourceRange().End;
}
DeclContext *ASTNode::getAsDeclContext() const {
if (Expr *E = this->dyn_cast<Expr*>()) {
if (isa<AbstractClosureExpr>(E))
return static_cast<AbstractClosureExpr*>(E);
} else if (is<Stmt*>()) {
return nullptr;
} else if (Decl *D = this->dyn_cast<Decl*>()) {
if (isa<DeclContext>(D))
return cast<DeclContext>(D);
} else if (getOpaqueValue())
llvm_unreachable("unsupported AST node");
return nullptr;
}
void ASTNode::walk(ASTWalker &Walker) {
if (Expr *E = this->dyn_cast<Expr*>())
E->walk(Walker);

View File

@@ -206,6 +206,11 @@ void ResolvedRangeInfo::print(llvm::raw_ostream &OS) {
Ty->print(OS);
OS << "</Type>\n";
}
OS << "<Context>";
printContext(OS, RangeContext);
OS << "</Context>\n";
for (auto *VD : DeclaredDecls) {
OS << "<Declared>" << VD->getNameStr() << "</Declared>\n";
}
@@ -273,15 +278,18 @@ private:
if (Node.is<Expr*>())
return ResolvedRangeInfo(RangeKind::SingleExpression,
resolveNodeType(Node), Content,
getImmediateContext(),
llvm::makeArrayRef(DeclaredDecls),
llvm::makeArrayRef(ReferencedDecls));
else if (Node.is<Stmt*>())
return ResolvedRangeInfo(RangeKind::SingleStatement, resolveNodeType(Node),
Content, llvm::makeArrayRef(DeclaredDecls),
Content, getImmediateContext(),
llvm::makeArrayRef(DeclaredDecls),
llvm::makeArrayRef(ReferencedDecls));
else {
assert(Node.is<Decl*>());
return ResolvedRangeInfo(RangeKind::SingleDecl, Type(), Content,
getImmediateContext(),
llvm::makeArrayRef(DeclaredDecls),
llvm::makeArrayRef(ReferencedDecls));
}
@@ -332,6 +340,14 @@ private:
return SourceLoc();
}
DeclContext *getImmediateContext() {
for (auto It = ContextStack.rbegin(); It != ContextStack.rend(); It ++) {
if (auto *DC = It->Parent.getAsDeclContext())
return DC;
}
return static_cast<DeclContext*>(&File);
}
Implementation(SourceFile &File, SourceLoc Start, SourceLoc End) :
File(File), Ctx(File.getASTContext()), SM(Ctx.SourceMgr), Start(Start),
End(End), Content(getContent()) {}
@@ -401,6 +417,7 @@ public:
Result = {RangeKind::MultiStatement,
/* Last node has the type */
resolveNodeType(DCInfo.EndMatches.back()), Content,
getImmediateContext(),
llvm::makeArrayRef(DeclaredDecls),
llvm::makeArrayRef(ReferencedDecls)};
return;

View File

@@ -52,6 +52,25 @@ func foo5(c : C1) -> C1 {
return a.take(another: b).take(another: d)
}
func foo6() -> Int {
let a = { () -> Int in
let a = 3
var b = a.bigEndian
let c = a.byteSwapped
b = b.bigEndian.bigEndian.byteSwapped
print(b + c)
return { () -> Int in
let a = 3
var b = a.bigEndian
let c = a.byteSwapped
b = b.bigEndian.bigEndian.byteSwapped
print(b + c)
return 1
}()
}()
return a
}
// 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
@@ -64,19 +83,26 @@ func foo5(c : C1) -> C1 {
// RUN: %target-swift-ide-test -range -pos=49:1 -end-pos=50:34 -source-filename %s | %FileCheck %s -check-prefix=CHECK10
// RUN: %target-swift-ide-test -range -pos=49:1 -end-pos=51:32 -source-filename %s | %FileCheck %s -check-prefix=CHECK11
// RUN: %target-swift-ide-test -range -pos=49:1 -end-pos=52:45 -source-filename %s | %FileCheck %s -check-prefix=CHECK12
// RUN: %target-swift-ide-test -range -pos=57:1 -end-pos=61:17 -source-filename %s | %FileCheck %s -check-prefix=CHECK13
// RUN: %target-swift-ide-test -range -pos=57:1 -end-pos=69:8 -source-filename %s | %FileCheck %s -check-prefix=CHECK14
// RUN: %target-swift-ide-test -range -pos=63:1 -end-pos=66:44 -source-filename %s | %FileCheck %s -check-prefix=CHECK15
// RUN: %target-swift-ide-test -range -pos=63:1 -end-pos=68:15 -source-filename %s | %FileCheck %s -check-prefix=CHECK16
// CHECK1: <Kind>SingleDecl</Kind>
// CHECK1-NEXT: <Content>func foo1() -> Int { return 0 }</Content>
// CHECK1-NEXT: <Context>swift_ide_test.(file)</Context>
// CHECK1-NEXT: <Declared>foo1</Declared>
// CHECK1-NEXT: <end>
// CHECK2: <Kind>SingleDecl</Kind>
// CHECK2-NEXT: <Content>class C { func foo() {} }</Content>
// CHECK2-NEXT: <Context>swift_ide_test.(file)</Context>
// CHECK2-NEXT: <Declared>C</Declared>
// CHECK2-NEXT: <end>
// CHECK3: <Kind>SingleDecl</Kind>
// CHECK3-NEXT: <Content>struct S { func foo() {} }</Content>
// CHECK3-NEXT: <Context>swift_ide_test.(file)</Context>
// CHECK3-NEXT: <Declared>S</Declared>
// CHECK3-NEXT: <end>
@@ -84,6 +110,7 @@ func foo5(c : C1) -> C1 {
// CHECK4-NEXT: <Content>aaa = aaa + 3
// CHECK4-NEXT: if aaa == 3 { aaa = 4 }</Content>
// CHECK4-NEXT: <Type>Void</Type>
// CHECK4-NEXT: <Context>swift_ide_test.(file).func decl</Context>
// CHECK4-NEXT: <Referenced>aaa</Referenced><Type>@lvalue Int</Type>
// CHECK4-NEXT: <end>
@@ -92,6 +119,7 @@ func foo5(c : C1) -> C1 {
// CHECK5-NEXT: if aaa == 3 { aaa = 4 }
// CHECK5-NEXT: return aaa</Content>
// CHECK5-NEXT: <Type>Int</Type>
// CHECK5-NEXT: <Context>swift_ide_test.(file).func decl</Context>
// CHECK5-NEXT: <Referenced>aaa</Referenced><Type>@lvalue Int</Type>
// CHECK5-NEXT: <end>
@@ -99,6 +127,7 @@ func foo5(c : C1) -> C1 {
// CHECK6-NEXT: if aaa == 3 { aaa = 4 }
// CHECK6-NEXT: return aaa</Content>
// CHECK6-NEXT: <Type>Int</Type>
// CHECK6-NEXT: <Context>swift_ide_test.(file).func decl</Context>
// CHECK6-NEXT: <Referenced>aaa</Referenced><Type>@lvalue Int</Type>
// CHECK6-NEXT: <end>
@@ -108,6 +137,7 @@ func foo5(c : C1) -> C1 {
// CHECK7-NEXT: b = b.bigEndian.bigEndian.byteSwapped
// CHECK7-NEXT: print(b + c)</Content>
// CHECK7-NEXT: <Type>()</Type>
// CHECK7-NEXT: <Context>swift_ide_test.(file).func decl</Context>
// CHECK7-NEXT: <Declared>b</Declared>
// CHECK7-NEXT: <Declared>c</Declared>
// CHECK7-NEXT: <Referenced>a</Referenced><Type>Int</Type>
@@ -119,6 +149,7 @@ func foo5(c : C1) -> C1 {
// CHECK8-NEXT: s = s.increment()
// CHECK8-NEXT: return c + b</Content>
// CHECK8-NEXT: <Type>Int</Type>
// CHECK8-NEXT: <Context>swift_ide_test.(file).func decl</Context>
// CHECK8-NEXT: <Declared>c</Declared>
// CHECK8-NEXT: <Referenced>s</Referenced><Type>@lvalue S1</Type>
// CHECK8-NEXT: <Referenced>b</Referenced><Type>Int</Type>
@@ -129,6 +160,7 @@ func foo5(c : C1) -> C1 {
// CHECK9-NEXT: let c = s.foo() + b
// CHECK9-NEXT: return c + b</Content>
// CHECK9-NEXT: <Type>Int</Type>
// CHECK9-NEXT: <Context>swift_ide_test.(file).func decl</Context>
// CHECK9-NEXT: <Declared>b</Declared>
// CHECK9-NEXT: <Declared>c</Declared>
// CHECK9-NEXT: <Referenced>s</Referenced><Type>S1</Type>
@@ -138,6 +170,7 @@ func foo5(c : C1) -> C1 {
// CHECK10: <Kind>MultiStatement</Kind>
// CHECK10-NEXT: <Content>let a = c.c.getC().c.getC().getC().getC()
// CHECK10-NEXT: let b = a.c.c.c.c.getC().getC()</Content>
// CHECK10-NEXT: <Context>swift_ide_test.(file).func decl</Context>
// CHECK10-NEXT: <Declared>a</Declared>
// CHECK10-NEXT: <Declared>b</Declared>
// CHECK10-NEXT: <Referenced>c</Referenced><Type>C1</Type>
@@ -147,6 +180,7 @@ func foo5(c : C1) -> C1 {
// CHECK11-NEXT: <Content>let a = c.c.getC().c.getC().getC().getC()
// CHECK11-NEXT: let b = a.c.c.c.c.getC().getC()
// CHECK11-NEXT: let d = a.c.getC().getC().c.c</Content>
// CHECK11-NEXT: <Context>swift_ide_test.(file).func decl</Context>
// CHECK11-NEXT: <Declared>a</Declared>
// CHECK11-NEXT: <Declared>b</Declared>
// CHECK11-NEXT: <Declared>d</Declared>
@@ -160,9 +194,79 @@ func foo5(c : C1) -> C1 {
// CHECK12-NEXT: let d = a.c.getC().getC().c.c
// CHECK12-NEXT: return a.take(another: b).take(another: d)</Content>
// CHECK12-NEXT: <Type>C1</Type>
// CHECK12-NEXT: <Context>swift_ide_test.(file).func decl</Context>
// CHECK12-NEXT: <Declared>a</Declared>
// CHECK12-NEXT: <Declared>b</Declared>
// CHECK12-NEXT: <Declared>d</Declared>
// CHECK12-NEXT: <Referenced>c</Referenced><Type>C1</Type>
// CHECK12-NEXT: <Referenced>a</Referenced><Type>C1</Type>
// CHECK12-NEXT: <end>
// CHECK13: <Kind>MultiStatement</Kind>
// CHECK13-NEXT: <Content>let a = 3
// CHECK13-NEXT: var b = a.bigEndian
// CHECK13-NEXT: let c = a.byteSwapped
// CHECK13-NEXT: b = b.bigEndian.bigEndian.byteSwapped
// CHECK13-NEXT: print(b + c)</Content>
// CHECK13-NEXT: <Type>()</Type>
// CHECK13-NEXT: <Context>swift_ide_test.(file).func decl.explicit closure discriminator=0</Context>
// CHECK13-NEXT: <Declared>a</Declared>
// CHECK13-NEXT: <Declared>b</Declared>
// CHECK13-NEXT: <Declared>c</Declared>
// CHECK13-NEXT: <Referenced>a</Referenced><Type>Int</Type>
// CHECK13-NEXT: <Referenced>b</Referenced><Type>@lvalue Int</Type>
// CHECK13-NEXT: <end>
// CHECK14: <Kind>MultiStatement</Kind>
// CHECK14-NEXT: <Content>let a = 3
// CHECK14-NEXT: var b = a.bigEndian
// CHECK14-NEXT: let c = a.byteSwapped
// CHECK14-NEXT: b = b.bigEndian.bigEndian.byteSwapped
// CHECK14-NEXT: print(b + c)
// CHECK14-NEXT: return { () -> Int in
// CHECK14-NEXT: let a = 3
// CHECK14-NEXT: var b = a.bigEndian
// CHECK14-NEXT: let c = a.byteSwapped
// CHECK14-NEXT: b = b.bigEndian.bigEndian.byteSwapped
// CHECK14-NEXT: print(b + c)
// CHECK14-NEXT: return 1
// CHECK14-NEXT: }()</Content>
// CHECK14-NEXT: <Type>Int</Type>
// CHECK14-NEXT: <Context>swift_ide_test.(file).func decl.explicit closure discriminator=0</Context>
// CHECK14-NEXT: <Declared>a</Declared>
// CHECK14-NEXT: <Declared>b</Declared>
// CHECK14-NEXT: <Declared>c</Declared>
// CHECK14-NEXT: <Referenced>a</Referenced><Type>Int</Type>
// CHECK14-NEXT: <Referenced>b</Referenced><Type>@lvalue Int</Type>
// CHECK14-NEXT: <Referenced>c</Referenced><Type>Int</Type>
// CHECK14-NEXT: <end>
// CHECK15: <Kind>MultiStatement</Kind>
// CHECK15-NEXT: <Content>let a = 3
// CHECK15-NEXT: var b = a.bigEndian
// CHECK15-NEXT: let c = a.byteSwapped
// CHECK15-NEXT: b = b.bigEndian.bigEndian.byteSwapped</Content>
// CHECK15-NEXT: <Type>()</Type>
// CHECK15-NEXT: <Context>swift_ide_test.(file).func decl.explicit closure discriminator=0.explicit closure discriminator=0</Context>
// CHECK15-NEXT: <Declared>a</Declared>
// CHECK15-NEXT: <Declared>b</Declared>
// CHECK15-NEXT: <Declared>c</Declared>
// CHECK15-NEXT: <Referenced>a</Referenced><Type>Int</Type>
// CHECK15-NEXT: <end>
// CHECK16: <Kind>MultiStatement</Kind>
// CHECK16-NEXT: <Content>let a = 3
// CHECK16-NEXT: var b = a.bigEndian
// CHECK16-NEXT: let c = a.byteSwapped
// CHECK16-NEXT: b = b.bigEndian.bigEndian.byteSwapped
// CHECK16-NEXT: print(b + c)
// CHECK16-NEXT: return 1</Content>
// CHECK16-NEXT: <Type>Int</Type>
// CHECK16-NEXT: <Context>swift_ide_test.(file).func decl.explicit closure discriminator=0.explicit closure discriminator=0</Context>
// CHECK16-NEXT: <Declared>a</Declared>
// CHECK16-NEXT: <Declared>b</Declared>
// CHECK16-NEXT: <Declared>c</Declared>
// CHECK16-NEXT: <Referenced>a</Referenced><Type>Int</Type>
// CHECK16-NEXT: <Referenced>b</Referenced><Type>@lvalue Int</Type>
// CHECK16-NEXT: <Referenced>c</Referenced><Type>Int</Type>
// CHECK16-NEXT: <end>