[cfe-commits] r135651 - in /cfe/trunk: include/clang-c/Index.h include/clang/Sema/CodeCompleteConsumer.h lib/Sema/SemaCodeComplete.cpp test/Index/code-completion.cpp test/Index/complete-member-access.m test/Index/complete-objc-message.m tools/c-index-test/c-index-test.c tools/libclang/CIndexCodeCompletion.cpp tools/libclang/libclang.darwin.exports tools/libclang/libclang.exports

Douglas Gregor dgregor at apple.com
Wed Jul 20 18:05:27 PDT 2011


Author: dgregor
Date: Wed Jul 20 20:05:26 2011
New Revision: 135651

URL: http://llvm.org/viewvc/llvm-project?rev=135651&view=rev
Log:
New libclang API to expose container type for code completion, from
Connor Wakamo!

Modified:
    cfe/trunk/include/clang-c/Index.h
    cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h
    cfe/trunk/lib/Sema/SemaCodeComplete.cpp
    cfe/trunk/test/Index/code-completion.cpp
    cfe/trunk/test/Index/complete-member-access.m
    cfe/trunk/test/Index/complete-objc-message.m
    cfe/trunk/tools/c-index-test/c-index-test.c
    cfe/trunk/tools/libclang/CIndexCodeCompletion.cpp
    cfe/trunk/tools/libclang/libclang.darwin.exports
    cfe/trunk/tools/libclang/libclang.exports

Modified: cfe/trunk/include/clang-c/Index.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=135651&r1=135650&r2=135651&view=diff
==============================================================================
--- cfe/trunk/include/clang-c/Index.h (original)
+++ cfe/trunk/include/clang-c/Index.h Wed Jul 20 20:05:26 2011
@@ -3144,6 +3144,39 @@
 CINDEX_LINKAGE
 unsigned long long clang_codeCompleteGetContexts(
                                                 CXCodeCompleteResults *Results);
