aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-07-07 16:03:39 +0000
committerDouglas Gregor <dgregor@apple.com>2011-07-07 16:03:39 +0000
commit3da626b4f38eb0350de960d71271ca77af7a9cc8 (patch)
tree7033914fa939a04b65cef3767a1e4524149f7ad9
parent63ff703393543904046462aee2ac0a53b8937a3e (diff)
Introduce a new libclang aPI function,
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
-rw-r--r--include/clang-c/Index.h144
-rw-r--r--include/clang/Sema/CodeCompleteConsumer.h30
-rw-r--r--lib/Frontend/ASTUnit.cpp46
-rw-r--r--lib/Sema/CodeCompleteConsumer.cpp8
-rw-r--r--lib/Sema/SemaCodeComplete.cpp57
-rw-r--r--test/Index/code-completion.cpp20
-rw-r--r--test/Index/complete-natural.m5
-rw-r--r--tools/c-index-test/c-index-test.c78
-rw-r--r--tools/libclang/CIndexCodeCompletion.cpp192
-rw-r--r--tools/libclang/libclang.darwin.exports1
-rw-r--r--tools/libclang/libclang.exports1
11 files changed, 541 insertions, 41 deletions
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h
index 5bf20316b1..f7a0f569a3 100644
--- a/include/clang-c/Index.h
+++ b/include/clang-c/Index.h
@@ -2871,6 +2871,137 @@ enum CXCodeComplete_Flags {
};
/**
+ * \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().
*/
@@ -2991,6 +3122,19 @@ 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);
+
+/**
* @}
*/
diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h
index d3221809b9..74b0105b33 100644
--- a/include/clang/Sema/CodeCompleteConsumer.h
+++ b/include/clang/Sema/CodeCompleteConsumer.h
@@ -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;
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index 4407d2d3e2..ad476455eb 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -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;
diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp
index 2334ab5128..d7dc5b2538 100644
--- a/lib/Sema/CodeCompleteConsumer.cpp
+++ b/lib/Sema/CodeCompleteConsumer.cpp
@@ -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;
}
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 69b38593fb..b555c8a9aa 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -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());
}
diff --git a/test/Index/code-completion.cpp b/test/Index/code-completion.cpp
index 62b9e4dd1a..f75d61f1b0 100644
--- a/test/Index/code-completion.cpp
+++ b/test/Index/code-completion.cpp
@@ -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
diff --git a/test/Index/complete-natural.m b/test/Index/complete-natural.m
index e1aba393ae..326b8a7a0c 100644
--- a/test/Index/complete-natural.m
+++ b/test/Index/complete-natural.m
@@ -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
diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c
index d077653335..e574b872ae 100644
--- a/tools/c-index-test/c-index-test.c
+++ b/tools/c-index-test/c-index-test.c
@@ -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);
diff --git a/tools/libclang/CIndexCodeCompletion.cpp b/tools/libclang/CIndexCodeCompletion.cpp
index 0c8317e446..832e2f2f71 100644
--- a/tools/libclang/CIndexCodeCompletion.cpp
+++ b/tools/libclang/CIndexCodeCompletion.cpp
@@ -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 = CXComp