[cfe-commits] r90314 - in /cfe/trunk: include/clang-c/Index.h test/Index/Inputs/remap-complete-to.c test/Index/remap-complete.c tools/CIndex/CIndex.cpp tools/c-index-test/c-index-test.c
Douglas Gregor
dgregor at apple.com
Wed Dec 2 01:21:35 PST 2009
Author: dgregor
Date: Wed Dec 2 03:21:34 2009
New Revision: 90314
URL: http://llvm.org/viewvc/llvm-project?rev=90314&view=rev
Log:
Extend the CIndex code-completion API to perform code completion
involving unsaved files, using the -remap-file= functionality recently
added to clang-cc.
Added:
cfe/trunk/test/Index/Inputs/remap-complete-to.c (with props)
cfe/trunk/test/Index/remap-complete.c (with props)
Modified:
cfe/trunk/include/clang-c/Index.h
cfe/trunk/tools/CIndex/CIndex.cpp
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=90314&r1=90313&r2=90314&view=diff
==============================================================================
--- cfe/trunk/include/clang-c/Index.h (original)
+++ cfe/trunk/include/clang-c/Index.h Wed Dec 2 03:21:34 2009
@@ -104,6 +104,34 @@
CXCursor_LastInvalid = 72
};
+/**
+ * \brief Provides the contents of a file that has not yet been saved to disk.
+ *
+ * Each CXUnsavedFile instance provides the name of a file on the
+ * system along with the current contents of that file that have not
+ * yet been saved to disk.
+ */
+struct CXUnsavedFile {
+ /**
+ * \brief The file whose contents have not yet been saved.
+ *
+ * This file must already exist in the file system.
+ */
+ const char *Filename;
+
+ /**
+ * \brief A null-terminated buffer containing the unsaved contents
+ * of this file.
+ */
+ const char *Contents;
+
+ /**
+ * \brief The length of the unsaved contents of this buffer, not
+ * counting the NULL at the end of the buffer.
+ */
+ unsigned long Length;
+};
+
/* A cursor into the CXTranslationUnit. */
typedef struct {
@@ -621,6 +649,13 @@
* includes, etc., but should not include any information specific to
* code completion.
*
+ * \param num_unsaved_files the number of unsaved file entries in \p
+ * unsaved_files.
+ *
+ * \param unsaved_files the files that have not yet been saved to disk
+ * but may be required for code completion, including the contents of
+ * those files.
+ *
* \param complete_filename the name of the source file where code completion
* should be performed. In many cases, this name will be the same as the
* source filename. However, the completion filename may also be a file
@@ -643,6 +678,8 @@
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,
Added: cfe/trunk/test/Index/Inputs/remap-complete-to.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/Inputs/remap-complete-to.c?rev=90314&view=auto
==============================================================================
--- cfe/trunk/test/Index/Inputs/remap-complete-to.c (added)
+++ cfe/trunk/test/Index/Inputs/remap-complete-to.c Wed Dec 2 03:21:34 2009
@@ -0,0 +1 @@
+void f0() { }
Propchange: cfe/trunk/test/Index/Inputs/remap-complete-to.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cfe/trunk/test/Index/Inputs/remap-complete-to.c
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: cfe/trunk/test/Index/Inputs/remap-complete-to.c
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: cfe/trunk/test/Index/remap-complete.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/remap-complete.c?rev=90314&view=auto
==============================================================================
--- cfe/trunk/test/Index/remap-complete.c (added)
+++ cfe/trunk/test/Index/remap-complete.c Wed Dec 2 03:21:34 2009
@@ -0,0 +1,4 @@
+// RUN: c-index-test -code-completion-at=%s:1:12 -remap-file="%s;%S/Inputs/remap-complete-to.c" %s | FileCheck %s
+
+// CHECK: FunctionDecl:{TypedText f0}{LeftParen (}{RightParen )}
+void f() { }
Propchange: cfe/trunk/test/Index/remap-complete.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cfe/trunk/test/Index/remap-complete.c
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: cfe/trunk/test/Index/remap-complete.c
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: cfe/trunk/tools/CIndex/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/CIndex/CIndex.cpp?rev=90314&r1=90313&r2=90314&view=diff
==============================================================================
--- cfe/trunk/tools/CIndex/CIndex.cpp (original)
+++ cfe/trunk/tools/CIndex/CIndex.cpp Wed Dec 2 03:21:34 2009
@@ -1141,6 +1141,8 @@
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,
@@ -1149,6 +1151,9 @@
// The indexer, which is mainly used to determine where diagnostics go.
CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
+ // The set of temporary files that we've built.
+ std::vector<llvm::sys::Path> TemporaryFiles;
+
// Build up the arguments for invoking 'clang'.
std::vector<const char *> argv;
@@ -1174,6 +1179,40 @@
argv.push_back("-Xclang");
argv.push_back("-no-code-completion-debug-printer");
+ std::vector<std::string> RemapArgs;
+ for (unsigned i = 0; i != num_unsaved_files; ++i) {
+ char tmpFile[L_tmpnam];
+ char *tmpFileName = tmpnam(tmpFile);
+
+ // Write the contents of this unsaved file into the temporary file.
+ llvm::sys::Path SavedFile(tmpFileName);
+ std::string ErrorInfo;
+ llvm::raw_fd_ostream OS(SavedFile.c_str(), ErrorInfo);
+ if (!ErrorInfo.empty())
+ continue;
+
+ OS.write(unsaved_files[i].Contents, unsaved_files[i].Length);
+ OS.close();
+ if (OS.has_error()) {
+ SavedFile.eraseFromDisk();
+ continue;
+ }
+
+ // Remap the file.
+ std::string RemapArg = "-remap-file=";
+ RemapArg += unsaved_files[i].Filename;
+ RemapArg += ';';
+ RemapArg += tmpFileName;
+ RemapArgs.push_back("-Xclang");
+ RemapArgs.push_back(RemapArg);
+ TemporaryFiles.push_back(SavedFile);
+ }
+
+ // The pointers into the elements of RemapArgs are stable because we
+ // won't be adding anything to RemapArgs after this point.
+ for (unsigned i = 0, e = RemapArgs.size(); i != e; ++i)
+ argv.push_back(RemapArgs[i].c_str());
+
// Add the source file name (FIXME: later, we'll want to build temporary
// file from the buffer, or just feed the source text via standard input).
if (source_filename)
@@ -1203,6 +1242,7 @@
char tmpFile[L_tmpnam];
char *tmpFileName = tmpnam(tmpFile);
llvm::sys::Path ResultsFile(tmpFileName);
+ TemporaryFiles.push_back(ResultsFile);
// Invoke 'clang'.
llvm::sys::Path DevNull; // leave empty, causes redirection to /dev/null
@@ -1255,7 +1295,8 @@
delete F;
}
- ResultsFile.eraseFromDisk();
+ for (unsigned i = 0, e = TemporaryFiles.size(); i != e; ++i)
+ TemporaryFiles[i].eraseFromDisk();
}
} // end extern "C"
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=90314&r1=90313&r2=90314&view=diff
==============================================================================
--- cfe/trunk/tools/c-index-test/c-index-test.c (original)
+++ cfe/trunk/tools/c-index-test/c-index-test.c Wed Dec 2 03:21:34 2009
@@ -389,6 +389,91 @@
fprintf(file, "\n");
}
+void free_remapped_files(struct CXUnsavedFile *unsaved_files,
+ int num_unsaved_files) {
+ int i;
+ for (i = 0; i != num_unsaved_files; ++i) {
+ free((char *)unsaved_files[i].Filename);
+ free((char *)unsaved_files[i].Contents);
+ }
+}
+
+int parse_remapped_files(int argc, const char **argv, int start_arg,
+ struct CXUnsavedFile **unsaved_files,
+ int *num_unsaved_files) {
+ int i;
+ int arg;
+ int prefix_len = strlen("-remap-file=");
+ *unsaved_files = 0;
+ *num_unsaved_files = 0;
+
+ /* Count the number of remapped files. */
+ for (arg = start_arg; arg < argc; ++arg) {
+ if (strncmp(argv[arg], "-remap-file=", prefix_len))
+ break;
+
+ ++*num_unsaved_files;
+ }
+
+ if (*num_unsaved_files == 0)
+ return 0;
+
+ *unsaved_files
+ = (struct CXUnsavedFile *)malloc(sizeof(struct CXUnsavedFile) *
+ *num_unsaved_files);
+ for (arg = start_arg, i = 0; i != *num_unsaved_files; ++i, ++arg) {
+ struct CXUnsavedFile *unsaved = *unsaved_files + i;
+ const char *arg_string = argv[arg] + prefix_len;
+ int filename_len;
+ char *filename;
+ char *contents;
+ FILE *to_file;
+ const char *semi = strchr(arg_string, ';');
+ if (!semi) {
+ fprintf(stderr,
+ "error: -remap-file=from;to argument is missing semicolon\n");
+ free_remapped_files(*unsaved_files, i);
+ *unsaved_files = 0;
+ *num_unsaved_files = 0;
+ return -1;
+ }
+
+ /* Open the file that we're remapping to. */
+ to_file = fopen(semi + 1, "r");
+ if (!to_file) {
+ fprintf(stderr, "error: cannot open file %s that we are remapping to\n",
+ semi + 1);
+ free_remapped_files(*unsaved_files, i);
+ *unsaved_files = 0;
+ *num_unsaved_files = 0;
+ return -1;
+ }
+
+ /* Determine the length of the file we're remapping to. */
+ fseek(to_file, 0, SEEK_END);
+ unsaved->Length = ftell(to_file);
+ fseek(to_file, 0, SEEK_SET);
+
+ /* Read the contents of the file we're remapping to. */
+ contents = (char *)malloc(unsaved->Length + 1);
+ fread(contents, 1, unsaved->Length, to_file);
+ contents[unsaved->Length] = 0;
+ unsaved->Contents = contents;
+
+ /* Close the file. */
+ fclose(to_file);
+
+ /* Copy the file name that we're remapping from. */
+ filename_len = semi - arg_string;
+ filename = (char *)malloc(filename_len + 1);
+ memcpy(filename, arg_string, filename_len);
+ filename[filename_len] = 0;
+ unsaved->Filename = filename;
+ }
+
+ return 0;
+}
+
int perform_code_completion(int argc, const char **argv) {
const char *input = argv[1];
char *filename = 0;
@@ -396,17 +481,26 @@
unsigned column;
CXIndex CIdx;
int errorCode;
+ struct CXUnsavedFile *unsaved_files = 0;
+ int num_unsaved_files = 0;
input += strlen("-code-completion-at=");
if ((errorCode = parse_file_line_column(input, &filename, &line, &column)))
return errorCode;
+ if (parse_remapped_files(argc, argv, 2, &unsaved_files, &num_unsaved_files))
+ return -1;
+
CIdx = clang_createIndex(0, 0);
- clang_codeComplete(CIdx, argv[argc - 1], argc - 3, argv + 2,
+ 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);
clang_disposeIndex(CIdx);
free(filename);
+ free_remapped_files(unsaved_files, num_unsaved_files);
+
return 0;
}
More information about the cfe-commits
mailing list