+
+/**
+ * \brief Returns the cursor kind for the container for the current code
+ * completion context. The container is only guaranteed to be set for
+ * contexts where a container exists (i.e. member accesses or Objective-C
+ * message sends); if there is not a container, this function will return
+ * CXCursor_InvalidCode.
+ *
+ * \param Results the code completion results to query
+ *
+ * \param IsIncomplete on return, this value will be false if Clang has complete
+ * information about the container. If Clang does not have complete
+ * information, this value will be true.
+ *
+ * \returns the container kind, or CXCursor_InvalidCode if there is not a
+ * container
+ */
+CINDEX_LINKAGE
+enum CXCursorKind clang_codeCompleteGetContainerKind(
+                                                 CXCodeCompleteResults *Results,
+                                                     unsigned *IsIncomplete);
+
+/**
+ * \brief Returns the USR for the container for the current code completion
+ * context. If there is not a container for the current context, this
+ * function will return the empty string.
+ *
+ * \param Results the code completion results to query
+ *
+ * \returns the USR for the container
+ */
+CINDEX_LINKAGE
+CXString clang_codeCompleteGetContainerUSR(CXCodeCompleteResults *Results);
   
 /**
  * @}

Modified: cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h?rev=135651&r1=135650&r2=135651&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h (original)
+++ cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h Wed Jul 20 20:05:26 2011
@@ -275,7 +275,8 @@
   /// \brief Construct a new code-completion context of the given kind.
   CodeCompletionContext(enum Kind Kind, QualType T) : Kind(Kind) { 
     if (Kind == CCC_DotMemberAccess || Kind == CCC_ArrowMemberAccess ||
-        Kind == CCC_ObjCPropertyAccess)
+        Kind == CCC_ObjCPropertyAccess || Kind == CCC_ObjCClassMessage ||
+        Kind == CCC_ObjCInstanceMessage)
       BaseType = T;
     else
       PreferredType = T;

Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=135651&r1=135650&r2=135651&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Wed Jul 20 20:05:26 2011
@@ -4955,8 +4955,13 @@
                                         unsigned NumSelIdents,
                                         bool AtArgumentExpression,
                                         bool IsSuper) {
+  
+  QualType T = this->GetTypeFromParser(Receiver);
+  
   ResultBuilder Results(*this, CodeCompleter->getAllocator(),
-                        CodeCompletionContext::CCC_ObjCClassMessage);
+              CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage,
+                                    T));
+    
   AddClassMessageCompletions(*this, S, Receiver, SelIdents, NumSelIdents, 
                              AtArgumentExpression, IsSuper, Results);
   
@@ -4967,7 +4972,7 @@
   // our preferred type, improving completion results.
   if (AtArgumentExpression) {
     QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results, 
-                                                                    NumSelIdents);
+                                                                  NumSelIdents);
     if (PreferredType.isNull())
       CodeCompleteOrdinaryName(S, PCC_Expression);
     else
@@ -4976,7 +4981,7 @@
   }
 
   HandleCodeCompleteResults(this, CodeCompleter, 
-                            CodeCompletionContext::CCC_ObjCClassMessage,
+                            Results.getCompletionContext(),
                             Results.data(), Results.size());
 }
 
@@ -5019,7 +5024,9 @@
 
   // Build the set of methods we can see.
   ResultBuilder Results(*this, CodeCompleter->getAllocator(),
-                        CodeCompletionContext::CCC_ObjCInstanceMessage);
+           CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
+                                 ReceiverType));
+  
   Results.EnterNewScope();
 
   // If this is a send-to-super, try to add the special "super" send 
@@ -5132,7 +5139,7 @@
   }
   
   HandleCodeCompleteResults(this, CodeCompleter, 
-                            CodeCompletionContext::CCC_ObjCInstanceMessage,
+                            Results.getCompletionContext(),
                             Results.data(),Results.size());
 }
 

Modified: cfe/trunk/test/Index/code-completion.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/code-completion.cpp?rev=135651&r1=135650&r2=135651&view=diff
==============================================================================
--- cfe/trunk/test/Index/code-completion.cpp (original)
+++ cfe/trunk/test/Index/code-completion.cpp Wed Jul 20 20:05:26 2011
@@ -54,6 +54,9 @@
 // CHECK-MEMBER: CXXDestructor:{ResultType void}{TypedText ~Z}{LeftParen (}{RightParen )}
 // CHECK-MEMBER: Completion contexts:
 // CHECK-MEMBER-NEXT: Dot member access
+// CHECK-MEMBER-NEXT: Container Kind: StructDecl
+// CHECK-MEMBER-NEXT: Container is complete
+// CHECK-MEMBER-NEXT: Container USR: c:@S at Z
 
 // CHECK-OVERLOAD: NotImplemented:{ResultType int &}{Text overloaded}{LeftParen (}{Text Z z}{Comma , }{CurrentParameter int second}{RightParen )}
 // CHECK-OVERLOAD: NotImplemented:{ResultType float &}{Text overloaded}{LeftParen (}{Text int i}{Comma , }{CurrentParameter long second}{RightParen )}

Modified: cfe/trunk/test/Index/complete-member-access.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/complete-member-access.m?rev=135651&r1=135650&r2=135651&view=diff
==============================================================================
--- cfe/trunk/test/Index/complete-member-access.m (original)
+++ cfe/trunk/test/Index/complete-member-access.m Wed Jul 20 20:05:26 2011
@@ -37,11 +37,26 @@
 // RUN: c-index-test -code-completion-at=%s:21:7 %s | FileCheck -check-prefix=CHECK-CC1 %s
 // CHECK-CC1: ObjCPropertyDecl:{ResultType int}{TypedText prop1}
 // CHECK-CC1: ObjCPropertyDecl:{ResultType float}{TypedText ProtoProp}
+// CHECK-CC1: Completion contexts:
+// CHECK-CC1-NEXT: Objective-C property access
+// CHECK-CC1-NEXT: Container Kind: ObjCInterfaceDecl
+// CHECK-CC1-NEXT: Container is complete
+// CHECK-CC1-NEXT: Container USR: c:objc(cs)Int
 // RUN: c-index-test -code-completion-at=%s:22:8 %s | FileCheck -check-prefix=CHECK-CC2 %s
 // CHECK-CC2: ObjCIvarDecl:{ResultType int}{TypedText IVar} (35)
 // CHECK-CC2: ObjCIvarDecl:{ResultType int}{TypedText SuperIVar} (37)
+// CHECK-CC2: Completion contexts:
+// CHECK-CC2-NEXT: Arrow member access
+// CHECK-CC2-NEXT: Container Kind: ObjCInterfaceDecl
+// CHECK-CC2-NEXT: Container is complete
+// CHECK-CC2-NEXT: Container USR: c:objc(cs)Int
 // RUN: c-index-test -code-completion-at=%s:34:12 %s | FileCheck -check-prefix=CHECK-CC3 %s
 // CHECK-CC3: ObjCInstanceMethodDecl:{ResultType int}{TypedText myOtherPropLikeThing} (37)
 // CHECK-CC3: ObjCPropertyDecl:{ResultType int}{TypedText myProp} (35)
 // CHECK-CC3: ObjCPropertyDecl:{ResultType int}{TypedText prop1} (35)
 // CHECK-CC3: ObjCPropertyDecl:{ResultType float}{TypedText ProtoProp} (35)
+// CHECK-CC3: Completion contexts:
+// CHECK-CC3-NEXT: Objective-C property access
+// CHECK-CC3-NEXT: Container Kind: ObjCInterfaceDecl
+// CHECK-CC3-NEXT: Container is complete
+// CHECK-CC3-NEXT: Container USR: c:objc(cs)Sub
\ No newline at end of file

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=135651&r1=135650&r2=135651&view=diff
==============================================================================
--- cfe/trunk/test/Index/complete-objc-message.m (original)
+++ cfe/trunk/test/Index/complete-objc-message.m Wed Jul 20 20:05:26 2011
@@ -187,10 +187,20 @@
 // CHECK-CC1: {TypedText classMethod2}
 // CHECK-CC1: {TypedText new}
 // CHECK-CC1: {TypedText protocolClassMethod}
+// CHECK-CC1: Completion contexts:
+// CHECK-CC1-NEXT: Objective-C class method
+// CHECK-CC1-NEXT: Container Kind: ObjCInterfaceDecl
+// CHECK-CC1-NEXT: Container is complete
+// CHECK-CC1-NEXT: Container USR: c:objc(cs)Foo
 // 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)}
+// CHECK-CC2: Completion contexts:
+// CHECK-CC2-NEXT: Objective-C instance method
+// CHECK-CC2-NEXT: Container Kind: ObjCInterfaceDecl
+// CHECK-CC2-NEXT: Container is complete
+// CHECK-CC2-NEXT: Container USR: c:objc(cs)Foo
 // RUN: c-index-test -code-completion-at=%s:61:16 %s | FileCheck -check-prefix=CHECK-CC3 %s
 // CHECK-CC3: ObjCClassMethodDecl:{ResultType int}{TypedText MyClassMethod:}{Placeholder (id)}
 // CHECK-CC3: ObjCClassMethodDecl:{ResultType int}{TypedText MyPrivateMethod}

Modified: cfe/trunk/tools/c-index-test/c-index-test.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/c-index-test/c-index-test.c?rev=135651&r1=135650&r2=135651&view=diff
==============================================================================
--- cfe/trunk/tools/c-index-test/c-index-test.c (original)
+++ cfe/trunk/tools/c-index-test/c-index-test.c Wed Jul 20 20:05:26 2011
@@ -1171,8 +1171,9 @@
   }
 
   if (results) {
-    unsigned i, n = results->NumResults;
+    unsigned i, n = results->NumResults, containerIsIncomplete = 0;
     unsigned long long contexts;
+    enum CXCursorKind containerKind;
     if (!timing_only) {      
       /* Sort the code-completion results based on the typed text. */
       clang_sortCodeCompletionResults(results->Results, results->NumResults);
