1 //===- 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"
16 #include "CIndexDiagnostic.h"
17 #include "clang/Basic/SourceManager.h"
18 #include "clang/Basic/FileManager.h"
19 #include "clang/Frontend/CompilerInstance.h"
20 #include "clang/Frontend/FrontendDiagnostic.h"
21 #include "clang/Sema/CodeCompleteConsumer.h"
22 #include "llvm/ADT/StringExtras.h"
23 #include "llvm/Support/MemoryBuffer.h"
24 #include "llvm/System/Program.h"
25 
26 #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 
37 using namespace clang;
38 using namespace clang::cxstring;
39 
40 extern "C" {
41 
42 enum CXCompletionChunkKind
43 clang_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;
82   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;
92   }
93 
94   // Should be unreachable, but let's be careful.
95   return CXCompletionChunk_Text;
96 }
97 
98 CXString clang_getCompletionChunkText(CXCompletionString completion_string,
99                                       unsigned chunk_number) {
100   CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
101   if (!CCStr || chunk_number >= CCStr->size())
102     return createCXString(0);
103 
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:
120   case CodeCompletionString::CK_Colon:
121   case CodeCompletionString::CK_SemiColon:
122   case CodeCompletionString::CK_Equal:
123   case CodeCompletionString::CK_HorizontalSpace:
124   case CodeCompletionString::CK_VerticalSpace:
125     return createCXString((*CCStr)[chunk_number].Text, false);
126 
127   case CodeCompletionString::CK_Optional:
128     // Note: treated as an empty text block.
129     return createCXString("");
130   }
131 
132   // Should be unreachable, but let's be careful.
133   return createCXString(0);
134 }
135 
136 
137 CXCompletionString
138 clang_getCompletionChunkCompletionString(CXCompletionString completion_string,
139                                          unsigned chunk_number) {
140   CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
141   if (!CCStr || chunk_number >= CCStr->size())
142     return 0;
143 
144   switch ((*CCStr)[chunk_number].Kind) {
145   case CodeCompletionString::CK_TypedText:
146   case CodeCompletionString::CK_Text:
147   case CodeCompletionString::CK_Placeholder:
148   case CodeCompletionString::CK_CurrentParameter:
149   case CodeCompletionString::CK_Informative:
150   case CodeCompletionString::CK_LeftParen:
151   case CodeCompletionString::CK_RightParen:
152   case CodeCompletionString::CK_LeftBracket:
153   case CodeCompletionString::CK_RightBracket:
154   case CodeCompletionString::CK_LeftBrace:
155   case CodeCompletionString::CK_RightBrace:
156   case CodeCompletionString::CK_LeftAngle:
157   case CodeCompletionString::CK_RightAngle:
158   case CodeCompletionString::CK_Comma:
159   case CodeCompletionString::CK_ResultType:
160   case CodeCompletionString::CK_Colon:
161   case CodeCompletionString::CK_SemiColon:
162   case CodeCompletionString::CK_Equal:
163   case CodeCompletionString::CK_HorizontalSpace:
164   case CodeCompletionString::CK_VerticalSpace:
165     return 0;
166 
167   case CodeCompletionString::CK_Optional:
168     // Note: treated as an empty text block.
169     return (*CCStr)[chunk_number].Optional;
170   }
171 
172   // Should be unreachable, but let's be careful.
173   return 0;
174 }
175 
176 unsigned clang_getNumCompletionChunks(CXCompletionString completion_string) {
177   CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
178   return CCStr? CCStr->size() : 0;
179 }
180 
181 static bool ReadUnsigned(const char *&Memory, const char *MemoryEnd,
182                          unsigned &Value) {
183   if (Memory + sizeof(unsigned) > MemoryEnd)
184     return true;
185 
186   memmove(&Value, Memory, sizeof(unsigned));
187   Memory += sizeof(unsigned);
188   return false;
189 }
190 
191 /// \brief The CXCodeCompleteResults structure we allocate internally;
192 /// the client only sees the initial CXCodeCompleteResults structure.
193 struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults {
194   AllocatedCXCodeCompleteResults();
195   ~AllocatedCXCodeCompleteResults();
196 
197   /// \brief The memory buffer from which we parsed the results. We
198   /// retain this buffer because the completion strings point into it.
199   llvm::MemoryBuffer *Buffer;
200 
201   /// \brief Diagnostics produced while performing code completion.
202   llvm::SmallVector<StoredDiagnostic, 8> Diagnostics;
203 
204   /// \brief Diag object
205   Diagnostic Diag;
206 
207   /// \brief Language options used to adjust source locations.
208   LangOptions LangOpts;
209 
210   /// \brief Source manager, used for diagnostics.
211   SourceManager SourceMgr;
212 
213   /// \brief File manager, used for diagnostics.
214   FileManager FileMgr;
215 
216   /// \brief Temporary files that should be removed once we have finished
217   /// with the code-completion results.
218   std::vector<llvm::sys::Path> TemporaryFiles;
219 };
220 
221 AllocatedCXCodeCompleteResults::AllocatedCXCodeCompleteResults()
222   : CXCodeCompleteResults(), Buffer(0), SourceMgr(Diag) { }
223 
224 AllocatedCXCodeCompleteResults::~AllocatedCXCodeCompleteResults() {
225   for (unsigned I = 0, N = NumResults; I != N; ++I)
226     delete (CodeCompletionString *)Results[I].CompletionString;
227   delete [] Results;
228   delete Buffer;
229 
230   for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I)
231     TemporaryFiles[I].eraseFromDisk();
232 }
233 
234 CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx,
235                                           const char *source_filename,
236                                           int num_command_line_args,
237                                           const char **command_line_args,
238                                           unsigned num_unsaved_files,
239                                           struct CXUnsavedFile *unsaved_files,
240                                           const char *complete_filename,
241                                           unsigned complete_line,
242                                           unsigned complete_column) {
243 #ifdef UDP_CODE_COMPLETION_LOGGER
244 #ifdef UDP_CODE_COMPLETION_LOGGER_PORT
245   const llvm::TimeRecord &StartTime =  llvm::TimeRecord::getCurrentTime();
246 #endif
247 #endif
248 
249   // The indexer, which is mainly used to determine where diagnostics go.
250   CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
251 
252   // Configure the diagnostics.
253   DiagnosticOptions DiagOpts;
254   llvm::IntrusiveRefCntPtr<Diagnostic> Diags;
255   Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0);
256 
257   // The set of temporary files that we've built.
258   std::vector<llvm::sys::Path> TemporaryFiles;
259 
260   // Build up the arguments for invoking 'clang'.
261   std::vector<const char *> argv;
262 
263   // First add the complete path to the 'clang' executable.
264   llvm::sys::Path ClangPath = CXXIdx->getClangPath();
265   argv.push_back(ClangPath.c_str());
266 
267   // Add the '-fsyntax-only' argument so that we only perform a basic
268   // syntax check of the code.
269   argv.push_back("-fsyntax-only");
270 
271   // Add the appropriate '-code-completion-at=file:line:column' argument
272   // to perform code completion, with an "-Xclang" preceding it.
273   std::string code_complete_at;
274   code_complete_at += complete_filename;
275   code_complete_at += ":";
276   code_complete_at += llvm::utostr(complete_line);
277   code_complete_at += ":";
278   code_complete_at += llvm::utostr(complete_column);
279   argv.push_back("-Xclang");
280   argv.push_back("-code-completion-at");
281   argv.push_back("-Xclang");
282   argv.push_back(code_complete_at.c_str());
283   argv.push_back("-Xclang");
284   argv.push_back("-no-code-completion-debug-printer");
285   argv.push_back("-Xclang");
286   argv.push_back("-code-completion-macros");
287   argv.push_back("-fdiagnostics-binary");
288 
289   // Remap any unsaved files to temporary files.
290   std::vector<std::string> RemapArgs;
291   if (RemapFiles(num_unsaved_files, unsaved_files, RemapArgs, TemporaryFiles))
292     return 0;
293 
294   // The pointers into the elements of RemapArgs are stable because we
295   // won't be adding anything to RemapArgs after this point.
296   for (unsigned i = 0, e = RemapArgs.size(); i != e; ++i)
297     argv.push_back(RemapArgs[i].c_str());
298 
299   // Add the source file name (FIXME: later, we'll want to build temporary
300   // file from the buffer, or just feed the source text via standard input).
301   if (source_filename)
302     argv.push_back(source_filename);
303 
304   // Process the compiler options, stripping off '-o', '-c', '-fsyntax-only'.
305   for (int i = 0; i < num_command_line_args; ++i)
306     if (const char *arg = command_line_args[i]) {
307       if (strcmp(arg, "-o") == 0) {
308         ++i; // Also skip the matching argument.
309         continue;
310       }
311       if (strcmp(arg, "-emit-ast") == 0 ||
312           strcmp(arg, "-c") == 0 ||
313           strcmp(arg, "-fsyntax-only") == 0) {
314         continue;
315       }
316 
317       // Keep the argument.
318       argv.push_back(arg);
319     }
320 
321   // Add the null terminator.
322   argv.push_back(NULL);
323 
324   // Generate a temporary name for the code-completion results file.
325   char tmpFile[L_tmpnam];
326   char *tmpFileName = tmpnam(tmpFile);
327   llvm::sys::Path ResultsFile(tmpFileName);
328   TemporaryFiles.push_back(ResultsFile);
329 
330   // Generate a temporary name for the diagnostics file.
331   char tmpFileResults[L_tmpnam];
332   char *tmpResultsFileName = tmpnam(tmpFileResults);
333   llvm::sys::Path DiagnosticsFile(tmpResultsFileName);
334   TemporaryFiles.push_back(DiagnosticsFile);
335 
336   // Invoke 'clang'.
337   llvm::sys::Path DevNull; // leave empty, causes redirection to /dev/null
338                            // on Unix or NUL (Windows).
339   std::string ErrMsg;
340   const llvm::sys::Path *Redirects[] = { &DevNull, &ResultsFile,
341                                          &DiagnosticsFile, 0 };
342   llvm::sys::Program::ExecuteAndWait(ClangPath, &argv[0], /* env */ NULL,
343                                      /* redirects */ &Redirects[0],
344                                      /* secondsToWait */ 0,
345                                      /* memoryLimits */ 0, &ErrMsg);
346 
347   if (!ErrMsg.empty()) {
348     std::string AllArgs;
349     for (std::vector<const char*>::iterator I = argv.begin(), E = argv.end();
350          I != E; ++I) {
351       AllArgs += ' ';
352       if (*I)
353         AllArgs += *I;
354     }
355 
356     Diags->Report(diag::err_fe_invoking) << AllArgs << ErrMsg;
357   }
358 
359   // Parse the resulting source file to find code-completion results.
360   using llvm::MemoryBuffer;
361   using llvm::StringRef;
362   AllocatedCXCodeCompleteResults *Results = new AllocatedCXCodeCompleteResults;
363   Results->Results = 0;
364   Results->NumResults = 0;
365   Results->Buffer = 0;
366   // FIXME: Set Results->LangOpts!
367   if (MemoryBuffer *F = MemoryBuffer::getFile(ResultsFile.c_str())) {
368     llvm::SmallVector<CXCompletionResult, 4> CompletionResults;
369     StringRef Buffer = F->getBuffer();
370     for (const char *Str = Buffer.data(), *StrEnd = Str + Buffer.size();
371          Str < StrEnd;) {
372       unsigned KindValue;
373       if (ReadUnsigned(Str, StrEnd, KindValue))
374         break;
375 
376       CodeCompletionString *CCStr
377         = CodeCompletionString::Deserialize(Str, StrEnd);
378       if (!CCStr)
379         continue;
380 
381       if (!CCStr->empty()) {
382         // Vend the code-completion result to the caller.
383         CXCompletionResult Result;
384         Result.CursorKind = (CXCursorKind)KindValue;
385         Result.CompletionString = CCStr;
386         CompletionResults.push_back(Result);
387       }
388     };
389 
390     // Allocate the results.
391     Results->Results = new CXCompletionResult [CompletionResults.size()];
392     Results->NumResults = CompletionResults.size();
393     memcpy(Results->Results, CompletionResults.data(),
394            CompletionResults.size() * sizeof(CXCompletionResult));
395     Results->Buffer = F;
396   }
397 
398   LoadSerializedDiagnostics(DiagnosticsFile, num_unsaved_files, unsaved_files,
399                             Results->FileMgr, Results->SourceMgr,
400                             Results->Diagnostics);
401 
402   // Make sure we delete temporary files when the code-completion results are
403   // destroyed.
404   Results->TemporaryFiles.swap(TemporaryFiles);
405 
406 #ifdef UDP_CODE_COMPLETION_LOGGER
407 #ifdef UDP_CODE_COMPLETION_LOGGER_PORT
408   const llvm::TimeRecord &EndTime =  llvm::TimeRecord::getCurrentTime();
409   llvm::SmallString<256> LogResult;
410   llvm::raw_svector_ostream os(LogResult);
411 
412   // Figure out the language and whether or not it uses PCH.
413   const char *lang = 0;
414   bool usesPCH = false;
415 
416   for (std::vector<const char*>::iterator I = argv.begin(), E = argv.end();
417        I != E; ++I) {
418     if (*I == 0)
419       continue;
420     if (strcmp(*I, "-x") == 0) {
421       if (I + 1 != E) {
422         lang = *(++I);
423         continue;
424       }
425     }
426     else if (strcmp(*I, "-include") == 0) {
427       if (I+1 != E) {
428         const char *arg = *(++I);
429         llvm::SmallString<512> pchName;
430         {
431           llvm::raw_svector_ostream os(pchName);
432           os << arg << ".pth";
433         }
434         pchName.push_back('\0');
435         struct stat stat_results;
436         if (stat(pchName.data(), &stat_results) == 0)
437           usesPCH = true;
438         continue;
439       }
440     }
441   }
442 
443   os << "{ ";
444   os << "\"wall\": " << (EndTime.getWallTime() - StartTime.getWallTime());
445   os << ", \"numRes\": " << Results->NumResults;
446   os << ", \"diags\": " << Results->Diagnostics.size();
447   os << ", \"pch\": " << (usesPCH ? "true" : "false");
448   os << ", \"lang\": \"" << (lang ? lang : "<unknown>") << '"';
449   const char *name = getlogin();
450   os << ", \"user\": \"" << (name ? name : "unknown") << '"';
451   os << ", \"clangVer\": \"" << getClangFullVersion() << '"';
452   os << " }";
453 
454   llvm::StringRef res = os.str();
455   if (res.size() > 0) {
456     do {
457       // Setup the UDP socket.
458       struct sockaddr_in servaddr;
459       bzero(&servaddr, sizeof(servaddr));
460       servaddr.sin_family = AF_INET;
461       servaddr.sin_port = htons(UDP_CODE_COMPLETION_LOGGER_PORT);
462       if (inet_pton(AF_INET, UDP_CODE_COMPLETION_LOGGER,
463                     &servaddr.sin_addr) <= 0)
464         break;
465 
466       int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
467       if (sockfd < 0)
468         break;
469 
470       sendto(sockfd, res.data(), res.size(), 0,
471              (struct sockaddr *)&servaddr, sizeof(servaddr));
472       close(sockfd);
473     }
474     while (false);
475   }
476 #endif
477 #endif
478   return Results;
479 }
480 
481 void clang_disposeCodeCompleteResults(CXCodeCompleteResults *ResultsIn) {
482   if (!ResultsIn)
483     return;
484 
485   AllocatedCXCodeCompleteResults *Results
486     = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);
487   delete Results;
488 }
489 
490 unsigned
491 clang_codeCompleteGetNumDiagnostics(CXCodeCompleteResults *ResultsIn) {
492   AllocatedCXCodeCompleteResults *Results
493     = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);
494   if (!Results)
495     return 0;
496 
497   return Results->Diagnostics.size();
498 }
499 
500 CXDiagnostic
501 clang_codeCompleteGetDiagnostic(CXCodeCompleteResults *ResultsIn,
502                                 unsigned Index) {
503   AllocatedCXCodeCompleteResults *Results
504     = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);
505   if (!Results || Index >= Results->Diagnostics.size())
506     return 0;
507 
508   return new CXStoredDiagnostic(Results->Diagnostics[Index], Results->LangOpts);
509 }
510 
511 
512 } // end extern "C"
513