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;