Skip to content

Commit ab7ba4c

Browse files
committed
[CodeCompletion] Don't show protocol extension only members in override
Protocol extension only members are not customization point. Code completion should not suggest them in override/conformance completion. rdar://problem/53591636
1 parent 6557794 commit ab7ba4c

File tree

8 files changed

+96
-26
lines changed

8 files changed

+96
-26
lines changed

include/swift/AST/NameLookup.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,7 @@ void lookupVisibleMemberDecls(VisibleDeclConsumer &Consumer,
473473
const DeclContext *CurrDC,
474474
bool includeInstanceMembers,
475475
bool includeDerivedRequirements,
476+
bool includeProtocolExtensionMembers,
476477
GenericSignatureBuilder *GSB = nullptr);
477478

478479
namespace namelookup {

lib/IDE/CodeCompletion.cpp

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3531,7 +3531,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
35313531
if (Type Unwrapped = ExprType->getOptionalObjectType()) {
35323532
lookupVisibleMemberDecls(*this, Unwrapped, CurrDeclContext,
35333533
IncludeInstanceMembers,
3534-
/*includeDerivedRequirements*/false);
3534+
/*includeDerivedRequirements*/false,
3535+
/*includeProtocolExtensionMembers*/true);
35353536
return true;
35363537
}
35373538
assert(IsUnwrappedOptional && "IUOs should be optional if not bound/forced");
@@ -3552,7 +3553,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
35523553
if (!tryTupleExprCompletions(Unwrapped)) {
35533554
lookupVisibleMemberDecls(*this, Unwrapped, CurrDeclContext,
35543555
IncludeInstanceMembers,
3555-
/*includeDerivedRequirements*/false);
3556+
/*includeDerivedRequirements*/false,
3557+
/*includeProtocolExtensionMembers*/true);
35563558
}
35573559
}
35583560
return true;
@@ -3623,7 +3625,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
36233625

36243626
lookupVisibleMemberDecls(*this, ExprType, CurrDeclContext,
36253627
IncludeInstanceMembers,
3626-
/*includeDerivedRequirements*/false);
3628+
/*includeDerivedRequirements*/false,
3629+
/*includeProtocolExtensionMembers*/true);
36273630
}
36283631

36293632
void collectOperators(SmallVectorImpl<OperatorDecl *> &results) {
@@ -4099,7 +4102,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
40994102
llvm::SaveAndRestore<bool> SaveUnresolved(IsUnresolvedMember, true);
41004103
lookupVisibleMemberDecls(consumer, baseType, CurrDeclContext,
41014104
/*includeInstanceMembers=*/false,
4102-
/*includeDerivedRequirements*/false);
4105+
/*includeDerivedRequirements*/false,
4106+
/*includeProtocolExtensionMembers*/true);
41034107
}
41044108

41054109
void getUnresolvedMemberCompletions(ArrayRef<Type> Types) {
@@ -4161,7 +4165,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
41614165
lookupVisibleMemberDecls(*this, MetatypeType::get(BaseType),
41624166
CurrDeclContext,
41634167
IncludeInstanceMembers,
4164-
/*includeDerivedRequirements*/false);
4168+
/*includeDerivedRequirements*/false,
4169+
/*includeProtocolExtensionMembers*/false);
41654170
if (BaseType->isAnyExistentialType()) {
41664171
addKeyword("Protocol", MetatypeType::get(BaseType));
41674172
addKeyword("Type", ExistentialMetatypeType::get(BaseType));
@@ -4195,7 +4200,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
41954200
NeedLeadingDot = false;
41964201
lookupVisibleMemberDecls(*this, MetatypeType::get(selfTy),
41974202
CurrDeclContext, IncludeInstanceMembers,
4198-
/*includeDerivedRequirements*/false);
4203+
/*includeDerivedRequirements*/false,
4204+
/*includeProtocolExtensionMembers*/true);
41994205
}
42004206

