Skip to content

Commit 470dcde

Browse files
committed
[CodeCompletion] Don't show call pattern completions for overridden functions
1 parent 390d7a6 commit 470dcde

File tree

3 files changed

+80
-11
lines changed

3 files changed

+80
-11
lines changed

include/swift/IDE/ArgumentCompletion.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@ class ArgumentTypeCheckCompletionCallback : public TypeCheckCompletionCallback {
7272

7373
void sawSolutionImpl(const constraints::Solution &solution) override;
7474

75+
/// Populates \p ShadowedDecls with all \c FuncD in \p Results that are
76+
/// defined in protocol extensions but redeclared on a nominal type and thus
77+
/// cannot be accessed
78+
void computeShadowedDecls(SmallPtrSetImpl<ValueDecl *> &ShadowedDecls);
79+
7580
public:
7681
ArgumentTypeCheckCompletionCallback(CodeCompletionExpr *CompletionExpr,
7782
DeclContext *DC)

lib/IDE/ArgumentCompletion.cpp

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,35 @@ void ArgumentTypeCheckCompletionCallback::sawSolutionImpl(const Solution &S) {
238238
Info.BaseTy, HasLabel, IsAsync, SolutionSpecificVarTypes});
239239
}
240240

241+
void ArgumentTypeCheckCompletionCallback::computeShadowedDecls(
242+
SmallPtrSetImpl<ValueDecl *> &ShadowedDecls) {
243+
for (size_t i = 0; i < Results.size(); ++i) {
244+
auto &ResultA = Results[i];
245+
for (size_t j = i + 1; j < Results.size(); ++j) {
246+
auto &ResultB = Results[j];
247+
if (!ResultA.FuncD || !ResultB.FuncD || !ResultA.FuncTy || !ResultB.FuncTy) {
248+
continue;
249+
}
250+
if (ResultA.FuncD->getName() != ResultB.FuncD->getName()) {
251+
continue;
252+
}
253+
if (!ResultA.FuncTy->isEqual(ResultB.FuncTy)) {
254+
continue;
255+
}
256+
ProtocolDecl *inProtocolExtensionA =
257+
ResultA.FuncD->getDeclContext()->getExtendedProtocolDecl();
258+
ProtocolDecl *inProtocolExtensionB =
259+
ResultB.FuncD->getDeclContext()->getExtendedProtocolDecl();
260+
261+
if (inProtocolExtensionA && !inProtocolExtensionB) {
262+
ShadowedDecls.insert(ResultA.FuncD);
263+
} else if (!inProtocolExtensionA && inProtocolExtensionB) {
264+
ShadowedDecls.insert(ResultB.FuncD);
265+
}
266+
}
267+
}
268+
}
269+
241270
void ArgumentTypeCheckCompletionCallback::deliverResults(
242271
bool IncludeSignature, SourceLoc Loc, DeclContext *DC,
243272
ide::CodeCompletionContext &CompletionCtx,
@@ -246,6 +275,9 @@ void ArgumentTypeCheckCompletionCallback::deliverResults(
246275
CompletionLookup Lookup(CompletionCtx.getResultSink(), Ctx, DC,
247276
&CompletionCtx);
248277

278+
SmallPtrSet<ValueDecl *, 4> ShadowedDecls;
279+
computeShadowedDecls(ShadowedDecls);
280+
249281
// Perform global completion as a fallback if we don't have any results.
250282
bool shouldPerformGlobalCompletion = Results.empty();
251283
SmallVector<Type, 4> ExpectedCallTypes;
@@ -290,13 +322,17 @@ void ArgumentTypeCheckCompletionCallback::deliverResults(
290322
}
291323
if (Result.FuncTy) {
292324
if (auto FuncTy = Result.FuncTy) {
293-
if (Result.IsSubscript) {
294-
assert(SemanticContext != SemanticContextKind::None);
295-
auto *SD = dyn_cast_or_null<SubscriptDecl>(Result.FuncD);
296-
Lookup.addSubscriptCallPattern(FuncTy, SD, SemanticContext);
297-
} else {
298-
auto *FD = dyn_cast_or_null<AbstractFunctionDecl>(Result.FuncD);
299-
Lookup.addFunctionCallPattern(FuncTy, FD, SemanticContext);
325+
if (ShadowedDecls.count(Result.FuncD) == 0) {
326+
// Don't show call pattern completions if the function is
327+
// overridden.
328+
if (Result.IsSubscript) {
329+
assert(SemanticContext != SemanticContextKind::None);
330+
auto *SD = dyn_cast_or_null<SubscriptDecl>(Result.FuncD);
331+
Lookup.addSubscriptCallPattern(FuncTy, SD, SemanticContext);
332+
} else {
333+
auto *FD = dyn_cast_or_null<AbstractFunctionDecl>(Result.FuncD);
334+
Lookup.addFunctionCallPattern(FuncTy, FD, SemanticContext);
335+
}
300336
}
301337
}
302338
}

test/IDE/complete_expr_after_paren.swift

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=INITIALIZER | %FileCheck %s --check-prefix=INITIALIZER
2-
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=METHOD | %FileCheck %s --check-prefix=METHOD
3-
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=AVAILABILITY | %FileCheck %s --check-prefix=AVAILABILITY
4-
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=STATIC | %FileCheck %s --check-prefix=STATIC
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-ide-test -batch-code-completion -source-filename %s -filecheck %raw-FileCheck -completion-output-dir %t
53

64
protocol MyProtocol {
75
init(init1: Int)
@@ -89,3 +87,33 @@ func testStaticFunc() {
8987
// STATIC-DAG: Decl[InstanceMethod]/CurrNominal/Flair[ArgLabels]: ['(']{#(self): TestStatic#}[')'][#() -> Void#];
9088
// STATIC: End completions
9189
}
90+
91+
protocol TestShadowedProtocol {}
92+
93+
extension TestShadowedProtocol {
94+
func argOverloaded(arg: String) {}
95+
func argOverloaded(arg: Int) {}
96+
97+
func returnTypeOverloaded() -> String {}
98+
func returnTypeOverloaded() -> Int {}
99+
}
100+
101+
struct TestShadowedStruct: TestShadowedProtocol {
102+
func argOverloaded(arg: String) {}
103+
104+
func returnTypeOverloaded() -> String {}
105+
106+
func test() {
107+
self.argOverloaded(#^ARG_OVERLOADED^#)
108+
// ARG_OVERLOADED: Begin completions, 2 items
109+
// ARG_OVERLOADED-DAG: Decl[InstanceMethod]/CurrNominal/Flair[ArgLabels]: ['(']{#arg: String#}[')'][#Void#]; name=arg:
110+
// ARG_OVERLOADED-DAG: Decl[InstanceMethod]/Super/Flair[ArgLabels]: ['(']{#arg: Int#}[')'][#Void#]; name=arg:
111+
// ARG_OVERLOADED: End completions
112+
113+
self.returnTypeOverloaded(#^RETURN_OVERLOADED^#)
114+
// RETURN_OVERLOADED: Begin completions, 2 items
115+
// RETURN_OVERLOADED-DAG: Decl[InstanceMethod]/CurrNominal/Flair[ArgLabels]: ['('][')'][#String#]; name=
116+
// RETURN_OVERLOADED-DAG: Decl[InstanceMethod]/Super/Flair[ArgLabels]: ['('][')'][#Int#]; name=
117+
// RETURN_OVERLOADED: End completions
118+
}
119+
}

0 commit comments

Comments
 (0)