Exemple #1
0
int main(int argc, const char* argv[]) {
    if (argc < 4) {
        std::cerr << "Usage:\n"
            << "    " << argv[0] << " <dbFilename> <indexFilename> [<options>] <sourceFilename>\n";
        return 1;
    }

    const char* dbFilename = argv[1];
    const char* indexFilename = argv[2];
    const char* sourceFilename = argv[argc-1];

    // Set up the clang translation unit
    CXIndex cxindex = clang_createIndex(0, 0);
    CXTranslationUnit tu = clang_parseTranslationUnit(
        cxindex, 0,
        argv + 3, argc - 3, // Skip over dbFilename and indexFilename
        0, 0,
        CXTranslationUnit_None);

    // Print any errors or warnings
    int n = clang_getNumDiagnostics(tu);
    if (n > 0) {
        int nErrors = 0;
        for (unsigned i = 0; i != n; ++i) {
            CXDiagnostic diag = clang_getDiagnostic(tu, i);
            CXString string = clang_formatDiagnostic(diag, clang_defaultDiagnosticDisplayOptions());
            fprintf(stderr, "%s\n", clang_getCString(string));
            if (clang_getDiagnosticSeverity(diag) == CXDiagnostic_Error
                    || clang_getDiagnosticSeverity(diag) == CXDiagnostic_Fatal)
                nErrors++;
        }
    }

    // Create the index
    EverythingIndexer visitor(sourceFilename);
    clang_visitChildren(
            clang_getTranslationUnitCursor(tu),
            &visitorFunction,
            &visitor);
    ClicIndex& index = visitor.usrToReferences;

    // OK, now write the index to a compressed file
    std::ofstream fout(indexFilename);
    boost::iostreams::filtering_stream<boost::iostreams::output> zout;
    zout.push(boost::iostreams::gzip_compressor());
    zout.push(fout);
    printIndex(zout, index);

    // Now open the database and add the index to it
    ClicDb db(dbFilename);

    BOOST_FOREACH(const ClicIndex::value_type& it, index) {
        const std::string& usr = it.first;
        db.addMultiple(usr, it.second);
    }

    return 0;
}
Diagnostic DiagnosticWrapToDiagnostic( DiagnosticWrap diagnostic_wrap ) {
  Diagnostic diagnostic;

  if ( !diagnostic_wrap )
    return diagnostic;

  diagnostic.kind_ = DiagnosticSeverityToType(
                       clang_getDiagnosticSeverity( diagnostic_wrap.get() ) );

  // If this is an "ignored" diagnostic, there's no point in continuing since we
  // won't display those to the user
  if ( diagnostic.kind_ == 'I' )
    return diagnostic;

  CXSourceLocation location = clang_getDiagnosticLocation( diagnostic_wrap.get() );
  CXFile file;
  uint unused_offset;
  clang_getSpellingLocation( location,
                             &file,
                             &diagnostic.line_number_,
                             &diagnostic.column_number_,
                             &unused_offset );

  diagnostic.filename_ = CXFileToFilepath( file );
  diagnostic.text_ = CXStringToString(
                       clang_getDiagnosticSpelling( diagnostic_wrap.get() ) );
  diagnostic.long_formatted_text_ = FullDiagnosticText( diagnostic_wrap.get() );

  return diagnostic;
}
    std::vector<diagnostic> translation_unit::diagnose() {
        // Get all the diagnostics
        uint32_t n = clang_getNumDiagnostics(mUnit);

        if (n == 0)
            return {};

        std::vector<diagnostic> ret;
        ret.reserve(n);

        for (uint32_t i = 0; i < n; ++i) {
            CXFile file;
            uint32_t row = 0, col = 0, offset = 0;

            CXDiagnostic diag = clang_getDiagnostic(mUnit, i);
            CXSourceLocation loc = clang_getDiagnosticLocation(diag);
            clang_getExpansionLocation( loc, &file, &row, &col, &offset );

            ret.push_back({
                { cx2std(clang_getFileName(file)), row, col },
                clang_getDiagnosticSeverity(diag),
                diagnostic_text(diag),
                diagnostic_summary(diag)
            });

            clang_disposeDiagnostic(diag);
        }

        return ret;
    }
