Skip to content

Commit ff2ccd4

Browse files
committed
[CodeCompletion] Workaround fast-completion issue in UnqualifiedLookup
In fast-completion, a function body can be replaced with another function body parsed from a new buffer. In such cases, during typechecking the expressions in the *new* function body, a source location range check in UnqualifiedLookup didn't work well because they are not from the same buffer. This patch workaround it by skipping the source range checks and returns 'success' in such cases. rdar://problem/58881999
1 parent 24826e0 commit ff2ccd4

File tree

3 files changed

+73
-4
lines changed

3 files changed

+73
-4
lines changed

include/swift/Basic/SourceManager.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ class SourceManager {
7676
CodeCompletionOffset = Offset;
7777
}
7878

79+
bool hasCodeCompletionBuffer() const {
80+
return CodeCompletionBufferID != 0U;
81+
}
82+
7983
unsigned getCodeCompletionBufferID() const {
8084
return CodeCompletionBufferID;
8185
}

lib/AST/UnqualifiedLookup.cpp

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,19 +58,34 @@ namespace {
5858
// lookup.
5959
if (loc.isInvalid() || decl->getBraces().isInvalid())
6060
return true;
61-
61+
62+
SourceManager &SM = decl->getASTContext().SourceMgr;
63+
64+
// If a code completion happens inside a function body, some lookups may
65+
// happen from the 'loc' that is in a different buffer from the 'decl'.
66+
// In such cases, look for members of the 'decl' because we know 'loc' is
67+
// inside a function body in the 'decl'.
68+
if (SM.hasCodeCompletionBuffer()) {
69+
auto completionBufferID = SM.getCodeCompletionBufferID();
70+
if (SM.getRangeForBuffer(completionBufferID).contains(loc)) {
71+
auto declBufferID =
72+
decl->getDeclContext()->getParentSourceFile()->getBufferID();
73+
if (completionBufferID != declBufferID)
74+
return true;
75+
}
76+
}
77+
6278
// Within the braces, always look for members.
63-
auto &ctx = decl->getASTContext();
6479
auto braces = decl->getBraces();
6580
if (braces.Start != braces.End &&
66-
ctx.SourceMgr.rangeContainsTokenLoc(braces, loc))
81+
SM.rangeContainsTokenLoc(braces, loc))
6782
return true;
6883

6984
// Within 'where' clause, we can also look for members.
7085
if (auto *whereClause = decl->getTrailingWhereClause()) {
7186
SourceRange whereClauseRange = whereClause->getSourceRange();
7287
if (whereClauseRange.isValid() &&
73-
ctx.SourceMgr.rangeContainsTokenLoc(whereClauseRange, loc)) {
88+
SM.rangeContainsTokenLoc(whereClauseRange, loc)) {
7489
return true;
7590
}
7691
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
struct Outer {
2+
enum Inner {
3+
case east, west
4+
static func staticMethod() {}
5+
func instanceMethod() {}
6+
7+
func test() {
8+
Inner.
9+
}
10+
}
11+
12+
func test() {
13+
Inner.
14+
}
15+
}
16+
17+
// RUN: %sourcekitd-test \
18+
// RUN: -req=track-compiles == \
19+
// RUN: -req=complete -req-opts=reuseastcontext=1 -pos=8:13 %s -- %s == \
20+
// RUN: -req=complete -req-opts=reuseastcontext=1 -pos=8:13 %s -- %s == \
21+
// RUN: -req=complete -req-opts=reuseastcontext=1 -pos=13:11 %s -- %s \
22+
// RUN: > %t.response
23+
// RUN: %FileCheck --check-prefix=RESULT %s < %t.response
24+
// RUN: %FileCheck --check-prefix=TRACE %s < %t.response
25+
26+
// RESULT-LABEL: key.results: [
27+
// RESULT-DAG: key.description: "east"
28+
// RESULT-DAG: key.description: "west"
29+
// RESULT-DAG: key.description: "staticMethod()"
30+
// RESULT-DAG: key.description: "instanceMethod(self: Outer.Inner)"
31+
// RESULT: ]
32+
// RESULT-LABEL: key.results: [
33+
// RESULT-DAG: key.description: "east"
34+
// RESULT-DAG: key.description: "west"
35+
// RESULT-DAG: key.description: "staticMethod()"
36+
// RESULT-DAG: key.description: "instanceMethod(self: Outer.Inner)"
37+
// RESULT: ]
38+
// RESULT-LABEL: key.results: [
39+
// RESULT-DAG: key.description: "east"
40+
// RESULT-DAG: key.description: "west"
41+
// RESULT-DAG: key.description: "staticMethod()"
42+
// RESULT-DAG: key.description: "instanceMethod(self: Inner)"
43+
// RESULT: ]
44+
45+
// TRACE-LABEL: key.notification: source.notification.compile-did-finish,
46+
// TRACE-NOT: key.description: "completion reusing previous ASTContext (benign diagnostic)"
47+
// TRACE-LABEL: key.notification: source.notification.compile-did-finish,
48+
// TRACE: key.description: "completion reusing previous ASTContext (benign diagnostic)"
49+
// TRACE-LABEL: key.notification: source.notification.compile-did-finish,
50+
// TRACE: key.description: "completion reusing previous ASTContext (benign diagnostic)"

0 commit comments

Comments
 (0)