[cfe-commits] r89163 - in /cfe/trunk: lib/Sema/SemaCodeComplete.cpp test/CodeCompletion/objc-message.m test/Index/complete-objc-message.m

Douglas Gregor dgregor at apple.com
Tue Nov 17 15:22:23 PST 2009


Author: dgregor
Date: Tue Nov 17 17:22:23 2009
New Revision: 89163

URL: http://llvm.org/viewvc/llvm-project?rev=89163&view=rev
Log:
Refactor code-completion support for message sends, collecting the
code to find and add Objective-C methods (starting at an
ObjCContainerDecl) into a single, static function. Also, make sure
that we search into the implementations of classes and categories to
find even more methods.


Modified:
    cfe/trunk/lib/Sema/SemaCodeComplete.cpp
    cfe/trunk/test/CodeCompletion/objc-message.m
    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=89163&r1=89162&r2=89163&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Tue Nov 17 17:22:23 2009
@@ -1047,7 +1047,9 @@
     typedef CodeCompleteConsumer::Result Result;
     
     bool isEarlierDeclarationName(DeclarationName X, DeclarationName Y) const {
-      if (X.getNameKind() != Y.getNameKind())
+      if (!X.getObjCSelector().isNull() && !Y.getObjCSelector().isNull()) {
+        // Consider all selector kinds to be equivalent.
+      } else if (X.getNameKind() != Y.getNameKind())
         return X.getNameKind() < Y.getNameKind();
       
       return llvm::LowercaseString(X.getAsString()) 
@@ -1554,6 +1556,74 @@
   HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
 }
 
+/// \brief Add all of the Objective-C methods in the given Objective-C 
+/// container to the set of results.
+///
+/// The container will be a class, protocol, category, or implementation of 
+/// any of the above. This mether will recurse to include methods from 
+/// the superclasses of classes along with their categories, protocols, and
+/// implementations.
+///
+/// \param Container the container in which we'll look to find methods.
+///
+/// \param WantInstance whether to add instance methods (only); if false, this
+/// routine will add factory methods (only).
+///
+/// \param CurContext the context in which we're performing the lookup that
+/// finds methods.
+///
+/// \param Results the structure into which we'll add results.
+static void AddObjCMethods(ObjCContainerDecl *Container, 
+                           bool WantInstanceMethods,
+                           DeclContext *CurContext,
+                           ResultBuilder &Results) {
+  typedef CodeCompleteConsumer::Result Result;
+  for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
+                                       MEnd = Container->meth_end();
+       M != MEnd; ++M) {
+    if ((*M)->isInstanceMethod() == WantInstanceMethods)
+      Results.MaybeAddResult(Result(*M, 0), CurContext);
+  }
+  
+  ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
+  if (!IFace)
+    return;
+  
+  // Add methods in protocols.
+  const ObjCList<ObjCProtocolDecl> &Protocols= IFace->getReferencedProtocols();
+  for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
+                                            E = Protocols.end(); 
+       I != E; ++I)
+    AddObjCMethods(*I, WantInstanceMethods, CurContext, Results);
+  
+  // Add methods in categories.
+  for (ObjCCategoryDecl *CatDecl = IFace->getCategoryList(); CatDecl;
+       CatDecl = CatDecl->getNextClassCategory()) {
+    AddObjCMethods(CatDecl, WantInstanceMethods, CurContext, Results);
+    
+    // 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, CurContext, Results);
+    
+    // Add methods in category implementations.
+    if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
+      AddObjCMethods(Impl, WantInstanceMethods, CurContext, Results);
+  }
+  
+  // Add methods in superclass.
+  if (IFace->getSuperClass())
+    AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, CurContext,
+                   Results);
+
+  // Add methods in our implementation, if any.
+  if (ObjCImplementationDecl *Impl = IFace->getImplementation())
+    AddObjCMethods(Impl, WantInstanceMethods, CurContext, Results);
+}
+
 void Sema::CodeCompleteObjCFactoryMethod(Scope *S, IdentifierInfo *FName) {
   typedef CodeCompleteConsumer::Result Result;
   ObjCInterfaceDecl *CDecl = 0;
@@ -1608,109 +1678,52 @@
     return CodeCompleteObjCInstanceMethod(S, (Expr *)Super.get());
   }
 
+  // Add all of the factory methods in this Objective-C class, its protocols,
+  // superclasses, categories, implementation, etc.
   ResultBuilder Results(*this);
   Results.EnterNewScope();
