示例#1
0
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;
    }
}
示例#2
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;
}
示例#3
0
void TranslationUnit::reparseTranslationUnit() const
{
    clang_reparseTranslationUnit(d->translationUnit,
                                 unsavedFiles().count(),
                                 unsavedFiles().cxUnsavedFiles(),
                                 clang_defaultReparseOptions(d->translationUnit));

    d->needsToBeReparsed = false;
}
示例#4
0
 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;
 }
示例#5
0
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");
}
示例#8
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);
        }
    }
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;
    }
}
示例#10
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();
}
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());
    }
}
示例#12
0
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;
}