aboutsummaryrefslogtreecommitdiff
path: root/tools
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 /tools
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
Diffstat (limited to 'tools')
-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
4 files changed, 272 insertions, 0 deletions
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 = 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"
diff --git a/tools/libclang/libclang.darwin.exports b/tools/libclang/libclang.darwin.exports
index daada6d3f0..df7cda2e7d 100644
--- a/tools/libclang/libclang.darwin.exports
+++ b/tools/libclang/libclang.darwin.exports
@@ -6,6 +6,7 @@ _clang_annotateTokens
_clang_codeCompleteAt
_clang_codeCompleteGetDiagnostic
_clang_codeCompleteGetNumDiagnostics
+_clang_codeCompleteGetContexts
_clang_constructUSR_ObjCCategory
_clang_constructUSR_ObjCClass
_clang_constructUSR_ObjCIvar
diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports
index 0d27f6babb..f5e0a304e6 100644
--- a/tools/libclang/libclang.exports
+++ b/tools/libclang/libclang.exports
@@ -6,6 +6,7 @@ clang_annotateTokens
clang_codeCompleteAt
clang_codeCompleteGetDiagnostic
clang_codeCompleteGetNumDiagnostics
+clang_codeCompleteGetContexts
clang_constructUSR_ObjCCategory
clang_constructUSR_ObjCClass
clang_constructUSR_ObjCIvar