Various improvements to Clang's code-completion infrastructure:
- Introduce more code-completion string "chunk" kinds that describe
symbols, the actual text that the user is expected to type, etc.
- Make the generation of macro results optional, since it can be
slow
- Make code-completion accessible through the C API, marshalling the
code-completion results through a temporary file (ick) to maintain
process separation.
The last doesn't have tests yet.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@86306 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c
index 8791ee2..429c5e5 100644
--- a/tools/c-index-test/c-index-test.c
+++ b/tools/c-index-test/c-index-test.c
@@ -1,6 +1,7 @@
/* c-index-test.c */
#include "clang-c/Index.h"
+#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -94,10 +95,115 @@
}
}
+/* Parse file:line:column from the input string. Returns 0 on success, non-zero
+ on failure. If successful, the pointer *filename will contain newly-allocated
+ memory (that will be owned by the caller) to store the file name. */
+int parse_file_line_column(const char *input, char **filename, unsigned *line,
+ unsigned *column) {
+ const char *colon = strchr(input, ':');
+ char *endptr = 0;
+ if (!colon) {
+ fprintf(stderr, "could not parse filename:line:column in '%s'\n", input);
+ return 1;
+ }
+
+ /* Copy the file name. */
+ *filename = (char*)malloc(colon - input);
+ strncpy(*filename, input, colon - input);
+ (*filename)[colon - input] = 0;
+ input = colon + 1;
+
+ /* Parse the line number. */
+ *line = strtol(input, &endptr, 10);
+ if (*endptr != ':') {
+ fprintf(stderr, "could not parse line:column in '%s'\n", input);
+ free(filename);
+ *filename = 0;
+ return 1;
+ }
+ input = endptr + 1;
+
+ /* Parse the column number. */
+ *column = strtol(input, &endptr, 10);
+ if (*endptr != 0) {
+ fprintf(stderr, "could not parse column in '%s'\n", input);
+ free(filename);
+ *filename = 0;
+ return 1;
+ }
+
+ return 0;
+}
+
+const char *
+clang_getCompletionChunkKindSpelling(enum CXCompletionChunkKind Kind) {
+ switch (Kind) {
+ case CXCompletionChunk_Optional: return "Optional";
+ case CXCompletionChunk_TypedText: return "TypedText";
+ case CXCompletionChunk_Text: return "Text";
+ case CXCompletionChunk_Placeholder: return "Placeholder";
+ case CXCompletionChunk_Informative: return "Informative";
+ case CXCompletionChunk_CurrentParameter: return "CurrentParameter";
+ case CXCompletionChunk_LeftParen: return "LeftParen";
+ case CXCompletionChunk_RightParen: return "RightParen";
+ case CXCompletionChunk_LeftBracket: return "LeftBracket";
+ case CXCompletionChunk_RightBracket: return "RightBracket";
+ case CXCompletionChunk_LeftBrace: return "LeftBrace";
+ case CXCompletionChunk_RightBrace: return "RightBrace";
+ case CXCompletionChunk_LeftAngle: return "LeftAngle";
+ case CXCompletionChunk_RightAngle: return "RightAngle";
+ case CXCompletionChunk_Comma: return "Comma";
+ }
+
+ return "Unknown";
+}
+
+void print_completion_result(CXCompletionResult *completion_result,
+ CXClientData client_data) {
+ FILE *file = (FILE *)client_data;
+
+ fprintf(file, "%s:",
+ clang_getCursorKindSpelling(completion_result->CursorKind));
+ int I, N = clang_getNumCompletionChunks(completion_result->CompletionString);
+ for (I = 0; I != N; ++I) {
+ const char *text
+ = clang_getCompletionChunkText(completion_result->CompletionString, I);
+
+ enum CXCompletionChunkKind Kind
+ = clang_getCompletionChunkKind(completion_result->CompletionString, I);
+ fprintf(file, "{%s %s}",
+ clang_getCompletionChunkKindSpelling(Kind),
+ text? text : "");
+ }
+ fprintf(file, "\n");
+}
+
+void perform_code_completion(int argc, const char **argv) {
+ const char *input = argv[1];
+ char *filename = 0;
+ unsigned line;
+ unsigned column;
+ input += strlen("-code-completion-at=");
+ if (parse_file_line_column(input, &filename, &line, &column))
+ return;
+
+ CXIndex CIdx = clang_createIndex(0, 0);
+ clang_codeComplete(CIdx, argv[argc - 1], argc - 3, argv + 2,
+ filename, line, column, &print_completion_result, stdout);
+ clang_disposeIndex(CIdx);
+ free(filename);
+}
+
/*
* First sign of life:-)
*/
int main(int argc, char **argv) {
+ if (argc > 2 && strstr(argv[1], "-code-completion-at=") == argv[1]) {
+ perform_code_completion(argc, (const char **)argv);
+ return 0;
+ }
+
+
if (argc != 3) {
printf("Incorrect usage of c-index-test (requires 3 arguments)\n");
return 0;