Skip to content

Commit 7b4466f

Browse files
committed
[CodeCompletion] Ignore implicit decl when finding equivalent decl
TypeChecker sometimes (e.g. property wrappers) inserts implicit decls (e.g. 'PatternBindingDecl's and 'VarDecl's) between decls in the AST. This used to confuse 'getEquivalentDeclContextFromSourceFile()'. It canceled fast-completion, caused crashes, or completed in a wrong context. Ignore implicit decls in the AST so that we can find the correct decl context. rdar://problem/58665268
1 parent 0895235 commit 7b4466f

File tree

2 files changed

+42
-0
lines changed

2 files changed

+42
-0
lines changed

lib/IDE/CompletionInstance.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ template <typename Range>
5656
unsigned findIndexInRange(Decl *D, const Range &Decls) {
5757
unsigned N = 0;
5858
for (auto I = Decls.begin(), E = Decls.end(); I != E; ++I) {
59+
if ((*I)->isImplicit())
60+
continue;
5961
if (*I == D)
6062
return N;
6163
++N;
@@ -66,6 +68,8 @@ unsigned findIndexInRange(Decl *D, const Range &Decls) {
6668
/// Return the element at \p N in \p Decls .
6769
template <typename Range> Decl *getElementAt(const Range &Decls, unsigned N) {
6870
for (auto I = Decls.begin(), E = Decls.end(); I != E; ++I) {
71+
if ((*I)->isImplicit())
72+
continue;
6973
if (N == 0)
7074
return *I;
7175
--N;
@@ -140,6 +144,8 @@ static DeclContext *getEquivalentDeclContextFromSourceFile(DeclContext *DC,
140144
llvm_unreachable("invalid DC kind for finding equivalent DC (query)");
141145

142146
if (auto storage = dyn_cast<AbstractStorageDecl>(D)) {
147+
if (IndexStack.empty())
148+
return nullptr;
143149
auto accessorN = IndexStack.pop_back_val();
144150
D = getElementAt(storage->getAllAccessors(), accessorN);
145151
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
@propertyWrapper
2+
struct TwelveOrLess {
3+
private var number = 0
4+
var wrappedValue: Int {
5+
get { return number }
6+
set { number = min(newValue, 12) }
7+
}
8+
}
9+
10+
struct MyStruct {
11+
@TwelveOrLess var value = 12
12+
13+
func foo() {}
14+
15+
func bar(barParam: Int) {
16+
17+
}
18+
}
19+
20+
// RUN: %sourcekitd-test \
21+
// RUN: -req=track-compiles == \
22+
// RUN: -req=complete -req-opts=reuseastcontext=1 -pos=16:1 -repeat-request=2 %s -- %s > %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: "barParam"
28+
// RESULT: ]
29+
// RESULT-LABEL: key.results: [
30+
// RESULT-DAG: key.description: "barParam"
31+
// RESULT: ]
32+
33+
// TRACE-LABEL: key.notification: source.notification.compile-did-finish,
34+
// TRACE-NOT: key.description: "completion reusing previous ASTContext (benign diagnostic)"
35+
// TRACE-LABEL: key.notification: source.notification.compile-did-finish,
36+
// TRACE: key.description: "completion reusing previous ASTContext (benign diagnostic)"

0 commit comments

Comments
 (0)