@@ -1190,6 +1191,27 @@
     contexts = clang_codeCompleteGetContexts(results);
     print_completion_contexts(contexts, stdout);
     
+    containerKind = clang_codeCompleteGetContainerKind(results, &containerIsIncomplete);
+    
+    if (containerKind != CXCursor_InvalidCode) {
+      /* We have found a container */
+      CXString containerUSR, containerKindSpelling;
+      containerKindSpelling = clang_getCursorKindSpelling(containerKind);
+      printf("Container Kind: %s\n", clang_getCString(containerKindSpelling));
+      clang_disposeString(containerKindSpelling);
+      
+      if (containerIsIncomplete) {
+        printf("Container is incomplete\n");
+      }
+      else {
+        printf("Container is complete\n");
+      }
+      
+      containerUSR = clang_codeCompleteGetContainerUSR(results);
+      printf("Container USR: %s\n", clang_getCString(containerUSR));
+      clang_disposeString(containerUSR);
+    }
+    
     clang_disposeCodeCompleteResults(results);
   }
   clang_disposeTranslationUnit(TU);

Modified: cfe/trunk/tools/libclang/CIndexCodeCompletion.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndexCodeCompletion.cpp?rev=135651&r1=135650&r2=135651&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndexCodeCompletion.cpp (original)
+++ cfe/trunk/tools/libclang/CIndexCodeCompletion.cpp Wed Jul 20 20:05:26 2011
@@ -15,7 +15,11 @@
 #include "CIndexer.h"
 #include "CXTranslationUnit.h"
 #include "CXString.h"
