mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[RangeInfo] Report the innermost decl context for the range under selection. (#6448)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
@@ -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 << '.';
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user