Skip to content

Commit d4a8ced

Browse files
committed
When adding KVC code completions, keep track of all of the selectors
that we've previously seen, both in declared methods and from previous KVC completions, to eliminate duplicates. Fixes <rdar://problem/9162207>. llvm-svn: 130890
1 parent 260c4a9 commit d4a8ced

File tree

2 files changed

+46
-23
lines changed

2 files changed

+46
-23
lines changed

clang/lib/Sema/SemaCodeComplete.cpp

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5549,7 +5549,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
55495549
bool IsInstanceMethod,
55505550
QualType ReturnType,
55515551
ASTContext &Context,
5552-
const KnownMethodsMap &KnownMethods,
5552+
VisitedSelectorSet &KnownSelectors,
55535553
ResultBuilder &Results) {
55545554
IdentifierInfo *PropName = Property->getIdentifier();
55555555
if (!PropName || PropName->getLength() == 0)
@@ -5595,7 +5595,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
55955595

55965596
// Add the normal accessor -(type)key.
55975597
if (IsInstanceMethod &&
5598-
!KnownMethods.count(Selectors.getNullarySelector(PropName)) &&
5598+
KnownSelectors.insert(Selectors.getNullarySelector(PropName)) &&
55995599
ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
56005600
if (ReturnType.isNull())
56015601
AddObjCPassingTypeChunk(Property->getType(), Context, Builder);
@@ -5615,7 +5615,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
56155615
Property->getType()->isBooleanType())))) {
56165616
std::string SelectorName = (llvm::Twine("is") + UpperKey).str();
56175617
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
5618-
if (!KnownMethods.count(Selectors.getNullarySelector(SelectorId))) {
5618+
if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
56195619
if (ReturnType.isNull()) {
56205620
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
56215621
Builder.AddTextChunk("BOOL");
@@ -5634,7 +5634,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
56345634
!Property->getSetterMethodDecl()) {
56355635
std::string SelectorName = (llvm::Twine("set") + UpperKey).str();
56365636
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
5637-
if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) {
5637+
if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
56385638
if (ReturnType.isNull()) {
56395639
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
56405640
Builder.AddTextChunk("void");
@@ -5685,7 +5685,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
56855685
(ReturnType.isNull() || ReturnType->isIntegerType())) {
56865686
std::string SelectorName = (llvm::Twine("countOf") + UpperKey).str();
56875687
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
5688-
if (!KnownMethods.count(Selectors.getNullarySelector(SelectorId))) {
5688+
if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
56895689
if (ReturnType.isNull()) {
56905690
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
56915691
Builder.AddTextChunk("NSUInteger");
@@ -5708,7 +5708,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
57085708
std::string SelectorName
57095709
= (llvm::Twine("objectIn") + UpperKey + "AtIndex").str();
57105710
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
5711-
if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) {
5711+
if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
57125712
if (ReturnType.isNull()) {
57135713
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
57145714
Builder.AddTextChunk("id");
@@ -5735,7 +5735,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
57355735
std::string SelectorName
57365736
= (llvm::Twine(Property->getName()) + "AtIndexes").str();
57375737
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
5738-
if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) {
5738+
if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
57395739
if (ReturnType.isNull()) {
57405740
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
57415741
Builder.AddTextChunk("NSArray *");
@@ -5760,7 +5760,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
57605760
&Context.Idents.get("range")
57615761
};
57625762

5763-
if (!KnownMethods.count(Selectors.getSelector(2, SelectorIds))) {
5763+
if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
57645764
if (ReturnType.isNull()) {
57655765
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
57665766
Builder.AddTextChunk("void");
@@ -5794,7 +5794,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
57945794
&Context.Idents.get(SelectorName)
57955795
};
57965796

5797-
if (!KnownMethods.count(Selectors.getSelector(2, SelectorIds))) {
5797+
if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
57985798
if (ReturnType.isNull()) {
57995799
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
58005800
Builder.AddTextChunk("void");
@@ -5826,7 +5826,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
58265826
&Context.Idents.get("atIndexes")
58275827
};
58285828

5829-
if (!KnownMethods.count(Selectors.getSelector(2, SelectorIds))) {
5829+
if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
58305830
if (ReturnType.isNull()) {
58315831
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
58325832
Builder.AddTextChunk("void");
@@ -5854,7 +5854,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
58545854
std::string SelectorName
58555855
= (llvm::Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
58565856
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
5857-
if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) {
5857+
if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
58585858
if (ReturnType.isNull()) {
58595859
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
58605860
Builder.AddTextChunk("void");
@@ -5876,7 +5876,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
58765876
std::string SelectorName
58775877
= (llvm::Twine("remove") + UpperKey + "AtIndexes").str();
58785878
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
5879-
if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) {
5879+
if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
58805880
if (ReturnType.isNull()) {
58815881
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
58825882
Builder.AddTextChunk("void");
@@ -5902,7 +5902,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
59025902
&Context.Idents.get("withObject")
59035903
};
59045904

5905-
if (!KnownMethods.count(Selectors.getSelector(2, SelectorIds))) {
5905+
if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
59065906
if (ReturnType.isNull()) {
59075907
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
59085908
Builder.AddTextChunk("void");
@@ -5935,7 +5935,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
59355935
&Context.Idents.get(SelectorName2)
59365936
};
59375937

5938-
if (!KnownMethods.count(Selectors.getSelector(2, SelectorIds))) {
5938+
if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
59395939
if (ReturnType.isNull()) {
59405940
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
59415941
Builder.AddTextChunk("void");
@@ -5968,7 +5968,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
59685968
->getName() == "NSEnumerator"))) {
59695969
std::string SelectorName = (llvm::Twine("enumeratorOf") + UpperKey).str();
59705970
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
5971-
if (!KnownMethods.count(Selectors.getNullarySelector(SelectorId))) {
5971+
if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
59725972
if (ReturnType.isNull()) {
59735973
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
59745974
Builder.AddTextChunk("NSEnumerator *");
@@ -5986,7 +5986,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
59865986
(ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
59875987
std::string SelectorName = (llvm::Twine("memberOf") + UpperKey).str();
59885988
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
5989-
if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) {
5989+
if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
59905990
if (ReturnType.isNull()) {
59915991
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
59925992
Builder.AddPlaceholderChunk("object-type");
@@ -6016,7 +6016,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
60166016
std::string SelectorName
60176017
= (llvm::Twine("add") + UpperKey + llvm::Twine("Object")).str();
60186018
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
6019-
if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) {
6019+
if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
60206020
if (ReturnType.isNull()) {
60216021
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
60226022
Builder.AddTextChunk("void");
@@ -6038,7 +6038,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
60386038
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
60396039
std::string SelectorName = (llvm::Twine("add") + UpperKey).str();
60406040
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
6041-
if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) {
6041+
if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
60426042
if (ReturnType.isNull()) {
60436043
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
60446044
Builder.AddTextChunk("void");
@@ -6060,7 +6060,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
60606060
std::string SelectorName
60616061
= (llvm::Twine("remove") + UpperKey + llvm::Twine("Object")).str();
60626062
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
6063-
if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) {
6063+
if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
60646064
if (ReturnType.isNull()) {
60656065
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
60666066
Builder.AddTextChunk("void");
@@ -6082,7 +6082,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
60826082
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
60836083
std::string SelectorName = (llvm::Twine("remove") + UpperKey).str();
60846084
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
6085-
if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) {
6085+
if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
60866086
if (ReturnType.isNull()) {
60876087
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
60886088
Builder.AddTextChunk("void");
@@ -6103,7 +6103,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
61036103
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
61046104
std::string SelectorName = (llvm::Twine("intersect") + UpperKey).str();
61056105
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
6106-
if (!KnownMethods.count(Selectors.getUnarySelector(SelectorId))) {
6106+
if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
61076107
if (ReturnType.isNull()) {
61086108
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
61096109
Builder.AddTextChunk("void");
@@ -6131,7 +6131,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
61316131
std::string SelectorName
61326132
= (llvm::Twine("keyPathsForValuesAffecting") + UpperKey).str();
61336133
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
6134-
if (!KnownMethods.count(Selectors.getNullarySelector(SelectorId))) {
6134+
if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
61356135
if (ReturnType.isNull()) {
61366136
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
61376137
Builder.AddTextChunk("NSSet *");
@@ -6271,6 +6271,13 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S,
62716271
llvm::SmallVector<ObjCContainerDecl *, 4> Containers;
62726272
Containers.push_back(SearchDecl);
62736273

6274+
VisitedSelectorSet KnownSelectors;
6275+
for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6276+
MEnd = KnownMethods.end();
6277+
M != MEnd; ++M)
6278+
KnownSelectors.insert(M->first);
6279+
6280+
62746281
ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
62756282
if (!IFace)
62766283
if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
@@ -6287,7 +6294,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S,
62876294
PEnd = Containers[I]->prop_end();
62886295
P != PEnd; ++P) {
62896296
AddObjCKeyValueCompletions(*P, IsInstanceMethod, ReturnType, Context,
6290-
KnownMethods, Results);
6297+
KnownSelectors, Results);
62916298
}
62926299
}
62936300
}

clang/test/Index/complete-kvc.m

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,17 @@ - (void)setIntProperty:(int)newValue { }
4141
+ (NSSet *)keyPathsForValuesAffectingIntProperty { return 0; }
4242
@end
4343

44+
@interface MySubClass : MyClass
45+
@end
46+
47+
@interface MySubClass ()
48+
@property int intProperty;
49+
@end
50+
51+
@implementation MySubClass
52+
- (int)intProperty { return 0; }
53+
@end
54+
4455
// RUN: c-index-test -code-completion-at=%s:39:3 %s | FileCheck -check-prefix=CHECK-CC1 %s
4556
// CHECK-CC1: ObjCInstanceMethodDecl:{LeftParen (}{Text void}{RightParen )}{TypedText addMutableArrayPropertyObject:}{LeftParen (}{Placeholder object-type}{Text *}{RightParen )}{Text object} (55)
4657
// CHECK-CC1: ObjCInstanceMethodDecl:{LeftParen (}{Text void}{RightParen )}{TypedText addMutableSetProperty:}{LeftParen (}{Text NSSet *}{RightParen )}{Text objects} (40)
@@ -85,3 +96,8 @@ + (NSSet *)keyPathsForValuesAffectingIntProperty { return 0; }
8596

8697
// RUN: c-index-test -code-completion-at=%s:41:3 %s | FileCheck -check-prefix=CHECK-CC2 %s
8798
// CHECK-CC2: ObjCInstanceMethodDecl:{LeftParen (}{Text NSSet *}{RightParen )}{TypedText keyPathsForValuesAffectingMutableArrayProperty} (40)
99+
100+
// RUN: c-index-test -code-completion-at=%s:52:8 %s | FileCheck -check-prefix=CHECK-CC3 %s
101+
// CHECK-CC3: ObjCInstanceMethodDecl:{TypedText countOfIntProperty} (55)
102+
// CHECK-CC3-NEXT: ObjCInstanceMethodDecl:{TypedText intProperty} (40)
103+
// CHECK-CC3-NEXT: ObjCInstanceMethodDecl:{TypedText isIntProperty} (40)

0 commit comments

Comments
 (0)