std::string tokenize_as_vimson(char const* const* args, size_t const argc) { CXIndex index = clang_createIndex(/*excludeDeclsFromPCH*/ 1, /*displayDiagnostics*/0); translation_unit = clang_parseTranslationUnit(index, file_name.c_str(), args, argc, NULL, 0, CXTranslationUnit_Incomplete); if (translation_unit == NULL) { clang_disposeIndex(index); return "{}"; } auto file_range = get_range_whole_file(); if (clang_Range_isNull(file_range)) { clang_disposeTranslationUnit(translation_unit); clang_disposeIndex(index); return "{}"; } CXToken *tokens_; unsigned int num_tokens; clang_tokenize(translation_unit, file_range, &tokens_, &num_tokens); std::vector<CXToken> tokens(tokens_, tokens_ + num_tokens); auto result = make_vimson_from_tokens(tokens); clang_disposeTokens(translation_unit, tokens_, num_tokens); clang_disposeTranslationUnit(translation_unit); clang_disposeIndex(index); return result; }
void ClangParser::finish() { if (p->tu) { delete[] p->cursors; clang_disposeTokens(p->tu, p->tokens, p->numTokens); clang_disposeTranslationUnit(p->tu); clang_disposeIndex(p->index); p->fileMapping.clear(); p->tokens = 0; p->numTokens = 0; p->cursors = 0; } for (uint i = 0; i < p->numFiles; i++) { free((void *)p->ufs[i].Filename); } delete[] p->ufs; delete[] p->sources; p->ufs = 0; p->sources = 0; p->numFiles = 0; p->tu = 0; }
void TearDown() override { clang_disposeTranslationUnit(ClangTU); clang_disposeIndex(Index); for (const std::string &Path : Files) llvm::sys::fs::remove(Path); llvm::sys::fs::remove(TestDir); }
void server_main() { struct sigaction sa; int sock; sock_path = get_socket_path(); sock = create_server_socket(sock_path); if (sock == -1) { fprintf(stderr, "Error! Failed to create a server socket: %s\n", sock_path->data); exit(1); } sa.sa_handler = handle_sigint; sa.sa_flags = 0; sigaction(SIGINT, &sa, 0); clang_index = clang_createIndex(0, 0); server_loop(sock); if (clang_tu) clang_disposeTranslationUnit(clang_tu); clang_disposeIndex(clang_index); close(sock); unlink(sock_path->data); str_free(sock_path); }
void DumpThread::run() { const auto key = mConnection->disconnected().connect([this](const std::shared_ptr<Connection> &) { abort(); }); CXIndex index = clang_createIndex(0, 0); CXTranslationUnit translationUnit = 0; String clangLine; RTags::parseTranslationUnit(mSource.sourceFile(), mSource.toCommandLine(Source::Default), translationUnit, index, 0, 0, CXTranslationUnit_DetailedPreprocessingRecord, &clangLine); if (!(mQueryFlags & QueryMessage::DumpCheckIncludes)) writeToConnetion(String::format<128>("Indexed: %s => %s", clangLine.constData(), translationUnit ? "success" : "failure")); if (translationUnit) { clang_visitChildren(clang_getTranslationUnitCursor(translationUnit), DumpThread::visitor, this); clang_disposeTranslationUnit(translationUnit); } clang_disposeIndex(index); mConnection->disconnected().disconnect(key); std::weak_ptr<Connection> conn = mConnection; if (mQueryFlags & QueryMessage::DumpCheckIncludes) { checkIncludes(); } EventLoop::mainEventLoop()->callLater([conn]() { if (auto c = conn.lock()) c->finish(); }); }
int main(int argc, char *argv[]) { CXIndex Index = clang_createIndex(0, 0); CXTranslationUnit TU; TU = clang_parseTranslationUnit(Index, 0, (const char**)argv, argc, 0, 0, CXTranslationUnit_None); CXCodeCompleteResults *results = clang_codeCompleteAt(TU, argv[1], 20, 7, NULL, 0, clang_defaultCodeCompleteOptions()); unsigned i; for(i =0; i<results->NumResults; i++) { printf("%s",results->Results[i].CompletionString); } // clang_disposeString(String); clang_disposeCodeCompleteResults(results); clang_disposeTranslationUnit(TU); clang_disposeIndex(Index); return 0; }
void ClangParser::finish() { static bool clangAssistedParsing = Config_getBool(CLANG_ASSISTED_PARSING); if (!clangAssistedParsing) return; if (p->tu) { //printf("ClangParser::finish()\n"); delete[] p->cursors; clang_disposeTokens(p->tu,p->tokens,p->numTokens); clang_disposeTranslationUnit(p->tu); clang_disposeIndex(p->index); p->fileMapping.clear(); p->tokens = 0; p->numTokens = 0; p->cursors = 0; } for (uint i=0;i<p->numFiles;i++) { free((void *)p->ufs[i].Filename); } delete[] p->ufs; delete[] p->sources; p->ufs = 0; p->sources = 0; p->numFiles = 0; p->tu = 0; }
/** * Параметр CXTranslationUnit_SkipFunctionBodies позволяет ускорить разбор * за счёт игнорирования парсером тел функций * Внутри функций обычно нет глобальных переменных */ void fileAction(const std::string &path) { CXTranslationUnit unit = clang_parseTranslationUnit( g_index, path.c_str(), nullptr, /* argv */ 0, /* argc */ nullptr, /* unsaved files */ 0, /* num unsaved files */ CXTranslationUnit_SkipFunctionBodies | CXTranslationUnit_DetailedPreprocessingRecord ); if (unit == nullptr) { std::cout << "Cannot parse: " << path << std::endl; return; } // Получаем курсор для всей единицы трансляции CXCursor cursorTU = clang_getTranslationUnitCursor(unit); clang_visitChildren(cursorTU, globalsFinder, NULL); clang_disposeTranslationUnit(unit); }
void TranslationUnit::removeTranslationUnitIfProjectPartWasChanged() const { if (projectPartIsOutdated()) { clang_disposeTranslationUnit(d->translationUnit); d->translationUnit = nullptr; } }
/* Update command line arguments passing to clang translation unit. Format of the coming CMDLINEARGS message is as follows: num_args: [#n_args#] arg1 arg2 ... (there should be n_args items here) */ void completion_doCmdlineArgs(completion_Session *session, FILE *fp) { int i_arg = 0; char arg[LINE_MAX]; /* destroy command line args, and we will rebuild it later */ completion_freeCmdlineArgs(session); /* get number of arguments */ fscanf(fp, "num_args:%d", &(session->num_args)); __skip_the_rest(fp); session->cmdline_args = (char**)calloc(sizeof(char*), session->num_args); /* rebuild command line arguments vector according to the message */ for ( ; i_arg < session->num_args; i_arg++) { /* fetch an argument from message */ fscanf(fp, "%s", arg); /* and add it to cmdline_args */ session->cmdline_args[i_arg] = (char*)calloc(sizeof(char), strlen(arg) + 1); strcpy(session->cmdline_args[i_arg], arg); } /* we have to rebuild our translation units to make these cmdline args changes take place */ clang_disposeTranslationUnit(session->cx_tu); completion_parseTranslationUnit(session); completion_reparseTranslationUnit(session); /* dump PCH for acceleration */ }
void TranslationUnitUpdater::removeTranslationUnitIfProjectPartWasChanged() { if (m_in.parseNeeded) { clang_disposeTranslationUnit(m_cxTranslationUnit); m_cxTranslationUnit = nullptr; } }
ReflectionParser::~ReflectionParser(void) { if (m_translationUnit) clang_disposeTranslationUnit( m_translationUnit ); if (m_index) clang_disposeIndex( m_index ); }
void TranslationUnit::Destroy() { unique_lock< mutex > lock( clang_access_mutex_ ); if ( clang_translation_unit_ ) { clang_disposeTranslationUnit( clang_translation_unit_ ); clang_translation_unit_ = nullptr; } }
void reparseTranslationUnit(CXTranslationUnit &unit, CXUnsavedFile *unsaved, int unsavedCount) { assert(unit); if (clang_reparseTranslationUnit(unit, 0, unsaved, clang_defaultReparseOptions(unit)) != 0) { clang_disposeTranslationUnit(unit); unit = 0; } }
Tokenizer::~Tokenizer() { CLangAutoLock lock(mCLangLock, __LINE__, this); if(mTransUnit) { clang_disposeTranslationUnit(mTransUnit); clang_disposeIndex(mContextIndex); } }
ClangIndexer::~ClangIndexer() { if (mLogFile) fclose(mLogFile); if (mClangUnit) clang_disposeTranslationUnit(mClangUnit); if (mIndex) clang_disposeIndex(mIndex); }
void translation_unit::reparse() { int err = clang_reparseTranslationUnit(tu, 0, 0, clang_defaultReparseOptions(tu)); if(err) { clang_disposeTranslationUnit(tu); tu = nullptr; throw error("unable to reparse tu"); } }
CXTranslationUnit ClangWorkerThread::DoCreateTU(CXIndex index, ClangThreadRequest* task, bool reparse) { wxFileName fn(task->GetFileName()); DoSetStatusMsg(wxString::Format(wxT("clang: parsing file %s..."), fn.GetFullName().c_str())); FileExtManager::FileType type = FileExtManager::GetType(task->GetFileName()); int argc(0); char** argv = MakeCommandLine(task, argc, type); for(int i = 0; i < argc; i++) { CL_DEBUG(wxT("Command Line Argument: %s"), wxString(argv[i], wxConvUTF8).c_str()); } std::string c_filename = task->GetFileName().mb_str(wxConvUTF8).data(); CL_DEBUG(wxT("Calling clang_parseTranslationUnit...")); // First time, need to create it unsigned flags; if(reparse) { flags = CXTranslationUnit_CacheCompletionResults | CXTranslationUnit_PrecompiledPreamble | CXTranslationUnit_Incomplete | CXTranslationUnit_DetailedPreprocessingRecord | CXTranslationUnit_CXXChainedPCH; } else { flags = CXTranslationUnit_Incomplete | #if HAS_LIBCLANG_BRIEFCOMMENTS CXTranslationUnit_SkipFunctionBodies | #endif CXTranslationUnit_DetailedPreprocessingRecord; } CXTranslationUnit TU = clang_parseTranslationUnit(index, c_filename.c_str(), argv, argc, NULL, 0, flags); CL_DEBUG(wxT("Calling clang_parseTranslationUnit... done")); ClangUtils::FreeArgv(argv, argc); DoSetStatusMsg(wxString::Format(wxT("clang: parsing file %s...done"), fn.GetFullName().c_str())); if(TU && reparse) { CL_DEBUG(wxT("Calling clang_reparseTranslationUnit...")); if(clang_reparseTranslationUnit(TU, 0, NULL, clang_defaultReparseOptions(TU)) == 0) { CL_DEBUG(wxT("Calling clang_reparseTranslationUnit... done")); return TU; } else { CL_DEBUG(wxT("An error occured during reparsing of the TU for file %s. TU: %p"), task->GetFileName().c_str(), (void*)TU); // The only thing that left to be done here, is to dispose the TU clang_disposeTranslationUnit(TU); PostEvent(wxEVT_CLANG_TU_CREATE_ERROR, task->GetFileName()); return NULL; } } return TU; }
int main(int argc, char * argv[]) { CXIndex index = clang_createIndex(0, 0); CXTranslationUnit txUnit = clang_parseTranslationUnit(index, 0, (const char * const *) argv, argc, 0, 0, CXTranslationUnit_None); CXCursor cur = clang_getTranslationUnitCursor(txUnit); clang_visitChildren(cur, visitor, NULL); clang_disposeTranslationUnit(txUnit); clang_disposeIndex(index); return 0; }
int main(int argc, const char* const argv[]){ if (argc < 2) { printf("Usage: %s header.h\n", argv[0]); printf("Standard clang arguments (-I, -D, etc.) may be used\n"); exit(1); } unsigned i; char filename[] = "ffigen.tmp.XXXXXX"; int fd = mkstemp(filename); FILE* file = fdopen(fd, "w"); fprintf(file, "#define _SIZE_T\n"); fprintf(file, "#define _PTRDIFF_T\n"); fprintf(file, "typedef __SIZE_TYPE__ size_t;\n"); fprintf(file, "typedef __PTRDIFF_TYPE__ ptrdiff_t;\n"); fprintf(file, "#include <%s>\n", argv[1]); fclose(file); int clang_argc = argc + 1; const char** clang_argv = malloc(sizeof(char*) * clang_argc); clang_argv[0] = "-x"; clang_argv[1] = "c"; clang_argv[2] = filename; for (i=3; i < clang_argc; i++) { clang_argv[i] = argv[i-1]; } CXIndex Index = clang_createIndex(0, 0); TU = clang_parseTranslationUnit(Index, 0, clang_argv, clang_argc, 0, 0, CXTranslationUnit_DetailedPreprocessingRecord); json_t* json = json_object(); clang_visitChildren(clang_getTranslationUnitCursor(TU), visit_program, (CXClientData)json); json_dumpf(json, stdout, JSON_INDENT(2) | JSON_PRESERVE_ORDER); printf("\n"); json_decref(json); for (i=0; i<clang_getNumDiagnostics(TU); i++) { putstring(clang_formatDiagnostic(clang_getDiagnostic(TU, i), clang_defaultDiagnosticDisplayOptions())); } clang_disposeTranslationUnit(TU); clang_disposeIndex(Index); free(clang_argv); unlink(filename); return 0; }
void TestCases::ClangTest() { #ifdef ENABLE_CLANG_COMPLETION std::cout << "checking to see if libclang/libclang.dll works" << std::endl; int argc = 1; char* argv[] = {"--version"}; CXIndex index = clang_createIndex(0, 0); CXTranslationUnit tu = clang_parseTranslationUnit(index, 0, argv, argc, 0, 0, CXTranslationUnit_None); clang_disposeTranslationUnit(tu); clang_disposeIndex(index); #endif }
/* When emacs buffer is killed, a SHUTDOWN message is sent automatically by a hook function to inform the completion server (this program) to terminate. */ void completion_doShutdown(completion_Session *session, FILE *fp) { (void) fp; /* this parameter is unused, the server will shutdown * directly without sending any messages to its client */ /* free clang parser infrastructures */ clang_disposeTranslationUnit(session->cx_tu); clang_disposeIndex(session->cx_index); /* free session properties */ completion_freeCmdlineArgs(session); free(session->src_buffer); exit(0); /* terminate completion process */ }
void DumpThread::run() { CXIndex index = clang_createIndex(0, 0); CXTranslationUnit translationUnit = 0; String clangLine; RTags::parseTranslationUnit(mSource.sourceFile(), mSource.toCommandLine(Source::Default), translationUnit, index, 0, 0, CXTranslationUnit_DetailedPreprocessingRecord, &clangLine); writeToConnetion(String::format<128>("Indexed: %s => %s", clangLine.constData(), translationUnit ? "success" : "failure")); if (translationUnit) { clang_visitChildren(clang_getTranslationUnitCursor(translationUnit), DumpThread::visitor, this); clang_disposeTranslationUnit(translationUnit); } clang_disposeIndex(index); EventLoop::mainEventLoop()->callLaterMove(std::bind((bool(Connection::*)(Message&&))&Connection::send, mConnection, std::placeholders::_1), FinishMessage()); }
int main(int argc, char* argv[]) { CXString version = clang_getClangVersion(); printf("%s\n", clang_getCString(version)); clang_disposeString(version); CXIndex index = clang_createIndex(1, 1); CXTranslationUnit tu = clang_createTranslationUnit(index, argv[1]); if (tu) { clang_visitChildren(clang_getTranslationUnitCursor(tu), visitor, argv[2]); clang_disposeTranslationUnit(tu); } clang_disposeIndex(index); return 0; }
void Tokenizer::parse(OovStringRef fileName, OovStringRef buffer, size_t bufLen, char const * const clang_args[], size_t num_clang_args) { CLangAutoLock lock(mCLangLock, __LINE__, this); try { if(!mSourceFile) { // The clang_defaultCodeCompleteOptions() options are not for the parse // function, they are for the clang_codeCompleteAt func. unsigned options = clang_defaultEditingTranslationUnitOptions(); // This is required to allow go to definition to work with #include. options |= CXTranslationUnit_DetailedPreprocessingRecord; mSourceFilename = fileName; mContextIndex = clang_createIndex(1, 1); mTransUnit = clang_parseTranslationUnit(mContextIndex, fileName, clang_args, static_cast<int>(num_clang_args), 0, 0, options); } else { static CXUnsavedFile file; file.Filename = mSourceFilename.c_str(); file.Contents = buffer; file.Length = bufLen; unsigned options = clang_defaultReparseOptions(mTransUnit); int stat = clang_reparseTranslationUnit(mTransUnit, 1, &file, options); if(stat != 0) { clang_disposeTranslationUnit(mTransUnit); mTransUnit = nullptr; } } mSourceFile = clang_getFile(mTransUnit, fileName); } catch(...) { DUMP_PARSE_INT("Tokenizer::parse - CRASHED", 0); } }
static int perform_test_load(CXIndex Idx, CXTranslationUnit TU, const char *filter, const char *prefix, CXCursorVisitor Visitor, PostVisitTU PV) { if (prefix) FileCheckPrefix = prefix; if (Visitor) { enum CXCursorKind K = CXCursor_NotImplemented; enum CXCursorKind *ck = &K; VisitorData Data; /* Perform some simple filtering. */ if (!strcmp(filter, "all") || !strcmp(filter, "local")) ck = NULL; else if (!strcmp(filter, "none")) K = (enum CXCursorKind) ~0; else if (!strcmp(filter, "category")) K = CXCursor_ObjCCategoryDecl; else if (!strcmp(filter, "interface")) K = CXCursor_ObjCInterfaceDecl; else if (!strcmp(filter, "protocol")) K = CXCursor_ObjCProtocolDecl; else if (!strcmp(filter, "function")) K = CXCursor_FunctionDecl; else if (!strcmp(filter, "typedef")) K = CXCursor_TypedefDecl; else if (!strcmp(filter, "scan-function")) Visitor = FunctionScanVisitor; else { fprintf(stderr, "Unknown filter for -test-load-tu: %s\n", filter); return 1; } Data.TU = TU; Data.Filter = ck; clang_visitChildren(clang_getTranslationUnitCursor(TU), Visitor, &Data); } if (PV) PV(TU); PrintDiagnostics(TU); clang_disposeTranslationUnit(TU); return 0; }
translation_unit& index::parse_translation_unit(const std::vector<std::string>& args, const std::vector<unsaved_file>& unsaved) { auto argv = convert_args(args); auto unsaved_files = convert_unsaved_files(unsaved); unsigned options = CXTranslationUnit_DetailedPreprocessingRecord | CXTranslationUnit_CacheCompletionResults; auto tu = clang_parseTranslationUnit(idx, nullptr, argv.data(), argv.size(), unsaved_files.data(), unsaved_files.size(), options); if(!tu) throw error("unable to parse tu"); // Have to reparse to cache completion results. int err = clang_reparseTranslationUnit(tu, unsaved_files.size(), unsaved_files.data(), clang_defaultReparseOptions(tu)); if(err) { clang_disposeTranslationUnit(tu); throw error("unable to reparse tu"); } tus.emplace_back(tu); return tus.back(); }
int main(int argc, char **argv) { if (argc < 2) return 1; CXIndex index = clang_createIndex(1, 1); const char * const *args = 0; if (argc > 2) args = (const char *const *)&argv[2]; CXTranslationUnit unit = clang_parseTranslationUnit(index, argv[1], args, argc - 2, 0, 0, clang_defaultEditingTranslationUnitOptions()); if (unit) { int indent = 0; clang_visitChildren(clang_getTranslationUnitCursor(unit), visit, &indent); const unsigned int diagnosticCount = clang_getNumDiagnostics(unit); unsigned int i; for (i=0; i<diagnosticCount; ++i) { CXDiagnostic diagnostic = clang_getDiagnostic(unit, i); const unsigned int diagnosticOptions = (CXDiagnostic_DisplaySourceLocation| CXDiagnostic_DisplayColumn| CXDiagnostic_DisplaySourceRanges| CXDiagnostic_DisplayOption| CXDiagnostic_DisplayCategoryId| CXDiagnostic_DisplayCategoryName); CXString diagnosticText = clang_formatDiagnostic(diagnostic, diagnosticOptions); const char *cstr = clang_getCString(diagnosticText); if (cstr) printf("%s\n", cstr); clang_disposeString(diagnosticText); } clang_disposeTranslationUnit(unit); } clang_disposeIndex(index); return 0; }
void CompletionThread::process(Request *request) { // if (!request->unsaved.isEmpty()) { // int line = request->location.line(); // int pos = 0; // while (line > 1) { // int p = request->unsaved.indexOf('\n', pos); // if (p == -1) { // pos = -1; // break; // } // pos = p + 1; // --line; // } // if (pos != -1) { // int end = request->unsaved.indexOf('\n', pos); // if (end == -1) // end = request->unsaved.size(); // error("Completing at %s:%d:%d line: [%s]\n", // request->location.path().constData(), // request->location.line(), // request->location.column(), // request->unsaved.mid(pos, end - pos).constData()); // } // } StopWatch sw; int parseTime = 0; int reparseTime = 0; int completeTime = 0; int processTime = 0; SourceFile *&cache = mCacheMap[request->source.fileId]; if (cache && cache->source != request->source) { delete cache; cache = 0; } if (!cache) { cache = new SourceFile; mCacheList.append(cache); while (mCacheMap.size() > mCacheSize) { SourceFile *c = mCacheList.removeFirst(); mCacheMap.remove(c->source.fileId); delete c; } } else { mCacheList.moveToEnd(cache); } const bool sendDebug = testLog(LogLevel::Debug); if (cache->translationUnit && cache->source != request->source) { clang_disposeTranslationUnit(cache->translationUnit); cache->translationUnit = 0; cache->source = request->source; } else if (!cache->translationUnit) { cache->source = request->source; } const Path sourceFile = request->source.sourceFile(); CXUnsavedFile unsaved = { sourceFile.constData(), request->unsaved.constData(), static_cast<unsigned long>(request->unsaved.size()) }; size_t hash = 0; uint64_t lastModified = 0; if (request->unsaved.size()) { std::hash<String> h; hash = h(request->unsaved); } else { lastModified = sourceFile.lastModifiedMs(); } const auto &options = Server::instance()->options(); if (!cache->translationUnit) { cache->completionsMap.clear(); cache->completionsList.deleteAll(); sw.restart(); Flags<CXTranslationUnit_Flags> flags = static_cast<CXTranslationUnit_Flags>(clang_defaultEditingTranslationUnitOptions()); flags |= CXTranslationUnit_PrecompiledPreamble; flags |= CXTranslationUnit_CacheCompletionResults; flags |= CXTranslationUnit_SkipFunctionBodies; for (const auto &inc : options.includePaths) { request->source.includePaths << inc; } request->source.defines << options.defines; String clangLine; RTags::parseTranslationUnit(sourceFile, request->source.toCommandLine(Source::Default|Source::ExcludeDefaultArguments), cache->translationUnit, mIndex, &unsaved, request->unsaved.size() ? 1 : 0, flags, &clangLine); // error() << "PARSING" << clangLine; parseTime = sw.restart(); if (cache->translationUnit) { RTags::reparseTranslationUnit(cache->translationUnit, &unsaved, request->unsaved.size() ? 1 : 0); } reparseTime = sw.elapsed(); if (!cache->translationUnit) return; cache->unsavedHash = hash; cache->lastModified = lastModified; } else if (cache->unsavedHash != hash || cache->lastModified != lastModified) { cache->completionsMap.clear(); cache->completionsList.deleteAll(); cache->unsavedHash = hash; cache->lastModified = lastModified; } else if (!(request->flags & Refresh)) { const auto it = cache->completionsMap.find(request->location); if (it != cache->completionsMap.end()) { cache->completionsList.moveToEnd(it->second); error("Found completions (%d) in cache %s:%d:%d", it->second->candidates.size(), sourceFile.constData(), request->location.line(), request->location.column()); printCompletions(it->second->candidates, request); return; } } sw.restart(); const unsigned int completionFlags = (CXCodeComplete_IncludeMacros|CXCodeComplete_IncludeCodePatterns); CXCodeCompleteResults *results = clang_codeCompleteAt(cache->translationUnit, sourceFile.constData(), request->location.line(), request->location.column(), &unsaved, unsaved.Length ? 1 : 0, completionFlags); completeTime = sw.restart(); if (results) { std::vector<Completions::Candidate> nodes; nodes.reserve(results->NumResults); int nodeCount = 0; Map<Token, int> tokens; if (!request->unsaved.isEmpty()) { tokens = Token::tokenize(request->unsaved.constData(), request->unsaved.size()); // for (Map<Token, int>::const_iterator it = tokens.begin(); it != tokens.end(); ++it) { // error() << String(it->first.data, it->first.length) << it->second; // } } for (unsigned int i = 0; i < results->NumResults; ++i) { const CXCursorKind kind = results->Results[i].CursorKind; if (!(options.options & Server::CompletionsNoFilter) && kind == CXCursor_Destructor) continue; const CXCompletionString &string = results->Results[i].CompletionString; const CXAvailabilityKind availabilityKind = clang_getCompletionAvailability(string); if (!(options.options & Server::CompletionsNoFilter) && availabilityKind != CXAvailability_Available) continue; const int priority = clang_getCompletionPriority(string); if (size_t(nodeCount) == nodes.size()) nodes.emplace_back(); Completions::Candidate &node = nodes.back(); node.cursorKind = kind; node.priority = priority; node.signature.reserve(256); const int chunkCount = clang_getNumCompletionChunks(string); bool ok = true; for (int j=0; j<chunkCount; ++j) { const CXCompletionChunkKind chunkKind = clang_getCompletionChunkKind(string, j); if (chunkKind == CXCompletionChunk_TypedText) { node.completion = RTags::eatString(clang_getCompletionChunkText(string, j)); if (node.completion.size() > 8 && node.completion.startsWith("operator") && !isPartOfSymbol(node.completion.at(8))) { ok = false; break; } node.signature.append(node.completion); } else { node.signature.append(RTags::eatString(clang_getCompletionChunkText(string, j))); if (chunkKind == CXCompletionChunk_ResultType) node.signature.append(' '); } } if (ok) { int ws = node.completion.size() - 1; while (ws >= 0 && isspace(node.completion.at(ws))) --ws; if (ws >= 0) { node.completion.truncate(ws + 1); node.signature.replace("\n", ""); node.distance = tokens.value(Token(node.completion.constData(), node.completion.size()), -1); if (sendDebug) debug() << node.signature << node.priority << kind << node.distance << clang_getCompletionAvailability(string); ++nodeCount; continue; } } node.completion.clear(); node.signature.clear(); } if (nodeCount) { // Sort pointers instead of shuffling candidates around std::vector<Completions::Candidate*> nodesPtr; nodesPtr.reserve(nodeCount); for (auto& n : nodes) nodesPtr.push_back(&n); std::sort(nodesPtr.begin(), nodesPtr.end(), compareCompletionCandidates); Completions *&c = cache->completionsMap[request->location]; if (c) { cache->completionsList.moveToEnd(c); } else { enum { MaxCompletionCache = 10 }; // ### configurable? c = new Completions(request->location); cache->completionsList.append(c); while (cache->completionsMap.size() > MaxCompletionCache) { Completions *cc = cache->completionsList.takeFirst(); cache->completionsMap.remove(cc->location); delete cc; } } c->candidates.resize(nodeCount); for (int i=0; i<nodeCount; ++i) c->candidates[i] = std::move(*nodesPtr[i]); printCompletions(c->candidates, request); processTime = sw.elapsed(); warning("Processed %s, parse %d/%d, complete %d, process %d => %d completions (unsaved %d)", sourceFile.constData(), parseTime, reparseTime, completeTime, processTime, nodeCount, request->unsaved.size()); } else { printCompletions(List<Completions::Candidate>(), request); error() << "No completion results available" << request->location << results->NumResults; } clang_disposeCodeCompleteResults(results); } }
void IndexerJob::execute() { if (isAborted()) return; mTimer.start(); mData.reset(new IndexData); if (mType == Dump) { assert(id() != -1); if (shared_ptr<Project> p = project()) { for (int i=0; i<mSourceInformation.builds.size(); ++i) { parse(i); if (mUnits.at(i).second) { DumpUserData u = { 0, this, !(queryFlags() & QueryMessage::NoContext) }; clang_visitChildren(clang_getTranslationUnitCursor(mUnits.at(i).second), IndexerJob::dumpVisitor, &u); } } } } else { { MutexLocker lock(&mMutex); mStarted = true; } int errorCount = 0; int unitCount = 0; const int buildCount = mSourceInformation.builds.size(); for (int i=0; i<buildCount; ++i) { if (!parse(i)) { goto end; } if (mUnits.at(i).second) ++unitCount; } mParseTime = time(0); for (int i=0; i<buildCount; ++i) { int err = 0; if (!visit(i) || !diagnose(i, &err)) goto end; errorCount += err; } { mData->message += mSourceInformation.sourceFile.toTilde(); if (buildCount > 1) mData->message += String::format<16>(" (%d builds)", buildCount); if (!unitCount) { mData->message += " error"; } else if (unitCount != buildCount) { mData->message += String::format<16>(" (%d errors, %d ok)", buildCount - unitCount, unitCount); } mData->message += String::format<16>(" in %sms. ", String::number(mTimer.elapsed()).constData()); if (unitCount) { mData->message += String::format<1024>("(%d syms, %d symNames, %d refs, %d deps, %d files)", mData->symbols.size(), mData->symbolNames.size(), mData->references.size(), mData->dependencies.size(), mVisitedFiles.size()); } else if (mData->dependencies.size()) { mData->message += String::format<16>("(%d deps)", mData->dependencies.size()); } if (mType == Dirty) mData->message += " (dirty)"; } end: shared_ptr<Project> p = project(); if (p) { shared_ptr<IndexerJob> job = static_pointer_cast<IndexerJob>(shared_from_this()); p->onJobFinished(job); } } for (int i=0; i<mUnits.size(); ++i) { if (mUnits.at(i).first) clang_disposeIndex(mUnits.at(i).first); if (mUnits.at(i).second) clang_disposeTranslationUnit(mUnits.at(i).second); } mUnits.clear(); }