[llvm-branch-commits] [cfe-branch] r105036 - in /cfe/branches/Apple/whitney: include/clang/Parse/Action.h lib/Parse/ParseObjc.cpp lib/Sema/Sema.h lib/Sema/SemaCodeComplete.cpp test/Index/complete-objc-message.m

Daniel Dunbar daniel at zuster.org
Fri May 28 16:06:42 PDT 2010


Author: ddunbar
Date: Fri May 28 18:06:41 2010
New Revision: 105036

URL: http://llvm.org/viewvc/llvm-project?rev=105036&view=rev
Log:
Merge r104895:
--
Author: Douglas Gregor <dgregor at apple.com>
Date:   Thu May 27 23:06:34 2010 +0000

    Implement a code-completion hook for the receiver of an Objective-C
    message. This completion gives better results than just using the
    "expression" completion, which is effectively what happened before.

Modified:
    cfe/branches/Apple/whitney/include/clang/Parse/Action.h
    cfe/branches/Apple/whitney/lib/Parse/ParseObjc.cpp
    cfe/branches/Apple/whitney/lib/Sema/Sema.h
    cfe/branches/Apple/whitney/lib/Sema/SemaCodeComplete.cpp
    cfe/branches/Apple/whitney/test/Index/complete-objc-message.m

Modified: cfe/branches/Apple/whitney/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney/include/clang/Parse/Action.h?rev=105036&r1=105035&r2=105036&view=diff
==============================================================================
--- cfe/branches/Apple/whitney/include/clang/Parse/Action.h (original)
+++ cfe/branches/Apple/whitney/include/clang/Parse/Action.h Fri May 28 18:06:41 2010
@@ -2853,6 +2853,14 @@
                                               unsigned NumMethods) {
   }
 
+  /// \brief Code completion for the receiver in an Objective-C message send.
+  ///
+  /// This code completion action is invoked when we see a '[' that indicates
+  /// the start of an Objective-C message send.
+  ///
+  /// \param S The scope in which the Objective-C message send occurs.
+  virtual void CodeCompleteObjCMessageReceiver(Scope *S) { }
+  
   /// \brief Code completion for an ObjC message expression that sends
   /// a message to the superclass.
   ///

Modified: cfe/branches/Apple/whitney/lib/Parse/ParseObjc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney/lib/Parse/ParseObjc.cpp?rev=105036&r1=105035&r2=105036&view=diff
==============================================================================
--- cfe/branches/Apple/whitney/lib/Parse/ParseObjc.cpp (original)
+++ cfe/branches/Apple/whitney/lib/Parse/ParseObjc.cpp Fri May 28 18:06:41 2010
@@ -1807,6 +1807,13 @@
   assert(Tok.is(tok::l_square) && "'[' expected");
   SourceLocation LBracLoc = ConsumeBracket(); // consume '['
 
+  if (Tok.is(tok::code_completion)) {
+    Actions.CodeCompleteObjCMessageReceiver(CurScope);
+    ConsumeCodeCompletionToken();
+    SkipUntil(tok::r_square);
+    return ExprError();
+  }
+  
   if (getLang().CPlusPlus) {
     // We completely separate the C and C++ cases because C++ requires
     // more complicated (read: slower) parsing. 

Modified: cfe/branches/Apple/whitney/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney/lib/Sema/Sema.h?rev=105036&r1=105035&r2=105036&view=diff
==============================================================================
--- cfe/branches/Apple/whitney/lib/Sema/Sema.h (original)
+++ cfe/branches/Apple/whitney/lib/Sema/Sema.h Fri May 28 18:06:41 2010
@@ -4440,7 +4440,7 @@
   virtual void CodeCompleteObjCPropertySetter(Scope *S, DeclPtrTy ClassDecl,
                                               DeclPtrTy *Methods,
                                               unsigned NumMethods);
-
+  virtual void CodeCompleteObjCMessageReceiver(Scope *S);
   virtual void CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
                                             IdentifierInfo **SelIdents,
                                             unsigned NumSelIdents);

