]> granicus.if.org Git - clang/commitdiff
Introduce a new libclang aPI function,
authorDouglas Gregor <dgregor@apple.com>
Thu, 7 Jul 2011 16:03:39 +0000 (16:03 +0000)
committerDouglas Gregor <dgregor@apple.com>
Thu, 7 Jul 2011 16:03:39 +0000 (16:03 +0000)
clang_codeCompleteGetContexts(), that provides the client with
information about the context in which code completion has occurred
and what kinds of entities make sense as completions at that
point. Patch by Connor Wakamo!

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@134615 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang-c/Index.h
include/clang/Sema/CodeCompleteConsumer.h
lib/Frontend/ASTUnit.cpp
lib/Sema/CodeCompleteConsumer.cpp
lib/Sema/SemaCodeComplete.cpp
test/Index/code-completion.cpp
test/Index/complete-natural.m
tools/c-index-test/c-index-test.c
tools/libclang/CIndexCodeCompletion.cpp
tools/libclang/libclang.darwin.exports
tools/libclang/libclang.exports

index 5bf20316b12751577b89fd2c40d21f3d3276653b..f7a0f569a3eecb65229bbdf0b68e151541b9a6af 100644 (file)
@@ -2870,6 +2870,137 @@ enum CXCodeComplete_Flags {
   CXCodeComplete_IncludeCodePatterns = 0x02
 };
 
+/**
+ * \brief Bits that represent the context under which completion is occurring.
+ *
+ * The enumerators in this enumeration may be bitwise-OR'd together if multiple
+ * contexts are occurring simultaneously.
+ */
+enum CXCompletionContext {
+  /**
+   * \brief The context for completions is unexposed, as only Clang results
+   * should be included. (This is equivalent to having no context bits set.)
+   */
+  CXCompletionContext_Unexposed = 0,
+  
+  /**
+   * \brief Completions for any possible type should be included in the results.
+   */
+  CXCompletionContext_AnyType = 1 << 0,
+  
+  /**
+   * \brief Completions for any possible value (variables, function calls, etc.)
+   * should be included in the results.
+   */
+  CXCompletionContext_AnyValue = 1 << 1,
+  /**
+   * \brief Completions for values that resolve to an Objective-C object should
+   * be included in the results.
+   */
+  CXCompletionContext_ObjCObjectValue = 1 << 2,
+  /**
+   * \brief Completions for values that resolve to an Objective-C selector
+   * should be included in the results.
+   */
+  CXCompletionContext_ObjCSelectorValue = 1 << 3,
+  /**
+   * \brief Completions for values that resolve to a C++ class type should be
+   * included in the results.
+   */
+  CXCompletionContext_CXXClassTypeValue = 1 << 4,
+  
+  /**
+   * \brief Completions for fields of the member being accessed using the dot
+   * operator should be included in the results.
+   */
+  CXCompletionContext_DotMemberAccess = 1 << 5,
+  /**
+   * \brief Completions for fields of the member being accessed using the arrow
+   * operator should be included in the results.
+   */
+  CXCompletionContext_ArrowMemberAccess = 1 << 6,
+  /**
+   * \brief Completions for properties of the Objective-C object being accessed
+   * using the dot operator should be included in the results.
+   */
+  CXCompletionContext_ObjCPropertyAccess = 1 << 7,
+  
+  /**
+   * \brief Completions for enum tags should be included in the results.
+   */
+  CXCompletionContext_EnumTag = 1 << 8,
+  /**
+   * \brief Completions for union tags should be included in the results.
+   */
+  CXCompletionContext_UnionTag = 1 << 9,
+  /**
+   * \brief Completions for struct tags should be included in the results.
+   */
+  CXCompletionContext_StructTag = 1 << 10,
+  
+  /**
+   * \brief Completions for C++ class names should be included in the results.
+   */
+  CXCompletionContext_ClassTag = 1 << 11,
+  /**
+   * \brief Completions for C++ namespaces and namespace aliases should be
+   * included in the results.
+   */
+  CXCompletionContext_Namespace = 1 << 12,
+  /**
+   * \brief Completions for C++ nested name specifiers should be included in
+   * the results.
+   */
+  CXCompletionContext_NestedNameSpecifier = 1 << 13,
+  
+  /**
+   * \brief Completions for Objective-C interfaces (classes) should be included
+   * in the results.
+   */
+  CXCompletionContext_ObjCInterface = 1 << 14,
+  /**
+   * \brief Completions for Objective-C protocols should be included in
+   * the results.
+   */
+  CXCompletionContext_ObjCProtocol = 1 << 15,
+  /**
+   * \brief Completions for Objective-C categories should be included in
+   * the results.
+   */
+  CXCompletionContext_ObjCCategory = 1 << 16,
+  /**
+   * \brief Completions for Objective-C instance messages should be included
+   * in the results.
+   */
+  CXCompletionContext_ObjCInstanceMessage = 1 << 17,
+  /**
+   * \brief Completions for Objective-C class messages should be included in
+   * the results.
+   */
+  CXCompletionContext_ObjCClassMessage = 1 << 18,
+  /**
+   * \brief Completions for Objective-C selector names should be included in
+   * the results.
+   */
+  CXCompletionContext_ObjCSelectorName = 1 << 19,
+  
+  /**
+   * \brief Completions for preprocessor macro names should be included in
+   * the results.
+   */
+  CXCompletionContext_MacroName = 1 << 20,
+  
+  /**
+   * \brief Natural language completions should be included in the results.
+   */
+  CXCompletionContext_NaturalLanguage = 1 << 21,
+  
+  /**
+   * \brief The current context is unknown, so set all contexts.
+   */
+  CXCompletionContext_Unknown = ((1 << 22) - 1)
+};
+  
 /**
  * \brief Returns a default set of code-completion options that can be
  * passed to\c clang_codeCompleteAt(). 
@@ -2990,6 +3121,19 @@ CINDEX_LINKAGE
 CXDiagnostic clang_codeCompleteGetDiagnostic(CXCodeCompleteResults *Results,
                                              unsigned Index);
 
+/**
+ * \brief Determines what compeltions are appropriate for the context
+ * the given code completion.
+ * 
+ * \param Results the code completion results to query
+ *
+ * \returns the kinds of completions that are appropriate for use
+ * along with the given code completion results.
+ */
+CINDEX_LINKAGE
+unsigned long long clang_codeCompleteGetContexts(
+                                                CXCodeCompleteResults *Results);
+  
 /**
  * @}
  */