+#include "CXCursor.h"
 #include "CIndexDiagnostic.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/FileManager.h"
 #include "clang/Frontend/ASTUnit.h"
@@ -242,6 +246,11 @@
   /// \brief A bitfield representing the acceptable completions for the
   /// current context.
   unsigned long long Contexts;
+  
+  enum CXCursorKind ContainerKind;
+  CXString ContainerUSR;
+  
+  unsigned ContainerIsIncomplete;
 };
 
 /// \brief Tracks the number of code-completion result objects that are 
@@ -267,6 +276,8 @@
 AllocatedCXCodeCompleteResults::~AllocatedCXCodeCompleteResults() {
   delete [] Results;
   
+  clang_disposeString(ContainerUSR);
+  
   for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I)
     TemporaryFiles[I].eraseFromDisk();
   for (unsigned I = 0, N = TemporaryBuffers.size(); I != N; ++I)
@@ -455,10 +466,12 @@
   class CaptureCompletionResults : public CodeCompleteConsumer {
     AllocatedCXCodeCompleteResults &AllocatedResults;
     llvm::SmallVector<CXCompletionResult, 16> StoredResults;
+    CXTranslationUnit *TU;
   public:
-    CaptureCompletionResults(AllocatedCXCodeCompleteResults &Results)
+    CaptureCompletionResults(AllocatedCXCodeCompleteResults &Results,
+                             CXTranslationUnit *TranslationUnit)
       : CodeCompleteConsumer(true, false, true, false), 
-        AllocatedResults(Results) { }
+        AllocatedResults(Results), TU(TranslationUnit) { }
     ~CaptureCompletionResults() { Finish(); }
     
     virtual void ProcessCodeCompleteResults(Sema &S, 
@@ -477,10 +490,53 @@
         StoredResults.push_back(R);
       }
       
-      enum CodeCompletionContext::Kind kind = Context.getKind();
+      enum CodeCompletionContext::Kind contextKind = Context.getKind();
+      
+      AllocatedResults.ContextKind = contextKind;
+      AllocatedResults.Contexts = getContextsForContextKind(contextKind, S);
+      
+      QualType baseType = Context.getBaseType();
+      NamedDecl *D = NULL;
+      
+      if (!baseType.isNull()) {
+        // Get the declaration for a class/struct/union/enum type
+        if (const TagType *Tag = baseType->getAs<TagType>())
+          D = Tag->getDecl();
+        // Get the @interface declaration for a (possibly-qualified) Objective-C
+        // object pointer type, e.g., NSString*
+        else if (const ObjCObjectPointerType *ObjPtr = 
+                 baseType->getAs<ObjCObjectPointerType>())
+          D = ObjPtr->getInterfaceDecl();
+        // Get the @interface declaration for an Objective-C object type
+        else if (const ObjCObjectType *Obj = baseType->getAs<ObjCObjectType>())
+          D = Obj->getInterface();
+        // Get the class for a C++ injected-class-name
+        else if (const InjectedClassNameType *Injected =
+                 baseType->getAs<InjectedClassNameType>())
+          D = Injected->getDecl();
+      }
       
-      AllocatedResults.ContextKind = kind;
-      AllocatedResults.Contexts = getContextsForContextKind(kind, S);
+      if (D != NULL) {
+        CXCursor cursor = cxcursor::MakeCXCursor(D, *TU);
+        
+        CXCursorKind cursorKind = clang_getCursorKind(cursor);
+        CXString cursorUSR = clang_getCursorUSR(cursor);
+        
+        AllocatedResults.ContainerKind = cursorKind;
+        AllocatedResults.ContainerUSR = cursorUSR;
+        const Type *type = baseType.getTypePtrOrNull();
+        if (type != NULL) {
+          AllocatedResults.ContainerIsIncomplete = type->isIncompleteType();
+        }
+        else {
+          AllocatedResults.ContainerIsIncomplete = 1;
+        }
+      }
+      else {
+        AllocatedResults.ContainerKind = CXCursor_InvalidCode;
+        AllocatedResults.ContainerUSR = createCXString("");
+        AllocatedResults.ContainerIsIncomplete = 1;
+      }
     }
     
     virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