Modified: cfe/branches/Apple/whitney/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney/lib/Sema/SemaCodeComplete.cpp?rev=105036&r1=105035&r2=105036&view=diff
==============================================================================
--- cfe/branches/Apple/whitney/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/branches/Apple/whitney/lib/Sema/SemaCodeComplete.cpp Fri May 28 18:06:41 2010
@@ -222,6 +222,7 @@
     bool IsType(NamedDecl *ND) const;
     bool IsMember(NamedDecl *ND) const;
     bool IsObjCIvar(NamedDecl *ND) const;
+    bool IsObjCMessageReceiver(NamedDecl *ND) const;
     //@}    
   };  
 }
@@ -732,6 +733,78 @@
     isa<ObjCPropertyDecl>(ND);
 }
 
+/// \brief Get the type that a given expression will have if this declaration
+/// is used as an expression in its "typical" code-completion form.
+static QualType getDeclUsageType(ASTContext &C, NamedDecl *ND) {
+  ND = cast<NamedDecl>(ND->getUnderlyingDecl());
+  
+  if (TypeDecl *Type = dyn_cast<TypeDecl>(ND))
+    return C.getTypeDeclType(Type);
+  if (ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
+    return C.getObjCInterfaceType(Iface);
+    
+  QualType T;
+  if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
+    T = Function->getResultType();
+  else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
+    T = Method->getResultType();
+  else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
+    T = FunTmpl->getTemplatedDecl()->getResultType();
+  else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
+    T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
+  else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
+    T = Property->getType();
+  else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND))
+    T = Value->getType();
+  else
+    return QualType();
+  
+  return T.getNonReferenceType();
+}
+
+static bool isObjCReceiverType(ASTContext &C, QualType T) {
+  T = C.getCanonicalType(T);
+  switch (T->getTypeClass()) {
+  case Type::ObjCObject: 
+  case Type::ObjCInterface:
+  case Type::ObjCObjectPointer:
+    return true;
+      
+  case Type::Builtin:
+    switch (cast<BuiltinType>(T)->getKind()) {
+    case BuiltinType::ObjCId:
+    case BuiltinType::ObjCClass:
+    case BuiltinType::ObjCSel:
+      return true;
+      
+    default:
+      break;
+    }
+    return false;
+      
+  default:
+    break;
+  }
+  
+  if (!C.getLangOptions().CPlusPlus)
+    return false;
+
+  // FIXME: We could perform more analysis here to determine whether a 
+  // particular class type has any conversions to Objective-C types. For now,
+  // just accept all class types.
+  return T->isDependentType() || T->isRecordType();
+}
+
+bool ResultBuilder::IsObjCMessageReceiver(NamedDecl *ND) const {
+  QualType T = getDeclUsageType(SemaRef.Context, ND);
+  if (T.isNull())
+    return false;
+  
+  T = SemaRef.Context.getBaseElementType(T);
+  return isObjCReceiverType(SemaRef.Context, T);
+}
+
+
 /// \rief Determines whether the given declaration is an Objective-C
 /// instance variable.
 bool ResultBuilder::IsObjCIvar(NamedDecl *ND) const {
@@ -3021,6 +3094,31 @@
     .Default(0);
 }
 
+void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
+  typedef CodeCompleteConsumer::Result Result;
+  ResultBuilder Results(*this);
+  
+  // Find anything that looks like it could be a message receiver.
+  Results.setFilter(&ResultBuilder::IsObjCMessageReceiver);
+  CodeCompletionDeclConsumer Consumer(Results, CurContext);
+  Results.EnterNewScope();
+  LookupVisibleDecls(S, LookupOrdinaryName, Consumer);
+  
+  // If we are in an Objective-C method inside a class that has a superclass,
+  // add "super" as an option.
+  if (ObjCMethodDecl *Method = getCurMethodDecl())
+    if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
+      if (Iface->getSuperClass())
+        Results.AddResult(Result("super"));
+  
+  Results.ExitScope();
+  
+  if (CodeCompleter->includeMacros())
+    AddMacroResults(PP, Results);
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+  
+}
+
 void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
                                         IdentifierInfo **SelIdents,
                                         unsigned NumSelIdents) {

Modified: cfe/branches/Apple/whitney/test/Index/complete-objc-message.m
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/whitney/test/Index/complete-objc-message.m?rev=105036&r1=105035&r2=105036&view=diff
==============================================================================
--- cfe/branches/Apple/whitney/test/Index/complete-objc-message.m (original)
+++ cfe/branches/Apple/whitney/test/Index/complete-objc-message.m Fri May 28 18:06:41 2010
@@ -51,7 +51,7 @@
   return 3;
 }
 @end