index d3221809b9813a8eea3e56e0c4b67eefc49fcff4..74b0105b331008a12827f70db0fef7c1c3de7c95 100644 (file)
@@ -185,12 +185,26 @@ public:
     /// is expected.
     CCC_ObjCMessageReceiver,
     /// \brief Code completion occurred on the right-hand side of a member
-    /// access expression.
+    /// access expression using the dot operator.
     ///
     /// The results of this completion are the members of the type being 
     /// accessed. The type itself is available via 
     /// \c CodeCompletionContext::getType().
-    CCC_MemberAccess,
+    CCC_DotMemberAccess,
+    /// \brief Code completion occurred on the right-hand side of a member
+    /// access expression using the arrow operator.
+    ///
+    /// The results of this completion are the members of the type being 
+    /// accessed. The type itself is available via 
+    /// \c CodeCompletionContext::getType().
+    CCC_ArrowMemberAccess,
+    /// \brief Code completion occurred on the right-hand side of an Objective-C
+    /// property access expression.
+    ///
+    /// The results of this completion are the members of the type being 
+    /// accessed. The type itself is available via 
+    /// \c CodeCompletionContext::getType().
+    CCC_ObjCPropertyAccess,
     /// \brief Code completion occurred after the "enum" keyword, to indicate
     /// an enumeration name.
     CCC_EnumTag,
@@ -235,6 +249,15 @@ public:
     /// \brief Code completion in a parenthesized expression, which means that
     /// we may also have types here in C and Objective-C (as well as in C++).
     CCC_ParenthesizedExpression,
+    /// \brief Code completion where an Objective-C instance message is expcted.
+    CCC_ObjCInstanceMessage,
+    /// \brief Code completion where an Objective-C class message is expected. 
+    CCC_ObjCClassMessage,
+    /// \brief Code completion where a superclass of an Objective-C class is
+    /// expected.
+    CCC_ObjCSuperclass,
+    /// \brief Code completion where an Objective-C category name is expected.
+    CCC_ObjCCategoryName,
     /// \brief An unknown context, in which we are recovering from a parsing 
     /// error and don't know which completions we should give.
     CCC_Recovery