-  
-  while (CDecl != NULL) {
-    for (ObjCInterfaceDecl::classmeth_iterator I = CDecl->classmeth_begin(), 
-                                               E = CDecl->classmeth_end(); 
-         I != E; ++I) {
-      Results.MaybeAddResult(Result(*I, 0), CurContext);
-    }
-    // Add class methods in protocols.
-    const ObjCList<ObjCProtocolDecl> &Protocols=CDecl->getReferencedProtocols();
-    for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
-         E = Protocols.end(); I != E; ++I) {
-      for (ObjCProtocolDecl::classmeth_iterator I2 = (*I)->classmeth_begin(), 
-                                                E2 = (*I)->classmeth_end(); 
-           I2 != E2; ++I2) {
-        Results.MaybeAddResult(Result(*I2, 0), CurContext);
-      }
-    }
-    // Add class methods in categories.
-    ObjCCategoryDecl *CatDecl = CDecl->getCategoryList();
-    while (CatDecl) {
-      for (ObjCCategoryDecl::classmeth_iterator I = CatDecl->classmeth_begin(), 
-                                                E = CatDecl->classmeth_end(); 
-           I != E; ++I) {
-        Results.MaybeAddResult(Result(*I, 0), CurContext);
-      }
-      // Add a categories protocol methods.
-      const ObjCList<ObjCProtocolDecl> &Protocols =
-        CatDecl->getReferencedProtocols();
-      for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
-           E = Protocols.end(); I != E; ++I) {
-        for (ObjCProtocolDecl::classmeth_iterator I2 = (*I)->classmeth_begin(), 
-                                                  E2 = (*I)->classmeth_end(); 
-             I2 != E2; ++I2) {
-          Results.MaybeAddResult(Result(*I2, 0), CurContext);
-        }
-      }
-      CatDecl = CatDecl->getNextClassCategory();
-    }
-    CDecl = CDecl->getSuperClass();
-  }
+  AddObjCMethods(CDecl, false, CurContext, Results);  
   Results.ExitScope();
+  
   // This also suppresses remaining diagnostics.
   HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
 }
 
 void Sema::CodeCompleteObjCInstanceMethod(Scope *S, ExprTy *Receiver) {
   typedef CodeCompleteConsumer::Result Result;
-  ResultBuilder Results(*this);
-  Results.EnterNewScope();
   
   Expr *RecExpr = static_cast<Expr *>(Receiver);
   QualType RecType = RecExpr->getType();
   
-  const ObjCObjectPointerType* OCOPT = RecType->getAs<ObjCObjectPointerType>();
+  // If necessary, apply function/array conversion to the receiver.
+  // C99 6.7.5.3p[7,8].
+  DefaultFunctionArrayConversion(RecExpr);
+  QualType ReceiverType = RecExpr->getType();
   
+  if (ReceiverType->isObjCIdType() || ReceiverType->isBlockPointerType()) {
+    // FIXME: We're messaging 'id'. Do we actually want to look up every method
+    // in the universe?
+    return;
+  }
+  
+  const ObjCObjectPointerType* OCOPT 
+    = ReceiverType->getAs<ObjCObjectPointerType>();  
   if (!OCOPT)
     return;
   
   // FIXME: handle 'id', 'Class', and qualified types. 
-  ObjCInterfaceDecl *CDecl = OCOPT->getInterfaceDecl();
+  
+  // Build the set of methods we can see.
+  ResultBuilder Results(*this);
+  Results.EnterNewScope();
 
-  while (CDecl != NULL) {
-    for (ObjCInterfaceDecl::instmeth_iterator I = CDecl->instmeth_begin(), 
-                                               E = CDecl->instmeth_end(); 
-         I != E; ++I) {
-      Results.MaybeAddResult(Result(*I, 0), CurContext);
-    }
-    // Add class methods in protocols.
-    const ObjCList<ObjCProtocolDecl> &Protocols=CDecl->getReferencedProtocols();
-    for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
-         E = Protocols.end(); I != E; ++I) {
-      for (ObjCProtocolDecl::instmeth_iterator I2 = (*I)->instmeth_begin(), 
-                                                E2 = (*I)->instmeth_end(); 
-           I2 != E2; ++I2) {
-        Results.MaybeAddResult(Result(*I2, 0), CurContext);
-      }
-    }
-    // Add class methods in categories.
-    ObjCCategoryDecl *CatDecl = CDecl->getCategoryList();
-    while (CatDecl) {
-      for (ObjCCategoryDecl::instmeth_iterator I = CatDecl->instmeth_begin(), 
-                                                E = CatDecl->instmeth_end(); 
-           I != E; ++I) {
-        Results.MaybeAddResult(Result(*I, 0), CurContext);
-      }
-      // Add a categories protocol methods.
-      const ObjCList<ObjCProtocolDecl> &Protocols =
-        CatDecl->getReferencedProtocols();
-      for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
-           E = Protocols.end(); I != E; ++I) {
-        for (ObjCProtocolDecl::instmeth_iterator I2 = (*I)->instmeth_begin(), 
-                                                  E2 = (*I)->instmeth_end(); 
-             I2 != E2; ++I2) {
-          Results.MaybeAddResult(Result(*I2, 0), CurContext);
-        }
-      }
-      CatDecl = CatDecl->getNextClassCategory();
-    }
-    CDecl = CDecl->getSuperClass();
-  }
+  ObjCInterfaceDecl *CDecl = OCOPT->getInterfaceDecl();
+  if (!CDecl)
+    return;
+  
+  AddObjCMethods(CDecl, true, CurContext, Results);
   Results.ExitScope();
