blob: 3d66843a5993b9d90f63c3f454d468e451497999 [file] [log] [blame]
Ted Kremenek0ec2cca2010-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 Gregorba965fb2010-01-28 00:56:43 +000016#include "CIndexDiagnostic.h"
Benjamin Kramer064414532010-04-12 19:45:50 +000017#include "clang/Basic/SourceManager.h"
18#include "clang/Basic/FileManager.h"
19#include "clang/Frontend/CompilerInstance.h"
Douglas Gregorba965fb2010-01-28 00:56:43 +000020#include "clang/Frontend/FrontendDiagnostic.h"
Ted Kremenek0ec2cca2010-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 Kremenek9e0cf092010-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 Kremenek0ec2cca2010-01-05 19:32:54 +000037using namespace clang;
Ted Kremenekf602f962010-02-17 01:42:24 +000038using namespace clang::cxstring;
Ted Kremenek0ec2cca2010-01-05 19:32:54 +000039
40extern "C" {
41
42enum CXCompletionChunkKind
43clang_getCompletionChunkKind(CXCompletionString completion_string,
44 unsigned chunk_number) {
45 CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
46 if (!CCStr || chunk_number >= CCStr->size())
47 return CXCompletionChunk_Text;
48
49 switch ((*CCStr)[chunk_number].Kind) {
50 case CodeCompletionString::CK_TypedText:
51 return CXCompletionChunk_TypedText;
52 case CodeCompletionString::CK_Text:
53 return CXCompletionChunk_Text;
54 case CodeCompletionString::CK_Optional:
55 return CXCompletionChunk_Optional;
56 case CodeCompletionString::CK_Placeholder:
57 return CXCompletionChunk_Placeholder;
58 case CodeCompletionString::CK_Informative:
59 return CXCompletionChunk_Informative;
60 case CodeCompletionString::CK_ResultType:
61 return CXCompletionChunk_ResultType;
62 case CodeCompletionString::CK_CurrentParameter:
63 return CXCompletionChunk_CurrentParameter;
64 case CodeCompletionString::CK_LeftParen:
65 return CXCompletionChunk_LeftParen;
66 case CodeCompletionString::CK_RightParen:
67 return CXCompletionChunk_RightParen;
68 case CodeCompletionString::CK_LeftBracket:
69 return CXCompletionChunk_LeftBracket;
70 case CodeCompletionString::CK_RightBracket:
71 return CXCompletionChunk_RightBracket;
72 case CodeCompletionString::CK_LeftBrace:
73 return CXCompletionChunk_LeftBrace;
74 case CodeCompletionString::CK_RightBrace:
75 return CXCompletionChunk_RightBrace;
76 case CodeCompletionString::CK_LeftAngle:
77 return CXCompletionChunk_LeftAngle;
78 case CodeCompletionString::CK_RightAngle:
79 return CXCompletionChunk_RightAngle;
80 case CodeCompletionString::CK_Comma:
81 return CXCompletionChunk_Comma;
Douglas Gregor504a6ae2010-01-10 23:08:15 +000082 case CodeCompletionString::CK_Colon:
83 return CXCompletionChunk_Colon;
84 case CodeCompletionString::CK_SemiColon:
85 return CXCompletionChunk_SemiColon;
86 case CodeCompletionString::CK_Equal:
87 return CXCompletionChunk_Equal;
88 case CodeCompletionString::CK_HorizontalSpace:
89 return CXCompletionChunk_HorizontalSpace;
90 case CodeCompletionString::CK_VerticalSpace:
91 return CXCompletionChunk_VerticalSpace;
Ted Kremenek0ec2cca2010-01-05 19:32:54 +000092 }
93
94 // Should be unreachable, but let's be careful.
95 return CXCompletionChunk_Text;
96}
97
Ted Kremenekf602f962010-02-17 01:42:24 +000098CXString clang_getCompletionChunkText(CXCompletionString completion_string,
99 unsigned chunk_number) {
Ted Kremenek0ec2cca2010-01-05 19:32:54 +0000100 CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
101 if (!CCStr || chunk_number >= CCStr->size())
Ted Kremenekf602f962010-02-17 01:42:24 +0000102 return createCXString(0);
Ted Kremenek0ec2cca2010-01-05 19:32:54 +0000103
104 switch ((*CCStr)[chunk_number].Kind) {
105 case CodeCompletionString::CK_TypedText:
106 case CodeCompletionString::CK_Text:
107 case CodeCompletionString::CK_Placeholder:
108 case CodeCompletionString::CK_CurrentParameter:
109 case CodeCompletionString::CK_Informative:
110 case CodeCompletionString::CK_LeftParen:
111 case CodeCompletionString::CK_RightParen:
112 case CodeCompletionString::CK_LeftBracket:
113 case CodeCompletionString::CK_RightBracket:
114 case CodeCompletionString::CK_LeftBrace:
115 case CodeCompletionString::CK_RightBrace:
116 case CodeCompletionString::CK_LeftAngle:
117 case CodeCompletionString::CK_RightAngle:
118 case CodeCompletionString::CK_Comma:
119 case CodeCompletionString::CK_ResultType:
Douglas Gregor504a6ae2010-01-10 23:08:15 +0000120 case CodeCompletionString::CK_Colon:
121 case CodeCompletionString::CK_SemiColon:
122 case CodeCompletionString::CK_Equal:
123 case CodeCompletionString::CK_HorizontalSpace:
Ted Kremenekf602f962010-02-17 01:42:24 +0000124 return createCXString((*CCStr)[chunk_number].Text, false);
Ted Kremenek0ec2cca2010-01-05 19:32:54 +0000125
Douglas Gregor09737ee2010-05-25 06:14:46 +0000126 case CodeCompletionString::CK_VerticalSpace:
127 // FIXME: Temporary hack until we figure out how to handle vertical space.
128 return createCXString(" ");
129
Ted Kremenek0ec2cca2010-01-05 19:32:54 +0000130 case CodeCompletionString::CK_Optional:
131 // Note: treated as an empty text block.
Ted Kremenekf602f962010-02-17 01:42:24 +0000132 return createCXString("");
Ted Kremenek0ec2cca2010-01-05 19:32:54 +0000133 }
134
135 // Should be unreachable, but let's be careful.
Ted Kremenekf602f962010-02-17 01:42:24 +0000136 return createCXString(0);
Ted Kremenek0ec2cca2010-01-05 19:32:54 +0000137}
138
Ted Kremenekf602f962010-02-17 01:42:24 +0000139
Ted Kremenek0ec2cca2010-01-05 19:32:54 +0000140CXCompletionString
141clang_getCompletionChunkCompletionString(CXCompletionString completion_string,
142 unsigned chunk_number) {
143 CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
144 if (!CCStr || chunk_number >= CCStr->size())
145 return 0;
146
147 switch ((*CCStr)[chunk_number].Kind) {
148 case CodeCompletionString::CK_TypedText:
149 case CodeCompletionString::CK_Text:
150 case CodeCompletionString::CK_Placeholder:
151 case CodeCompletionString::CK_CurrentParameter:
152 case CodeCompletionString::CK_Informative:
153 case CodeCompletionString::CK_LeftParen:
154 case CodeCompletionString::CK_RightParen:
155 case CodeCompletionString::CK_LeftBracket:
156 case CodeCompletionString::CK_RightBracket:
157 case CodeCompletionString::CK_LeftBrace:
158 case CodeCompletionString::CK_RightBrace:
159 case CodeCompletionString::CK_LeftAngle:
160 case CodeCompletionString::CK_RightAngle:
161 case CodeCompletionString::CK_Comma:
162 case CodeCompletionString::CK_ResultType:
Douglas Gregor504a6ae2010-01-10 23:08:15 +0000163 case CodeCompletionString::CK_Colon:
164 case CodeCompletionString::CK_SemiColon:
165 case CodeCompletionString::CK_Equal:
166 case CodeCompletionString::CK_HorizontalSpace:
167 case CodeCompletionString::CK_VerticalSpace:
Ted Kremenek0ec2cca2010-01-05 19:32:54 +0000168 return 0;
169
170 case CodeCompletionString::CK_Optional:
171 // Note: treated as an empty text block.
172 return (*CCStr)[chunk_number].Optional;
173 }
174
175 // Should be unreachable, but let's be careful.
176 return 0;
177}
178
179unsigned clang_getNumCompletionChunks(CXCompletionString completion_string) {
180 CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
181 return CCStr? CCStr->size() : 0;
182}
183
184static bool ReadUnsigned(const char *&Memory, const char *MemoryEnd,
185 unsigned &Value) {
186 if (Memory + sizeof(unsigned) > MemoryEnd)
187 return true;
188
189 memmove(&Value, Memory, sizeof(unsigned));
190 Memory += sizeof(unsigned);
191 return false;
192}
193
194/// \brief The CXCodeCompleteResults structure we allocate internally;
195/// the client only sees the initial CXCodeCompleteResults structure.
196struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults {
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000197 AllocatedCXCodeCompleteResults();
198 ~AllocatedCXCodeCompleteResults();
199
Ted Kremenek0ec2cca2010-01-05 19:32:54 +0000200 /// \brief The memory buffer from which we parsed the results. We
201 /// retain this buffer because the completion strings point into it.
202 llvm::MemoryBuffer *Buffer;
Daniel Dunbar854d36b2010-01-30 23:31:40 +0000203
Douglas Gregor33cdd812010-02-18 18:08:43 +0000204 /// \brief Diagnostics produced while performing code completion.
205 llvm::SmallVector<StoredDiagnostic, 8> Diagnostics;
206
Douglas Gregore0fbb832010-03-16 00:06:06 +0000207 /// \brief Diag object
208 Diagnostic Diag;
209
Douglas Gregor33cdd812010-02-18 18:08:43 +0000210 /// \brief Language options used to adjust source locations.
Daniel Dunbar854d36b2010-01-30 23:31:40 +0000211 LangOptions LangOpts;
Douglas Gregor33cdd812010-02-18 18:08:43 +0000212
213 /// \brief Source manager, used for diagnostics.
214 SourceManager SourceMgr;
215
216 /// \brief File manager, used for diagnostics.
217 FileManager FileMgr;
Douglas Gregor6cb5ba42010-02-18 23:35:40 +0000218
219 /// \brief Temporary files that should be removed once we have finished
220 /// with the code-completion results.
221 std::vector<llvm::sys::Path> TemporaryFiles;
Ted Kremenek0ec2cca2010-01-05 19:32:54 +0000222};
223
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000224AllocatedCXCodeCompleteResults::AllocatedCXCodeCompleteResults()
Douglas Gregore0fbb832010-03-16 00:06:06 +0000225 : CXCodeCompleteResults(), Buffer(0), SourceMgr(Diag) { }
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000226
227AllocatedCXCodeCompleteResults::~AllocatedCXCodeCompleteResults() {
228 for (unsigned I = 0, N = NumResults; I != N; ++I)
229 delete (CodeCompletionString *)Results[I].CompletionString;
230 delete [] Results;
231 delete Buffer;
Douglas Gregor6cb5ba42010-02-18 23:35:40 +0000232
233 for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I)
234 TemporaryFiles[I].eraseFromDisk();
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000235}
236
Ted Kremenek0ec2cca2010-01-05 19:32:54 +0000237CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx,
238 const char *source_filename,
239 int num_command_line_args,
240 const char **command_line_args,
241 unsigned num_unsaved_files,
242 struct CXUnsavedFile *unsaved_files,
243 const char *complete_filename,
244 unsigned complete_line,
Douglas Gregor33cdd812010-02-18 18:08:43 +0000245 unsigned complete_column) {
Ted Kremenek9e0cf092010-04-15 01:02:28 +0000246#ifdef UDP_CODE_COMPLETION_LOGGER
247#ifdef UDP_CODE_COMPLETION_LOGGER_PORT
248 const llvm::TimeRecord &StartTime = llvm::TimeRecord::getCurrentTime();
249#endif
250#endif
251
Ted Kremenek0ec2cca2010-01-05 19:32:54 +0000252 // The indexer, which is mainly used to determine where diagnostics go.
253 CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
254
Douglas Gregorba965fb2010-01-28 00:56:43 +0000255 // Configure the diagnostics.
256 DiagnosticOptions DiagOpts;
Douglas Gregor7f95d262010-04-05 23:52:57 +0000257 llvm::IntrusiveRefCntPtr<Diagnostic> Diags;
258 Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0);
Douglas Gregorba965fb2010-01-28 00:56:43 +0000259
Ted Kremenek0ec2cca2010-01-05 19:32:54 +0000260 // The set of temporary files that we've built.
261 std::vector<llvm::sys::Path> TemporaryFiles;
262
263 // Build up the arguments for invoking 'clang'.
264 std::vector<const char *> argv;
265
266 // First add the complete path to the 'clang' executable.
267 llvm::sys::Path ClangPath = CXXIdx->getClangPath();
268 argv.push_back(ClangPath.c_str());
269
270 // Add the '-fsyntax-only' argument so that we only perform a basic
271 // syntax check of the code.
272 argv.push_back("-fsyntax-only");
273
274 // Add the appropriate '-code-completion-at=file:line:column' argument
275 // to perform code completion, with an "-Xclang" preceding it.
276 std::string code_complete_at;
277 code_complete_at += complete_filename;
278 code_complete_at += ":";
279 code_complete_at += llvm::utostr(complete_line);
280 code_complete_at += ":";
281 code_complete_at += llvm::utostr(complete_column);
282 argv.push_back("-Xclang");
283 argv.push_back("-code-completion-at");
284 argv.push_back("-Xclang");
285 argv.push_back(code_complete_at.c_str());
286 argv.push_back("-Xclang");
287 argv.push_back("-no-code-completion-debug-printer");
288 argv.push_back("-Xclang");
289 argv.push_back("-code-completion-macros");
Douglas Gregorac0605e2010-01-28 06:00:51 +0000290 argv.push_back("-fdiagnostics-binary");
291
Douglas Gregoraa98ed92010-01-23 00:14:00 +0000292 // Remap any unsaved files to temporary files.
Ted Kremenek0ec2cca2010-01-05 19:32:54 +0000293 std::vector<std::string> RemapArgs;
Douglas Gregoraa98ed92010-01-23 00:14:00 +0000294 if (RemapFiles(num_unsaved_files, unsaved_files, RemapArgs, TemporaryFiles))
295 return 0;
Ted Kremenek0ec2cca2010-01-05 19:32:54 +0000296
297 // The pointers into the elements of RemapArgs are stable because we
298 // won't be adding anything to RemapArgs after this point.
299 for (unsigned i = 0, e = RemapArgs.size(); i != e; ++i)
300 argv.push_back(RemapArgs[i].c_str());
301
302 // Add the source file name (FIXME: later, we'll want to build temporary
303 // file from the buffer, or just feed the source text via standard input).
304 if (source_filename)
305 argv.push_back(source_filename);
306
307 // Process the compiler options, stripping off '-o', '-c', '-fsyntax-only'.
308 for (int i = 0; i < num_command_line_args; ++i)
309 if (const char *arg = command_line_args[i]) {
310 if (strcmp(arg, "-o") == 0) {
311 ++i; // Also skip the matching argument.
312 continue;
313 }
314 if (strcmp(arg, "-emit-ast") == 0 ||
315 strcmp(arg, "-c") == 0 ||
316 strcmp(arg, "-fsyntax-only") == 0) {
317 continue;
318 }
319
320 // Keep the argument.
321 argv.push_back(arg);
322 }
323
324 // Add the null terminator.
325 argv.push_back(NULL);
326
Douglas Gregorac0605e2010-01-28 06:00:51 +0000327 // Generate a temporary name for the code-completion results file.
Benjamin Kramerf156b9d2010-03-13 21:22:49 +0000328 char tmpFile[L_tmpnam];
329 char *tmpFileName = tmpnam(tmpFile);
330 llvm::sys::Path ResultsFile(tmpFileName);
Ted Kremenek0ec2cca2010-01-05 19:32:54 +0000331 TemporaryFiles.push_back(ResultsFile);
332
Douglas Gregorac0605e2010-01-28 06:00:51 +0000333 // Generate a temporary name for the diagnostics file.
Benjamin Kramerf156b9d2010-03-13 21:22:49 +0000334 char tmpFileResults[L_tmpnam];
335 char *tmpResultsFileName = tmpnam(tmpFileResults);
336 llvm::sys::Path DiagnosticsFile(tmpResultsFileName);
Douglas Gregorac0605e2010-01-28 06:00:51 +0000337 TemporaryFiles.push_back(DiagnosticsFile);
338
Ted Kremenek0ec2cca2010-01-05 19:32:54 +0000339 // Invoke 'clang'.
340 llvm::sys::Path DevNull; // leave empty, causes redirection to /dev/null
341 // on Unix or NUL (Windows).
342 std::string ErrMsg;
Douglas Gregorac0605e2010-01-28 06:00:51 +0000343 const llvm::sys::Path *Redirects[] = { &DevNull, &ResultsFile,
344 &DiagnosticsFile, 0 };
Ted Kremenek0ec2cca2010-01-05 19:32:54 +0000345 llvm::sys::Program::ExecuteAndWait(ClangPath, &argv[0], /* env */ NULL,
346 /* redirects */ &Redirects[0],
347 /* secondsToWait */ 0,
348 /* memoryLimits */ 0, &ErrMsg);
349
Douglas Gregorba965fb2010-01-28 00:56:43 +0000350 if (!ErrMsg.empty()) {
351 std::string AllArgs;
Ted Kremenek0ec2cca2010-01-05 19:32:54 +0000352 for (std::vector<const char*>::iterator I = argv.begin(), E = argv.end();
Douglas Gregorba965fb2010-01-28 00:56:43 +0000353 I != E; ++I) {
354 AllArgs += ' ';
Ted Kremenek0ec2cca2010-01-05 19:32:54 +0000355 if (*I)
Douglas Gregorba965fb2010-01-28 00:56:43 +0000356 AllArgs += *I;
Ted Kremenek0ec2cca2010-01-05 19:32:54 +0000357 }
Douglas Gregorba965fb2010-01-28 00:56:43 +0000358
Daniel Dunbar253dbad2010-02-23 20:23:45 +0000359 Diags->Report(diag::err_fe_invoking) << AllArgs << ErrMsg;
Ted Kremenek0ec2cca2010-01-05 19:32:54 +0000360 }
361
362 // Parse the resulting source file to find code-completion results.
363 using llvm::MemoryBuffer;
364 using llvm::StringRef;
Douglas Gregor33cdd812010-02-18 18:08:43 +0000365 AllocatedCXCodeCompleteResults *Results = new AllocatedCXCodeCompleteResults;
366 Results->Results = 0;
367 Results->NumResults = 0;
368 Results->Buffer = 0;
369 // FIXME: Set Results->LangOpts!
Ted Kremenek0ec2cca2010-01-05 19:32:54 +0000370 if (MemoryBuffer *F = MemoryBuffer::getFile(ResultsFile.c_str())) {
371 llvm::SmallVector<CXCompletionResult, 4> CompletionResults;
372 StringRef Buffer = F->getBuffer();
373 for (const char *Str = Buffer.data(), *StrEnd = Str + Buffer.size();
374 Str < StrEnd;) {
375 unsigned KindValue;
376 if (ReadUnsigned(Str, StrEnd, KindValue))
377 break;
378
379 CodeCompletionString *CCStr
380 = CodeCompletionString::Deserialize(Str, StrEnd);
381 if (!CCStr)
382 continue;
383
384 if (!CCStr->empty()) {
385 // Vend the code-completion result to the caller.
386 CXCompletionResult Result;
387 Result.CursorKind = (CXCursorKind)KindValue;
388 Result.CompletionString = CCStr;
389 CompletionResults.push_back(Result);
390 }
391 };
392
393 // Allocate the results.
Ted Kremenek0ec2cca2010-01-05 19:32:54 +0000394 Results->Results = new CXCompletionResult [CompletionResults.size()];
395 Results->NumResults = CompletionResults.size();
396 memcpy(Results->Results, CompletionResults.data(),
397 CompletionResults.size() * sizeof(CXCompletionResult));
398 Results->Buffer = F;
399 }
400
Douglas Gregor33cdd812010-02-18 18:08:43 +0000401 LoadSerializedDiagnostics(DiagnosticsFile, num_unsaved_files, unsaved_files,
402 Results->FileMgr, Results->SourceMgr,
403 Results->Diagnostics);
404
Douglas Gregor6cb5ba42010-02-18 23:35:40 +0000405 // Make sure we delete temporary files when the code-completion results are
406 // destroyed.
407 Results->TemporaryFiles.swap(TemporaryFiles);
Ted Kremenek0ec2cca2010-01-05 19:32:54 +0000408
Ted Kremenek9e0cf092010-04-15 01:02:28 +0000409#ifdef UDP_CODE_COMPLETION_LOGGER
410#ifdef UDP_CODE_COMPLETION_LOGGER_PORT
411 const llvm::TimeRecord &EndTime = llvm::TimeRecord::getCurrentTime();
412 llvm::SmallString<256> LogResult;
413 llvm::raw_svector_ostream os(LogResult);
414
415 // Figure out the language and whether or not it uses PCH.
416 const char *lang = 0;
417 bool usesPCH = false;
418
419 for (std::vector<const char*>::iterator I = argv.begin(), E = argv.end();
420 I != E; ++I) {
421 if (*I == 0)
422 continue;
423 if (strcmp(*I, "-x") == 0) {
424 if (I + 1 != E) {
425 lang = *(++I);
426 continue;
427 }
428 }
429 else if (strcmp(*I, "-include") == 0) {
430 if (I+1 != E) {
431 const char *arg = *(++I);
432 llvm::SmallString<512> pchName;
433 {
434 llvm::raw_svector_ostream os(pchName);
435 os << arg << ".pth";
436 }
437 pchName.push_back('\0');
438 struct stat stat_results;
439 if (stat(pchName.data(), &stat_results) == 0)
440 usesPCH = true;
441 continue;
442 }
443 }
444 }
445
Ted Kremenekcab334c2010-04-17 00:21:42 +0000446 os << "{ ";
447 os << "\"wall\": " << (EndTime.getWallTime() - StartTime.getWallTime());
448 os << ", \"numRes\": " << Results->NumResults;
449 os << ", \"diags\": " << Results->Diagnostics.size();
450 os << ", \"pch\": " << (usesPCH ? "true" : "false");
451 os << ", \"lang\": \"" << (lang ? lang : "<unknown>") << '"';
Ted Kremenek9e0cf092010-04-15 01:02:28 +0000452 const char *name = getlogin();
Ted Kremenekcab334c2010-04-17 00:21:42 +0000453 os << ", \"user\": \"" << (name ? name : "unknown") << '"';
454 os << ", \"clangVer\": \"" << getClangFullVersion() << '"';
455 os << " }";
Ted Kremenek9e0cf092010-04-15 01:02:28 +0000456
457 llvm::StringRef res = os.str();
458 if (res.size() > 0) {
459 do {
460 // Setup the UDP socket.
461 struct sockaddr_in servaddr;
462 bzero(&servaddr, sizeof(servaddr));
463 servaddr.sin_family = AF_INET;
464 servaddr.sin_port = htons(UDP_CODE_COMPLETION_LOGGER_PORT);
465 if (inet_pton(AF_INET, UDP_CODE_COMPLETION_LOGGER,
466 &servaddr.sin_addr) <= 0)
467 break;
468
469 int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
470 if (sockfd < 0)
471 break;
472
473 sendto(sockfd, res.data(), res.size(), 0,
474 (struct sockaddr *)&servaddr, sizeof(servaddr));
475 close(sockfd);
476 }
477 while (false);
478 }
479#endif
480#endif
Ted Kremenek0ec2cca2010-01-05 19:32:54 +0000481 return Results;
482}
483
484void clang_disposeCodeCompleteResults(CXCodeCompleteResults *ResultsIn) {
485 if (!ResultsIn)
486 return;
487
488 AllocatedCXCodeCompleteResults *Results
489 = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);
Ted Kremenek0ec2cca2010-01-05 19:32:54 +0000490 delete Results;
491}
492
Douglas Gregor33cdd812010-02-18 18:08:43 +0000493unsigned
494clang_codeCompleteGetNumDiagnostics(CXCodeCompleteResults *ResultsIn) {
495 AllocatedCXCodeCompleteResults *Results
496 = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);
497 if (!Results)
498 return 0;
499
500 return Results->Diagnostics.size();
501}
502
503CXDiagnostic
504clang_codeCompleteGetDiagnostic(CXCodeCompleteResults *ResultsIn,
505 unsigned Index) {
506 AllocatedCXCodeCompleteResults *Results
507 = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);
508 if (!Results || Index >= Results->Diagnostics.size())
509 return 0;
510
511 return new CXStoredDiagnostic(Results->Diagnostics[Index], Results->LangOpts);
512}
513
514
Ted Kremenek0ec2cca2010-01-05 19:32:54 +0000515} // end extern "C"