@@ -256,7 +279,8 @@ public:
   
   /// \brief Construct a new code-completion context of the given kind.
   CodeCompletionContext(enum Kind Kind, QualType T) : Kind(Kind) { 
-    if (Kind == CCC_MemberAccess)
+    if (Kind == CCC_DotMemberAccess || Kind == CCC_ArrowMemberAccess ||
+        Kind == CCC_ObjCPropertyAccess)
       BaseType = T;
     else
       PreferredType = T;
index 4407d2d3e22b1fe5c184c3c7613b633df32e2bfe..ad476455ebc91051d1766a8b5c3747fe404888d1 100644 (file)
@@ -182,6 +182,10 @@ static unsigned getDeclShowContexts(NamedDecl *ND,
     // all types are available due to functional casts.
     if (LangOpts.CPlusPlus || isa<ObjCInterfaceDecl>(ND))
       Contexts |= (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1));
+    
+    // In Objective-C, you can only be a subclass of another Objective-C class
+    if (isa<ObjCInterfaceDecl>(ND))
+      Contexts |= (1 << (CodeCompletionContext::CCC_ObjCSuperclass - 1));
 
     // Deal with tag names.
     if (isa<EnumDecl>(ND)) {
@@ -208,6 +212,8 @@ static unsigned getDeclShowContexts(NamedDecl *ND,
              | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1));
   } else if (isa<ObjCProtocolDecl>(ND)) {
     Contexts = (1 << (CodeCompletionContext::CCC_ObjCProtocolName - 1));
+  } else if (isa<ObjCCategoryDecl>(ND)) {
+    Contexts = (1 << (CodeCompletionContext::CCC_ObjCCategoryName - 1));
   } else if (isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) {
     Contexts = (1 << (CodeCompletionContext::CCC_Namespace - 1));
    
@@ -1902,7 +1908,7 @@ namespace {
   /// results from an ASTUnit with the code-completion results provided to it,
   /// then passes the result on to 
   class AugmentedCodeCompleteConsumer : public CodeCompleteConsumer {
-    unsigned NormalContexts;
+    unsigned long long NormalContexts;
     ASTUnit &AST;
     CodeCompleteConsumer &Next;
     
@@ -1916,22 +1922,24 @@ namespace {
       // Compute the set of contexts in which we will look when we don't have
       // any information about the specific context.
       NormalContexts 
-        = (1 << (CodeCompletionContext::CCC_TopLevel - 1))
-        | (1 << (CodeCompletionContext::CCC_ObjCInterface - 1))
-        | (1 << (CodeCompletionContext::CCC_ObjCImplementation - 1))
-        | (1 << (CodeCompletionContext::CCC_ObjCIvarList - 1))
-        | (1 << (CodeCompletionContext::CCC_Statement - 1))
-        | (1 << (CodeCompletionContext::CCC_Expression - 1))
-        | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1))
-        | (1 << (CodeCompletionContext::CCC_MemberAccess - 1))
-        | (1 << (CodeCompletionContext::CCC_ObjCProtocolName - 1))
-        | (1 << (CodeCompletionContext::CCC_ParenthesizedExpression - 1))
-        | (1 << (CodeCompletionContext::CCC_Recovery - 1));
+        = (1LL << (CodeCompletionContext::CCC_TopLevel - 1))
+        | (1LL << (CodeCompletionContext::CCC_ObjCInterface - 1))
+        | (1LL << (CodeCompletionContext::CCC_ObjCImplementation - 1))
+        | (1LL << (CodeCompletionContext::CCC_ObjCIvarList - 1))
+        | (1LL << (CodeCompletionContext::CCC_Statement - 1))
+        | (1LL << (CodeCompletionContext::CCC_Expression - 1))
+        | (1LL << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1))
+        | (1LL << (CodeCompletionContext::CCC_DotMemberAccess - 1))
+        | (1LL << (CodeCompletionContext::CCC_ArrowMemberAccess - 1))
+        | (1LL << (CodeCompletionContext::CCC_ObjCPropertyAccess - 1))
+        | (1LL << (CodeCompletionContext::CCC_ObjCProtocolName - 1))
+        | (1LL << (CodeCompletionContext::CCC_ParenthesizedExpression - 1))
+        | (1LL << (CodeCompletionContext::CCC_Recovery - 1));
 
       if (AST.getASTContext().getLangOptions().CPlusPlus)
-        NormalContexts |= (1 << (CodeCompletionContext::CCC_EnumTag - 1))
-                    | (1 << (CodeCompletionContext::CCC_UnionTag - 1))
-                    | (1 << (CodeCompletionContext::CCC_ClassOrStructTag - 1));
+        NormalContexts |= (1LL << (CodeCompletionContext::CCC_EnumTag - 1))
+                   | (1LL << (CodeCompletionContext::CCC_UnionTag - 1))
+                   | (1LL << (CodeCompletionContext::CCC_ClassOrStructTag - 1));
     }
     
     virtual void ProcessCodeCompleteResults(Sema &S, 
@@ -1969,12 +1977,15 @@ static void CalculateHiddenNames(const CodeCompletionContext &Context,
   case CodeCompletionContext::CCC_Statement:
   case CodeCompletionContext::CCC_Expression:
   case CodeCompletionContext::CCC_ObjCMessageReceiver:
-  case CodeCompletionContext::CCC_MemberAccess:
+  case CodeCompletionContext::CCC_DotMemberAccess:
+  case CodeCompletionContext::CCC_ArrowMemberAccess:
+  case CodeCompletionContext::CCC_ObjCPropertyAccess:
   case CodeCompletionContext::CCC_Namespace:
   case CodeCompletionContext::CCC_Type:
   case CodeCompletionContext::CCC_Name:
   case CodeCompletionContext::CCC_PotentiallyQualifiedName:
   case CodeCompletionContext::CCC_ParenthesizedExpression:
+  case CodeCompletionContext::CCC_ObjCSuperclass:
     break;
     
   case CodeCompletionContext::CCC_EnumTag:
@@ -1993,6 +2004,9 @@ static void CalculateHiddenNames(const CodeCompletionContext &Context,
   case CodeCompletionContext::CCC_TypeQualifiers:
   case CodeCompletionContext::CCC_Other:
   case CodeCompletionContext::CCC_OtherWithMacros:
+  case CodeCompletionContext::CCC_ObjCInstanceMessage:
+  case CodeCompletionContext::CCC_ObjCClassMessage:
+  case CodeCompletionContext::CCC_ObjCCategoryName:
     // We're looking for nothing, or we're looking for names that cannot
     // be hidden.
     return;
index 2334ab5128a70d9648ab1c57ea36e51b89966e50..d7dc5b2538c6b35d5deb2950c551202e98f20abc 100644 (file)
@@ -46,7 +46,9 @@ bool CodeCompletionContext::wantConstructorResults() const {
   case CCC_ObjCImplementation:
   case CCC_ObjCIvarList:
   case CCC_ClassStructUnion:
-  case CCC_MemberAccess:
+  case CCC_DotMemberAccess:
+  case CCC_ArrowMemberAccess:
+  case CCC_ObjCPropertyAccess:
   case CCC_EnumTag:
   case CCC_UnionTag:
   case CCC_ClassOrStructTag:
@@ -64,6 +66,10 @@ bool CodeCompletionContext::wantConstructorResults() const {
   case CCC_TypeQualifiers:
   case CCC_Other:
   case CCC_OtherWithMacros:
+  case CCC_ObjCInstanceMessage:
+  case CCC_ObjCClassMessage:
+  case CCC_ObjCSuperclass:
+  case CCC_ObjCCategoryName:
     return false;
   }
   
index 69b38593fbfd76233f45d0fd2174ca29d68b5d55..b555c8a9aa1f247cc24efe77c58671c76371e480 100644 (file)
@@ -3244,8 +3244,23 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE,
       return;
   }
   
+  enum CodeCompletionContext::Kind contextKind;
+  
+  if (IsArrow) {
+    contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
+  }
+  else {
+    if (BaseType->isObjCObjectPointerType() ||
+        BaseType->isObjCObjectOrInterfaceType()) {
+      contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
+    }
+    else {
+      contextKind = CodeCompletionContext::CCC_DotMemberAccess;
+    }
+  }
+  
   ResultBuilder Results(*this, CodeCompleter->getAllocator(),
-                  CodeCompletionContext(CodeCompletionContext::CCC_MemberAccess,
+                  CodeCompletionContext(contextKind,
                                         BaseType),
                         &ResultBuilder::IsMember);
   Results.EnterNewScope();
@@ -3471,10 +3486,17 @@ void Sema::CodeCompleteCase(Scope *S) {
   }
   Results.ExitScope();
 
-  if (CodeCompleter->includeMacros())
+  //We need to make sure we're setting the right context, 
+  //so only say we include macros if the code completer says we do
+  enum CodeCompletionContext::Kind kind = CodeCompletionContext::CCC_Other;
+  if (CodeCompleter->includeMacros()) {
     AddMacroResults(PP, Results);
+    kind = CodeCompletionContext::CCC_OtherWithMacros;
+  }
+  
+  
   HandleCodeCompleteResults(this, CodeCompleter, 
-                            CodeCompletionContext::CCC_OtherWithMacros,
+                            kind,
                             Results.data(),Results.size());
 }
 
@@ -4934,7 +4956,7 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
                                         bool AtArgumentExpression,
                                         bool IsSuper) {
   ResultBuilder Results(*this, CodeCompleter->getAllocator(),
-                        CodeCompletionContext::CCC_Other);
+                        CodeCompletionContext::CCC_ObjCClassMessage);
   AddClassMessageCompletions(*this, S, Receiver, SelIdents, NumSelIdents, 
                              AtArgumentExpression, IsSuper, Results);
   
@@ -4954,7 +4976,7 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
   }
 
   HandleCodeCompleteResults(this, CodeCompleter, 
-                            CodeCompletionContext::CCC_Other,
+                            CodeCompletionContext::CCC_ObjCClassMessage,
                             Results.data(), Results.size());
 }
 
