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

Douglas Gregor dgregor at apple.com
Tue Nov 17 09:59:40 PST 2009


Author: dgregor
Date: Tue Nov 17 11:59:40 2009
New Revision: 89112

URL: http://llvm.org/viewvc/llvm-project?rev=89112&view=rev
Log:
Implement code completion for Objective-C message sends to "super".

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=89112&r1=89111&r2=89112&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Tue Nov 17 11:59:40 2009
@@ -13,6 +13,7 @@
 #include "Sema.h"
 #include "clang/Sema/CodeCompleteConsumer.h"
 #include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
 #include "clang/Lex/MacroInfo.h"
 #include "clang/Lex/Preprocessor.h"
 #include "llvm/ADT/SmallPtrSet.h"
@@ -1555,11 +1556,61 @@
 
 void Sema::CodeCompleteObjCFactoryMethod(Scope *S, IdentifierInfo *FName) {
   typedef CodeCompleteConsumer::Result Result;
+  ObjCInterfaceDecl *CDecl = 0;
+
+  // FIXME: Pass this in!
+  SourceLocation NameLoc;
+
+  if (FName->isStr("super")) {
+    // We're sending a message to "super".
+    if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
+      // Figure out which interface we're in.
+      CDecl = CurMethod->getClassInterface();
+      if (!CDecl)
+        return;
+
+      // Find the superclass of this class.
+      CDecl = CDecl->getSuperClass();
+      if (!CDecl)
+        return;
+
+      if (CurMethod->isInstanceMethod()) {
+        // We are inside an instance method, which means that the message
+        // send [super ...] is actually calling an instance method on the
+        // current object. Build the super expression and handle this like
+        // an instance method.
+        QualType SuperTy = Context.getObjCInterfaceType(CDecl);
+        SuperTy = Context.getObjCObjectPointerType(SuperTy);
+        OwningExprResult Super
+          = Owned(new (Context) ObjCSuperExpr(NameLoc, SuperTy));
+        return CodeCompleteObjCInstanceMethod(S, (Expr *)Super.get());
+      }
+
+      // Okay, we're calling a factory method in our superclass.
+    } 
+  }
+
+  // If the given name refers to an interface type, retrieve the
+  // corresponding declaration.
+  if (!CDecl)
+    if (TypeTy *Ty = getTypeName(*FName, NameLoc, S, 0, false)) {
+      QualType T = GetTypeFromParser(Ty, 0);
+      if (!T.isNull()) 
+        if (const ObjCInterfaceType *Interface = T->getAs<ObjCInterfaceType>())
+          CDecl = Interface->getDecl();
+    }
+
+  if (!CDecl && FName->isStr("super")) {
+    // "super" may be the name of a variable, in which case we are
+    // probably calling an instance method.
+    OwningExprResult Super = ActOnDeclarationNameExpr(S, NameLoc, FName,
+                                                      false, 0, false);
+    return CodeCompleteObjCInstanceMethod(S, (Expr *)Super.get());
+  }
+
   ResultBuilder Results(*this);
   Results.EnterNewScope();
   
-  ObjCInterfaceDecl *CDecl = getObjCInterfaceDecl(FName);
-    
   while (CDecl != NULL) {
     for (ObjCInterfaceDecl::classmeth_iterator I = CDecl->classmeth_begin(), 
                                                E = CDecl->classmeth_end(); 

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=89112&r1=89111&r2=89112&view=diff

==============================================================================
--- cfe/trunk/test/Index/complete-objc-message.m (original)
+++ cfe/trunk/test/Index/complete-objc-message.m Tue Nov 17 11:59:40 2009
@@ -23,6 +23,57 @@
   Foo *obj = [Foo new];
   [obj xx];
 }
+
+ at interface MyClass { }
++ (int)MyClassMethod:(id)obj;
+- (int)MyInstMethod:(id)x second:(id)y;
+ at end
+
+ at interface MySubClass : MyClass { }
++ (int)MySubClassMethod;
+- (int)MySubInstMethod;
+ at end
+
+ at implementation MyClass 
++ (int)MyClassMethod:(id)obj {
+  return 0;
+}
+
++ (int)MyPrivateMethod {
+  return 1;
+}
+
+- (int)MyInstMethod:(id)x second:(id)y {
+  return 2;
+}
+
+- (int)MyPrivateInstMethod {
+  return 3;
+}
+ at end
+
+ at implementation MySubClass
++ (int)MySubClassMethod {
+  return 2;
+}
+
++ (int)MySubPrivateMethod {
+  return [super MyPrivateMethod];
+}
+
+- (int)MySubInstMethod:(id)obj {
+  return [super MyInstMethod: obj second:obj];
+}
+
+- (int)MyInstMethod:(id)x second:(id)y {
+  return 3;
+}
+ at end
+
+void test_super_var(MySubClass *super) {
+  [super MyInstMethod: super second:super];
+}
+
 // RUN: c-index-test -code-completion-at=%s:23:19 %s | FileCheck -check-prefix=CHECK-CC1 %s
 // CHECK-CC1: {TypedText categoryClassMethod}
 // CHECK-CC1: {TypedText classMethod2}
@@ -33,3 +84,13 @@
 // 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}
+// 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}
+// 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}
+





More information about the cfe-commits mailing list