+  
   // This also suppresses remaining diagnostics.
   HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
 }

Modified: cfe/trunk/test/CodeCompletion/objc-message.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeCompletion/objc-message.m?rev=89163&r1=89162&r2=89163&view=diff

==============================================================================
--- cfe/trunk/test/CodeCompletion/objc-message.m (original)
+++ cfe/trunk/test/CodeCompletion/objc-message.m Tue Nov 17 17:22:23 2009
@@ -25,10 +25,10 @@
 }
 // RUN: clang-cc -fsyntax-only -code-completion-at=%s:23:19 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
 // CHECK-CC1: categoryClassMethod : 0
+// CHECK-CC1: classMethod1:withKeyword: : 0
 // CHECK-CC1: classMethod2 : 0
 // CHECK-CC1: new : 0
 // CHECK-CC1: protocolClassMethod : 0
-// CHECK-CC1: classMethod1:withKeyword: : 0
 // RUN: clang-cc -fsyntax-only -code-completion-at=%s:24:8 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
 // CHECK-CC2: categoryInstanceMethod : 0
 // CHECK-CC2: instanceMethod1 : 0

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=89163&r1=89162&r2=89163&view=diff

==============================================================================
--- cfe/trunk/test/Index/complete-objc-message.m (original)
+++ cfe/trunk/test/Index/complete-objc-message.m Tue Nov 17 17:22:23 2009
@@ -76,21 +76,21 @@
 
 // RUN: c-index-test -code-completion-at=%s:23:19 %s | FileCheck -check-prefix=CHECK-CC1 %s
 // CHECK-CC1: {TypedText categoryClassMethod}
+// CHECK-CC1: {TypedText classMethod1:}{Placeholder (id)a}{Text  withKeyword:}{Placeholder (int)b}
 // CHECK-CC1: {TypedText classMethod2}
 // CHECK-CC1: {TypedText new}
 // CHECK-CC1: {TypedText protocolClassMethod}
-// CHECK-CC1: {TypedText classMethod1:}{Placeholder (id)a}{Text  withKeyword:}{Placeholder (int)b}
 // RUN: c-index-test -code-completion-at=%s:24:8 %s | FileCheck -check-prefix=CHECK-CC2 %s
 // CHECK-CC2: {TypedText categoryInstanceMethod}
 // CHECK-CC2: {TypedText instanceMethod1}
 // CHECK-CC2: {TypedText protocolInstanceMethod:}{Placeholder (int)value}
 // RUN: c-index-test -code-completion-at=%s:61:16 %s | FileCheck -check-prefix=CHECK-CC3 %s
 // CHECK-CC3: ObjCClassMethodDecl:{TypedText MyClassMethod:}{Placeholder (id)obj}
-// FIXME-CC3: ObjCClassMethodDecl:{TypedText MyPrivateMethod}
+// CHECK-CC3: ObjCClassMethodDecl:{TypedText MyPrivateMethod}
 // RUN: c-index-test -code-completion-at=%s:65:16 %s | FileCheck -check-prefix=CHECK-CC4 %s
 // CHECK-CC4: ObjCInstanceMethodDecl:{TypedText MyInstMethod:}{Placeholder (id)x}{Text  second:}{Placeholder (id)y}
-// FIXME-CC4: ObjCInstanceMethodDecl:{TypedText MyPrivateInstMethod}
+// CHECK-CC4: ObjCInstanceMethodDecl:{TypedText MyPrivateInstMethod}
 // RUN: c-index-test -code-completion-at=%s:74:9 %s | FileCheck -check-prefix=CHECK-CC5 %s
-// CHECK-CC5: ObjCInstanceMethodDecl:{TypedText MySubInstMethod}
 // CHECK-CC5: ObjCInstanceMethodDecl:{TypedText MyInstMethod:}{Placeholder (id)x}{Text  second:}{Placeholder (id)y}
+// CHECK-CC5: ObjCInstanceMethodDecl:{TypedText MySubInstMethod}
 





More information about the cfe-commits mailing list