@@ -4997,7 +5019,7 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
 
   // Build the set of methods we can see.
   ResultBuilder Results(*this, CodeCompleter->getAllocator(),
-                        CodeCompletionContext::CCC_Other);
+                        CodeCompletionContext::CCC_ObjCInstanceMessage);
   Results.EnterNewScope();
 
   // If this is a send-to-super, try to add the special "super" send 
@@ -5110,7 +5132,7 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
   }
   
   HandleCodeCompleteResults(this, CodeCompleter, 
-                            CodeCompletionContext::CCC_Other,
+                            CodeCompletionContext::CCC_ObjCInstanceMessage,
                             Results.data(),Results.size());
 }
 
@@ -5301,8 +5323,7 @@ void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
                       false, Results);
 
   Results.ExitScope();
-  // FIXME: Add a special context for this, use cached global completion 
-  // results.
+  // FIXME: Use cached global completion results.
   HandleCodeCompleteResults(this, CodeCompleter,
                             CodeCompletionContext::CCC_Other,
                             Results.data(),Results.size());
@@ -5311,7 +5332,7 @@ void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
 void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
                                       SourceLocation ClassNameLoc) { 
   ResultBuilder Results(*this, CodeCompleter->getAllocator(),
-                        CodeCompletionContext::CCC_Other);
+                        CodeCompletionContext::CCC_ObjCSuperclass);
   Results.EnterNewScope();
   
   // Make sure that we ignore the class we're currently defining.
@@ -5325,10 +5346,9 @@ void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
                       false, Results);
 
   Results.ExitScope();
