Skip to content

Commit 9d88e25

Browse files
committed
[CodeCompletion] Only include results from other modules once
In case of ambigous expression/global completions, we call `getValueCompletionsInDeclContext` multiple times for the amigous solutions to the constraint system. This can cause modules to be included multiple times in `RequestedCachedResults` and thus global results from these modules are reported multiple times. Make `RequestedCachedResults` a set so we don’t get duplicate results. rdar://92048610
1 parent 07efec4 commit 9d88e25

File tree

3 files changed

+68
-7
lines changed

3 files changed

+68
-7
lines changed

include/swift/IDE/CompletionLookup.h

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,9 +209,17 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
209209
static RequestedResultsTy toplevelResults() {
210210
return {nullptr, false, false, false, true};
211211
}
212+
213+
friend bool operator==(const RequestedResultsTy &LHS,
214+
const RequestedResultsTy &RHS) {
215+
return LHS.TheModule == RHS.TheModule && LHS.OnlyTypes == RHS.OnlyTypes &&
216+
LHS.OnlyPrecedenceGroups == RHS.OnlyPrecedenceGroups &&
217+
LHS.NeedLeadingDot == RHS.NeedLeadingDot &&
218+
LHS.IncludeModuleQualifier == RHS.IncludeModuleQualifier;
219+
}
212220
};
213221

214-
std::vector<RequestedResultsTy> RequestedCachedResults;
222+
llvm::SetVector<RequestedResultsTy> RequestedCachedResults;
215223

216224
public:
217225
CompletionLookup(CodeCompletionResultSink &Sink, ASTContext &Ctx,
@@ -598,4 +606,29 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
598606
} // end namespace ide
599607
} // end namespace swift
600608

609+
namespace llvm {
610+
using RequestedResultsTy = swift::ide::CompletionLookup::RequestedResultsTy;
611+
template <>
612+
struct DenseMapInfo<RequestedResultsTy> {
613+
static inline RequestedResultsTy getEmptyKey() {
614+
return {DenseMapInfo<swift::ModuleDecl *>::getEmptyKey(), false, false,
615+
false, false};
616+
}
617+
static inline RequestedResultsTy getTombstoneKey() {
618+
return {DenseMapInfo<swift::ModuleDecl *>::getTombstoneKey(), false, false,
619+
false, false};
620+
}
621+
static unsigned getHashValue(const RequestedResultsTy &Val) {
622+
return hash_combine(
623+
DenseMapInfo<swift::ModuleDecl *>::getHashValue(Val.TheModule),
624+
Val.OnlyTypes, Val.OnlyPrecedenceGroups, Val.NeedLeadingDot,
625+
Val.IncludeModuleQualifier);
626+
}
627+
static bool isEqual(const RequestedResultsTy &LHS,
628+
const RequestedResultsTy &RHS) {
629+
return LHS == RHS;
630+
}
631+
};
632+
} // namespace llvm
633+
601634
#endif // SWIFT_IDE_COMPLETIONLOOKUP_H

lib/IDE/CompletionLookup.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2076,7 +2076,7 @@ bool CompletionLookup::tryModuleCompletions(Type ExprType, bool TypesOnly) {
20762076
.withModuleQualifier(false);
20772077
if (TypesOnly)
20782078
Request = Request.onlyTypes();
2079-
RequestedCachedResults.push_back(Request);
2079+
RequestedCachedResults.insert(Request);
20802080
}
20812081
return true;
20822082
}
@@ -2639,7 +2639,7 @@ void CompletionLookup::getValueCompletionsInDeclContext(SourceLoc Loc,
26392639

26402640
lookupVisibleDecls(FilteringConsumer, CurrDeclContext,
26412641
/*IncludeTopLevel=*/false, Loc);
2642-
RequestedCachedResults.push_back(
2642+
RequestedCachedResults.insert(
26432643
RequestedResultsTy::toplevelResults().withModuleQualifier(
26442644
ModuleQualifier));
26452645

@@ -2941,9 +2941,9 @@ void CompletionLookup::collectPrecedenceGroups() {
29412941
if (Module == CurrModule)
29422942
continue;
29432943

2944-
RequestedCachedResults.push_back(RequestedResultsTy::fromModule(Module)
2945-
.onlyPrecedenceGroups()
2946-
.withModuleQualifier(false));
2944+
RequestedCachedResults.insert(RequestedResultsTy::fromModule(Module)
2945+
.onlyPrecedenceGroups()
2946+
.withModuleQualifier(false));
29472947
}
29482948
}
29492949

@@ -3033,7 +3033,7 @@ void CompletionLookup::getTypeCompletionsInDeclContext(SourceLoc Loc,
30333033
lookupVisibleDecls(AccessFilteringConsumer, CurrDeclContext,
30343034
/*IncludeTopLevel=*/false, Loc);
30353035

3036-
RequestedCachedResults.push_back(
3036+
RequestedCachedResults.insert(
30373037
RequestedResultsTy::toplevelResults().onlyTypes().withModuleQualifier(
30383038
ModuleQualifier));
30393039
}

test/IDE/complete_from_swift_module.swift

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@
5353
// rdar://15305873 Code completion: implement proper shadowing of declarations represented by cached results
5454
// FIXME: %FileCheck %s -check-prefix=TOP_LEVEL_1_NEGATIVE < %t.compl.txt
5555

56+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -I %t -code-completion-token=AMBIGOUS_RESULT_BUILER > %t.compl.txt
57+
// RUN: %FileCheck %s -check-prefix=AMBIGOUS_RESULT_BUILER < %t.compl.txt
58+
5659
// ERROR_COMMON: found code completion token
5760
// ERROR_COMMON-NOT: Begin completions
5861

@@ -161,3 +164,28 @@ func foo() -> foo_swift_module.#^MODULE_TYPE_QUALIFIED^# {}
161164
// MODULE_TYPE_QUALIFIED: Decl[Struct]/OtherModule[foo_swift_module]: FooSwiftStruct[#FooSwiftStruct#]; name=FooSwiftStruct
162165
// MODULE_TYPE_QUALIFIED: Decl[Struct]/OtherModule[foo_swift_module]: BarGenericSwiftStruct2[#BarGenericSwiftStruct2#]; name=BarGenericSwiftStruct2
163166
// MODULE_TYPE_QUALIFIED: End completions
167+
168+
// rdar://92048610
169+
func testAmbiguousResultBuilder() {
170+
@resultBuilder
171+
struct MyBuilder {
172+
static func buildBlock(_ x: Int) -> Int {}
173+
}
174+
175+
struct Foo {
176+
init(arg: Int = 1, @MyBuilder content: () -> Int) {}
177+
init(arg: Int = 1) {}
178+
}
179+
180+
func test() {
181+
Foo {
182+
#^AMBIGOUS_RESULT_BUILER^#
183+
}
184+
// Results should only contain globalVar once
185+
// AMBIGOUS_RESULT_BUILER: Begin completions
186+
// AMBIGOUS_RESULT_BUILER-NOT: globalVar
187+
// AMBIGOUS_RESULT_BUILER-DAG: Decl[GlobalVar]/OtherModule[foo_swift_module]: globalVar[#Int#]; name=globalVar
188+
// AMBIGOUS_RESULT_BUILER-NOT: globalVar
189+
// AMBIGOUS_RESULT_BUILER: End completions
190+
}
191+
}

0 commit comments

Comments
 (0)