r292932 - [CodeCompletion] Ensure that ObjC root class completes instance

Alex Lorenz via cfe-commits cfe-commits at lists.llvm.org
Tue Jan 24 06:15:10 PST 2017


Author: arphaman
Date: Tue Jan 24 08:15:08 2017
New Revision: 292932

URL: http://llvm.org/viewvc/llvm-project?rev=292932&view=rev
Log:
[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

Modified:
    cfe/trunk/lib/Sema/SemaCodeComplete.cpp
    cfe/trunk/test/Index/complete-objc-message.m

Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=292932&r1=292931&r2=292932&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Tue Jan 24 08:15:08 2017
@@ -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(ObjCContainer
       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(ObjCContainer
   
   // 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);
 }
 
 

Modified: cfe/trunk/test/Index/complete-objc-message.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/complete-objc-message.m?rev=292932&r1=292931&r2=292932&view=diff
==============================================================================
--- cfe/trunk/test/Index/complete-objc-message.m (original)
+++ cfe/trunk/test/Index/complete-objc-message.m Tue Jan 24 08:15:08 2017
@@ -346,3 +346,54 @@ void test_Nullability(Nullability *n, 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).
+
+ at protocol SubRootProtocol
+
+- (void)subProtocolInstanceMethod;
+
+ at end
+
+ at protocol RootProtocol <SubRootProtocol>
+
+- (void)protocolInstanceMethod;
++ (void)protocolClassMethod;
+
+ at end
+
+ at interface RootClass <RootProtocol>
+
+- (void)instanceMethod;
++ (void)classMethod;
+
+ at end
+
+ at protocol RootCategoryProtocol
+
+- (void)categoryProtocolInstanceMethod;
+
+ at end
+
+ at interface RootClass (Cat) <RootCategoryProtocol>
+
+- (void)categoryInstanceMethod;
+
+ at 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)




More information about the cfe-commits mailing list