*/
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.
CINDEX_LINKAGE unsigned
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.
*
* 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
* 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.
*
* 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
}
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);
// 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;) {
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"
_clang_createIndex
_clang_createTranslationUnit
_clang_createTranslationUnitFromSourceFile
+_clang_disposeCodeCompleteResults
_clang_disposeIndex
_clang_disposeString
_clang_disposeTranslationUnit
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)))
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);