Diagnostic BuildDiagnostic( DiagnosticWrap diagnostic_wrap,
                            CXTranslationUnit translation_unit ) {
  Diagnostic diagnostic;

  if ( !diagnostic_wrap )
    return diagnostic;

  diagnostic.kind_ = DiagnosticSeverityToType(
                       clang_getDiagnosticSeverity( diagnostic_wrap.get() ) );

  // If this is an "ignored" diagnostic, there's no point in continuing since we
  // won't display those to the user
  if ( diagnostic.kind_ == INFORMATION )
    return diagnostic;

  CXSourceLocation source_location =
      clang_getDiagnosticLocation( diagnostic_wrap.get() );
  diagnostic.location_ = Location( source_location );
  diagnostic.location_extent_ = GetLocationExtent( source_location,
                                                   translation_unit );
  diagnostic.ranges_ = GetRanges( diagnostic_wrap );
  diagnostic.text_ = CXStringToString(
                       clang_getDiagnosticSpelling( diagnostic_wrap.get() ) );
  diagnostic.long_formatted_text_ = FullDiagnosticText( diagnostic_wrap.get() );

  return diagnostic;
}
Exemple #5
0
void PrintDiagnostic(CXDiagnostic Diagnostic) {
  FILE *out = stderr;
  CXFile file;
  CXString Msg;
  unsigned display_opts = CXDiagnostic_DisplaySourceLocation
    | CXDiagnostic_DisplayColumn | CXDiagnostic_DisplaySourceRanges;
  unsigned i, num_fixits;

  if (clang_getDiagnosticSeverity(Diagnostic) == CXDiagnostic_Ignored)
    return;

  Msg = clang_formatDiagnostic(Diagnostic, display_opts);
  fprintf(stderr, "%s\n", clang_getCString(Msg));
  clang_disposeString(Msg);

  clang_getInstantiationLocation(clang_getDiagnosticLocation(Diagnostic),
                                 &file, 0, 0, 0);
  if (!file)
    return;

  num_fixits = clang_getDiagnosticNumFixIts(Diagnostic);
  for (i = 0; i != num_fixits; ++i) {
    CXSourceRange range;
    CXString insertion_text = clang_getDiagnosticFixIt(Diagnostic, i, &range);
    CXSourceLocation start = clang_getRangeStart(range);
    CXSourceLocation end = clang_getRangeEnd(range);
    unsigned start_line, start_column, end_line, end_column;
    CXFile start_file, end_file;
    clang_getInstantiationLocation(start, &start_file, &start_line,
                                   &start_column, 0);
    clang_getInstantiationLocation(end, &end_file, &end_line, &end_column, 0);
    if (clang_equalLocations(start, end)) {
      /* Insertion. */
      if (start_file == file)
        fprintf(out, "FIX-IT: Insert \"%s\" at %d:%d\n",
                clang_getCString(insertion_text), start_line, start_column);
    } else if (strcmp(clang_getCString(insertion_text), "") == 0) {
      /* Removal. */
      if (start_file == file && end_file == file) {
        fprintf(out, "FIX-IT: Remove ");
        PrintExtent(out, start_line, start_column, end_line, end_column);
        fprintf(out, "\n");
      }
    } else {
      /* Replacement. */
      if (start_file == end_file) {
        fprintf(out, "FIX-IT: Replace ");
        PrintExtent(out, start_line, start_column, end_line, end_column);
        fprintf(out, " with \"%s\"\n", clang_getCString(insertion_text));
      }
      break;
    }
    clang_disposeString(insertion_text);
  }
}
Exemple #6
0
void Irony::check(const std::string &file,
                  const std::vector<std::string> &flags,
                  const std::vector<CXUnsavedFile> &unsavedFiles) {
  std::cout << "(";

  unsigned numDiag = 0;
  int fatals = 0;
  int errors = 0;
  int warnings = 0;

  CXTranslationUnit tu = tuManager_.parse(file, flags, unsavedFiles);

  if (tu) {
    numDiag = clang_getNumDiagnostics(tu);
  } else {
    fatals = 1;
  }

  for (unsigned i = 0; i < numDiag; ++i) {
    CXDiagnostic diagnostic = clang_getDiagnostic(tu, i);

    switch (clang_getDiagnosticSeverity(diagnostic)) {
    case CXDiagnostic_Fatal:
      fatals++;
      break;

    case CXDiagnostic_Error:
      errors++;
      break;

    case CXDiagnostic_Warning:
      warnings++;
      break;

    default:
      break;
    }

    clang_disposeDiagnostic(diagnostic);
  }

  if (fatals > 0)
    std::cout << " :fatals " << fatals;

  if (errors > 0)
    std::cout << " :errors " << errors;

  if (warnings > 0)
    std::cout << " :warnings " << warnings;

  std::cout << ")\n";
}
Exemple #7
0
void ClangUtils::printCompletionDiagnostics(CXCodeCompleteResults *res)
{
	//// Report diagnostics to the log file
	const unsigned diagCount = clang_codeCompleteGetNumDiagnostics(res);
	for(unsigned i=0; i<diagCount; i++) {
		CXDiagnostic diag = clang_codeCompleteGetDiagnostic(res, i);
		CXString diagStr = clang_getDiagnosticSpelling(diag);
		wxString wxDiagString = wxString(clang_getCString(diagStr), wxConvUTF8);

		CL_DEBUG(wxT("Completion diagnostic [%d]: %s"), clang_getDiagnosticSeverity(diag), wxDiagString.c_str());
		clang_disposeString(diagStr);
		clang_disposeDiagnostic(diag);
	}
}
/**
 * \attention \c clang_formatDiagnostic have a nasty BUG since clang 3.3!
 * It fails (<em>pure virtual function call</em>) on messages w/o location attached
 * (like notices). DO NOT USE IT! EVER!
 * \todo Check for fresh clang versions!
 */
