forked from OSchip/llvm-project
[CodeCompletion] Ensure that ObjC root class completes instance
methods from protocols and categories as well Code completion results for class methods already include instance methods from Objective-C root classes. This commit ensures that the results also include instance methods from protocols that the root class implements and root class categories as well. rdar://28012953 Differential Revision: https://reviews.llvm.org/D27257 llvm-svn: 292932
This commit is contained in:
parent
b8ad01559f
commit
638dbc3036
|
@ -5230,24 +5230,22 @@ namespace {
|
|||
/// when it has the same number of parameters as we have selector identifiers.
|
||||
///
|
||||
/// \param Results the structure into which we'll add results.
|
||||
static void AddObjCMethods(ObjCContainerDecl *Container,
|
||||
bool WantInstanceMethods,
|
||||
ObjCMethodKind WantKind,
|
||||
static void AddObjCMethods(ObjCContainerDecl *Container,
|
||||
bool WantInstanceMethods, ObjCMethodKind WantKind,
|
||||
ArrayRef<IdentifierInfo *> SelIdents,
|
||||
DeclContext *CurContext,
|
||||
VisitedSelectorSet &Selectors,
|
||||
bool AllowSameLength,
|
||||
ResultBuilder &Results,
|
||||
bool InOriginalClass = true) {
|
||||
VisitedSelectorSet &Selectors, bool AllowSameLength,
|
||||
ResultBuilder &Results, bool InOriginalClass = true,
|
||||
bool IsRootClass = false) {
|
||||
typedef CodeCompletionResult Result;
|
||||
Container = getContainerDef(Container);
|
||||
ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
|
||||
bool isRootClass = IFace && !IFace->getSuperClass();
|
||||
IsRootClass = IsRootClass || (IFace && !IFace->getSuperClass());
|
||||
for (auto *M : Container->methods()) {
|
||||
// The instance methods on the root class can be messaged via the
|
||||
// metaclass.
|
||||
if (M->isInstanceMethod() == WantInstanceMethods ||
|
||||
(isRootClass && !WantInstanceMethods)) {
|
||||
(IsRootClass && !WantInstanceMethods)) {
|
||||
// Check whether the selector identifiers we've been given are a
|
||||
// subset of the identifiers for this particular method.
|
||||
if (!isAcceptableObjCMethod(M, WantKind, SelIdents, AllowSameLength))
|
||||
|
@ -5273,8 +5271,8 @@ static void AddObjCMethods(ObjCContainerDecl *Container,
|
|||
for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
|
||||
E = Protocols.end();
|
||||
I != E; ++I)
|
||||
AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
|
||||
CurContext, Selectors, AllowSameLength, Results, false);
|
||||
AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
|
||||
Selectors, AllowSameLength, Results, false, IsRootClass);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5283,43 +5281,43 @@ static void AddObjCMethods(ObjCContainerDecl *Container,
|
|||
|
||||
// Add methods in protocols.
|
||||
for (auto *I : IFace->protocols())
|
||||
AddObjCMethods(I, WantInstanceMethods, WantKind, SelIdents,
|
||||
CurContext, Selectors, AllowSameLength, Results, false);
|
||||
|
||||
AddObjCMethods(I, WantInstanceMethods, WantKind, SelIdents, CurContext,
|
||||
Selectors, AllowSameLength, Results, false, IsRootClass);
|
||||
|
||||
// Add methods in categories.
|
||||
for (auto *CatDecl : IFace->known_categories()) {
|
||||
AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
|
||||
CurContext, Selectors, AllowSameLength,
|
||||
Results, InOriginalClass);
|
||||
|
||||
CurContext, Selectors, AllowSameLength, Results,
|
||||
InOriginalClass, IsRootClass);
|
||||
|
||||
// Add a categories protocol methods.
|
||||
const ObjCList<ObjCProtocolDecl> &Protocols
|
||||
= CatDecl->getReferencedProtocols();
|
||||
for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
|
||||
E = Protocols.end();
|
||||
I != E; ++I)
|
||||
AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
|
||||
CurContext, Selectors, AllowSameLength,
|
||||
Results, false);
|
||||
|
||||
AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
|
||||
Selectors, AllowSameLength, Results, false, IsRootClass);
|
||||
|
||||
// Add methods in category implementations.
|
||||
if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
|
||||
AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
|
||||
CurContext, Selectors, AllowSameLength,
|
||||
Results, InOriginalClass);
|
||||
AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
|
||||
Selectors, AllowSameLength, Results, InOriginalClass,
|
||||
IsRootClass);
|
||||
}
|
||||
|
||||
// Add methods in superclass.
|
||||
// Avoid passing in IsRootClass since root classes won't have super classes.
|
||||
if (IFace->getSuperClass())
|
||||
AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
|
||||
SelIdents, CurContext, Selectors,
|
||||
AllowSameLength, Results, false);
|
||||
AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
|
||||
SelIdents, CurContext, Selectors, AllowSameLength, Results,
|
||||
/*IsRootClass=*/false);
|
||||
|
||||
// Add methods in our implementation, if any.
|
||||
if (ObjCImplementationDecl *Impl = IFace->getImplementation())
|
||||
AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
|
||||
CurContext, Selectors, AllowSameLength,
|
||||
Results, InOriginalClass);
|
||||
AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
|
||||
Selectors, AllowSameLength, Results, InOriginalClass,
|
||||
IsRootClass);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -346,3 +346,54 @@ void test_Nullability(Nullability *n, A* a) {
|
|||
|
||||
// RUN: c-index-test -code-completion-at=%s:197:6 %s | FileCheck -check-prefix=CHECK-NULLABLE %s
|
||||
// CHECK-NULLABLE: ObjCInstanceMethodDecl:{ResultType A * _Nonnull}{TypedText method:}{Placeholder (nullable A *)}
|
||||
|
||||
// rdar://28012953
|
||||
// Code completion results should include instance methods from RootProtocol and
|
||||
// RootClass when completing a method invocation for a RootClass object because
|
||||
// RootClasses metaclass subclasses from RootClass (i.e. RootClass is actually
|
||||
// an instance of RootClass).
|
||||
|
||||
@protocol SubRootProtocol
|
||||
|
||||
- (void)subProtocolInstanceMethod;
|
||||
|
||||
@end
|
||||
|
||||
@protocol RootProtocol <SubRootProtocol>
|
||||
|
||||
- (void)protocolInstanceMethod;
|
||||
+ (void)protocolClassMethod;
|
||||
|
||||
@end
|
||||
|
||||
@interface RootClass <RootProtocol>
|
||||
|
||||
- (void)instanceMethod;
|
||||
+ (void)classMethod;
|
||||
|
||||
@end
|
||||
|
||||
@protocol RootCategoryProtocol
|
||||
|
||||
- (void)categoryProtocolInstanceMethod;
|
||||
|
||||
@end
|
||||
|
||||
@interface RootClass (Cat) <RootCategoryProtocol>
|
||||
|
||||
- (void)categoryInstanceMethod;
|
||||
|
||||
@end
|
||||
|
||||
void completeAllTheRootThings() {
|
||||
[RootClass classMethod];
|
||||
}
|
||||
|
||||
// RUN: c-index-test -code-completion-at=%s:389:14 %s | FileCheck -check-prefix=CHECK-ROOT %s
|
||||
// CHECK-ROOT: ObjCInstanceMethodDecl:{ResultType void}{TypedText categoryInstanceMethod} (35)
|
||||
// CHECK-ROOT-NEXT: ObjCInstanceMethodDecl:{ResultType void}{TypedText categoryProtocolInstanceMethod} (37)
|
||||
// CHECK-ROOT-NEXT: ObjCClassMethodDecl:{ResultType void}{TypedText classMethod} (35)
|
||||
// CHECK-ROOT-NEXT: ObjCInstanceMethodDecl:{ResultType void}{TypedText instanceMethod} (35)
|
||||
// CHECK-ROOT-NEXT: ObjCClassMethodDecl:{ResultType void}{TypedText protocolClassMethod} (37)
|
||||
// CHECK-ROOT-NEXT: ObjCInstanceMethodDecl:{ResultType void}{TypedText protocolInstanceMethod} (37)
|
||||
// CHECK-ROOT-NEXT: ObjCInstanceMethodDecl:{ResultType void}{TypedText subProtocolInstanceMethod} (37)
|
||||
|
|
Loading…
Reference in New Issue