CIndexCodeCompletion.cpp revision 12e131385e892e3723483a1081a89bcad29c8a84
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
37using namespace clang;
38using namespace clang::cxstring;
39
40namespace {
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
54extern "C" {
55
56enum CXCompletionChunkKind
57clang_getCompletionChunkKind(CXCompletionString completion_string,
58                             unsigned chunk_number) {
59  CXStoredCodeCompletionString *CCStr
60    = (CXStoredCodeCompletionString *)completion_string;
61  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;
97  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;
107  }
108
109  // Should be unreachable, but let's be careful.
110  return CXCompletionChunk_Text;
111}
112
113CXString clang_getCompletionChunkText(CXCompletionString completion_string,
114                                      unsigned chunk_number) {
115  CXStoredCodeCompletionString *CCStr
116    = (CXStoredCodeCompletionString *)completion_string;
117  if (!CCStr || chunk_number >= CCStr->size())
118    return createCXString(0);
119
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:
136  case CodeCompletionString::CK_Colon:
137  case CodeCompletionString::CK_SemiColon:
138  case CodeCompletionString::CK_Equal:
139  case CodeCompletionString::CK_HorizontalSpace:
140    return createCXString((*CCStr)[chunk_number].Text, false);
141
142  case CodeCompletionString::CK_VerticalSpace:
143    // FIXME: Temporary hack until we figure out how to handle vertical space.
144    return createCXString(" ");
145
146  case CodeCompletionString::CK_Optional:
147    // Note: treated as an empty text block.
148    return createCXString("");
149  }
150
151  // Should be unreachable, but let's be careful.
152  return createCXString(0);
153}
154
155
156CXCompletionString
157clang_getCompletionChunkCompletionString(CXCompletionString completion_string,
158                                         unsigned chunk_number) {
159  CXStoredCodeCompletionString *CCStr
160    = (CXStoredCodeCompletionString *)completion_string;
161  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:
180  case CodeCompletionString::CK_Colon:
181  case CodeCompletionString::CK_SemiColon:
182  case CodeCompletionString::CK_Equal:
183  case CodeCompletionString::CK_HorizontalSpace:
184  case CodeCompletionString::CK_VerticalSpace:
185    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) {
197  CXStoredCodeCompletionString *CCStr
198    = (CXStoredCodeCompletionString *)completion_string;
199  return CCStr? CCStr->size() : 0;
200}
201
202unsigned clang_getCompletionPriority(CXCompletionString completion_string) {
203  CXStoredCodeCompletionString *CCStr
204    = (CXStoredCodeCompletionString *)completion_string;
205  return CCStr? CCStr->getPriority() : CCP_Unlikely;
206}
207
208static 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 {
221  AllocatedCXCodeCompleteResults();
222  ~AllocatedCXCodeCompleteResults();
223
224  /// \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;
227
228  /// \brief Diagnostics produced while performing code completion.
229  llvm::SmallVector<StoredDiagnostic, 8> Diagnostics;
230
231  /// \brief Diag object
232  Diagnostic Diag;
233
234  /// \brief Language options used to adjust source locations.
235  LangOptions LangOpts;
236
237  /// \brief Source manager, used for diagnostics.
238  SourceManager SourceMgr;
239
240  /// \brief File manager, used for diagnostics.
241  FileManager FileMgr;
242
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;
246};
247
248AllocatedCXCodeCompleteResults::AllocatedCXCodeCompleteResults()
249  : CXCodeCompleteResults(), Buffer(0), SourceMgr(Diag) { }
250
251AllocatedCXCodeCompleteResults::~AllocatedCXCodeCompleteResults() {
252  for (unsigned I = 0, N = NumResults; I != N; ++I)
253    delete (CXStoredCodeCompletionString *)Results[I].CompletionString;
254  delete [] Results;
255  delete Buffer;
256
257  for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I)
258    TemporaryFiles[I].eraseFromDisk();
259}
260
261CXCodeCompleteResults *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,
269                                          unsigned complete_column) {
270#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
276  // The indexer, which is mainly used to determine where diagnostics go.
277  CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
278
279  // Configure the diagnostics.
280  DiagnosticOptions DiagOpts;
281  llvm::IntrusiveRefCntPtr<Diagnostic> Diags;
282  Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0);
283
284  // 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");
314  argv.push_back("-fdiagnostics-binary");
315
316  // Remap any unsaved files to temporary files.
317  std::vector<std::string> RemapArgs;
318  if (RemapFiles(num_unsaved_files, unsaved_files, RemapArgs, TemporaryFiles))
319    return 0;
320
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
351  // Generate a temporary name for the code-completion results file.
352  char tmpFile[L_tmpnam];
353  char *tmpFileName = tmpnam(tmpFile);
354  llvm::sys::Path ResultsFile(tmpFileName);
355  TemporaryFiles.push_back(ResultsFile);
356
357  // Generate a temporary name for the diagnostics file.
358  char tmpFileResults[L_tmpnam];
359  char *tmpResultsFileName = tmpnam(tmpFileResults);
360  llvm::sys::Path DiagnosticsFile(tmpResultsFileName);
361  TemporaryFiles.push_back(DiagnosticsFile);
362
363  // Invoke 'clang'.
364  llvm::sys::Path DevNull; // leave empty, causes redirection to /dev/null
365                           // on Unix or NUL (Windows).
366  std::string ErrMsg;
367  const llvm::sys::Path *Redirects[] = { &DevNull, &ResultsFile,
368                                         &DiagnosticsFile, 0 };
369  llvm::sys::Program::ExecuteAndWait(ClangPath, &argv[0], /* env */ NULL,
370                                     /* redirects */ &Redirects[0],
371                                     /* secondsToWait */ 0,
372                                     /* memoryLimits */ 0, &ErrMsg);
373
374  if (!ErrMsg.empty()) {
375    std::string AllArgs;
376    for (std::vector<const char*>::iterator I = argv.begin(), E = argv.end();
377         I != E; ++I) {
378      AllArgs += ' ';
379      if (*I)
380        AllArgs += *I;
381    }
382
383    Diags->Report(diag::err_fe_invoking) << AllArgs << ErrMsg;
384  }
385
386  // Parse the resulting source file to find code-completion results.
387  using llvm::MemoryBuffer;
388  using llvm::StringRef;
389  AllocatedCXCodeCompleteResults *Results = new AllocatedCXCodeCompleteResults;
390  Results->Results = 0;
391  Results->NumResults = 0;
392  Results->Buffer = 0;
393  // FIXME: Set Results->LangOpts!
394  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
403      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;
411        continue;
412      }
413
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.
424    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
431  LoadSerializedDiagnostics(DiagnosticsFile, num_unsaved_files, unsaved_files,
432                            Results->FileMgr, Results->SourceMgr,
433                            Results->Diagnostics);
434
435  // Make sure we delete temporary files when the code-completion results are
436  // destroyed.
437  Results->TemporaryFiles.swap(TemporaryFiles);
438
439#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
476  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>") << '"';
482  const char *name = getlogin();
483  os << ", \"user\": \"" << (name ? name : "unknown") << '"';
484  os << ", \"clangVer\": \"" << getClangFullVersion() << '"';
485  os << " }";
486
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
511  return Results;
512}
513
514void clang_disposeCodeCompleteResults(CXCodeCompleteResults *ResultsIn) {
515  if (!ResultsIn)
516    return;
517
518  AllocatedCXCodeCompleteResults *Results
519    = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);
520  delete Results;
521}
522
523unsigned
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
545} // end extern "C"
546