blob: 2df5241d022575fb40fb77d454011838bfbf0203 [file] [log] [blame]
Ted Kremenekab188932010-01-05 19:32:54 +00001//===- CIndexCodeCompletion.cpp - Code Completion API hooks ---------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the Clang-C Source Indexing library hooks for
11// code completion.
12//
13//===----------------------------------------------------------------------===//
14
15#include "CIndexer.h"
Douglas Gregor936ea3b2010-01-28 00:56:43 +000016#include "CIndexDiagnostic.h"
Benjamin Kramerb846deb2010-04-12 19:45:50 +000017#include "clang/Basic/SourceManager.h"
18#include "clang/Basic/FileManager.h"
19#include "clang/Frontend/CompilerInstance.h"
Douglas Gregor936ea3b2010-01-28 00:56:43 +000020#include "clang/Frontend/FrontendDiagnostic.h"
Ted Kremenekab188932010-01-05 19:32:54 +000021#include "clang/Sema/CodeCompleteConsumer.h"
22#include "llvm/ADT/StringExtras.h"
23#include "llvm/Support/MemoryBuffer.h"
24#include "llvm/System/Program.h"
Douglas Gregor3d398aa2010-07-26 16:29:14 +000025#include <cstdlib>
26#include <cstdio>
Ted Kremenekab188932010-01-05 19:32:54 +000027
Ted Kremenekda7af322010-04-15 01:02:28 +000028#ifdef UDP_CODE_COMPLETION_LOGGER
29#include "clang/Basic/Version.h"
30#include "llvm/ADT/SmallString.h"
31#include "llvm/Support/Timer.h"
32#include "llvm/Support/raw_ostream.h"
33#include <arpa/inet.h>
34#include <sys/socket.h>
35#include <sys/types.h>
36#include <unistd.h>
37#endif
38
Ted Kremenekab188932010-01-05 19:32:54 +000039using namespace clang;
Ted Kremenek2ef6f8f2010-02-17 01:42:24 +000040using namespace clang::cxstring;
Ted Kremenekab188932010-01-05 19:32:54 +000041
Douglas Gregor12e13132010-05-26 22:00:08 +000042namespace {
43 /// \brief Stored representation of a completion string.
44 ///
45 /// This is the representation behind a CXCompletionString.
46 class CXStoredCodeCompletionString : public CodeCompletionString {
47 unsigned Priority;
48
49 public:
50 CXStoredCodeCompletionString(unsigned Priority) : Priority(Priority) { }
51
52 unsigned getPriority() const { return Priority; }
53 };
54}
55
Ted Kremenekab188932010-01-05 19:32:54 +000056extern "C" {
57
58enum CXCompletionChunkKind
59clang_getCompletionChunkKind(CXCompletionString completion_string,
60 unsigned chunk_number) {
Douglas Gregor12e13132010-05-26 22:00:08 +000061 CXStoredCodeCompletionString *CCStr
62 = (CXStoredCodeCompletionString *)completion_string;
Ted Kremenekab188932010-01-05 19:32:54 +000063 if (!CCStr || chunk_number >= CCStr->size())
64 return CXCompletionChunk_Text;
65
66 switch ((*CCStr)[chunk_number].Kind) {
67 case CodeCompletionString::CK_TypedText:
68 return CXCompletionChunk_TypedText;
69 case CodeCompletionString::CK_Text:
70 return CXCompletionChunk_Text;
71 case CodeCompletionString::CK_Optional:
72 return CXCompletionChunk_Optional;
73 case CodeCompletionString::CK_Placeholder:
74 return CXCompletionChunk_Placeholder;
75 case CodeCompletionString::CK_Informative:
76 return CXCompletionChunk_Informative;
77 case CodeCompletionString::CK_ResultType:
78 return CXCompletionChunk_ResultType;
79 case CodeCompletionString::CK_CurrentParameter:
80 return CXCompletionChunk_CurrentParameter;
81 case CodeCompletionString::CK_LeftParen:
82 return CXCompletionChunk_LeftParen;
83 case CodeCompletionString::CK_RightParen:
84 return CXCompletionChunk_RightParen;
85 case CodeCompletionString::CK_LeftBracket:
86 return CXCompletionChunk_LeftBracket;
87 case CodeCompletionString::CK_RightBracket:
88 return CXCompletionChunk_RightBracket;
89 case CodeCompletionString::CK_LeftBrace:
90 return CXCompletionChunk_LeftBrace;
91 case CodeCompletionString::CK_RightBrace:
92 return CXCompletionChunk_RightBrace;
93 case CodeCompletionString::CK_LeftAngle:
94 return CXCompletionChunk_LeftAngle;
95 case CodeCompletionString::CK_RightAngle:
96 return CXCompletionChunk_RightAngle;
97 case CodeCompletionString::CK_Comma:
98 return CXCompletionChunk_Comma;
Douglas Gregor01dfea02010-01-10 23:08:15 +000099 case CodeCompletionString::CK_Colon:
100 return CXCompletionChunk_Colon;
101 case CodeCompletionString::CK_SemiColon:
102 return CXCompletionChunk_SemiColon;
103 case CodeCompletionString::CK_Equal:
104 return CXCompletionChunk_Equal;
105 case CodeCompletionString::CK_HorizontalSpace:
106 return CXCompletionChunk_HorizontalSpace;
107 case CodeCompletionString::CK_VerticalSpace:
108 return CXCompletionChunk_VerticalSpace;
Ted Kremenekab188932010-01-05 19:32:54 +0000109 }
110
111 // Should be unreachable, but let's be careful.
112 return CXCompletionChunk_Text;
113}
114
Ted Kremenek2ef6f8f2010-02-17 01:42:24 +0000115CXString clang_getCompletionChunkText(CXCompletionString completion_string,
116 unsigned chunk_number) {
Douglas Gregor12e13132010-05-26 22:00:08 +0000117 CXStoredCodeCompletionString *CCStr
118 = (CXStoredCodeCompletionString *)completion_string;
Ted Kremenekab188932010-01-05 19:32:54 +0000119 if (!CCStr || chunk_number >= CCStr->size())
Ted Kremenek2ef6f8f2010-02-17 01:42:24 +0000120 return createCXString(0);
Ted Kremenekab188932010-01-05 19:32:54 +0000121
122 switch ((*CCStr)[chunk_number].Kind) {
123 case CodeCompletionString::CK_TypedText:
124 case CodeCompletionString::CK_Text:
125 case CodeCompletionString::CK_Placeholder:
126 case CodeCompletionString::CK_CurrentParameter:
127 case CodeCompletionString::CK_Informative:
128 case CodeCompletionString::CK_LeftParen:
129 case CodeCompletionString::CK_RightParen:
130 case CodeCompletionString::CK_LeftBracket:
131 case CodeCompletionString::CK_RightBracket:
132 case CodeCompletionString::CK_LeftBrace:
133 case CodeCompletionString::CK_RightBrace:
134 case CodeCompletionString::CK_LeftAngle:
135 case CodeCompletionString::CK_RightAngle:
136 case CodeCompletionString::CK_Comma:
137 case CodeCompletionString::CK_ResultType:
Douglas Gregor01dfea02010-01-10 23:08:15 +0000138 case CodeCompletionString::CK_Colon:
139 case CodeCompletionString::CK_SemiColon:
140 case CodeCompletionString::CK_Equal:
141 case CodeCompletionString::CK_HorizontalSpace:
Ted Kremenek2ef6f8f2010-02-17 01:42:24 +0000142 return createCXString((*CCStr)[chunk_number].Text, false);
Ted Kremenekab188932010-01-05 19:32:54 +0000143
Douglas Gregor21c241f2010-05-25 06:14:46 +0000144 case CodeCompletionString::CK_VerticalSpace:
145 // FIXME: Temporary hack until we figure out how to handle vertical space.
146 return createCXString(" ");
147
Ted Kremenekab188932010-01-05 19:32:54 +0000148 case CodeCompletionString::CK_Optional:
149 // Note: treated as an empty text block.
Ted Kremenek2ef6f8f2010-02-17 01:42:24 +0000150 return createCXString("");
Ted Kremenekab188932010-01-05 19:32:54 +0000151 }
152
153 // Should be unreachable, but let's be careful.
Ted Kremenek2ef6f8f2010-02-17 01:42:24 +0000154 return createCXString(0);
Ted Kremenekab188932010-01-05 19:32:54 +0000155}
156
Ted Kremenek2ef6f8f2010-02-17 01:42:24 +0000157
Ted Kremenekab188932010-01-05 19:32:54 +0000158CXCompletionString
159clang_getCompletionChunkCompletionString(CXCompletionString completion_string,
160 unsigned chunk_number) {
Douglas Gregor12e13132010-05-26 22:00:08 +0000161 CXStoredCodeCompletionString *CCStr
162 = (CXStoredCodeCompletionString *)completion_string;
Ted Kremenekab188932010-01-05 19:32:54 +0000163 if (!CCStr || chunk_number >= CCStr->size())
164 return 0;
165
166 switch ((*CCStr)[chunk_number].Kind) {
167 case CodeCompletionString::CK_TypedText:
168 case CodeCompletionString::CK_Text:
169 case CodeCompletionString::CK_Placeholder:
170 case CodeCompletionString::CK_CurrentParameter:
171 case CodeCompletionString::CK_Informative:
172 case CodeCompletionString::CK_LeftParen:
173 case CodeCompletionString::CK_RightParen:
174 case CodeCompletionString::CK_LeftBracket:
175 case CodeCompletionString::CK_RightBracket:
176 case CodeCompletionString::CK_LeftBrace:
177 case CodeCompletionString::CK_RightBrace:
178 case CodeCompletionString::CK_LeftAngle:
179 case CodeCompletionString::CK_RightAngle:
180 case CodeCompletionString::CK_Comma:
181 case CodeCompletionString::CK_ResultType:
Douglas Gregor01dfea02010-01-10 23:08:15 +0000182 case CodeCompletionString::CK_Colon:
183 case CodeCompletionString::CK_SemiColon:
184 case CodeCompletionString::CK_Equal:
185 case CodeCompletionString::CK_HorizontalSpace:
186 case CodeCompletionString::CK_VerticalSpace:
Ted Kremenekab188932010-01-05 19:32:54 +0000187 return 0;
188
189 case CodeCompletionString::CK_Optional:
190 // Note: treated as an empty text block.
191 return (*CCStr)[chunk_number].Optional;
192 }
193
194 // Should be unreachable, but let's be careful.
195 return 0;
196}
197
198unsigned clang_getNumCompletionChunks(CXCompletionString completion_string) {
Douglas Gregor12e13132010-05-26 22:00:08 +0000199 CXStoredCodeCompletionString *CCStr
200 = (CXStoredCodeCompletionString *)completion_string;
Ted Kremenekab188932010-01-05 19:32:54 +0000201 return CCStr? CCStr->size() : 0;
202}
203
Douglas Gregor12e13132010-05-26 22:00:08 +0000204unsigned clang_getCompletionPriority(CXCompletionString completion_string) {
205 CXStoredCodeCompletionString *CCStr
206 = (CXStoredCodeCompletionString *)completion_string;
Bill Wendlinga2ace582010-05-27 18:35:05 +0000207 return CCStr? CCStr->getPriority() : unsigned(CCP_Unlikely);
Douglas Gregor12e13132010-05-26 22:00:08 +0000208}
209
Ted Kremenekab188932010-01-05 19:32:54 +0000210static bool ReadUnsigned(const char *&Memory, const char *MemoryEnd,
211 unsigned &Value) {
212 if (Memory + sizeof(unsigned) > MemoryEnd)
213 return true;
214
215 memmove(&Value, Memory, sizeof(unsigned));
216 Memory += sizeof(unsigned);
217 return false;
218}
219
220/// \brief The CXCodeCompleteResults structure we allocate internally;
221/// the client only sees the initial CXCodeCompleteResults structure.
222struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults {
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000223 AllocatedCXCodeCompleteResults();
224 ~AllocatedCXCodeCompleteResults();
225
Ted Kremenekab188932010-01-05 19:32:54 +0000226 /// \brief The memory buffer from which we parsed the results. We
227 /// retain this buffer because the completion strings point into it.
228 llvm::MemoryBuffer *Buffer;
Daniel Dunbar35b84402010-01-30 23:31:40 +0000229
Douglas Gregora88084b2010-02-18 18:08:43 +0000230 /// \brief Diagnostics produced while performing code completion.
231 llvm::SmallVector<StoredDiagnostic, 8> Diagnostics;
232
Douglas Gregorf715ca12010-03-16 00:06:06 +0000233 /// \brief Diag object
234 Diagnostic Diag;
235
Douglas Gregora88084b2010-02-18 18:08:43 +0000236 /// \brief Language options used to adjust source locations.
Daniel Dunbar35b84402010-01-30 23:31:40 +0000237 LangOptions LangOpts;
Douglas Gregora88084b2010-02-18 18:08:43 +0000238
239 /// \brief Source manager, used for diagnostics.
240 SourceManager SourceMgr;
241
242 /// \brief File manager, used for diagnostics.
243 FileManager FileMgr;
Douglas Gregor313e26c2010-02-18 23:35:40 +0000244
245 /// \brief Temporary files that should be removed once we have finished
246 /// with the code-completion results.
247 std::vector<llvm::sys::Path> TemporaryFiles;
Ted Kremenekab188932010-01-05 19:32:54 +0000248};
249
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000250AllocatedCXCodeCompleteResults::AllocatedCXCodeCompleteResults()
Douglas Gregorf715ca12010-03-16 00:06:06 +0000251 : CXCodeCompleteResults(), Buffer(0), SourceMgr(Diag) { }
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000252
253AllocatedCXCodeCompleteResults::~AllocatedCXCodeCompleteResults() {
254 for (unsigned I = 0, N = NumResults; I != N; ++I)
Douglas Gregor12e13132010-05-26 22:00:08 +0000255 delete (CXStoredCodeCompletionString *)Results[I].CompletionString;
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000256 delete [] Results;
257 delete Buffer;
Douglas Gregor313e26c2010-02-18 23:35:40 +0000258
259 for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I)
260 TemporaryFiles[I].eraseFromDisk();
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000261}
262
Ted Kremenekab188932010-01-05 19:32:54 +0000263CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx,
264 const char *source_filename,
265 int num_command_line_args,
266 const char **command_line_args,
267 unsigned num_unsaved_files,
268 struct CXUnsavedFile *unsaved_files,
269 const char *complete_filename,
270 unsigned complete_line,
Douglas Gregora88084b2010-02-18 18:08:43 +0000271 unsigned complete_column) {
Ted Kremenekda7af322010-04-15 01:02:28 +0000272#ifdef UDP_CODE_COMPLETION_LOGGER
273#ifdef UDP_CODE_COMPLETION_LOGGER_PORT
274 const llvm::TimeRecord &StartTime = llvm::TimeRecord::getCurrentTime();
275#endif
276#endif
277
Douglas Gregor3d398aa2010-07-26 16:29:14 +0000278 bool EnableLogging = getenv("LIBCLANG_CODE_COMPLETION_LOGGING") != 0;
279
Ted Kremenekab188932010-01-05 19:32:54 +0000280 // The indexer, which is mainly used to determine where diagnostics go.
281 CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
282
Douglas Gregor936ea3b2010-01-28 00:56:43 +0000283 // Configure the diagnostics.
284 DiagnosticOptions DiagOpts;
Douglas Gregor28019772010-04-05 23:52:57 +0000285 llvm::IntrusiveRefCntPtr<Diagnostic> Diags;
286 Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0);
Douglas Gregor936ea3b2010-01-28 00:56:43 +0000287
Ted Kremenekab188932010-01-05 19:32:54 +0000288 // The set of temporary files that we've built.
289 std::vector<llvm::sys::Path> TemporaryFiles;
290
291 // Build up the arguments for invoking 'clang'.
292 std::vector<const char *> argv;
293
294 // First add the complete path to the 'clang' executable.
295 llvm::sys::Path ClangPath = CXXIdx->getClangPath();
296 argv.push_back(ClangPath.c_str());
297
Daniel Dunbar3d9c6e12010-06-30 21:40:01 +0000298 // Always use Clang C++ support.
299 argv.push_back("-ccc-clang-cxx");
300
Ted Kremenekab188932010-01-05 19:32:54 +0000301 // Add the '-fsyntax-only' argument so that we only perform a basic
302 // syntax check of the code.
303 argv.push_back("-fsyntax-only");
304
305 // Add the appropriate '-code-completion-at=file:line:column' argument
306 // to perform code completion, with an "-Xclang" preceding it.
307 std::string code_complete_at;
308 code_complete_at += complete_filename;
309 code_complete_at += ":";
310 code_complete_at += llvm::utostr(complete_line);
311 code_complete_at += ":";
312 code_complete_at += llvm::utostr(complete_column);
313 argv.push_back("-Xclang");
314 argv.push_back("-code-completion-at");
315 argv.push_back("-Xclang");
316 argv.push_back(code_complete_at.c_str());
317 argv.push_back("-Xclang");
318 argv.push_back("-no-code-completion-debug-printer");
319 argv.push_back("-Xclang");
320 argv.push_back("-code-completion-macros");
Douglas Gregord93256e2010-01-28 06:00:51 +0000321 argv.push_back("-fdiagnostics-binary");
322
Douglas Gregor4db64a42010-01-23 00:14:00 +0000323 // Remap any unsaved files to temporary files.
Ted Kremenekab188932010-01-05 19:32:54 +0000324 std::vector<std::string> RemapArgs;
Douglas Gregor4db64a42010-01-23 00:14:00 +0000325 if (RemapFiles(num_unsaved_files, unsaved_files, RemapArgs, TemporaryFiles))
326 return 0;
Ted Kremenekab188932010-01-05 19:32:54 +0000327
328 // The pointers into the elements of RemapArgs are stable because we
329 // won't be adding anything to RemapArgs after this point.
330 for (unsigned i = 0, e = RemapArgs.size(); i != e; ++i)
331 argv.push_back(RemapArgs[i].c_str());
332
333 // Add the source file name (FIXME: later, we'll want to build temporary
334 // file from the buffer, or just feed the source text via standard input).
335 if (source_filename)
336 argv.push_back(source_filename);
337
338 // Process the compiler options, stripping off '-o', '-c', '-fsyntax-only'.
339 for (int i = 0; i < num_command_line_args; ++i)
340 if (const char *arg = command_line_args[i]) {
341 if (strcmp(arg, "-o") == 0) {
342 ++i; // Also skip the matching argument.
343 continue;
344 }
345 if (strcmp(arg, "-emit-ast") == 0 ||
346 strcmp(arg, "-c") == 0 ||
347 strcmp(arg, "-fsyntax-only") == 0) {
348 continue;
349 }
350
351 // Keep the argument.
352 argv.push_back(arg);
353 }
354
Douglas Gregor3d398aa2010-07-26 16:29:14 +0000355 if (EnableLogging) {
356 std::string Log = ClangPath.str();
357 for (unsigned I = 0, N = argv.size(); I != N; ++I) {
358 Log += ' ';
359 Log += argv[I];
360 }
361 fprintf(stderr, "libclang (Code Completion): %s\n", Log.c_str());
362 }
363
Ted Kremenekab188932010-01-05 19:32:54 +0000364 // Add the null terminator.
365 argv.push_back(NULL);
366
Douglas Gregord93256e2010-01-28 06:00:51 +0000367 // Generate a temporary name for the code-completion results file.
Benjamin Kramerc2a98162010-03-13 21:22:49 +0000368 char tmpFile[L_tmpnam];
369 char *tmpFileName = tmpnam(tmpFile);
370 llvm::sys::Path ResultsFile(tmpFileName);
Ted Kremenekab188932010-01-05 19:32:54 +0000371 TemporaryFiles.push_back(ResultsFile);
372
Douglas Gregord93256e2010-01-28 06:00:51 +0000373 // Generate a temporary name for the diagnostics file.
Benjamin Kramerc2a98162010-03-13 21:22:49 +0000374 char tmpFileResults[L_tmpnam];
375 char *tmpResultsFileName = tmpnam(tmpFileResults);
376 llvm::sys::Path DiagnosticsFile(tmpResultsFileName);
Douglas Gregord93256e2010-01-28 06:00:51 +0000377 TemporaryFiles.push_back(DiagnosticsFile);
378
Douglas Gregor3d398aa2010-07-26 16:29:14 +0000379
380
Ted Kremenekab188932010-01-05 19:32:54 +0000381 // Invoke 'clang'.
382 llvm::sys::Path DevNull; // leave empty, causes redirection to /dev/null
383 // on Unix or NUL (Windows).
384 std::string ErrMsg;
Douglas Gregord93256e2010-01-28 06:00:51 +0000385 const llvm::sys::Path *Redirects[] = { &DevNull, &ResultsFile,
386 &DiagnosticsFile, 0 };
Ted Kremenekab188932010-01-05 19:32:54 +0000387 llvm::sys::Program::ExecuteAndWait(ClangPath, &argv[0], /* env */ NULL,
388 /* redirects */ &Redirects[0],
389 /* secondsToWait */ 0,
390 /* memoryLimits */ 0, &ErrMsg);
391
Douglas Gregor936ea3b2010-01-28 00:56:43 +0000392 if (!ErrMsg.empty()) {
393 std::string AllArgs;
Ted Kremenekab188932010-01-05 19:32:54 +0000394 for (std::vector<const char*>::iterator I = argv.begin(), E = argv.end();
Douglas Gregor936ea3b2010-01-28 00:56:43 +0000395 I != E; ++I) {
396 AllArgs += ' ';
Ted Kremenekab188932010-01-05 19:32:54 +0000397 if (*I)
Douglas Gregor936ea3b2010-01-28 00:56:43 +0000398 AllArgs += *I;
Ted Kremenekab188932010-01-05 19:32:54 +0000399 }
Douglas Gregor936ea3b2010-01-28 00:56:43 +0000400
Daniel Dunbar32141c82010-02-23 20:23:45 +0000401 Diags->Report(diag::err_fe_invoking) << AllArgs << ErrMsg;
Ted Kremenekab188932010-01-05 19:32:54 +0000402 }
403
404 // Parse the resulting source file to find code-completion results.
405 using llvm::MemoryBuffer;
406 using llvm::StringRef;
Douglas Gregora88084b2010-02-18 18:08:43 +0000407 AllocatedCXCodeCompleteResults *Results = new AllocatedCXCodeCompleteResults;
408 Results->Results = 0;
409 Results->NumResults = 0;
410 Results->Buffer = 0;
411 // FIXME: Set Results->LangOpts!
Ted Kremenekab188932010-01-05 19:32:54 +0000412 if (MemoryBuffer *F = MemoryBuffer::getFile(ResultsFile.c_str())) {
413 llvm::SmallVector<CXCompletionResult, 4> CompletionResults;
414 StringRef Buffer = F->getBuffer();
415 for (const char *Str = Buffer.data(), *StrEnd = Str + Buffer.size();
416 Str < StrEnd;) {
417 unsigned KindValue;
418 if (ReadUnsigned(Str, StrEnd, KindValue))
419 break;
420
Douglas Gregor12e13132010-05-26 22:00:08 +0000421 unsigned Priority;
422 if (ReadUnsigned(Str, StrEnd, Priority))
423 break;
424
425 CXStoredCodeCompletionString *CCStr
426 = new CXStoredCodeCompletionString(Priority);
427 if (!CCStr->Deserialize(Str, StrEnd)) {
428 delete CCStr;
Ted Kremenekab188932010-01-05 19:32:54 +0000429 continue;
Douglas Gregor12e13132010-05-26 22:00:08 +0000430 }
Ted Kremenekab188932010-01-05 19:32:54 +0000431
432 if (!CCStr->empty()) {
433 // Vend the code-completion result to the caller.
434 CXCompletionResult Result;
435 Result.CursorKind = (CXCursorKind)KindValue;
436 Result.CompletionString = CCStr;
437 CompletionResults.push_back(Result);
438 }
439 };
440
441 // Allocate the results.
Ted Kremenekab188932010-01-05 19:32:54 +0000442 Results->Results = new CXCompletionResult [CompletionResults.size()];
443 Results->NumResults = CompletionResults.size();
444 memcpy(Results->Results, CompletionResults.data(),
445 CompletionResults.size() * sizeof(CXCompletionResult));
446 Results->Buffer = F;
447 }
448
Douglas Gregora88084b2010-02-18 18:08:43 +0000449 LoadSerializedDiagnostics(DiagnosticsFile, num_unsaved_files, unsaved_files,
450 Results->FileMgr, Results->SourceMgr,
451 Results->Diagnostics);
452
Douglas Gregor313e26c2010-02-18 23:35:40 +0000453 // Make sure we delete temporary files when the code-completion results are
454 // destroyed.
455 Results->TemporaryFiles.swap(TemporaryFiles);
Ted Kremenekab188932010-01-05 19:32:54 +0000456
Ted Kremenekda7af322010-04-15 01:02:28 +0000457#ifdef UDP_CODE_COMPLETION_LOGGER
458#ifdef UDP_CODE_COMPLETION_LOGGER_PORT
459 const llvm::TimeRecord &EndTime = llvm::TimeRecord::getCurrentTime();
460 llvm::SmallString<256> LogResult;
461 llvm::raw_svector_ostream os(LogResult);
462
463 // Figure out the language and whether or not it uses PCH.
464 const char *lang = 0;
465 bool usesPCH = false;
466
467 for (std::vector<const char*>::iterator I = argv.begin(), E = argv.end();
468 I != E; ++I) {
469 if (*I == 0)
470 continue;
471 if (strcmp(*I, "-x") == 0) {
472 if (I + 1 != E) {
473 lang = *(++I);
474 continue;
475 }
476 }
477 else if (strcmp(*I, "-include") == 0) {
478 if (I+1 != E) {
479 const char *arg = *(++I);
480 llvm::SmallString<512> pchName;
481 {
482 llvm::raw_svector_ostream os(pchName);
483 os << arg << ".pth";
484 }
485 pchName.push_back('\0');
486 struct stat stat_results;
487 if (stat(pchName.data(), &stat_results) == 0)
488 usesPCH = true;
489 continue;
490 }
491 }
492 }
493
Ted Kremenek2ee297f2010-04-17 00:21:42 +0000494 os << "{ ";
495 os << "\"wall\": " << (EndTime.getWallTime() - StartTime.getWallTime());
496 os << ", \"numRes\": " << Results->NumResults;
497 os << ", \"diags\": " << Results->Diagnostics.size();
498 os << ", \"pch\": " << (usesPCH ? "true" : "false");
499 os << ", \"lang\": \"" << (lang ? lang : "<unknown>") << '"';
Ted Kremenekda7af322010-04-15 01:02:28 +0000500 const char *name = getlogin();
Ted Kremenek2ee297f2010-04-17 00:21:42 +0000501 os << ", \"user\": \"" << (name ? name : "unknown") << '"';
502 os << ", \"clangVer\": \"" << getClangFullVersion() << '"';
503 os << " }";
Ted Kremenekda7af322010-04-15 01:02:28 +0000504
505 llvm::StringRef res = os.str();
506 if (res.size() > 0) {
507 do {
508 // Setup the UDP socket.
509 struct sockaddr_in servaddr;
510 bzero(&servaddr, sizeof(servaddr));
511 servaddr.sin_family = AF_INET;
512 servaddr.sin_port = htons(UDP_CODE_COMPLETION_LOGGER_PORT);
513 if (inet_pton(AF_INET, UDP_CODE_COMPLETION_LOGGER,
514 &servaddr.sin_addr) <= 0)
515 break;
516
517 int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
518 if (sockfd < 0)
519 break;
520
521 sendto(sockfd, res.data(), res.size(), 0,
522 (struct sockaddr *)&servaddr, sizeof(servaddr));
523 close(sockfd);
524 }
525 while (false);
526 }
527#endif
528#endif
Ted Kremenekab188932010-01-05 19:32:54 +0000529 return Results;
530}
531
532void clang_disposeCodeCompleteResults(CXCodeCompleteResults *ResultsIn) {
533 if (!ResultsIn)
534 return;
535
536 AllocatedCXCodeCompleteResults *Results
537 = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);
Ted Kremenekab188932010-01-05 19:32:54 +0000538 delete Results;
539}
540
Douglas Gregora88084b2010-02-18 18:08:43 +0000541unsigned
542clang_codeCompleteGetNumDiagnostics(CXCodeCompleteResults *ResultsIn) {
543 AllocatedCXCodeCompleteResults *Results
544 = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);
545 if (!Results)
546 return 0;
547
548 return Results->Diagnostics.size();
549}
550
551CXDiagnostic
552clang_codeCompleteGetDiagnostic(CXCodeCompleteResults *ResultsIn,
553 unsigned Index) {
554 AllocatedCXCodeCompleteResults *Results
555 = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);
556 if (!Results || Index >= Results->Diagnostics.size())
557 return 0;
558
559 return new CXStoredDiagnostic(Results->Diagnostics[Index], Results->LangOpts);
560}
561
562
Ted Kremenekab188932010-01-05 19:32:54 +0000563} // end extern "C"