void TranslationUnit::appendDiagnostic(const CXDiagnostic& diag)
{
    // Should we ignore this item?
    const auto severity = clang_getDiagnosticSeverity(diag);
    if (severity == CXDiagnostic_Ignored)
        return;
    kDebug(DEBUG_AREA) << "TU diagnostic severity level: " << severity;

    // Get record type
    clang::diagnostic_message::type type;
    switch (severity)
    {
        case CXDiagnostic_Note:
            type = clang::diagnostic_message::type::info;
            break;
        case CXDiagnostic_Warning:
            type = clang::diagnostic_message::type::warning;
            break;
        case CXDiagnostic_Error:
        case CXDiagnostic_Fatal:
            type = clang::diagnostic_message::type::error;
            break;
        default:
            assert(!"Unexpected severity level! Code review required!");
    }

    // Get location
    clang::location loc;
    /// \attention \c Notes have no location attached!?
    if (severity != CXDiagnostic_Note)
    {
        try
        {
            loc = {clang_getDiagnosticLocation(diag)};
        }
        catch (std::exception& e)
        {
            kDebug(DEBUG_AREA) << "TU diag.fmt: Can't get diagnostic location";
        }
    }

    // Get diagnostic text and form a new diagnostic record
    m_last_diagnostic_messages.emplace_back(
        std::move(loc)
      , clang::toString(clang_getDiagnosticSpelling(diag))
      , type
      );
}
Exemple #9
0
static const char *diagnosticSeverity(CXDiagnostic diagnostic) {
  switch (clang_getDiagnosticSeverity(diagnostic)) {
  case CXDiagnostic_Ignored:
    return "ignored";
  case CXDiagnostic_Note:
    return "note";
  case CXDiagnostic_Warning:
    return "warning";
  case CXDiagnostic_Error:
    return "error";
  case CXDiagnostic_Fatal:
    return "fatal";
  }

  return "unknown";
}
Exemple #10
0
DiagnosticSeverity Diagnostic::severity() const
{
    return static_cast<DiagnosticSeverity>(clang_getDiagnosticSeverity(cxDiagnostic));
}
Exemple #11
0
bool IndexerJob::diagnose(int build, int *errorCount)
{
    if (errorCount)
        *errorCount = 0;
    if (!mUnits.at(build).second) {
        abort();
        return false;
    }

    List<String> compilationErrors;
    const unsigned diagnosticCount = clang_getNumDiagnostics(mUnits.at(build).second);
    const unsigned options = Server::instance()->options().options;

    for (unsigned i=0; i<diagnosticCount; ++i) {
        CXDiagnostic diagnostic = clang_getDiagnostic(mUnits.at(build).second, i);
        int logLevel = INT_MAX;
        const CXDiagnosticSeverity severity = clang_getDiagnosticSeverity(diagnostic);
        switch (severity) {
        case CXDiagnostic_Fatal:
        case CXDiagnostic_Error:
            if (errorCount)
                ++*errorCount;
            logLevel = Error;
            break;
        case CXDiagnostic_Warning:
            logLevel = Warning;
            break;
        case CXDiagnostic_Note:
            logLevel = Debug;
            break;
        case CXDiagnostic_Ignored:
            break;
        }

        const unsigned diagnosticOptions = (CXDiagnostic_DisplaySourceLocation|
                                            CXDiagnostic_DisplayColumn|
                                            CXDiagnostic_DisplaySourceRanges|
                                            CXDiagnostic_DisplayOption|
                                            CXDiagnostic_DisplayCategoryId|
                                            CXDiagnostic_DisplayCategoryName);
        const uint32_t fileId = createLocation(clang_getDiagnosticLocation(diagnostic), 0).fileId();
        if (mVisitedFiles.contains(fileId)) {
            const String text = RTags::eatString(clang_formatDiagnostic(diagnostic, diagnosticOptions));
            if (testLog(logLevel) || testLog(CompilationError)) {
                log(logLevel, "%s: %s => %s", mSourceInformation.sourceFile.constData(), mClangLines.at(build).constData(), text.constData());
                compilationErrors.append(text);
            }

            const unsigned fixItCount = clang_getDiagnosticNumFixIts(diagnostic);
            RegExp rx;
            if (options & Server::IgnorePrintfFixits) {
                rx = "^%[A-Za-z0-9]\\+$";
            }
            for (unsigned f=0; f<fixItCount; ++f) {
                CXSourceRange range;
                const String string = RTags::eatString(clang_getDiagnosticFixIt(diagnostic, f, &range));
                unsigned startOffset;
                CXFile file;
                clang_getSpellingLocation(clang_getRangeStart(range), &file, 0, 0, &startOffset);
                unsigned endOffset;
                clang_getSpellingLocation(clang_getRangeEnd(range), 0, 0, 0, &endOffset);
                const Location loc(file, startOffset);
                if (options & Server::IgnorePrintfFixits && rx.indexIn(string) == 0) {
                    error("Ignored fixit for %s: Replace %d-%d with [%s]", loc.path().constData(),
                          startOffset, endOffset, string.constData());
                } else {
                    error("Fixit for %s: Replace %d-%d with [%s]", loc.path().constData(),
                          startOffset, endOffset, string.constData());
                    compilationErrors.append(String::format<128>("Fixit for %s: Replace %d-%d with [%s]", loc.path().constData(),
                                                                 startOffset, endOffset, string.constData()));
                    mData->fixIts[loc.fileId()].insert(FixIt(startOffset, endOffset, string));
                }
            }
        }

        clang_disposeDiagnostic(diagnostic);
    }
    if (testLog(CompilationError))
        sendDiagnostics(compilationErrors);
    return !isAborted();
}
Exemple #12
0
CXDiagnosticSeverity diagnostic::severity()
{
    return clang_getDiagnosticSeverity(diag);
}
Exemple #13
0
CppInstr::eErrorTypes CppInstr::parse(OovStringRef const srcFn, OovStringRef const srcRootDir,
        OovStringRef const outDir,
        char const * const clang_args[], int num_clang_args)
    {
    eErrorTypes errType = ET_None;

    mOutputFileContents.read(srcFn);
    mTopParseFn.setPath(srcFn, FP_File);
    FilePath rootDir(srcRootDir, FP_Dir);
    setFileDefine(mTopParseFn, rootDir);

    CXIndex index = clang_createIndex(1, 1);

// This doesn't appear to change anything.
//    clang_toggleCrashRecovery(true);
    // Get inclusion directives to be in AST.
    unsigned options = 0;
    CXTranslationUnit tu;
    CXErrorCode errCode = clang_parseTranslationUnit2(index, srcFn,
        clang_args, num_clang_args, 0, 0, options, &tu);
    if(errCode == CXError_Success)
        {
        CXCursor rootCursor = clang_getTranslationUnitCursor(tu);
        try
            {
            clang_visitChildren(rootCursor, ::visitTranslationUnit, this);
            }
        catch(...)
            {
            errType = ET_ParseError;
            sCrashDiagnostics.setCrashed();
            }

        std::string outFileName;
        for(int i=0; i<num_clang_args; i++)
            {
            std::string testArg = clang_args[i];
            if(testArg.compare("-o") == 0)
                {
                if(i+1 < num_clang_args)
                    outFileName = clang_args[i+1];
                }
            }
        try
            {
            mOutputFileContents.write(outFileName);
            }
        catch(...)
            {
            errType = ET_ParseError;
            }
        std::string outErrFileName = outFileName;
        outErrFileName += "-err.txt";
        size_t numDiags = clang_getNumDiagnostics(tu);
        if(numDiags > 0 || sCrashDiagnostics.hasCrashed())
            {
            FILE *fp = fopen(outErrFileName.c_str(), "w");
            if(fp)
                {
                sCrashDiagnostics.dumpCrashed(fp);
                for (size_t i = 0; i<numDiags; i++)
                    {
                    CXDiagnostic diag = clang_getDiagnostic(tu, i);
                    CXDiagnosticSeverity sev = clang_getDiagnosticSeverity(diag);
                    if(errType == ET_None || errType == ET_CompileWarnings)
                        {
                        if(sev >= CXDiagnostic_Error)
                            errType = ET_CompileErrors;
                        else
                            errType = ET_CompileWarnings;
                        }
                    CXStringDisposer diagStr = clang_formatDiagnostic(diag,
                        clang_defaultDiagnosticDisplayOptions());
                        fprintf(fp, "%s\n", diagStr.c_str());
                    }

                fprintf(fp, "Arguments: %s %s %s ", static_cast<char const *>(srcFn),
                        static_cast<char const *>(srcRootDir),
                        static_cast<char const *>(outDir));
                for(int i=0 ; i<num_clang_args; i++)
                    {
                    fprintf(fp, "%s ", clang_args[i]);
                    }
                fprintf(fp, "\n");

                fclose(fp);
                }
            }
        else
            {
            unlink(outErrFileName.c_str());
            }
        FilePath covDir(outDir, FP_Dir);
        updateCoverageHeader(mTopParseFn, covDir, mInstrCount);
        updateCoverageSource(mTopParseFn, covDir);
        }
    else
        {
        errType = ET_CLangError;
        }
    return errType;
    }
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());
    }
}
Exemple #15
0
bool ClangIndexer::diagnose()
{
    if (!mClangUnit) {
        return false;
    }

    List<String> compilationErrors;
    const unsigned diagnosticCount = clang_getNumDiagnostics(mClangUnit);

    Map<Location, XmlEntry> xmlEntries;

    for (unsigned i=0; i<diagnosticCount; ++i) {
        CXDiagnostic diagnostic = clang_getDiagnostic(mClangUnit, i);
        const CXSourceLocation diagLoc = clang_getDiagnosticLocation(diagnostic);
        const Location loc = createLocation(diagLoc, 0);
        const uint32_t fileId = loc.fileId();
        if (mData->visited.value(fileId)) {
            const String msg = RTags::eatString(clang_getDiagnosticSpelling(diagnostic));
            const CXDiagnosticSeverity sev = clang_getDiagnosticSeverity(diagnostic);
            XmlEntry::Type type = XmlEntry::None;
            switch (sev) {
            case CXDiagnostic_Warning:
                type = XmlEntry::Warning;
                break;
            case CXDiagnostic_Error:
            case CXDiagnostic_Fatal:
                type = XmlEntry::Error;
                break;
            default:
                break;
            }
            if (type != XmlEntry::None) {
                const unsigned rangeCount = clang_getDiagnosticNumRanges(diagnostic);
                bool ok = false;
                for (unsigned rangePos = 0; rangePos < rangeCount; ++rangePos) {
                    const CXSourceRange range = clang_getDiagnosticRange(diagnostic, rangePos);
                    const CXSourceLocation start = clang_getRangeStart(range);
                    const CXSourceLocation end = clang_getRangeEnd(range);

                    unsigned startOffset, endOffset;
                    clang_getSpellingLocation(start, 0, 0, 0, &startOffset);
                    clang_getSpellingLocation(end, 0, 0, 0, &endOffset);
                    if (!rangePos && !startOffset && !endOffset) {
                        // huh, range invalid? fall back to diag location
                        break;
                    } else {
                        unsigned int line, column;
                        clang_getPresumedLocation(start, 0, &line, &column);
                        const Location key(loc.fileId(), line, column);
                        xmlEntries[key] = XmlEntry(type, msg, endOffset - startOffset);
                        ok = true;
                        break;
                    }
                }
                if (!ok) {
                    unsigned line, column;
                    clang_getPresumedLocation(diagLoc, 0, &line, &column);
                    const Location key(loc.fileId(), line, column);
                    xmlEntries[key] = XmlEntry(type, msg);
                    // no length
                }
            }
            // logDirect(RTags::CompilationError, msg.constData());

            const unsigned fixItCount = clang_getDiagnosticNumFixIts(diagnostic);
            for (unsigned f=0; f<fixItCount; ++f) {
                CXSourceRange range;
                const CXStringScope stringScope = clang_getDiagnosticFixIt(diagnostic, f, &range);
                CXSourceLocation start = clang_getRangeStart(range);

                unsigned line, column;
                CXString file;
                clang_getPresumedLocation(start, &file, &line, &column);
                CXStringScope fileScope(file);

                const Location loc = createLocation(clang_getCString(file), line, column);
                if (mData->visited.value(loc.fileId())) {
                    unsigned int startOffset, endOffset;
                    CXSourceLocation end = clang_getRangeEnd(range);
                    clang_getSpellingLocation(start, 0, 0, 0, &startOffset);
                    clang_getSpellingLocation(end, 0, 0, 0, &endOffset);
                    const char *string = clang_getCString(stringScope);
                    error("Fixit for %s:%d:%d: Replace %d characters with [%s]", loc.path().constData(),
                          line, column, endOffset - startOffset, string);
                    XmlEntry &entry = xmlEntries[Location(loc.fileId(), line, column)];
                    entry.type = XmlEntry::Fixit;
                    if (entry.message.isEmpty()) {
                        entry.message = String::format<64>("did you mean '%s'?", string);
                    }
                    entry.length = endOffset - startOffset;
                    mData->fixIts[loc.fileId()].insert(FixIt(line, column, endOffset - startOffset, string));
                }
            }
        }

        clang_disposeDiagnostic(diagnostic);
    }

    mData->xmlDiagnostics = "<?xml version=\"1.0\" encoding=\"utf-8\"?><checkstyle>";
    if (!xmlEntries.isEmpty()) {
        Map<Location, XmlEntry>::const_iterator entry = xmlEntries.begin();
        const Map<Location, XmlEntry>::const_iterator end = xmlEntries.end();

        const char *severities[] = { "none", "warning", "error", "fixit" };

        uint32_t lastFileId = 0;
        while (entry != end) {
            const Location &loc = entry->first;
            const XmlEntry &xmlEntry = entry->second;
            if (loc.fileId() != lastFileId) {
                if (lastFileId)
                    mData->xmlDiagnostics += "</file>";
                lastFileId = loc.fileId();
                mData->xmlDiagnostics += String::format<128>("<file name=\"%s\">", loc.path().constData());
            }
            mData->xmlDiagnostics += String::format("<error line=\"%d\" column=\"%d\" %sseverity=\"%s\" message=\"%s\"/>",
                                                    loc.line(), loc.column(),
                                                    (xmlEntry.length <= 0 ? ""
                                                     : String::format<32>("length=\"%d\" ", xmlEntry.length).constData()),
                                                    severities[xmlEntry.type], xmlEscape(xmlEntry.message).constData());
            ++entry;
        }
        if (lastFileId)
            mData->xmlDiagnostics += "</file>";
    }

    for (Hash<uint32_t, bool>::const_iterator it = mData->visited.begin(); it != mData->visited.end(); ++it) {
        if (it->second) {
            const Map<Location, XmlEntry>::const_iterator x = xmlEntries.lower_bound(Location(it->first, 0, 0));
            if (x == xmlEntries.end() || x->first.fileId() != it->first) {
                const String fn = Location::path(it->first);
                mData->xmlDiagnostics += String::format("<file name=\"%s\"/>", fn.constData());
            }
        }
    }

    mData->xmlDiagnostics += "</checkstyle>";
    return true;
}
Exemple #16
0
void PrintDiagnostic(CXDiagnostic Diagnostic) {
  FILE *out = stderr;
  CXFile file;
  CXString text;
  unsigned display_opts = CXDiagnostic_DisplaySourceLocation
    | CXDiagnostic_DisplayColumn | CXDiagnostic_DisplaySourceRanges;
  unsigned i, num_fixits;

  clang_displayDiagnostic(Diagnostic, out, display_opts);
  if (clang_getDiagnosticSeverity(Diagnostic) == CXDiagnostic_Ignored)
    return;

  clang_getInstantiationLocation(clang_getDiagnosticLocation(Diagnostic),
                                 &file, 0, 0, 0);
  if (!file)
    return;

  num_fixits = clang_getDiagnosticNumFixIts(Diagnostic);
  for (i = 0; i != num_fixits; ++i) {
    switch (clang_getDiagnosticFixItKind(Diagnostic, i)) {
    case CXFixIt_Insertion: {
      CXSourceLocation insertion_loc;
      CXFile insertion_file;
      unsigned insertion_line, insertion_column;
      text = clang_getDiagnosticFixItInsertion(Diagnostic, i, &insertion_loc);
      clang_getInstantiationLocation(insertion_loc, &insertion_file,
                                     &insertion_line, &insertion_column, 0);
      if (insertion_file == file)
        fprintf(out, "FIX-IT: Insert \"%s\" at %d:%d\n",
                clang_getCString(text), insertion_line, insertion_column);
      clang_disposeString(text);
      break;
    }
      
    case CXFixIt_Removal: {
      CXFile start_file, end_file;
      unsigned start_line, start_column, end_line, end_column;
      CXSourceRange remove_range
        = clang_getDiagnosticFixItRemoval(Diagnostic, i);
      clang_getInstantiationLocation(clang_getRangeStart(remove_range),
                                     &start_file, &start_line, &start_column,
                                     0);
      clang_getInstantiationLocation(clang_getRangeEnd(remove_range),
                                     &end_file, &end_line, &end_column, 0);
      if (start_file == file && end_file == file) {
        fprintf(out, "FIX-IT: Remove ");
        PrintExtent(out, start_line, start_column, end_line, end_column);
        fprintf(out, "\n");
      }
      break;
    }
      
    case CXFixIt_Replacement: {
      CXFile start_file, end_file;
      unsigned start_line, start_column, end_line, end_column;
      CXSourceRange remove_range;
      text = clang_getDiagnosticFixItReplacement(Diagnostic, i,&remove_range);
      clang_getInstantiationLocation(clang_getRangeStart(remove_range),
                                     &start_file, &start_line, &start_column,
                                     0);
      clang_getInstantiationLocation(clang_getRangeEnd(remove_range),
                                     &end_file, &end_line, &end_column, 0);
      if (start_file == end_file) {
        fprintf(out, "FIX-IT: Replace ");
        PrintExtent(out, start_line, start_column, end_line, end_column);
        fprintf(out, " with \"%s\"\n", clang_getCString(text));
      }
      clang_disposeString(text);
      break;
    }
    }
  }
}