-  // FIXME: Add a special context for this, use cached global completion 
-  // results.
+  // FIXME: Use cached global completion results.
   HandleCodeCompleteResults(this, CodeCompleter, 
-                            CodeCompletionContext::CCC_Other,
+                            CodeCompletionContext::CCC_ObjCSuperclass,
                             Results.data(),Results.size());
 }
 
@@ -5342,8 +5362,7 @@ void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
                       true, Results);
 
   Results.ExitScope();
-  // FIXME: Add a special context for this, use cached global completion 
-  // results.
+  // FIXME: Use cached global completion results.
   HandleCodeCompleteResults(this, CodeCompleter, 
                             CodeCompletionContext::CCC_Other,
                             Results.data(),Results.size());
@@ -5355,7 +5374,7 @@ void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
   typedef CodeCompletionResult Result;
   
   ResultBuilder Results(*this, CodeCompleter->getAllocator(),
-                        CodeCompletionContext::CCC_Other);
+                        CodeCompletionContext::CCC_ObjCCategoryName);
   
   // Ignore any categories we find that have already been implemented by this
   // interface.
@@ -5379,7 +5398,7 @@ void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
   Results.ExitScope();
   
   HandleCodeCompleteResults(this, CodeCompleter, 
-                            CodeCompletionContext::CCC_Other,
+                            CodeCompletionContext::CCC_ObjCCategoryName,
                             Results.data(),Results.size());  
 }
 
@@ -5398,7 +5417,7 @@ void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
     return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
     
   ResultBuilder Results(*this, CodeCompleter->getAllocator(),
-                        CodeCompletionContext::CCC_Other);
+                        CodeCompletionContext::CCC_ObjCCategoryName);
   
   // Add all of the categories that have have corresponding interface 
   // declarations in this class and any of its superclasses, except for
@@ -5419,7 +5438,7 @@ void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
   Results.ExitScope();
   
   HandleCodeCompleteResults(this, CodeCompleter, 
-                            CodeCompletionContext::CCC_Other,
+                            CodeCompletionContext::CCC_ObjCCategoryName,
                             Results.data(),Results.size());  
 }
 