@@ -571,7 +627,7 @@
   Results->NumResults = 0;
   
   // Create a code-completion consumer to capture the results.
-  CaptureCompletionResults Capture(*Results);
+  CaptureCompletionResults Capture(*Results, &TU);
 
   // Perform completion.
   AST->CodeComplete(complete_filename, complete_line, complete_column,
@@ -731,6 +787,30 @@
   return Results->Contexts;
 }
 
+enum CXCursorKind clang_codeCompleteGetContainerKind(
+                                               CXCodeCompleteResults *ResultsIn,
+                                                     unsigned *IsIncomplete) {
+  AllocatedCXCodeCompleteResults *Results =
+    static_cast<AllocatedCXCodeCompleteResults *>(ResultsIn);
+  if (!Results)
+    return CXCursor_InvalidCode;
+  
+  if (IsIncomplete != NULL) {
+    *IsIncomplete = Results->ContainerIsIncomplete;
+  }
+  
+  return Results->ContainerKind;
+}
+  
+CXString clang_codeCompleteGetContainerUSR(CXCodeCompleteResults *ResultsIn) {
+  AllocatedCXCodeCompleteResults *Results =
+    static_cast<AllocatedCXCodeCompleteResults *>(ResultsIn);
+  if (!Results)
+    return createCXString("");
+  
+  return createCXString(clang_getCString(Results->ContainerUSR));
+}
+  
 } // end extern "C"
 
 /// \brief Simple utility function that appends a \p New string to the given

Modified: cfe/trunk/tools/libclang/libclang.darwin.exports
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/libclang.darwin.exports?rev=135651&r1=135650&r2=135651&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/libclang.darwin.exports (original)
+++ cfe/trunk/tools/libclang/libclang.darwin.exports Wed Jul 20 20:05:26 2011
@@ -6,6 +6,8 @@
 _clang_codeCompleteAt
 _clang_codeCompleteGetDiagnostic
 _clang_codeCompleteGetNumDiagnostics
+_clang_codeCompleteGetContainerKind
+_clang_codeCompleteGetContainerUSR
 _clang_codeCompleteGetContexts
 _clang_constructUSR_ObjCCategory
 _clang_constructUSR_ObjCClass

Modified: cfe/trunk/tools/libclang/libclang.exports
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/libclang.exports?rev=135651&r1=135650&r2=135651&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/libclang.exports (original)
+++ cfe/trunk/tools/libclang/libclang.exports Wed Jul 20 20:05:26 2011
@@ -6,6 +6,8 @@
 clang_codeCompleteAt
 clang_codeCompleteGetDiagnostic
 clang_codeCompleteGetNumDiagnostics
+clang_codeCompleteGetContainerKind
+clang_codeCompleteGetContainerUSR
 clang_codeCompleteGetContexts
 clang_constructUSR_ObjCCategory
 clang_constructUSR_ObjCClass





More information about the cfe-commits mailing list