[cfe-commits] r91690 - in /cfe/trunk: include/clang-c/Index.h tools/CIndex/CIndex.cpp tools/CIndex/CIndex.exports tools/c-index-test/c-index-test.c

Douglas Gregor dgregor at apple.com
Fri Dec 18 08:20:58 PST 2009


Author: dgregor
Date: Fri Dec 18 10:20:58 2009
New Revision: 91690

URL: http://llvm.org/viewvc/llvm-project?rev=91690&view=rev
Log:
Change clang_codeComplete API to return the results in a structure on
the heap, so that clients are not forced to copy the results during
the initial iteration. A separate clang_disposeCodeCompleteResults
function frees the returned results.

Modified:
    cfe/trunk/include/clang-c/Index.h
    cfe/trunk/tools/CIndex/CIndex.cpp
    cfe/trunk/tools/CIndex/CIndex.exports
    cfe/trunk/tools/c-index-test/c-index-test.c

Modified: cfe/trunk/include/clang-c/Index.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=91690&r1=91689&r2=91690&view=diff

==============================================================================
--- cfe/trunk/include/clang-c/Index.h (original)
+++ cfe/trunk/include/clang-c/Index.h Fri Dec 18 10:20:58 2009
@@ -558,21 +558,6 @@
    */
   CXCompletionChunk_Comma
 };
-
-/**
- * \brief Callback function that receives a single code-completion result.
- *
- * This callback will be invoked by \c clang_codeComplete() for each
- * code-completion result.
- *
- * \param completion_result a pointer to the current code-completion result,
- * providing one possible completion. The pointer itself is only valid
- * during the execution of the completion callback.
- *
- * \param client_data the client data provided to \c clang_codeComplete().
- */
-typedef void (*CXCompletionIterator)(CXCompletionResult *completion_result,
-                                     CXClientData client_data);
   
 /**
  * \brief Determine the kind of a particular chunk within a completion string.
@@ -624,6 +609,26 @@
 clang_getNumCompletionChunks(CXCompletionString completion_string);
 
 /**
+ * \brief Contains the results of code-completion.
+ *
+ * This data structure contains the results of code completion, as
+ * produced by \c clang_codeComplete. Its contents must be freed by 
+ * \c clang_disposeCodeCompleteResults.
+ */
+typedef struct {
+  /**
+   * \brief The code-completion results.
+   */
+  CXCompletionResult *Results;
+
+  /**
+   * \brief The number of code-completion results stored in the
+   * \c Results array.
+   */
+  unsigned NumResults;
+} CXCodeCompleteResults;
+
+/**
  * \brief Perform code completion at a given location in a source file.
  *
  * This function performs code completion at a particular file, line, and
@@ -635,7 +640,7 @@
  * to the parser, which recognizes this token and determines, based on the
  * current location in the C/Objective-C/C++ grammar and the state of 
  * semantic analysis, what completions to provide. These completions are
- * enumerated through a callback interface to the client.
+ * returned via a new \c CXCodeCompleteResults structure.
  *
  * Code completion itself is meant to be triggered by the client when the
  * user types punctuation characters or whitespace, at which point the 
@@ -650,7 +655,7 @@
  * the ">" (e.g., pointing at the "g") to this code-completion hook. Then, the
  * client can filter the results based on the current token text ("get"), only
  * showing those results that start with "get". The intent of this interface
- * is to separate the relatively high-latency acquisition of code-competion
+ * is to separate the relatively high-latency acquisition of code-completion
  * results from the filtering of results on a per-character basis, which must
  * have a lower latency.
  *
@@ -691,24 +696,27 @@
  * Note that the column should point just after the syntactic construct that
  * initiated code completion, and not in the middle of a lexical token.
  *
- * \param completion_iterator a callback function that will receive 
- * code-completion results.
- *
- * \param client_data client-specific data that will be passed back via the
- * code-completion callback function.
+ * \returns if successful, a new CXCodeCompleteResults structure
+ * containing code-completion results, which should eventually be
+ * freed with \c clang_disposeCodeCompleteResults(). If code
+ * completion fails, returns NULL.
+ */
+CINDEX_LINKAGE 
+CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx, 
+                                          const char *source_filename,
+                                          int num_command_line_args, 
+                                          const char **command_line_args,
+                                          unsigned num_unsaved_files,
+                                          struct CXUnsavedFile *unsaved_files,
+                                          const char *complete_filename,
+                                          unsigned complete_line,
+                                          unsigned complete_column);
+  
+/**
+ * \brief Free the given set of code-completion results.
  */
-CINDEX_LINKAGE void clang_codeComplete(CXIndex CIdx, 
-                                       const char *source_filename,
-                                       int num_command_line_args, 
-                                       const char **command_line_args,
-                                       unsigned num_unsaved_files,
-                                       struct CXUnsavedFile *unsaved_files,
-                                       const char *complete_filename,
-                                       unsigned complete_line,
-                                       unsigned complete_column,
-                                       CXCompletionIterator completion_iterator,
-                                       CXClientData client_data);
-    
+CINDEX_LINKAGE 
+void clang_disposeCodeCompleteResults(CXCodeCompleteResults *Results);
   
 #ifdef __cplusplus
 }

Modified: cfe/trunk/tools/CIndex/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/CIndex/CIndex.cpp?rev=91690&r1=91689&r2=91690&view=diff

==============================================================================
--- cfe/trunk/tools/CIndex/CIndex.cpp (original)
+++ cfe/trunk/tools/CIndex/CIndex.cpp Fri Dec 18 10:20:58 2009
@@ -1220,17 +1220,23 @@
   return false;
 }
 