42014207
static bool canUseAttributeOnDecl(DeclAttrKind DAK, bool IsInSil,
@@ -4864,7 +4870,8 @@ class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
48644870
Type Meta = MetatypeType::get(CurrTy);
48654871
lookupVisibleMemberDecls(*this, Meta, CurrDeclContext,
48664872
/*includeInstanceMembers=*/true,
4867-
/*includeDerivedRequirements*/true);
4873+
/*includeDerivedRequirements*/true,
4874+
/*includeProtocolExtensionMembers*/false);
48684875
addDesignatedInitializers(NTD);
48694876
addAssociatedTypes(NTD);
48704877
}

lib/IDE/ConformingMethodList.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,8 @@ void ConformingMethodListCallbacks::getMatchingMethods(
165165

166166
lookupVisibleMemberDecls(LocalConsumer, MetatypeType::get(T), CurDeclContext,
167167
/*includeInstanceMembers=*/false,
168-
/*includeDerivedRequirements*/false);
168+
/*includeDerivedRequirements*/false,
169+
/*includeProtocolExtensionMembers*/true);
169170
}
170171

171172
} // anonymous namespace.

lib/IDE/TypeContextInfo.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,8 @@ void ContextInfoCallbacks::getImplicitMembers(
168168

169169
lookupVisibleMemberDecls(LocalConsumer, MetatypeType::get(T), CurDeclContext,
170170
/*includeInstanceMembers=*/false,
171-
/*includeDerivedRequirements*/false);
171+
/*includeDerivedRequirements*/false,
172+
/*includeProtocolExtensionMembers*/true);
172173
}
173174

