CIndexCodeCompletion.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606
  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. #include "CIndexer.h"
  15. #include "CIndexDiagnostic.h"
  16. #include "clang/Basic/SourceManager.h"
  17. #include "clang/Basic/FileManager.h"
  18. #include "clang/Frontend/ASTUnit.h"
  19. #include "clang/Frontend/CompilerInstance.h"
  20. #include "clang/Frontend/FrontendDiagnostic.h"
  21. #include "clang/Sema/CodeCompleteConsumer.h"
  22. #include "llvm/ADT/SmallString.h"
  23. #include "llvm/ADT/StringExtras.h"
  24. #include "llvm/Support/CrashRecoveryContext.h"
  25. #include "llvm/Support/MemoryBuffer.h"
  26. #include "llvm/Support/Timer.h"
  27. #include "llvm/Support/raw_ostream.h"
  28. #include "llvm/System/Program.h"
  29. #include <cstdlib>
  30. #include <cstdio>
  31. #ifdef UDP_CODE_COMPLETION_LOGGER
  32. #include "clang/Basic/Version.h"
  33. #include <arpa/inet.h>
  34. #include <sys/socket.h>
  35. #include <sys/types.h>
  36. #include <unistd.h>
  37. #endif
  38. using namespace clang;
  39. using namespace clang::cxstring;
  40. namespace {
  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. CXAvailabilityKind Availability;
  47. public:
  48. CXStoredCodeCompletionString(unsigned Priority,
  49. CXAvailabilityKind Availability)
  50. : Priority(Priority), Availability(Availability) { }
  51. unsigned getPriority() const { return Priority; }
  52. CXAvailabilityKind getAvailability() const { return Availability; }
  53. };
  54. }
  55. extern "C" {
  56. enum CXCompletionChunkKind
  57. clang_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. switch ((*CCStr)[chunk_number].Kind) {
  64. case CodeCompletionString::CK_TypedText:
  65. return CXCompletionChunk_TypedText;
  66. case CodeCompletionString::CK_Text:
  67. return CXCompletionChunk_Text;
  68. case CodeCompletionString::CK_Optional:
  69. return CXCompletionChunk_Optional;
  70. case CodeCompletionString::CK_Placeholder:
  71. return CXCompletionChunk_Placeholder;
  72. case CodeCompletionString::CK_Informative:
  73. return CXCompletionChunk_Informative;
  74. case CodeCompletionString::CK_ResultType:
  75. return CXCompletionChunk_ResultType;
  76. case CodeCompletionString::CK_CurrentParameter:
  77. return CXCompletionChunk_CurrentParameter;
  78. case CodeCompletionString::CK_LeftParen:
  79. return CXCompletionChunk_LeftParen;
  80. case CodeCompletionString::CK_RightParen:
  81. return CXCompletionChunk_RightParen;
  82. case CodeCompletionString::CK_LeftBracket:
  83. return CXCompletionChunk_LeftBracket;
  84. case CodeCompletionString::CK_RightBracket:
  85. return CXCompletionChunk_RightBracket;
  86. case CodeCompletionString::CK_LeftBrace:
  87. return CXCompletionChunk_LeftBrace;
  88. case CodeCompletionString::CK_RightBrace:
  89. return CXCompletionChunk_RightBrace;
  90. case CodeCompletionString::CK_LeftAngle:
  91. return CXCompletionChunk_LeftAngle;
  92. case CodeCompletionString::CK_RightAngle:
  93. return CXCompletionChunk_RightAngle;
  94. case CodeCompletionString::CK_Comma:
  95. return CXCompletionChunk_Comma;
  96. case CodeCompletionString::CK_Colon:
  97. return CXCompletionChunk_Colon;
  98. case CodeCompletionString::CK_SemiColon:
  99. return CXCompletionChunk_SemiColon;
  100. case CodeCompletionString::CK_Equal:
  101. return CXCompletionChunk_Equal;
  102. case CodeCompletionString::CK_HorizontalSpace:
  103. return CXCompletionChunk_HorizontalSpace;
  104. case CodeCompletionString::CK_VerticalSpace:
  105. return CXCompletionChunk_VerticalSpace;
  106. }
  107. // Should be unreachable, but let's be careful.
  108. return CXCompletionChunk_Text;
  109. }
  110. CXString clang_getCompletionChunkText(CXCompletionString completion_string,
  111. unsigned chunk_number) {
  112. CXStoredCodeCompletionString *CCStr
  113. = (CXStoredCodeCompletionString *)completion_string;
  114. if (!CCStr || chunk_number >= CCStr->size())
  115. return createCXString(0);
  116. switch ((*CCStr)[chunk_number].Kind) {
  117. case CodeCompletionString::CK_TypedText:
  118. case CodeCompletionString::CK_Text:
  119. case CodeCompletionString::CK_Placeholder:
  120. case CodeCompletionString::CK_CurrentParameter:
  121. case CodeCompletionString::CK_Informative:
  122. case CodeCompletionString::CK_LeftParen:
  123. case CodeCompletionString::CK_RightParen:
  124. case CodeCompletionString::CK_LeftBracket:
  125. case CodeCompletionString::CK_RightBracket:
  126. case CodeCompletionString::CK_LeftBrace:
  127. case CodeCompletionString::CK_RightBrace:
  128. case CodeCompletionString::CK_LeftAngle:
  129. case CodeCompletionString::CK_RightAngle:
  130. case CodeCompletionString::CK_Comma:
  131. case CodeCompletionString::CK_ResultType:
  132. case CodeCompletionString::CK_Colon:
  133. case CodeCompletionString::CK_SemiColon:
  134. case CodeCompletionString::CK_Equal:
  135. case CodeCompletionString::CK_HorizontalSpace:
  136. case CodeCompletionString::CK_VerticalSpace:
  137. return createCXString((*CCStr)[chunk_number].Text, false);
  138. case CodeCompletionString::CK_Optional:
  139. // Note: treated as an empty text block.
  140. return createCXString("");
  141. }
  142. // Should be unreachable, but let's be careful.
  143. return createCXString(0);
  144. }
  145. CXCompletionString
  146. clang_getCompletionChunkCompletionString(CXCompletionString completion_string,
  147. unsigned chunk_number) {
  148. CXStoredCodeCompletionString *CCStr
  149. = (CXStoredCodeCompletionString *)completion_string;
  150. if (!CCStr || chunk_number >= CCStr->size())
  151. return 0;
  152. switch ((*CCStr)[chunk_number].Kind) {
  153. case CodeCompletionString::CK_TypedText:
  154. case CodeCompletionString::CK_Text:
  155. case CodeCompletionString::CK_Placeholder:
  156. case CodeCompletionString::CK_CurrentParameter:
  157. case CodeCompletionString::CK_Informative:
  158. case CodeCompletionString::CK_LeftParen:
  159. case CodeCompletionString::CK_RightParen:
  160. case CodeCompletionString::CK_LeftBracket:
  161. case CodeCompletionString::CK_RightBracket:
  162. case CodeCompletionString::CK_LeftBrace:
  163. case CodeCompletionString::CK_RightBrace:
  164. case CodeCompletionString::CK_LeftAngle:
  165. case CodeCompletionString::CK_RightAngle:
  166. case CodeCompletionString::CK_Comma:
  167. case CodeCompletionString::CK_ResultType:
  168. case CodeCompletionString::CK_Colon:
  169. case CodeCompletionString::CK_SemiColon:
  170. case CodeCompletionString::CK_Equal:
  171. case CodeCompletionString::CK_HorizontalSpace:
  172. case CodeCompletionString::CK_VerticalSpace:
  173. return 0;
  174. case CodeCompletionString::CK_Optional:
  175. // Note: treated as an empty text block.
  176. return (*CCStr)[chunk_number].Optional;
  177. }
  178. // Should be unreachable, but let's be careful.
  179. return 0;
  180. }
  181. unsigned clang_getNumCompletionChunks(CXCompletionString completion_string) {
  182. CXStoredCodeCompletionString *CCStr
  183. = (CXStoredCodeCompletionString *)completion_string;
  184. return CCStr? CCStr->size() : 0;
  185. }
  186. unsigned clang_getCompletionPriority(CXCompletionString completion_string) {
  187. CXStoredCodeCompletionString *CCStr
  188. = (CXStoredCodeCompletionString *)completion_string;
  189. return CCStr? CCStr->getPriority() : unsigned(CCP_Unlikely);
  190. }
  191. enum CXAvailabilityKind
  192. clang_getCompletionAvailability(CXCompletionString completion_string) {
  193. CXStoredCodeCompletionString *CCStr
  194. = (CXStoredCodeCompletionString *)completion_string;
  195. return CCStr? CCStr->getAvailability() : CXAvailability_Available;
  196. }
  197. /// \brief The CXCodeCompleteResults structure we allocate internally;
  198. /// the client only sees the initial CXCodeCompleteResults structure.
  199. struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults {
  200. AllocatedCXCodeCompleteResults();
  201. ~AllocatedCXCodeCompleteResults();
  202. /// \brief Diagnostics produced while performing code completion.
  203. llvm::SmallVector<StoredDiagnostic, 8> Diagnostics;
  204. /// \brief Diag object
  205. llvm::IntrusiveRefCntPtr<Diagnostic> Diag;
  206. /// \brief Language options used to adjust source locations.
  207. LangOptions LangOpts;
  208. /// \brief File manager, used for diagnostics.
  209. FileManager FileMgr;
  210. FileSystemOptions FileSystemOpts;
  211. /// \brief Source manager, used for diagnostics.
  212. SourceManager SourceMgr;
  213. /// \brief Temporary files that should be removed once we have finished
  214. /// with the code-completion results.
  215. std::vector<llvm::sys::Path> TemporaryFiles;
  216. /// \brief Temporary buffers that will be deleted once we have finished with the code-completion results.
  217. llvm::SmallVector<const llvm::MemoryBuffer *, 1> TemporaryBuffers;
  218. };
  219. AllocatedCXCodeCompleteResults::AllocatedCXCodeCompleteResults()
  220. : CXCodeCompleteResults(), Diag(new Diagnostic),
  221. SourceMgr(*Diag, FileMgr, FileSystemOpts) { }
  222. AllocatedCXCodeCompleteResults::~AllocatedCXCodeCompleteResults() {
  223. for (unsigned I = 0, N = NumResults; I != N; ++I)
  224. delete (CXStoredCodeCompletionString *)Results[I].CompletionString;
  225. delete [] Results;
  226. for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I)
  227. TemporaryFiles[I].eraseFromDisk();
  228. for (unsigned I = 0, N = TemporaryBuffers.size(); I != N; ++I)
  229. delete TemporaryBuffers[I];
  230. }
  231. } // end extern "C"
  232. namespace {
  233. class CaptureCompletionResults : public CodeCompleteConsumer {
  234. AllocatedCXCodeCompleteResults &AllocatedResults;
  235. llvm::SmallVector<CXCompletionResult, 16> StoredResults;
  236. public:
  237. explicit CaptureCompletionResults(AllocatedCXCodeCompleteResults &Results)
  238. : CodeCompleteConsumer(true, false, true, false),
  239. AllocatedResults(Results) { }
  240. ~CaptureCompletionResults() { Finish(); }
  241. virtual void ProcessCodeCompleteResults(Sema &S,
  242. CodeCompletionContext Context,
  243. CodeCompletionResult *Results,
  244. unsigned NumResults) {
  245. StoredResults.reserve(StoredResults.size() + NumResults);
  246. for (unsigned I = 0; I != NumResults; ++I) {
  247. CXStoredCodeCompletionString *StoredCompletion
  248. = new CXStoredCodeCompletionString(Results[I].Priority,
  249. Results[I].Availability);
  250. (void)Results[I].CreateCodeCompletionString(S, StoredCompletion);
  251. CXCompletionResult R;
  252. R.CursorKind = Results[I].CursorKind;
  253. R.CompletionString = StoredCompletion;
  254. StoredResults.push_back(R);
  255. }
  256. }
  257. virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
  258. OverloadCandidate *Candidates,
  259. unsigned NumCandidates) {
  260. StoredResults.reserve(StoredResults.size() + NumCandidates);
  261. for (unsigned I = 0; I != NumCandidates; ++I) {
  262. // FIXME: Set priority, availability appropriately.
  263. CXStoredCodeCompletionString *StoredCompletion
  264. = new CXStoredCodeCompletionString(1, CXAvailability_Available);
  265. (void)Candidates[I].CreateSignatureString(CurrentArg, S,
  266. StoredCompletion);
  267. CXCompletionResult R;
  268. R.CursorKind = CXCursor_NotImplemented;
  269. R.CompletionString = StoredCompletion;
  270. StoredResults.push_back(R);
  271. }
  272. }
  273. private:
  274. void Finish() {
  275. AllocatedResults.Results = new CXCompletionResult [StoredResults.size()];
  276. AllocatedResults.NumResults = StoredResults.size();
  277. std::memcpy(AllocatedResults.Results, StoredResults.data(),
  278. StoredResults.size() * sizeof(CXCompletionResult));
  279. StoredResults.clear();
  280. }
  281. };
  282. }
  283. extern "C" {
  284. struct CodeCompleteAtInfo {
  285. CXTranslationUnit TU;
  286. const char *complete_filename;
  287. unsigned complete_line;
  288. unsigned complete_column;
  289. struct CXUnsavedFile *unsaved_files;
  290. unsigned num_unsaved_files;
  291. unsigned options;
  292. CXCodeCompleteResults *result;
  293. };
  294. void clang_codeCompleteAt_Impl(void *UserData) {
  295. CodeCompleteAtInfo *CCAI = static_cast<CodeCompleteAtInfo*>(UserData);
  296. CXTranslationUnit TU = CCAI->TU;
  297. const char *complete_filename = CCAI->complete_filename;
  298. unsigned complete_line = CCAI->complete_line;
  299. unsigned complete_column = CCAI->complete_column;
  300. struct CXUnsavedFile *unsaved_files = CCAI->unsaved_files;
  301. unsigned num_unsaved_files = CCAI->num_unsaved_files;
  302. unsigned options = CCAI->options;
  303. CCAI->result = 0;
  304. #ifdef UDP_CODE_COMPLETION_LOGGER
  305. #ifdef UDP_CODE_COMPLETION_LOGGER_PORT
  306. const llvm::TimeRecord &StartTime = llvm::TimeRecord::getCurrentTime();
  307. #endif
  308. #endif
  309. bool EnableLogging = getenv("LIBCLANG_CODE_COMPLETION_LOGGING") != 0;
  310. ASTUnit *AST = static_cast<ASTUnit *>(TU);
  311. if (!AST)
  312. return;
  313. ASTUnit::ConcurrencyCheck Check(*AST);
  314. // Perform the remapping of source files.
  315. llvm::SmallVector<ASTUnit::RemappedFile, 4> RemappedFiles;
  316. for (unsigned I = 0; I != num_unsaved_files; ++I) {
  317. llvm::StringRef Data(unsaved_files[I].Contents, unsaved_files[I].Length);
  318. const llvm::MemoryBuffer *Buffer
  319. = llvm::MemoryBuffer::getMemBufferCopy(Data, unsaved_files[I].Filename);
  320. RemappedFiles.push_back(std::make_pair(unsaved_files[I].Filename,
  321. Buffer));
  322. }
  323. if (EnableLogging) {
  324. // FIXME: Add logging.
  325. }
  326. // Parse the resulting source file to find code-completion results.
  327. AllocatedCXCodeCompleteResults *Results = new AllocatedCXCodeCompleteResults;
  328. Results->Results = 0;
  329. Results->NumResults = 0;
  330. // Create a code-completion consumer to capture the results.
  331. CaptureCompletionResults Capture(*Results);
  332. // Perform completion.
  333. AST->CodeComplete(complete_filename, complete_line, complete_column,
  334. RemappedFiles.data(), RemappedFiles.size(),
  335. (options & CXCodeComplete_IncludeMacros),
  336. (options & CXCodeComplete_IncludeCodePatterns),
  337. Capture,
  338. *Results->Diag, Results->LangOpts, Results->SourceMgr,
  339. Results->FileMgr, Results->Diagnostics,
  340. Results->TemporaryBuffers);
  341. #ifdef UDP_CODE_COMPLETION_LOGGER
  342. #ifdef UDP_CODE_COMPLETION_LOGGER_PORT
  343. const llvm::TimeRecord &EndTime = llvm::TimeRecord::getCurrentTime();
  344. llvm::SmallString<256> LogResult;
  345. llvm::raw_svector_ostream os(LogResult);
  346. // Figure out the language and whether or not it uses PCH.
  347. const char *lang = 0;
  348. bool usesPCH = false;
  349. for (std::vector<const char*>::iterator I = argv.begin(), E = argv.end();
  350. I != E; ++I) {
  351. if (*I == 0)
  352. continue;
  353. if (strcmp(*I, "-x") == 0) {
  354. if (I + 1 != E) {
  355. lang = *(++I);
  356. continue;
  357. }
  358. }
  359. else if (strcmp(*I, "-include") == 0) {
  360. if (I+1 != E) {
  361. const char *arg = *(++I);
  362. llvm::SmallString<512> pchName;
  363. {
  364. llvm::raw_svector_ostream os(pchName);
  365. os << arg << ".pth";
  366. }
  367. pchName.push_back('\0');
  368. struct stat stat_results;
  369. if (stat(pchName.data(), &stat_results) == 0)
  370. usesPCH = true;
  371. continue;
  372. }
  373. }
  374. }
  375. os << "{ ";
  376. os << "\"wall\": " << (EndTime.getWallTime() - StartTime.getWallTime());
  377. os << ", \"numRes\": " << Results->NumResults;
  378. os << ", \"diags\": " << Results->Diagnostics.size();
  379. os << ", \"pch\": " << (usesPCH ? "true" : "false");
  380. os << ", \"lang\": \"" << (lang ? lang : "<unknown>") << '"';
  381. const char *name = getlogin();
  382. os << ", \"user\": \"" << (name ? name : "unknown") << '"';
  383. os << ", \"clangVer\": \"" << getClangFullVersion() << '"';
  384. os << " }";
  385. llvm::StringRef res = os.str();
  386. if (res.size() > 0) {
  387. do {
  388. // Setup the UDP socket.
  389. struct sockaddr_in servaddr;
  390. bzero(&servaddr, sizeof(servaddr));
  391. servaddr.sin_family = AF_INET;
  392. servaddr.sin_port = htons(UDP_CODE_COMPLETION_LOGGER_PORT);
  393. if (inet_pton(AF_INET, UDP_CODE_COMPLETION_LOGGER,
  394. &servaddr.sin_addr) <= 0)
  395. break;
  396. int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
  397. if (sockfd < 0)
  398. break;
  399. sendto(sockfd, res.data(), res.size(), 0,
  400. (struct sockaddr *)&servaddr, sizeof(servaddr));
  401. close(sockfd);
  402. }
  403. while (false);
  404. }
  405. #endif
  406. #endif
  407. CCAI->result = Results;
  408. }
  409. CXCodeCompleteResults *clang_codeCompleteAt(CXTranslationUnit TU,
  410. const char *complete_filename,
  411. unsigned complete_line,
  412. unsigned complete_column,
  413. struct CXUnsavedFile *unsaved_files,
  414. unsigned num_unsaved_files,
  415. unsigned options) {
  416. CodeCompleteAtInfo CCAI = { TU, complete_filename, complete_line,
  417. complete_column, unsaved_files, num_unsaved_files,
  418. options, 0 };
  419. llvm::CrashRecoveryContext CRC;
  420. if (!CRC.RunSafely(clang_codeCompleteAt_Impl, &CCAI)) {
  421. fprintf(stderr, "libclang: crash detected in code completion\n");
  422. static_cast<ASTUnit *>(TU)->setUnsafeToFree(true);
  423. return 0;
  424. }
  425. return CCAI.result;
  426. }
  427. unsigned clang_defaultCodeCompleteOptions(void) {
  428. return CXCodeComplete_IncludeMacros;
  429. }
  430. void clang_disposeCodeCompleteResults(CXCodeCompleteResults *ResultsIn) {
  431. if (!ResultsIn)
  432. return;
  433. AllocatedCXCodeCompleteResults *Results
  434. = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);
  435. delete Results;
  436. }
  437. unsigned
  438. clang_codeCompleteGetNumDiagnostics(CXCodeCompleteResults *ResultsIn) {
  439. AllocatedCXCodeCompleteResults *Results
  440. = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);
  441. if (!Results)
  442. return 0;
  443. return Results->Diagnostics.size();
  444. }
  445. CXDiagnostic
  446. clang_codeCompleteGetDiagnostic(CXCodeCompleteResults *ResultsIn,
  447. unsigned Index) {
  448. AllocatedCXCodeCompleteResults *Results
  449. = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);
  450. if (!Results || Index >= Results->Diagnostics.size())
  451. return 0;
  452. return new CXStoredDiagnostic(Results->Diagnostics[Index], Results->LangOpts);
  453. }
  454. } // end extern "C"
  455. /// \brief Simple utility function that appends a \p New string to the given
  456. /// \p Old string, using the \p Buffer for storage.
  457. ///
  458. /// \param Old The string to which we are appending. This parameter will be
  459. /// updated to reflect the complete string.
  460. ///
  461. ///
  462. /// \param New The string to append to \p Old.
  463. ///
  464. /// \param Buffer A buffer that stores the actual, concatenated string. It will
  465. /// be used if the old string is already-non-empty.
  466. static void AppendToString(llvm::StringRef &Old, llvm::StringRef New,
  467. llvm::SmallString<256> &Buffer) {
  468. if (Old.empty()) {
  469. Old = New;
  470. return;
  471. }
  472. if (Buffer.empty())
  473. Buffer.append(Old.begin(), Old.end());
  474. Buffer.append(New.begin(), New.end());
  475. Old = Buffer.str();
  476. }
  477. /// \brief Get the typed-text blocks from the given code-completion string
  478. /// and return them as a single string.
  479. ///
  480. /// \param String The code-completion string whose typed-text blocks will be
  481. /// concatenated.
  482. ///
  483. /// \param Buffer A buffer used for storage of the completed name.
  484. static llvm::StringRef GetTypedName(CodeCompletionString *String,
  485. llvm::SmallString<256> &Buffer) {
  486. llvm::StringRef Result;
  487. for (CodeCompletionString::iterator C = String->begin(), CEnd = String->end();
  488. C != CEnd; ++C) {
  489. if (C->Kind == CodeCompletionString::CK_TypedText)
  490. AppendToString(Result, C->Text, Buffer);
  491. }
  492. return Result;
  493. }
  494. namespace {
  495. struct OrderCompletionResults {
  496. bool operator()(const CXCompletionResult &XR,
  497. const CXCompletionResult &YR) const {
  498. CXStoredCodeCompletionString *X
  499. = (CXStoredCodeCompletionString *)XR.CompletionString;
  500. CXStoredCodeCompletionString *Y
  501. = (CXStoredCodeCompletionString *)YR.CompletionString;
  502. llvm::SmallString<256> XBuffer;
  503. llvm::StringRef XText = GetTypedName(X, XBuffer);
  504. llvm::SmallString<256> YBuffer;
  505. llvm::StringRef YText = GetTypedName(Y, YBuffer);
  506. if (XText.empty() || YText.empty())
  507. return !XText.empty();
  508. int result = XText.compare_lower(YText);
  509. if (result < 0)
  510. return true;
  511. if (result > 0)
  512. return false;
  513. result = XText.compare(YText);
  514. return result < 0;
  515. }
  516. };
  517. }
  518. extern "C" {
  519. void clang_sortCodeCompletionResults(CXCompletionResult *Results,
  520. unsigned NumResults) {
  521. std::stable_sort(Results, Results + NumResults, OrderCompletionResults());
  522. }
  523. }