Don't add two code-completion results for the same selector; it
doesn't add any value. Instead, we'll just take the first method with
that selector that we find and create a completion for it.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@114082 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 615d126..e305172 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -22,6 +22,7 @@
#include "clang/AST/ExprObjC.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
@@ -3824,7 +3825,13 @@
return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
NumSelIdents);
}
-
+
+namespace {
+ /// \brief A set of selectors, which is used to avoid introducing multiple
+ /// completions with the same selector into the result set.
+ typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
+}
+
/// \brief Add all of the Objective-C methods in the given Objective-C
/// container to the set of results.
///
@@ -3848,6 +3855,7 @@
IdentifierInfo **SelIdents,
unsigned NumSelIdents,
DeclContext *CurContext,
+ VisitedSelectorSet &Selectors,
ResultBuilder &Results,
bool InOriginalClass = true) {
typedef CodeCompletionResult Result;
@@ -3860,6 +3868,9 @@
if (!isAcceptableObjCMethod(*M, WantKind, SelIdents, NumSelIdents))
continue;
+ if (!Selectors.insert((*M)->getSelector()))
+ continue;
+
Result R = Result(*M, 0);
R.StartParameter = NumSelIdents;
R.AllParametersAreInformative = (WantKind != MK_Any);
@@ -3877,7 +3888,7 @@
E = Protocols.end();
I != E; ++I)
AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents,
- CurContext, Results, false);
+ CurContext, Selectors, Results, false);
}
ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
@@ -3890,13 +3901,14 @@
E = Protocols.end();
I != E; ++I)
AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents,
- CurContext, Results, false);
+ CurContext, Selectors, Results, false);
// Add methods in categories.
for (ObjCCategoryDecl *CatDecl = IFace->getCategoryList(); CatDecl;
CatDecl = CatDecl->getNextClassCategory()) {
AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
- NumSelIdents, CurContext, Results, InOriginalClass);
+ NumSelIdents, CurContext, Selectors, Results,
+ InOriginalClass);
// Add a categories protocol methods.
const ObjCList<ObjCProtocolDecl> &Protocols
@@ -3905,23 +3917,26 @@
E = Protocols.end();
I != E; ++I)
AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
- NumSelIdents, CurContext, Results, false);
+ NumSelIdents, CurContext, Selectors, Results, false);
// Add methods in category implementations.
if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
- NumSelIdents, CurContext, Results, InOriginalClass);
+ NumSelIdents, CurContext, Selectors, Results,
+ InOriginalClass);
}
// Add methods in superclass.
if (IFace->getSuperClass())
AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
- SelIdents, NumSelIdents, CurContext, Results, false);
+ SelIdents, NumSelIdents, CurContext, Selectors, Results,
+ false);
// Add methods in our implementation, if any.
if (ObjCImplementationDecl *Impl = IFace->getImplementation())
AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
- NumSelIdents, CurContext, Results, InOriginalClass);
+ NumSelIdents, CurContext, Selectors, Results,
+ InOriginalClass);
}
@@ -3958,7 +3973,9 @@
}
}
- AddObjCMethods(Class, true, MK_ZeroArgSelector, 0, 0, CurContext, Results);
+ VisitedSelectorSet Selectors;
+ AddObjCMethods(Class, true, MK_ZeroArgSelector, 0, 0, CurContext, Selectors,
+ Results);
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter,
CodeCompletionContext::CCC_Other,
@@ -3999,7 +4016,9 @@
}
}
- AddObjCMethods(Class, true, MK_OneArgSelector, 0, 0, CurContext, Results);
+ VisitedSelectorSet Selectors;
+ AddObjCMethods(Class, true, MK_OneArgSelector, 0, 0, CurContext,
+ Selectors, Results);
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter,
@@ -4357,9 +4376,10 @@
if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Results.setPreferredSelector(CurMethod->getSelector());
+ VisitedSelectorSet Selectors;
if (CDecl)
AddObjCMethods(CDecl, false, MK_Any, SelIdents, NumSelIdents,
- SemaRef.CurContext, Results);
+ SemaRef.CurContext, Selectors, Results);
else {
// We're messaging "id" as a type; provide all class/factory methods.
@@ -4450,6 +4470,9 @@
ReceiverType = Context.getObjCObjectPointerType(
Context.getObjCInterfaceType(IFace));
+ // Keep track of the selectors we've already added.
+ VisitedSelectorSet Selectors;
+
// Handle messages to Class. This really isn't a message to an instance
// method, so we treat it the same way we would treat a message send to a
// class method.
@@ -4458,7 +4481,7 @@
if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, NumSelIdents,
- CurContext, Results);
+ CurContext, Selectors, Results);
}
}
// Handle messages to a qualified ID ("id<foo>").
@@ -4469,21 +4492,21 @@
E = QualID->qual_end();
I != E; ++I)
AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
- Results);
+ Selectors, Results);
}
// Handle messages to a pointer to interface type.
else if (const ObjCObjectPointerType *IFacePtr
= ReceiverType->getAsObjCInterfacePointerType()) {
// Search the class, its superclasses, etc., for instance methods.
AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
- NumSelIdents, CurContext, Results);
+ NumSelIdents, CurContext, Selectors, Results);
// Search protocols for instance methods.
for (ObjCObjectPointerType::qual_iterator I = IFacePtr->qual_begin(),
E = IFacePtr->qual_end();
I != E; ++I)
AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
- Results);
+ Selectors, Results);
}
// Handle messages to "id".
else if (ReceiverType->isObjCIdType()) {
@@ -4512,7 +4535,10 @@
if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
NumSelIdents))
continue;
-
+
+ if (!Selectors.insert(MethList->Method->getSelector()))
+ continue;
+
Result R(MethList->Method, 0);
R.StartParameter = NumSelIdents;
R.AllParametersAreInformative = false;