-void clang_codeComplete(CXIndex CIdx,
-                        const char *source_filename,
-                        int num_command_line_args,
-                        const char **command_line_args,
-                        unsigned num_unsaved_files,
-                        struct CXUnsavedFile *unsaved_files,
-                        const char *complete_filename,
-                        unsigned complete_line,
-                        unsigned complete_column,
-                        CXCompletionIterator completion_iterator,
-                        CXClientData client_data)  {
+/// \brief The CXCodeCompleteResults structure we allocate internally;
+/// the client only sees the initial CXCodeCompleteResults structure.
+struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults {
+  /// \brief The memory buffer from which we parsed the results. We
+  /// retain this buffer because the completion strings point into it.
+  llvm::MemoryBuffer *Buffer;
+};
+
+CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx,
+                                          const char *source_filename,
+                                          int num_command_line_args,
+                                          const char **command_line_args,
+                                          unsigned num_unsaved_files,
+                                          struct CXUnsavedFile *unsaved_files,
+                                          const char *complete_filename,
+                                          unsigned complete_line,
+                                          unsigned complete_column) {
   // The indexer, which is mainly used to determine where diagnostics go.
   CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
 
@@ -1353,7 +1359,9 @@
   // Parse the resulting source file to find code-completion results.
   using llvm::MemoryBuffer;
   using llvm::StringRef;
+  AllocatedCXCodeCompleteResults *Results = 0;
   if (MemoryBuffer *F = MemoryBuffer::getFile(ResultsFile.c_str())) {
+    llvm::SmallVector<CXCompletionResult, 4> CompletionResults;
     StringRef Buffer = F->getBuffer();
     for (const char *Str = Buffer.data(), *StrEnd = Str + Buffer.size();
          Str < StrEnd;) {
@@ -1371,17 +1379,41 @@
         CXCompletionResult Result;
         Result.CursorKind = (CXCursorKind)KindValue;
         Result.CompletionString = CCStr;
-        if (completion_iterator)
-          completion_iterator(&Result, client_data);
+        CompletionResults.push_back(Result);
       }
-
-      delete CCStr;
     };
-    delete F;
+
+    // Allocate the results.
+    Results = new AllocatedCXCodeCompleteResults;
+    Results->Results = new CXCompletionResult [CompletionResults.size()];
+    Results->NumResults = CompletionResults.size();
+    memcpy(Results->Results, CompletionResults.data(),
+           CompletionResults.size() * sizeof(CXCompletionResult));
+    Results->Buffer = F;
   }
 
   for (unsigned i = 0, e = TemporaryFiles.size(); i != e; ++i)
     TemporaryFiles[i].eraseFromDisk();
+
+  return Results;
+}
+
+void clang_disposeCodeCompleteResults(CXCodeCompleteResults *ResultsIn) {
+  if (!ResultsIn)
+    return;
+
+  AllocatedCXCodeCompleteResults *Results
+    = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);
+
+  for (unsigned I = 0, N = Results->NumResults; I != N; ++I)
+    delete (CXCompletionString *)Results->Results[I].CompletionString;
+  delete [] Results->Results;
+
+  Results->Results = 0;
+  Results->NumResults = 0;
+  delete Results->Buffer;
+  Results->Buffer = 0;
+  delete Results;
 }
 
 } // end extern "C"

Modified: cfe/trunk/tools/CIndex/CIndex.exports
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/CIndex/CIndex.exports?rev=91690&r1=91689&r2=91690&view=diff

==============================================================================
--- cfe/trunk/tools/CIndex/CIndex.exports (original)
+++ cfe/trunk/tools/CIndex/CIndex.exports Fri Dec 18 10:20:58 2009
@@ -2,6 +2,7 @@
 _clang_createIndex
 _clang_createTranslationUnit
 _clang_createTranslationUnitFromSourceFile
+_clang_disposeCodeCompleteResults
 _clang_disposeIndex
 _clang_disposeString
 _clang_disposeTranslationUnit

Modified: cfe/trunk/tools/c-index-test/c-index-test.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/c-index-test/c-index-test.c?rev=91690&r1=91689&r2=91690&view=diff

==============================================================================
--- cfe/trunk/tools/c-index-test/c-index-test.c (original)
+++ cfe/trunk/tools/c-index-test/c-index-test.c Fri Dec 18 10:20:58 2009
@@ -496,6 +496,7 @@
   int errorCode;
   struct CXUnsavedFile *unsaved_files = 0;
   int num_unsaved_files = 0;
+  CXCodeCompleteResults *results = 0;
 
   input += strlen("-code-completion-at=");
   if ((errorCode = parse_file_line_column(input, &filename, &line, &column)))
@@ -505,10 +506,18 @@
     return -1;
 
   CIdx = clang_createIndex(0, 0);
-  clang_codeComplete(CIdx, argv[argc - 1], argc - num_unsaved_files - 3, 
-                     argv + num_unsaved_files + 2, 
-                     num_unsaved_files, unsaved_files,
-                     filename, line, column, &print_completion_result, stdout);
+  results = clang_codeComplete(CIdx, 
+                               argv[argc - 1], argc - num_unsaved_files - 3, 
+                               argv + num_unsaved_files + 2, 
+                               num_unsaved_files, unsaved_files,
+                               filename, line, column);
+  if (results) {
+    unsigned i, n = results->NumResults;
+    for (i = 0; i != n; ++i)
+      print_completion_result(results->Results + i, stdout);
+    clang_disposeCodeCompleteResults(results);
+  }
+
   clang_disposeIndex(CIdx);
   free(filename);
   





More information about the cfe-commits mailing list