-
+MyClass *getMyClass();
 @implementation MySubClass
 + (int)MySubClassMethod {
   return 2;
@@ -160,14 +160,13 @@
 // CHECK-CC9: ObjCInstanceMethodDecl:{ResultType int}{Informative Method:}{Informative Arg1:}{TypedText Arg2:}{Placeholder (int)i2}
 // CHECK-CC9: ObjCInstanceMethodDecl:{ResultType int}{Informative Method:}{Informative Arg1:}{TypedText OtherArg:}{Placeholder (id)obj}
 // RUN: c-index-test -code-completion-at=%s:61:11 %s | FileCheck -check-prefix=CHECK-CCA %s
-// CHECK-CCA: {ResultType SEL}{TypedText _cmd}
 // CHECK-CCA: TypedefDecl:{TypedText Class}
-// CHECK-CCA: ObjCInterfaceDecl:{TypedText Foo}
-// CHECK-CCA: FunctionDecl:{ResultType void}{TypedText func}{LeftParen (}{RightParen )}
+// CHECK-CCA-NEXT: ObjCInterfaceDecl:{TypedText Foo}
+// CHECK-CCA-NOT: FunctionDecl:{ResultType void}{TypedText func}{LeftParen (}{RightParen )}
+// CHECK-CCA:FunctionDecl:{ResultType MyClass *}{TypedText getMyClass}{LeftParen (}{RightParen )}
 // CHECK-CCA: TypedefDecl:{TypedText id}
 // CHECK-CCA: ObjCInterfaceDecl:{TypedText MyClass}
 // CHECK-CCA: ObjCInterfaceDecl:{TypedText MySubClass}
-// CHECK-CCA: TypedefDecl:{TypedText SEL}
 // CHECK-CCA: {ResultType Class}{TypedText self}
 // CHECK-CCA: {TypedText super}
 // RUN: c-index-test -code-completion-at=%s:103:6 %s | FileCheck -check-prefix=CHECK-CCB %s
@@ -188,14 +187,12 @@
 // CHECK-CCE: ObjCClassMethodDecl:{ResultType int}{Informative Method:}{Informative Arg1:}{TypedText Arg2:}{Placeholder (int)i2}
 // CHECK-CCE: ObjCClassMethodDecl:{ResultType int}{Informative Method:}{Informative Arg1:}{TypedText OtherArg:}{Placeholder (id)obj}
 // RUN: c-index-test -code-completion-at=%s:61:11 %s | FileCheck -check-prefix=CHECK-CCF %s
-// CHECK-CCF: {ResultType SEL}{TypedText _cmd}
 // CHECK-CCF: TypedefDecl:{TypedText Class}
 // CHECK-CCF: ObjCInterfaceDecl:{TypedText Foo}
-// CHECK-CCF: FunctionDecl:{ResultType void}{TypedText func}{LeftParen (}{RightParen )}
+// CHECK-CCF-NOT: FunctionDecl:{ResultType void}{TypedText func}{LeftParen (}{RightParen )}
 // CHECK-CCF: TypedefDecl:{TypedText id}
 // CHECK-CCF: ObjCInterfaceDecl:{TypedText MyClass}
 // CHECK-CCF: ObjCInterfaceDecl:{TypedText MySubClass}
-// CHECK-CCF: TypedefDecl:{TypedText SEL}
 // CHECK-CCF: {ResultType Class}{TypedText self}
 // CHECK-CCF: {TypedText super}
 // RUN: c-index-test -code-completion-at=%s:120:6 %s | FileCheck -check-prefix=CHECK-CCG %s
@@ -230,4 +227,3 @@
 // CHECK-CCH: ObjCClassMethodDecl:{ResultType id}{TypedText new}
 // CHECK-CCH: ObjCClassMethodDecl:{ResultType int}{TypedText OtherMethod:}{Placeholder (float)f}{HorizontalSpace  }{Text Arg1:}{Placeholder (int)i1}{HorizontalSpace  }{Text Arg2:}{Placeholder (int)i2}
 // CHECK-CCH: ObjCClassMethodDecl:{ResultType id}{TypedText protocolClassMethod}
-





More information about the llvm-branch-commits mailing list