174175
void PrintingTypeContextInfoConsumer::handleResults(

lib/Sema/LookupVisibleDecls.cpp

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,13 @@ struct LookupState {
6161
/// This option is only for override completion lookup.
6262
unsigned IncludeDerivedRequirements : 1;
6363

64+
/// Should protocol extension members be included?
65+
unsigned IncludeProtocolExtensionMembers : 1;
66+
6467
LookupState()
6568
: IsQualified(0), IsOnMetatype(0), IsOnSuperclass(0),
6669
InheritsSuperclassInitializers(0), IncludeInstanceMembers(0),
67-
IncludeDerivedRequirements(0) {}
70+
IncludeDerivedRequirements(0), IncludeProtocolExtensionMembers(0) {}
6871

6972
public:
7073
LookupState(const LookupState &) = default;
@@ -91,6 +94,9 @@ struct LookupState {
9194
bool isIncludingDerivedRequirements() const {
9295
return IncludeDerivedRequirements;
9396
}
97+
bool isIncludingProtocolExtensionMembers() const {
98+
return IncludeProtocolExtensionMembers;
99+
}
94100

95101
LookupState withOnMetatype() const {
96102
auto Result = *this;
@@ -127,6 +133,12 @@ struct LookupState {
127133
Result.IncludeDerivedRequirements = 1;
128134
return Result;
129135
}
136+
137+
LookupState withIncludeProtocolExtensionMembers() const {
138+
auto Result = *this;
139+
Result.IncludeProtocolExtensionMembers = 1;
140+
return Result;
141+
}
130142
};
131143
} // end anonymous namespace
132144

@@ -463,13 +475,20 @@ static void lookupDeclsFromProtocolsBeingConformedTo(
463475
};
464476
DeclVisibilityKind ReasonForThisDecl = ReasonForThisProtocol;
465477
if (const auto Witness = NormalConformance->getWitness(VD)) {
466-
if (Witness.getDecl()->getName() == VD->getName()) {
478+
auto *WD = Witness.getDecl();
479+
if (WD->getName() == VD->getName()) {
467480
if (LS.isIncludingDerivedRequirements() &&
468481
Reason == DeclVisibilityKind::MemberOfCurrentNominal &&
469-
isDerivedRequirement(Witness.getDecl())) {
482+
isDerivedRequirement(WD)) {
470483
ReasonForThisDecl =
471484
DeclVisibilityKind::MemberOfProtocolDerivedByCurrentNominal;
485+
} else if (!LS.isIncludingProtocolExtensionMembers() &&
486+
WD->getDeclContext()->getExtendedProtocolDecl()) {
487+
// Don't skip this requiement.
488+
// Witnesses in protocol extensions aren't reported.
472489
} else {
490+
// lookupVisibleMemberDecls() generally prefers witness members
491+
// over requirements.
473492
continue;
474493
}
475494
}
@@ -481,11 +500,13 @@ static void lookupDeclsFromProtocolsBeingConformedTo(
481500
}
482501

483502
// Add members from any extensions.
484-
SmallVector<ValueDecl *, 2> FoundDecls;
485-
doGlobalExtensionLookup(BaseTy, Proto->getDeclaredType(), FoundDecls,
486-
FromContext, LS, ReasonForThisProtocol);
487-
for (auto *VD : FoundDecls)
488-
Consumer.foundDecl(VD, ReasonForThisProtocol);
503+
if (LS.isIncludingProtocolExtensionMembers()) {
504+
SmallVector<ValueDecl *, 2> FoundDecls;
505+
doGlobalExtensionLookup(BaseTy, Proto->getDeclaredType(), FoundDecls,
506+
FromContext, LS, ReasonForThisProtocol);
507+
for (auto *VD : FoundDecls)
508+
Consumer.foundDecl(VD, ReasonForThisProtocol);
509+
}
489510
}
490511
}
491512

@@ -582,6 +603,9 @@ static void lookupVisibleMemberDeclsImpl(
582603
if (LS.isIncludingDerivedRequirements()) {
583604
subLS = subLS.withIncludedDerivedRequirements();
584605
}
606+
if (LS.isIncludingProtocolExtensionMembers()) {
607+
subLS = subLS.withIncludeProtocolExtensionMembers();
608+
}
585609

586610
// Just perform normal dot lookup on the type see if we find extensions or
587611
// anything else. For example, type SomeTy.SomeMember can look up static
@@ -1111,6 +1135,7 @@ static void lookupVisibleDeclsImpl(VisibleDeclConsumer &Consumer,
11111135
GenericParamList *GenericParams = nullptr;
11121136
Type ExtendedType;
11131137
auto LS = LookupState::makeUnqualified();
1138+
LS = LS.withIncludeProtocolExtensionMembers();
11141139

11151140
// Skip initializer contexts, we will not find any declarations there.
11161141
if (isa<Initializer>(DC)) {
@@ -1308,6 +1333,7 @@ void swift::lookupVisibleMemberDecls(VisibleDeclConsumer &Consumer, Type BaseTy,
13081333
const DeclContext *CurrDC,
13091334
bool includeInstanceMembers,
13101335
bool includeDerivedRequirements,
1336+
bool includeProtocolExtensionMembers,
13111337
GenericSignatureBuilder *GSB) {
13121338
assert(CurrDC);
13131339
LookupState ls = LookupState::makeQualified();
@@ -1317,6 +1343,9 @@ void swift::lookupVisibleMemberDecls(VisibleDeclConsumer &Consumer, Type BaseTy,
13171343
if (includeDerivedRequirements) {
13181344
ls = ls.withIncludedDerivedRequirements();
13191345
}
1346+
if (includeProtocolExtensionMembers) {
1347+
ls = ls.withIncludeProtocolExtensionMembers();
1348+
}
13201349

13211350
::lookupVisibleMemberDecls(BaseTy, Consumer, CurrDC, ls,
13221351
DeclVisibilityKind::MemberOfCurrentNominal,

lib/Sema/TypeCheckNameLookup.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -615,7 +615,8 @@ void TypeChecker::performTypoCorrection(DeclContext *DC, DeclRefKind refKind,
615615
if (baseTypeOrNull) {
616616
lookupVisibleMemberDecls(consumer, baseTypeOrNull, DC,
617617
/*includeInstanceMembers*/true,
618-
/*includeDerivedRequirements*/false, gsb);
618+
/*includeDerivedRequirements*/false,
619+
/*includeProtocolExtensionMembers*/true, gsb);
619620
} else {
620621
lookupVisibleDecls(consumer, DC, /*top level*/ true,
621622
corrections.Loc.getBaseNameLoc());

test/IDE/complete_from_stdlib.swift

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,6 @@
5252
// RUN: %FileCheck %s -check-prefix=PRIVATE_NOMINAL_MEMBERS_10 < %t.members10.txt
5353
// RUN: %FileCheck %s -check-prefix=NO_STDLIB_PRIVATE < %t.members10.txt
5454

55-
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=RETURNS_DROPFIRST_SEQUENCE | %FileCheck %s -check-prefix=RETURNS_DROPFIRST_SEQUENCE
56-
5755
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=POSTFIX_INT_1 | %FileCheck %s -check-prefix=POSTFIX_RVALUE_INT
5856
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=POSTFIX_INT_2 | %FileCheck %s -check-prefix=POSTFIX_LVALUE_INT
5957
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=POSTFIX_OPTIONAL_1 | %FileCheck %s -check-prefix=POSTFIX_OPTIONAL
@@ -218,12 +216,6 @@ func testArchetypeReplacement6() {
218216
// PRIVATE_NOMINAL_MEMBERS_10: Begin completions
219217
// PRIVATE_NOMINAL_MEMBERS_10-DAG: Decl[InstanceMethod]/CurrNominal: foo({#(t): P1 & P2#})[#Void#]{{; name=.+}}
220218

221-
// rdar://problem/22334700
222-
struct Test1000 : Sequence {
223-
func #^RETURNS_DROPFIRST_SEQUENCE^#
224-
}
225-
// RETURNS_DROPFIRST_SEQUENCE: Decl[InstanceMethod]/Super: dropFirst(_ k: Int = 1) -> DropFirstSequence<Test1000>
226-
227219
func testPostfixOperator1(_ x: Int) {
228220
x#^POSTFIX_INT_1^#
229221
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token CONFORMANCE_EXT | %FileCheck %s --check-prefix=CONFORMANCE_EXT
2+
3+
protocol P {
4+
init(requirement: Int)
5+
init(customizable: Int)
6+
7+
var requirementVar: Int { get }
8+
var customizableVar: Int { get }
9+
10+
func requirementMethod()
11+
func customizableMethod()
12+
}
13+
14+
extension P {
15+
init(customizable v: Int) { self.init(requirement: v) }
16+
init(nonRequirement v: Int) { self.init(requirement: v) }
17+
18+
var customizableVar: Int { 1 }
19+
var nonRequirementVar: Int { 1 }
20+
21+
func customizableMethod() {}
22+
func nonRequirement() {}
23+
}
24+
25+
struct S: P {
26+
#^CONFORMANCE_EXT^#
27+
28+
// CONFORMANCE_EXT: Begin completions
29+
// CONFORMANCE_EXT-NOT: nonRequirement
30+
// CONFORMANCE_EXT-DAG: Decl[Constructor]/Super: init(requirement: Int) {|};
31+
// CONFORMANCE_EXT-DAG: Decl[Constructor]/Super: init(customizable: Int) {|};
32+
// CONFORMANCE_EXT-DAG: Decl[InstanceVar]/Super: var requirementVar: Int;
33+
// CONFORMANCE_EXT-DAG: Decl[InstanceVar]/Super: var customizableVar: Int;
34+
// CONFORMANCE_EXT-DAG: Decl[InstanceMethod]/Super: func requirementMethod() {|};
35+
// CONFORMANCE_EXT-DAG: Decl[InstanceMethod]/Super: func customizableMethod() {|};
36+
// CONFORMANCE_EXT-NOT: nonRequirement
37+
// CONFORMANCE_EXT: End completions
38+
}

0 commit comments

Comments
 (0)