blob: fa1fd915596fc215de2db253fef8764696c455a9 [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"
25
Ted Kremenekda7af322010-04-15 01:02:28 +000026#ifdef UDP_CODE_COMPLETION_LOGGER
27#include "clang/Basic/Version.h"
28#include "llvm/ADT/SmallString.h"
29#include "llvm/Support/Timer.h"
30#include "llvm/Support/raw_ostream.h"
31#include <arpa/inet.h>
32#include <sys/socket.h>
33#include <sys/types.h>
34#include <unistd.h>
35#endif
36
Ted Kremenekab188932010-01-05 19:32:54 +000037using namespace clang;
Ted Kremenek2ef6f8f2010-02-17 01:42:24 +000038using namespace clang::cxstring;
Ted Kremenekab188932010-01-05 19:32:54 +000039
Douglas Gregor12e13132010-05-26 22:00:08 +000040namespace {
41 /// \brief Stored representation of a completion string.
42 ///
43 /// This is the representation behind a CXCompletionString.
44 class CXStoredCodeCompletionString : public CodeCompletionString {
45 unsigned Priority;
46
47 public:
48 CXStoredCodeCompletionString(unsigned Priority) : Priority(Priority) { }
49
50 unsigned getPriority() const { return Priority; }
51 };
52}
53
Ted Kremenekab188932010-01-05 19:32:54 +000054extern "C" {
55
56enum CXCompletionChunkKind
57clang_getCompletionChunkKind(CXCompletionString completion_string,
58 unsigned chunk_number) {
Douglas Gregor12e13132010-05-26 22:00:08 +000059 CXStoredCodeCompletionString *CCStr
60 = (CXStoredCodeCompletionString *)completion_string;
Ted Kremenekab188932010-01-05 19:32:54 +000061 if (!CCStr || chunk_number >= CCStr->size())
62 return CXCompletionChunk_Text;
63
64 switch ((*CCStr)[chunk_number].Kind) {
65 case CodeCompletionString::CK_TypedText:
66 return CXCompletionChunk_TypedText;
67 case CodeCompletionString::CK_Text:
68 return CXCompletionChunk_Text;
69 case CodeCompletionString::CK_Optional:
70 return CXCompletionChunk_Optional;
71 case CodeCompletionString::CK_Placeholder:
72 return CXCompletionChunk_Placeholder;
73 case CodeCompletionString::CK_Informative:
74 return CXCompletionChunk_Informative;
75 case CodeCompletionString::CK_ResultType:
76 return CXCompletionChunk_ResultType;
77 case CodeCompletionString::CK_CurrentParameter:
78 return CXCompletionChunk_CurrentParameter;
79 case CodeCompletionString::CK_LeftParen:
80 return CXCompletionChunk_LeftParen;
81 case CodeCompletionString::CK_RightParen:
82 return CXCompletionChunk_RightParen;
83 case CodeCompletionString::CK_LeftBracket:
84 return CXCompletionChunk_LeftBracket;
85 case CodeCompletionString::CK_RightBracket:
86 return CXCompletionChunk_RightBracket;
87 case CodeCompletionString::CK_LeftBrace:
88 return CXCompletionChunk_LeftBrace;
89 case CodeCompletionString::CK_RightBrace:
90 return CXCompletionChunk_RightBrace;
91 case CodeCompletionString::CK_LeftAngle:
92 return CXCompletionChunk_LeftAngle;
93 case CodeCompletionString::CK_RightAngle:
94 return CXCompletionChunk_RightAngle;
95 case CodeCompletionString::CK_Comma:
96 return CXCompletionChunk_Comma;
Douglas Gregor01dfea02010-01-10 23:08:15 +000097 case CodeCompletionString::CK_Colon:
98 return CXCompletionChunk_Colon;
99 case CodeCompletionString::CK_SemiColon:
100 return CXCompletionChunk_SemiColon;
101 case CodeCompletionString::CK_Equal:
102 return CXCompletionChunk_Equal;
103 case CodeCompletionString::CK_HorizontalSpace:
104 return CXCompletionChunk_HorizontalSpace;
105 case CodeCompletionString::CK_VerticalSpace:
106 return CXCompletionChunk_VerticalSpace;
Ted Kremenekab188932010-01-05 19:32:54 +0000107 }
108
109 // Should be unreachable, but let's be careful.
110 return CXCompletionChunk_Text;
111}
112
Ted Kremenek2ef6f8f2010-02-17 01:42:24 +0000113CXString clang_getCompletionChunkText(CXCompletionString completion_string,
114 unsigned chunk_number) {
Douglas Gregor12e13132010-05-26 22:00:08 +0000115 CXStoredCodeCompletionString *CCStr
116 = (CXStoredCodeCompletionString *)completion_string;
Ted Kremenekab188932010-01-05 19:32:54 +0000117 if (!CCStr || chunk_number >= CCStr->size())
Ted Kremenek2ef6f8f2010-02-17 01:42:24 +0000118 return createCXString(0);
Ted Kremenekab188932010-01-05 19:32:54 +0000119
120 switch ((*CCStr)[chunk_number].Kind) {
121 case CodeCompletionString::CK_TypedText:
122 case CodeCompletionString::CK_Text:
123 case CodeCompletionString::CK_Placeholder:
124 case CodeCompletionString::CK_CurrentParameter:
125 case CodeCompletionString::CK_Informative:
126 case CodeCompletionString::CK_LeftParen:
127 case CodeCompletionString::CK_RightParen:
128 case CodeCompletionString::CK_LeftBracket:
129 case CodeCompletionString::CK_RightBracket:
130 case CodeCompletionString::CK_LeftBrace:
131 case CodeCompletionString::CK_RightBrace:
132 case CodeCompletionString::CK_LeftAngle:
133 case CodeCompletionString::CK_RightAngle:
134 case CodeCompletionString::CK_Comma:
135 case CodeCompletionString::CK_ResultType:
Douglas Gregor01dfea02010-01-10 23:08:15 +0000136 case CodeCompletionString::CK_Colon:
137 case CodeCompletionString::CK_SemiColon:
138 case CodeCompletionString::CK_Equal:
139 case CodeCompletionString::CK_HorizontalSpace:
Ted Kremenek2ef6f8f2010-02-17 01:42:24 +0000140 return createCXString((*CCStr)[chunk_number].Text, false);
Ted Kremenekab188932010-01-05 19:32:54 +0000141
Douglas Gregor21c241f2010-05-25 06:14:46 +0000142 case CodeCompletionString::CK_VerticalSpace:
143 // FIXME: Temporary hack until we figure out how to handle vertical space.
144 return createCXString(" ");
145
Ted Kremenekab188932010-01-05 19:32:54 +0000146 case CodeCompletionString::CK_Optional:
147 // Note: treated as an empty text block.
Ted Kremenek2ef6f8f2010-02-17 01:42:24 +0000148 return createCXString("");
Ted Kremenekab188932010-01-05 19:32:54 +0000149 }
150
151 // Should be unreachable, but let's be careful.
Ted Kremenek2ef6f8f2010-02-17 01:42:24 +0000152 return createCXString(0);
Ted Kremenekab188932010-01-05 19:32:54 +0000153}
154
Ted Kremenek2ef6f8f2010-02-17 01:42:24 +0000155
Ted Kremenekab188932010-01-05 19:32:54 +0000156CXCompletionString
157clang_getCompletionChunkCompletionString(CXCompletionString completion_string,
158 unsigned chunk_number) {
Douglas Gregor12e13132010-05-26 22:00:08 +0000159 CXStoredCodeCompletionString *CCStr
160 = (CXStoredCodeCompletionString *)completion_string;
Ted Kremenekab188932010-01-05 19:32:54 +0000161 if (!CCStr || chunk_number >= CCStr->size())
162 return 0;
163
164 switch ((*CCStr)[chunk_number].Kind) {
165 case CodeCompletionString::CK_TypedText:
166 case CodeCompletionString::CK_Text:
167 case CodeCompletionString::CK_Placeholder:
168 case CodeCompletionString::CK_CurrentParameter:
169 case CodeCompletionString::CK_Informative:
170 case CodeCompletionString::CK_LeftParen:
171 case CodeCompletionString::CK_RightParen:
172 case CodeCompletionString::CK_LeftBracket:
173 case CodeCompletionString::CK_RightBracket:
174 case CodeCompletionString::CK_LeftBrace:
175 case CodeCompletionString::CK_RightBrace:
176 case CodeCompletionString::CK_LeftAngle:
177 case CodeCompletionString::CK_RightAngle:
178 case CodeCompletionString::CK_Comma:
179 case CodeCompletionString::CK_ResultType:
Douglas Gregor01dfea02010-01-10 23:08:15 +0000180 case CodeCompletionString::CK_Colon:
181 case CodeCompletionString::CK_SemiColon:
182 case CodeCompletionString::CK_Equal:
183 case CodeCompletionString::CK_HorizontalSpace:
184 case CodeCompletionString::CK_VerticalSpace:
Ted Kremenekab188932010-01-05 19:32:54 +0000185 return 0;
186
187 case CodeCompletionString::CK_Optional:
188 // Note: treated as an empty text block.
189 return (*CCStr)[chunk_number].Optional;
190 }
191
192 // Should be unreachable, but let's be careful.
193 return 0;
194}
195
196unsigned clang_getNumCompletionChunks(CXCompletionString completion_string) {
Douglas Gregor12e13132010-05-26 22:00:08 +0000197 CXStoredCodeCompletionString *CCStr
198 = (CXStoredCodeCompletionString *)completion_string;
Ted Kremenekab188932010-01-05 19:32:54 +0000199 return CCStr? CCStr->size() : 0;
200}
201
Douglas Gregor12e13132010-05-26 22:00:08 +0000202unsigned clang_getCompletionPriority(CXCompletionString completion_string) {
203 CXStoredCodeCompletionString *CCStr
204 = (CXStoredCodeCompletionString *)completion_string;
Bill Wendlinga2ace582010-05-27 18:35:05 +0000205 return CCStr? CCStr->getPriority() : unsigned(CCP_Unlikely);
Douglas Gregor12e13132010-05-26 22:00:08 +0000206}
207
Ted Kremenekab188932010-01-05 19:32:54 +0000208static bool ReadUnsigned(const char *&Memory, const char *MemoryEnd,
209 unsigned &Value) {
210 if (Memory + sizeof(unsigned) > MemoryEnd)
211 return true;
212
213 memmove(&Value, Memory, sizeof(unsigned));
214 Memory += sizeof(unsigned);
215 return false;
216}
217
218/// \brief The CXCodeCompleteResults structure we allocate internally;
219/// the client only sees the initial CXCodeCompleteResults structure.
220struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults {
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000221 AllocatedCXCodeCompleteResults();
222 ~AllocatedCXCodeCompleteResults();
223
Ted Kremenekab188932010-01-05 19:32:54 +0000224 /// \brief The memory buffer from which we parsed the results. We
225 /// retain this buffer because the completion strings point into it.
226 llvm::MemoryBuffer *Buffer;
Daniel Dunbar35b84402010-01-30 23:31:40 +0000227
Douglas Gregora88084b2010-02-18 18:08:43 +0000228 /// \brief Diagnostics produced while performing code completion.
229 llvm::SmallVector<StoredDiagnostic, 8> Diagnostics;
230
Douglas Gregorf715ca12010-03-16 00:06:06 +0000231 /// \brief Diag object
232 Diagnostic Diag;
233
Douglas Gregora88084b2010-02-18 18:08:43 +0000234 /// \brief Language options used to adjust source locations.
Daniel Dunbar35b84402010-01-30 23:31:40 +0000235 LangOptions LangOpts;
Douglas Gregora88084b2010-02-18 18:08:43 +0000236
237 /// \brief Source manager, used for diagnostics.
238 SourceManager SourceMgr;
239
240 /// \brief File manager, used for diagnostics.
241 FileManager FileMgr;
Douglas Gregor313e26c2010-02-18 23:35:40 +0000242
243 /// \brief Temporary files that should be removed once we have finished
244 /// with the code-completion results.
245 std::vector<llvm::sys::Path> TemporaryFiles;
Ted Kremenekab188932010-01-05 19:32:54 +0000246};
247
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000248AllocatedCXCodeCompleteResults::AllocatedCXCodeCompleteResults()
Douglas Gregorf715ca12010-03-16 00:06:06 +0000249 : CXCodeCompleteResults(), Buffer(0), SourceMgr(Diag) { }
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000250
251AllocatedCXCodeCompleteResults::~AllocatedCXCodeCompleteResults() {
252 for (unsigned I = 0, N = NumResults; I != N; ++I)
Douglas Gregor12e13132010-05-26 22:00:08 +0000253 delete (CXStoredCodeCompletionString *)Results[I].CompletionString;
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000254 delete [] Results;
255 delete Buffer;
Douglas Gregor313e26c2010-02-18 23:35:40 +0000256
257 for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I)
258 TemporaryFiles[I].eraseFromDisk();
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000259}
260
Ted Kremenekab188932010-01-05 19:32:54 +0000261CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx,
262 const char *source_filename,
263 int num_command_line_args,
264 const char **command_line_args,
265 unsigned num_unsaved_files,
266 struct CXUnsavedFile *unsaved_files,
267 const char *complete_filename,
268 unsigned complete_line,
Douglas Gregora88084b2010-02-18 18:08:43 +0000269 unsigned complete_column) {
Ted Kremenekda7af322010-04-15 01:02:28 +0000270#ifdef UDP_CODE_COMPLETION_LOGGER
271#ifdef UDP_CODE_COMPLETION_LOGGER_PORT
272 const llvm::TimeRecord &StartTime = llvm::TimeRecord::getCurrentTime();
273#endif
274#endif
275
Ted Kremenekab188932010-01-05 19:32:54 +0000276 // The indexer, which is mainly used to determine where diagnostics go.
277 CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
278
Douglas Gregor936ea3b2010-01-28 00:56:43 +0000279 // Configure the diagnostics.
280 DiagnosticOptions DiagOpts;
Douglas Gregor28019772010-04-05 23:52:57 +0000281 llvm::IntrusiveRefCntPtr<Diagnostic> Diags;
282 Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0);
Douglas Gregor936ea3b2010-01-28 00:56:43 +0000283
Ted Kremenekab188932010-01-05 19:32:54 +0000284 // The set of temporary files that we've built.
285 std::vector<llvm::sys::Path> TemporaryFiles;
286
287 // Build up the arguments for invoking 'clang'.
288 std::vector<const char *> argv;
289
290 // First add the complete path to the 'clang' executable.
291 llvm::sys::Path ClangPath = CXXIdx->getClangPath();
292 argv.push_back(ClangPath.c_str());
293
294 // Add the '-fsyntax-only' argument so that we only perform a basic
295 // syntax check of the code.
296 argv.push_back("-fsyntax-only");
297
298 // Add the appropriate '-code-completion-at=file:line:column' argument
299 // to perform code completion, with an "-Xclang" preceding it.
300 std::string code_complete_at;
301 code_complete_at += complete_filename;
302 code_complete_at += ":";
303 code_complete_at += llvm::utostr(complete_line);
304 code_complete_at += ":";
305 code_complete_at += llvm::utostr(complete_column);
306 argv.push_back("-Xclang");
307 argv.push_back("-code-completion-at");
308 argv.push_back("-Xclang");
309 argv.push_back(code_complete_at.c_str());
310 argv.push_back("-Xclang");
311 argv.push_back("-no-code-completion-debug-printer");
312 argv.push_back("-Xclang");
313 argv.push_back("-code-completion-macros");
Douglas Gregord93256e2010-01-28 06:00:51 +0000314 argv.push_back("-fdiagnostics-binary");
315
Douglas Gregor4db64a42010-01-23 00:14:00 +0000316 // Remap any unsaved files to temporary files.
Ted Kremenekab188932010-01-05 19:32:54 +0000317 std::vector<std::string> RemapArgs;
Douglas Gregor4db64a42010-01-23 00:14:00 +0000318 if (RemapFiles(num_unsaved_files, unsaved_files, RemapArgs, TemporaryFiles))
319 return 0;
Ted Kremenekab188932010-01-05 19:32:54 +0000320
321 // The pointers into the elements of RemapArgs are stable because we
322 // won't be adding anything to RemapArgs after this point.
323 for (unsigned i = 0, e = RemapArgs.size(); i != e; ++i)
324 argv.push_back(RemapArgs[i].c_str());
325
326 // Add the source file name (FIXME: later, we'll want to build temporary
327 // file from the buffer, or just feed the source text via standard input).
328 if (source_filename)
329 argv.push_back(source_filename);
330
331 // Process the compiler options, stripping off '-o', '-c', '-fsyntax-only'.
332 for (int i = 0; i < num_command_line_args; ++i)
333 if (const char *arg = command_line_args[i]) {
334 if (strcmp(arg, "-o") == 0) {
335 ++i; // Also skip the matching argument.
336 continue;
337 }
338 if (strcmp(arg, "-emit-ast") == 0 ||
339 strcmp(arg, "-c") == 0 ||
340 strcmp(arg, "-fsyntax-only") == 0) {
341 continue;
342 }
343
344 // Keep the argument.
345 argv.push_back(arg);
346 }
347
348 // Add the null terminator.
349 argv.push_back(NULL);
350
Douglas Gregord93256e2010-01-28 06:00:51 +0000351 // Generate a temporary name for the code-completion results file.
Benjamin Kramerc2a98162010-03-13 21:22:49 +0000352 char tmpFile[L_tmpnam];
353 char *tmpFileName = tmpnam(tmpFile);
354 llvm::sys::Path ResultsFile(tmpFileName);
Ted Kremenekab188932010-01-05 19:32:54 +0000355 TemporaryFiles.push_back(ResultsFile);
356
Douglas Gregord93256e2010-01-28 06:00:51 +0000357 // Generate a temporary name for the diagnostics file.
Benjamin Kramerc2a98162010-03-13 21:22:49 +0000358 char tmpFileResults[L_tmpnam];
359 char *tmpResultsFileName = tmpnam(tmpFileResults);
360 llvm::sys::Path DiagnosticsFile(tmpResultsFileName);
Douglas Gregord93256e2010-01-28 06:00:51 +0000361 TemporaryFiles.push_back(DiagnosticsFile);
362
Ted Kremenekab188932010-01-05 19:32:54 +0000363 // Invoke 'clang'.
364 llvm::sys::Path DevNull; // leave empty, causes redirection to /dev/null
365 // on Unix or NUL (Windows).
366 std::string ErrMsg;
Douglas Gregord93256e2010-01-28 06:00:51 +0000367 const llvm::sys::Path *Redirects[] = { &DevNull, &ResultsFile,
368 &DiagnosticsFile, 0 };
Ted Kremenekab188932010-01-05 19:32:54 +0000369 llvm::sys::Program::ExecuteAndWait(ClangPath, &argv[0], /* env */ NULL,
370 /* redirects */ &Redirects[0],
371 /* secondsToWait */ 0,
372 /* memoryLimits */ 0, &ErrMsg);
373
Douglas Gregor936ea3b2010-01-28 00:56:43 +0000374 if (!ErrMsg.empty()) {
375 std::string AllArgs;
Ted Kremenekab188932010-01-05 19:32:54 +0000376 for (std::vector<const char*>::iterator I = argv.begin(), E = argv.end();
Douglas Gregor936ea3b2010-01-28 00:56:43 +0000377 I != E; ++I) {
378 AllArgs += ' ';
Ted Kremenekab188932010-01-05 19:32:54 +0000379 if (*I)
Douglas Gregor936ea3b2010-01-28 00:56:43 +0000380 AllArgs += *I;
Ted Kremenekab188932010-01-05 19:32:54 +0000381 }
Douglas Gregor936ea3b2010-01-28 00:56:43 +0000382
Daniel Dunbar32141c82010-02-23 20:23:45 +0000383 Diags->Report(diag::err_fe_invoking) << AllArgs << ErrMsg;
Ted Kremenekab188932010-01-05 19:32:54 +0000384 }
385
386 // Parse the resulting source file to find code-completion results.
387 using llvm::MemoryBuffer;
388 using llvm::StringRef;
Douglas Gregora88084b2010-02-18 18:08:43 +0000389 AllocatedCXCodeCompleteResults *Results = new AllocatedCXCodeCompleteResults;
390 Results->Results = 0;
391 Results->NumResults = 0;
392 Results->Buffer = 0;
393 // FIXME: Set Results->LangOpts!
Ted Kremenekab188932010-01-05 19:32:54 +0000394 if (MemoryBuffer *F = MemoryBuffer::getFile(ResultsFile.c_str())) {
395 llvm::SmallVector<CXCompletionResult, 4> CompletionResults;
396 StringRef Buffer = F->getBuffer();
397 for (const char *Str = Buffer.data(), *StrEnd = Str + Buffer.size();
398 Str < StrEnd;) {
399 unsigned KindValue;
400 if (ReadUnsigned(Str, StrEnd, KindValue))
401 break;
402
Douglas Gregor12e13132010-05-26 22:00:08 +0000403 unsigned Priority;
404 if (ReadUnsigned(Str, StrEnd, Priority))
405 break;
406
407 CXStoredCodeCompletionString *CCStr
408 = new CXStoredCodeCompletionString(Priority);
409 if (!CCStr->Deserialize(Str, StrEnd)) {
410 delete CCStr;
Ted Kremenekab188932010-01-05 19:32:54 +0000411 continue;
Douglas Gregor12e13132010-05-26 22:00:08 +0000412 }
Ted Kremenekab188932010-01-05 19:32:54 +0000413
414 if (!CCStr->empty()) {
415 // Vend the code-completion result to the caller.
416 CXCompletionResult Result;
417 Result.CursorKind = (CXCursorKind)KindValue;
418 Result.CompletionString = CCStr;
419 CompletionResults.push_back(Result);
420 }
421 };
422
423 // Allocate the results.
Ted Kremenekab188932010-01-05 19:32:54 +0000424 Results->Results = new CXCompletionResult [CompletionResults.size()];
425 Results->NumResults = CompletionResults.size();
426 memcpy(Results->Results, CompletionResults.data(),
427 CompletionResults.size() * sizeof(CXCompletionResult));
428 Results->Buffer = F;
429 }
430
Douglas Gregora88084b2010-02-18 18:08:43 +0000431 LoadSerializedDiagnostics(DiagnosticsFile, num_unsaved_files, unsaved_files,
432 Results->FileMgr, Results->SourceMgr,
433 Results->Diagnostics);
434
Douglas Gregor313e26c2010-02-18 23:35:40 +0000435 // Make sure we delete temporary files when the code-completion results are
436 // destroyed.
437 Results->TemporaryFiles.swap(TemporaryFiles);
Ted Kremenekab188932010-01-05 19:32:54 +0000438
Ted Kremenekda7af322010-04-15 01:02:28 +0000439#ifdef UDP_CODE_COMPLETION_LOGGER
440#ifdef UDP_CODE_COMPLETION_LOGGER_PORT
441 const llvm::TimeRecord &EndTime = llvm::TimeRecord::getCurrentTime();
442 llvm::SmallString<256> LogResult;
443 llvm::raw_svector_ostream os(LogResult);
444
445 // Figure out the language and whether or not it uses PCH.
446 const char *lang = 0;
447 bool usesPCH = false;
448
449 for (std::vector<const char*>::iterator I = argv.begin(), E = argv.end();
450 I != E; ++I) {
451 if (*I == 0)
452 continue;
453 if (strcmp(*I, "-x") == 0) {
454 if (I + 1 != E) {
455 lang = *(++I);
456 continue;
457 }
458 }
459 else if (strcmp(*I, "-include") == 0) {
460 if (I+1 != E) {
461 const char *arg = *(++I);
462 llvm::SmallString<512> pchName;
463 {
464 llvm::raw_svector_ostream os(pchName);
465 os << arg << ".pth";
466 }
467 pchName.push_back('\0');
468 struct stat stat_results;
469 if (stat(pchName.data(), &stat_results) == 0)
470 usesPCH = true;
471 continue;
472 }
473 }
474 }
475
Ted Kremenek2ee297f2010-04-17 00:21:42 +0000476 os << "{ ";
477 os << "\"wall\": " << (EndTime.getWallTime() - StartTime.getWallTime());
478 os << ", \"numRes\": " << Results->NumResults;
479 os << ", \"diags\": " << Results->Diagnostics.size();
480 os << ", \"pch\": " << (usesPCH ? "true" : "false");
481 os << ", \"lang\": \"" << (lang ? lang : "<unknown>") << '"';
Ted Kremenekda7af322010-04-15 01:02:28 +0000482 const char *name = getlogin();
Ted Kremenek2ee297f2010-04-17 00:21:42 +0000483 os << ", \"user\": \"" << (name ? name : "unknown") << '"';
484 os << ", \"clangVer\": \"" << getClangFullVersion() << '"';
485 os << " }";
Ted Kremenekda7af322010-04-15 01:02:28 +0000486
487 llvm::StringRef res = os.str();
488 if (res.size() > 0) {
489 do {
490 // Setup the UDP socket.
491 struct sockaddr_in servaddr;
492 bzero(&servaddr, sizeof(servaddr));
493 servaddr.sin_family = AF_INET;
494 servaddr.sin_port = htons(UDP_CODE_COMPLETION_LOGGER_PORT);
495 if (inet_pton(AF_INET, UDP_CODE_COMPLETION_LOGGER,
496 &servaddr.sin_addr) <= 0)
497 break;
498
499 int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
500 if (sockfd < 0)
501 break;
502
503 sendto(sockfd, res.data(), res.size(), 0,
504 (struct sockaddr *)&servaddr, sizeof(servaddr));
505 close(sockfd);
506 }
507 while (false);
508 }
509#endif
510#endif
Ted Kremenekab188932010-01-05 19:32:54 +0000511 return Results;
512}
513
514void clang_disposeCodeCompleteResults(CXCodeCompleteResults *ResultsIn) {
515 if (!ResultsIn)
516 return;
517
518 AllocatedCXCodeCompleteResults *Results
519 = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);
Ted Kremenekab188932010-01-05 19:32:54 +0000520 delete Results;
521}
522
Douglas Gregora88084b2010-02-18 18:08:43 +0000523unsigned
524clang_codeCompleteGetNumDiagnostics(CXCodeCompleteResults *ResultsIn) {
525 AllocatedCXCodeCompleteResults *Results
526 = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);
527 if (!Results)
528 return 0;
529
530 return Results->Diagnostics.size();
531}
532
533CXDiagnostic
534clang_codeCompleteGetDiagnostic(CXCodeCompleteResults *ResultsIn,
535 unsigned Index) {
536 AllocatedCXCodeCompleteResults *Results
537 = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);
538 if (!Results || Index >= Results->Diagnostics.size())
539 return 0;
540
541 return new CXStoredDiagnostic(Results->Diagnostics[Index], Results->LangOpts);
542}
543
544
Ted Kremenekab188932010-01-05 19:32:54 +0000545} // end extern "C"