index 62b9e4dd1adc807921b9f712fbdd36302baa277e..f75d61f1b04b8413dbe858c746c1d496eecf3ad3 100644 (file)
@@ -52,10 +52,21 @@ Z::operator int() const {
 // CHECK-MEMBER: CXXDestructor:{ResultType void}{Informative X::}{TypedText ~X}{LeftParen (}{RightParen )}
 // CHECK-MEMBER: CXXDestructor:{ResultType void}{Informative Y::}{TypedText ~Y}{LeftParen (}{RightParen )}
 // CHECK-MEMBER: CXXDestructor:{ResultType void}{TypedText ~Z}{LeftParen (}{RightParen )}
+// CHECK-MEMBER: Completion contexts:
+// CHECK-MEMBER-NEXT: Dot member access
 
 // 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 )}
 // CHECK-OVERLOAD: NotImplemented:{ResultType double &}{Text overloaded}{LeftParen (}{Text float f}{Comma , }{CurrentParameter int second}{RightParen )}
+// CHECK-OVERLOAD: Completion contexts:
+// CHECK-OVERLOAD-NEXT: Any type
+// CHECK-OVERLOAD-NEXT: Any value
+// CHECK-OVERLOAD-NEXT: Enum tag
+// CHECK-OVERLOAD-NEXT: Union tag
+// CHECK-OVERLOAD-NEXT: Struct tag
+// CHECK-OVERLOAD-NEXT: Class name
+// CHECK-OVERLOAD-NEXT: Nested name specifier
+// CHECK-OVERLOAD-NEXT: Objective-C interface
 
 // RUN: c-index-test -code-completion-at=%s:37:10 %s | FileCheck -check-prefix=CHECK-EXPR %s
 // CHECK-EXPR: NotImplemented:{TypedText int} (50)
@@ -65,3 +76,12 @@ Z::operator int() const {
 // CHECK-EXPR: FieldDecl:{ResultType float}{Text Y::}{TypedText member} (18)
 // CHECK-EXPR: CXXMethod:{ResultType void}{TypedText memfunc}{LeftParen (}{Optional {Placeholder int i}}{RightParen )} (37)
 // CHECK-EXPR: Namespace:{TypedText N}{Text ::} (75)
+// CHECK-EXPR: Completion contexts:
+// CHECK-EXPR-NEXT: Any type
+// CHECK-EXPR-NEXT: Any value
+// CHECK-EXPR-NEXT: Enum tag
+// CHECK-EXPR-NEXT: Union tag
+// CHECK-EXPR-NEXT: Struct tag
+// CHECK-EXPR-NEXT: Class name
+// CHECK-EXPR-NEXT: Nested name specifier
+// CHECK-EXPR-NEXT: Objective-C interface
index e1aba393ae714941f6a1495d2c76067dac664854..326b8a7a0cdf183f8817b482be5ffe02285378fc 100644 (file)
@@ -11,8 +11,9 @@ char in_char = 'a';
 // RUN: c-index-test -code-completion-at=%s:4:32 %s > %t
 // RUN: echo "DONE" >> %t
 // RUN: FileCheck -check-prefix=CHECK-CC1 %s < %t
-// CHECK-CC1-NOT: :
-// CHECK-CC1: DONE
+// CHECK-CC1: Completion contexts:
+// CHECK-CC1-NEXT: Natural language
+// CHECK-CC1-NEXT: DONE
 // RUN: c-index-test -code-completion-at=%s:5:18 %s > %t
 // RUN: echo "DONE" >> %t
 // RUN: FileCheck -check-prefix=CHECK-CC1 %s < %t
index d077653335ee7a8492cebd5c833184bc6f22cd3c..e574b872ae2d381a8431b7022844e7b0f62a067a 100644 (file)
@@ -1018,6 +1018,79 @@ void print_completion_result(CXCompletionResult *completion_result,
   fprintf(file, "\n");
 }
 
+void print_completion_contexts(unsigned long long contexts, FILE *file) {
+  fprintf(file, "Completion contexts:\n");
+  if (contexts == CXCompletionContext_Unknown) {
+    fprintf(file, "Unknown\n");
+  }
+  if (contexts & CXCompletionContext_AnyType) {
+    fprintf(file, "Any type\n");
+  }
+  if (contexts & CXCompletionContext_AnyValue) {
+    fprintf(file, "Any value\n");
+  }
+  if (contexts & CXCompletionContext_ObjCObjectValue) {
+    fprintf(file, "Objective-C object value\n");
+  }
+  if (contexts & CXCompletionContext_ObjCSelectorValue) {
+    fprintf(file, "Objective-C selector value\n");
+  }
+  if (contexts & CXCompletionContext_CXXClassTypeValue) {
+    fprintf(file, "C++ class type value\n");
+  }
+  if (contexts & CXCompletionContext_DotMemberAccess) {
+    fprintf(file, "Dot member access\n");
+  }
+  if (contexts & CXCompletionContext_ArrowMemberAccess) {
+    fprintf(file, "Arrow member access\n");
+  }
+  if (contexts & CXCompletionContext_ObjCPropertyAccess) {
+    fprintf(file, "Objective-C property access\n");
+  }
+  if (contexts & CXCompletionContext_EnumTag) {
+    fprintf(file, "Enum tag\n");
+  }
+  if (contexts & CXCompletionContext_UnionTag) {
+    fprintf(file, "Union tag\n");
+  }
+  if (contexts & CXCompletionContext_StructTag) {
+    fprintf(file, "Struct tag\n");
+  }
+  if (contexts & CXCompletionContext_ClassTag) {
+    fprintf(file, "Class name\n");
+  }
+  if (contexts & CXCompletionContext_Namespace) {
+    fprintf(file, "Namespace or namespace alias\n");
+  }
+  if (contexts & CXCompletionContext_NestedNameSpecifier) {
+    fprintf(file, "Nested name specifier\n");
+  }
+  if (contexts & CXCompletionContext_ObjCInterface) {
+    fprintf(file, "Objective-C interface\n");
+  }
+  if (contexts & CXCompletionContext_ObjCProtocol) {
+    fprintf(file, "Objective-C protocol\n");
+  }
+  if (contexts & CXCompletionContext_ObjCCategory) {
+    fprintf(file, "Objective-C category\n");
+  }
+  if (contexts & CXCompletionContext_ObjCInstanceMessage) {
+    fprintf(file, "Objective-C instance method\n");
+  }
+  if (contexts & CXCompletionContext_ObjCClassMessage) {
+    fprintf(file, "Objective-C class method\n");
+  }
+  if (contexts & CXCompletionContext_ObjCSelectorName) {
+    fprintf(file, "Objective-C selector name\n");
+  }
+  if (contexts & CXCompletionContext_MacroName) {
+    fprintf(file, "Macro name\n");
+  }
+  if (contexts & CXCompletionContext_NaturalLanguage) {
+    fprintf(file, "Natural language\n");
+  }
+}
+
 int my_stricmp(const char *s1, const char *s2) {
   while (*s1 && *s2) {
     int c1 = tolower((unsigned char)*s1), c2 = tolower((unsigned char)*s2);
@@ -1099,6 +1172,7 @@ int perform_code_completion(int argc, const char **argv, int timing_only) {
 
   if (results) {
     unsigned i, n = results->NumResults;
+    unsigned long long contexts;
     if (!timing_only) {      
       /* Sort the code-completion results based on the typed text. */
       clang_sortCodeCompletionResults(results->Results, results->NumResults);
@@ -1112,6 +1186,10 @@ int perform_code_completion(int argc, const char **argv, int timing_only) {
       PrintDiagnostic(diag);
       clang_disposeDiagnostic(diag);
     }
+    
+    contexts = clang_codeCompleteGetContexts(results);
+    print_completion_contexts(contexts, stdout);
+    
     clang_disposeCodeCompleteResults(results);
   }
   clang_disposeTranslationUnit(TU);
index 0c8317e4461fca789d57e63acf5b925d2593bcfe..832e2f2f7147f10e048a306ae9f8528c2d21d800 100644 (file)
@@ -235,6 +235,13 @@ struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults {
   
   /// \brief Allocator used to store code completion results.
   clang::CodeCompletionAllocator CodeCompletionAllocator;
+  
+  /// \brief Context under which completion occurred.
+  enum clang::CodeCompletionContext::Kind ContextKind;
+  
+  /// \brief A bitfield representing the acceptable completions for the
+  /// current context.
+  unsigned long long Contexts;
 };
 
 /// \brief Tracks the number of code-completion result objects that are 
@@ -273,6 +280,177 @@ AllocatedCXCodeCompleteResults::~AllocatedCXCodeCompleteResults() {
   
 } // end extern "C"
 
+static unsigned long long getContextsForContextKind(
+                                          enum CodeCompletionContext::Kind kind, 
+                                                    Sema &S) {
+  unsigned long long contexts = 0;
+  switch (kind) {
+    case CodeCompletionContext::CCC_OtherWithMacros: {
+      //We can allow macros here, but we don't know what else is permissible
+      //So we'll say the only thing permissible are macros
+      contexts = CXCompletionContext_MacroName;
+      break;
+    }
+    case CodeCompletionContext::CCC_TopLevel:
+    case CodeCompletionContext::CCC_ObjCIvarList:
+    case CodeCompletionContext::CCC_ClassStructUnion:
+    case CodeCompletionContext::CCC_Type: {
+      contexts = CXCompletionContext_AnyType | 
+                 CXCompletionContext_ObjCInterface;
+      if (S.getLangOptions().CPlusPlus) {
+        contexts |= CXCompletionContext_EnumTag |
+                    CXCompletionContext_UnionTag |
+                    CXCompletionContext_StructTag |
+                    CXCompletionContext_ClassTag |
+                    CXCompletionContext_NestedNameSpecifier;
+      }
+      break;
+    }
+    case CodeCompletionContext::CCC_Statement: {
+      contexts = CXCompletionContext_AnyType |
+                 CXCompletionContext_ObjCInterface |
+                 CXCompletionContext_AnyValue;
+      if (S.getLangOptions().CPlusPlus) {
+        contexts |= CXCompletionContext_EnumTag |
+                    CXCompletionContext_UnionTag |
+                    CXCompletionContext_StructTag |
+                    CXCompletionContext_ClassTag |
+                    CXCompletionContext_NestedNameSpecifier;
+      }
+      break;
+    }
+    case CodeCompletionContext::CCC_Expression: {
+      contexts = CXCompletionContext_AnyValue;
+      if (S.getLangOptions().CPlusPlus) {
+        contexts |= CXCompletionContext_AnyType |
+                    CXCompletionContext_ObjCInterface |
+                    CXCompletionContext_EnumTag |
+                    CXCompletionContext_UnionTag |
+                    CXCompletionContext_StructTag |
+                    CXCompletionContext_ClassTag |
+                    CXCompletionContext_NestedNameSpecifier;
+      }
+      break;
+    }
+    case CodeCompletionContext::CCC_ObjCMessageReceiver: {
+      contexts = CXCompletionContext_ObjCObjectValue |
+                 CXCompletionContext_ObjCSelectorValue |
+                 CXCompletionContext_ObjCInterface;
+      if (S.getLangOptions().CPlusPlus) {
+        contexts |= CXCompletionContext_CXXClassTypeValue |
+                    CXCompletionContext_AnyType |
+                    CXCompletionContext_EnumTag |
+                    CXCompletionContext_UnionTag |
+                    CXCompletionContext_StructTag |
+                    CXCompletionContext_ClassTag |
+                    CXCompletionContext_NestedNameSpecifier;
+      }
+      break;
+    }
+    case CodeCompletionContext::CCC_DotMemberAccess: {
+      contexts = CXCompletionContext_DotMemberAccess;
+      break;
+    }
+    case CodeCompletionContext::CCC_ArrowMemberAccess: {
+      contexts = CXCompletionContext_ArrowMemberAccess;
+      break;
+    }
+    case CodeCompletionContext::CCC_ObjCPropertyAccess: {
+      contexts = CXCompletionContext_ObjCPropertyAccess;
+      break;
+    }
+    case CodeCompletionContext::CCC_EnumTag: {
+      contexts = CXCompletionContext_EnumTag |
+                 CXCompletionContext_NestedNameSpecifier;
+      break;
+    }
+    case CodeCompletionContext::CCC_UnionTag: {
+      contexts = CXCompletionContext_UnionTag |
+                 CXCompletionContext_NestedNameSpecifier;
+      break;
+    }
+    case CodeCompletionContext::CCC_ClassOrStructTag: {
+      contexts = CXCompletionContext_StructTag |
+                 CXCompletionContext_ClassTag |
+                 CXCompletionContext_NestedNameSpecifier;
+      break;
+    }
+    case CodeCompletionContext::CCC_ObjCProtocolName: {
+      contexts = CXCompletionContext_ObjCProtocol;
+      break;
+    }
+    case CodeCompletionContext::CCC_Namespace: {
+      contexts = CXCompletionContext_Namespace;
+      break;
+    }
+    case CodeCompletionContext::CCC_PotentiallyQualifiedName: {
+      contexts = CXCompletionContext_NestedNameSpecifier;
+      break;
+    }
+    case CodeCompletionContext::CCC_MacroNameUse: {
+      contexts = CXCompletionContext_MacroName;
+      break;
+    }
+    case CodeCompletionContext::CCC_NaturalLanguage: {
+      contexts = CXCompletionContext_NaturalLanguage;
+      break;
+    }
+    case CodeCompletionContext::CCC_SelectorName: {
+      contexts = CXCompletionContext_ObjCSelectorName;
+      break;
+    }
+    case CodeCompletionContext::CCC_ParenthesizedExpression: {
+      contexts = CXCompletionContext_AnyType |
+                 CXCompletionContext_ObjCInterface |
+                 CXCompletionContext_AnyValue;
+      if (S.getLangOptions().CPlusPlus) {
+        contexts |= CXCompletionContext_EnumTag |
+                    CXCompletionContext_UnionTag |
+                    CXCompletionContext_StructTag |
+                    CXCompletionContext_ClassTag |
+                    CXCompletionContext_NestedNameSpecifier;
+      }
+      break;
+    }
+    case CodeCompletionContext::CCC_ObjCInstanceMessage: {
+      contexts = CXCompletionContext_ObjCInstanceMessage;
+      break;
+    }
+    case CodeCompletionContext::CCC_ObjCClassMessage: {
+      contexts = CXCompletionContext_ObjCClassMessage;
+      break;
+    }
+    case CodeCompletionContext::CCC_ObjCSuperclass: {
+      contexts = CXCompletionContext_ObjCInterface;
+      break;
+    }
+    case CodeCompletionContext::CCC_ObjCCategoryName: {
+      contexts = CXCompletionContext_ObjCCategory;
+      break;
+    }
+    case CodeCompletionContext::CCC_Other:
+    case CodeCompletionContext::CCC_ObjCInterface:
+    case CodeCompletionContext::CCC_ObjCImplementation:
+    case CodeCompletionContext::CCC_Name:
+    case CodeCompletionContext::CCC_MacroName:
+    case CodeCompletionContext::CCC_PreprocessorExpression:
+    case CodeCompletionContext::CCC_PreprocessorDirective:
+    case CodeCompletionContext::CCC_TypeQualifiers: {
+      //Only Clang results should be accepted, so we'll set all of the other
+      //context bits to 0 (i.e. the empty set)
+      contexts = CXCompletionContext_Unexposed;
+      break;
+    }
+    case CodeCompletionContext::CCC_Recovery: {
+      //We don't know what the current context is, so we'll return unknown
+      //This is the equivalent of setting all of the other context bits
+      contexts = CXCompletionContext_Unknown;
+      break;
+    }
+  }
+  return contexts;
+}
+
 namespace {
   class CaptureCompletionResults : public CodeCompleteConsumer {
     AllocatedCXCodeCompleteResults &AllocatedResults;
@@ -298,6 +476,11 @@ namespace {
         R.CompletionString = StoredCompletion;
         StoredResults.push_back(R);
       }
+      
+      enum CodeCompletionContext::Kind kind = Context.getKind();
+      
+      AllocatedResults.ContextKind = kind;
+      AllocatedResults.Contexts = getContextsForContextKind(kind, S);
     }
     
     virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
@@ -538,6 +721,15 @@ clang_codeCompleteGetDiagnostic(CXCodeCompleteResults *ResultsIn,
   return new CXStoredDiagnostic(Results->Diagnostics[Index], Results->LangOpts);
 }
 
+unsigned long long
+clang_codeCompleteGetContexts(CXCodeCompleteResults *ResultsIn) {
+  AllocatedCXCodeCompleteResults *Results
+    = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);
+  if (!Results)
+    return 0;
+  
+  return Results->Contexts;
+}
 
 } // end extern "C"
 
index daada6d3f0531ec24169b27efd6401ae0d915aee..df7cda2e7df7575d90529b3c3f4ea5e61ac85094 100644 (file)
@@ -6,6 +6,7 @@ _clang_annotateTokens
 _clang_codeCompleteAt
 _clang_codeCompleteGetDiagnostic
 _clang_codeCompleteGetNumDiagnostics
+_clang_codeCompleteGetContexts
 _clang_constructUSR_ObjCCategory
 _clang_constructUSR_ObjCClass
 _clang_constructUSR_ObjCIvar
index 0d27f6babb334b523e649e88408a773d0eae7a28..f5e0a304e6303932b834630c32973825abe9fe15 100644 (file)
@@ -6,6 +6,7 @@ clang_annotateTokens
 clang_codeCompleteAt
 clang_codeCompleteGetDiagnostic
 clang_codeCompleteGetNumDiagnostics
+clang_codeCompleteGetContexts
 clang_constructUSR_ObjCCategory
 clang_constructUSR_ObjCClass
 clang_constructUSR_ObjCIvar