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; } }
bool CodeFile::ReparseTranslationUnit(const std::string& code) { if (!translationUnit) return false; CXUnsavedFile file; file.Filename = path.c_str(); file.Contents = code.c_str(); file.Length = code.size(); return clang_reparseTranslationUnit(translationUnit, 1, &file, clang_defaultReparseOptions(translationUnit)) == 0; }
void TranslationUnit::reparseTranslationUnit() const { clang_reparseTranslationUnit(d->translationUnit, unsavedFiles().count(), unsavedFiles().cxUnsavedFiles(), clang_defaultReparseOptions(d->translationUnit)); d->needsToBeReparsed = false; }
bool ReparseTU(unsigned num_unsaved_files, CXUnsavedFile* unsaved_files) { if (clang_reparseTranslationUnit(ClangTU, num_unsaved_files, unsaved_files, clang_defaultReparseOptions(ClangTU))) { DEBUG(llvm::dbgs() << "Reparse failed\n"); return false; } DisplayDiagnostics(); return true; }
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; }
void TranslationUnit::reparse(const clang::unsaved_files_list& unsaved_files) { auto files = unsaved_files.get(); auto result = clang_reparseTranslationUnit( m_unit , files.size() , files.data() , clang_defaultReparseOptions(m_unit) ); if (result) throw Exception::ReparseFailure("It seems preparsed file is invalid"); }
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); } }
void TranslationUnitUpdater::reparse() { UnsavedFilesShallowArguments unsaved = m_in.unsavedFiles.shallowArguments(); m_reparseErrorCode = clang_reparseTranslationUnit( m_cxTranslationUnit, unsaved.count(), unsaved.data(), clang_defaultReparseOptions(m_cxTranslationUnit)); if (reparseWasSuccessful()) { updateIncludeFilePaths(); m_out.reparseTimePoint = Clock::now(); m_out.needsToBeReparsedChangeTimePoint = m_in.needsToBeReparsedChangeTimePoint; } else { qWarning() << "Reparsing" << m_in.filePath << "failed:" << m_reparseErrorCode; m_out.hasParseOrReparseFailed = true; } }
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(); }
void ClangWorkerThread::ProcessRequest(ThreadRequest* request) { // Send start event PostEvent(wxEVT_CLANG_PCH_CACHE_STARTED, ""); ClangThreadRequest* task = dynamic_cast<ClangThreadRequest*>(request); wxASSERT_MSG(task, "ClangWorkerThread: NULL task"); { // A bit of optimization wxCriticalSectionLocker locker(m_criticalSection); if(task->GetContext() == CTX_CachePCH && m_cache.Contains(task->GetFileName())) { // Nothing to be done here PostEvent(wxEVT_CLANG_PCH_CACHE_ENDED, task->GetFileName()); return; } } CL_DEBUG(wxT("==========> [ ClangPchMakerThread ] ProcessRequest started: %s"), task->GetFileName().c_str()); CL_DEBUG(wxT("ClangWorkerThread:: processing request %d"), (int)task->GetContext()); ClangCacheEntry cacheEntry = findEntry(task->GetFileName()); CXTranslationUnit TU = cacheEntry.TU; CL_DEBUG(wxT("ClangWorkerThread:: found cached TU: %p"), (void*)TU); bool reparseRequired = true; if(!TU) { // First time creating the TU TU = DoCreateTU(task->GetIndex(), task, true); reparseRequired = false; cacheEntry.lastReparse = time(NULL); cacheEntry.TU = TU; cacheEntry.sourceFile = task->GetFileName(); } if(!TU) { CL_DEBUG(wxT("Failed to parse Translation UNIT...")); PostEvent(wxEVT_CLANG_TU_CREATE_ERROR, task->GetFileName()); return; } if(reparseRequired && task->GetContext() == ::CTX_ReparseTU) { DoSetStatusMsg(wxString::Format(wxT("clang: re-parsing file %s..."), task->GetFileName().c_str())); // We need to reparse the TU CL_DEBUG(wxT("Calling clang_reparseTranslationUnit... [CTX_ReparseTU]")); if(clang_reparseTranslationUnit(TU, 0, NULL, clang_defaultReparseOptions(TU)) == 0) { CL_DEBUG(wxT("Calling clang_reparseTranslationUnit... done [CTX_ReparseTU]")); cacheEntry.lastReparse = time(NULL); } 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; } } // Construct a cache-returner class // which makes sure that the TU is cached // when we leave the current scope CacheReturner cr(this, cacheEntry); // Prepare the 'End' event wxCommandEvent eEnd(wxEVT_CLANG_PCH_CACHE_ENDED); ClangThreadReply* reply = new ClangThreadReply; reply->context = task->GetContext(); reply->filterWord = task->GetFilterWord(); reply->filename = task->GetFileName().c_str(); reply->results = NULL; wxFileName realFileName(reply->filename); if(realFileName.GetFullName().StartsWith(CODELITE_CLANG_FILE_PREFIX)) { realFileName.SetFullName(realFileName.GetFullName().Mid(strlen(CODELITE_CLANG_FILE_PREFIX))); } reply->filename = realFileName.GetFullPath(); if(task->GetContext() == CTX_CodeCompletion || task->GetContext() == CTX_WordCompletion || task->GetContext() == CTX_Calltip) { CL_DEBUG(wxT("Calling clang_codeCompleteAt...")); ClangThreadRequest::List_t usList = task->GetModifiedBuffers(); usList.push_back(std::make_pair(task->GetFileName(), task->GetDirtyBuffer())); ClangUnsavedFiles usf(usList); CL_DEBUG(wxT("Location: %s:%u:%u"), task->GetFileName().c_str(), task->GetLine(), task->GetColumn()); reply->results = clang_codeCompleteAt(TU, cstr(task->GetFileName()), task->GetLine(), task->GetColumn(), usf.GetUnsavedFiles(), usf.GetCount(), clang_defaultCodeCompleteOptions() #if HAS_LIBCLANG_BRIEFCOMMENTS | CXCodeComplete_IncludeBriefComments #endif ); cacheEntry.lastReparse = time(NULL); CL_DEBUG(wxT("Calling clang_codeCompleteAt... done")); wxString displayTip; bool hasErrors(false); if(reply->results) { unsigned maxErrorToDisplay = 10; std::set<wxString> errorMessages; unsigned errorCount = clang_codeCompleteGetNumDiagnostics(reply->results); // Collect all errors / fatal errors and report them back to user for(unsigned i = 0; i < errorCount; i++) { CXDiagnostic diag = clang_codeCompleteGetDiagnostic(reply->results, i); CXDiagnosticSeverity severity = clang_getDiagnosticSeverity(diag); if(!hasErrors) { hasErrors = (severity == CXDiagnostic_Error || severity == CXDiagnostic_Fatal); } if(severity == CXDiagnostic_Error || severity == CXDiagnostic_Fatal || severity == CXDiagnostic_Note) { CXString diagStr = clang_getDiagnosticSpelling(diag); wxString wxDiagString = wxString(clang_getCString(diagStr), wxConvUTF8); // Collect up to 10 error messages // and dont collect the same error twice if(errorMessages.find(wxDiagString) == errorMessages.end() && errorMessages.size() <= maxErrorToDisplay) { errorMessages.insert(wxDiagString); displayTip << wxDiagString.c_str() << wxT("\n"); } clang_disposeString(diagStr); } clang_disposeDiagnostic(diag); } CL_DEBUG(wxT("Found %u matches"), reply->results->NumResults); ClangUtils::printCompletionDiagnostics(reply->results); } if(!displayTip.IsEmpty() && hasErrors) { // Send back the error messages reply->errorMessage << "clang: " << displayTip; reply->errorMessage.RemoveLast(); // Free the results clang_disposeCodeCompleteResults(reply->results); reply->results = NULL; } // Send the event eEnd.SetClientData(reply); EventNotifier::Get()->AddPendingEvent(eEnd); } else if(task->GetContext() == CTX_GotoDecl || task->GetContext() == CTX_GotoImpl) { // Check to see if the file was modified since it was last reparsed // If it does, we need to re-parse it again wxFileName fnSource(cacheEntry.sourceFile); time_t fileModificationTime = fnSource.GetModificationTime().GetTicks(); time_t lastReparseTime = cacheEntry.lastReparse; if(fileModificationTime > lastReparseTime) { // The file needs to be re-parsed DoSetStatusMsg(wxString::Format(wxT("clang: re-parsing file %s...\n"), cacheEntry.sourceFile)); // Try reparsing the TU ClangThreadRequest::List_t usList = task->GetModifiedBuffers(); usList.push_back(std::make_pair(task->GetFileName(), task->GetDirtyBuffer())); ClangUnsavedFiles usf(usList); if(clang_reparseTranslationUnit( TU, usf.GetCount(), usf.GetUnsavedFiles(), clang_defaultReparseOptions(TU)) != 0) { // Failed to reparse cr.SetCancelled(true); // cancel the re-caching of the TU DoSetStatusMsg( wxString::Format("clang: clang_reparseTranslationUnit '%s' failed\n", cacheEntry.sourceFile)); clang_disposeTranslationUnit(TU); wxDELETE(reply); PostEvent(wxEVT_CLANG_TU_CREATE_ERROR, task->GetFileName()); return; } DoSetStatusMsg( wxString::Format("clang: clang_reparseTranslationUnit '%s' - done\n", cacheEntry.sourceFile)); // Update the 'lastReparse' field cacheEntry.lastReparse = time(NULL); } bool success = DoGotoDefinition(TU, task, reply); if(success) { eEnd.SetClientData(reply); EventNotifier::Get()->AddPendingEvent(eEnd); } else { DoSetStatusMsg(wxT("clang: no matches were found")); CL_DEBUG(wxT("Clang Goto Decl/Impl: could not find a cursor matching for position %s:%d:%d"), task->GetFileName().c_str(), (int)task->GetLine(), (int)task->GetColumn()); // Failed, delete the 'reply' allocatd earlier wxDELETE(reply); PostEvent(wxEVT_CLANG_TU_CREATE_ERROR, task->GetFileName()); } } else { wxDELETE(reply); PostEvent(wxEVT_CLANG_PCH_CACHE_ENDED, task->GetFileName()); } }
CXTranslationUnit TUManager::parse(const std::string & filename, const std::vector<std::string> & flags) { CXTranslationUnit tu = translationUnits_[filename]; if (! tu) { // FIXME: needed ? // Note: the -cc1 argument indicates the compiler front-end, and // not the driver, should be run. The compiler front-end has // several additional Clang specific features which are not // exposed through the GCC compatible driver interface. // from: http://clang.llvm.org/get_started.html // const_cast<std::vector<std::string> &>(flags).push_back("-cc1"); std::size_t nbArgs = flags.size(); const char **argv = 0; if (nbArgs > 0) { argv = new const char *[nbArgs + 1]; argv[nbArgs] = 0; for (std::size_t i = 0; i < nbArgs; ++i) argv[i] = flags[i].c_str(); } tu = clang_parseTranslationUnit(index_, filename.c_str(), argv, nbArgs, 0, 0, clang_defaultEditingTranslationUnitOptions() | CXTranslationUnit_PrecompiledPreamble | CXTranslationUnit_CacheCompletionResults); delete [] argv; translationUnits_[filename] = tu; } if (! tu) { std::clog << "parsing \"" << filename << "\" failed." << std::endl; return 0; } // NOTE: Even at the first time the translation unit is reparsed, // because without this the completion is erroneous. // From the clang mailing list: // From: Douglas Gregor <*****@*****.**> // Subject: Re: Clang indexing library performance // Newsgroups: gmane.comp.compilers.clang.devel // ... // You want to use the "default editing options" when parsing the // translation unit // clang_defaultEditingTranslationUnitOptions() // and then reparse at least once. That will enable the various // code-completion optimizations that should bring this time down // significantly. if (clang_reparseTranslationUnit(tu, 0, 0, clang_defaultReparseOptions(tu))) { // a 'fatal' error occur (even a diagnostic is impossible) clang_disposeTranslationUnit(tu); translationUnits_[filename] = 0; } return tu; }