Пример #1
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;
}
Пример #2
0
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;
}
Пример #3
0
static void dumpDiagnostics(const CXTranslationUnit &tu) {
  std::cout << "(\n";

  std::string file;

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

    CXSourceLocation location = clang_getDiagnosticLocation(diagnostic);

    unsigned line, column, offset;
    if (clang_equalLocations(location, clang_getNullLocation())) {
      file.clear();
      line = 0;
      column = 0;
      offset = 0;
    } else {
      CXFile cxFile;

// clang_getInstantiationLocation() has been marked deprecated and
// is aimed to be replaced by clang_getExpansionLocation().
#if CINDEX_VERSION >= 6
      clang_getExpansionLocation(location, &cxFile, &line, &column, &offset);
#else
      clang_getInstantiationLocation(location, &cxFile, &line, &column, &offset);
#endif

      file = cxStringToStd(clang_getFileName(cxFile));
    }

    const char *severity = diagnosticSeverity(diagnostic);

    std::string message =
        cxStringToStd(clang_getDiagnosticSpelling(diagnostic));

    std::cout << '(' << support::quoted(file)    //
              << ' ' << line                     //
              << ' ' << column                   //
              << ' ' << offset                   //
              << ' ' << severity                 //
              << ' ' << support::quoted(message) //
              << ")\n";

    clang_disposeDiagnostic(diagnostic);
  }

  std::cout << ")\n";
}
Пример #4
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
      );
}
Пример #6
0
void GmacsPreprocessor::codeCompletion(const QTextCursor &cursor)
{
	int line = cursor.blockNumber();
	int column = cursor.columnNumber();
	//const char *name = filename->toLocal8Bit().data();
	const char *name = clang_getCString(clang_getTranslationUnitSpelling(unit));
	//qDebug() << cursor.document()->toPlainText();
	//qDebug() << cursor.document()->toPlainText().size();
	QString document = cursor.document()->toPlainText();
	QString text = cursor.block().text();
	QRegExp exp("\t");
	int tab_count = text.count(exp);
	fprintf(stderr, "column = [%d]\n", cursor.positionInBlock());
	//unsaved_file->Filename = name;
	//unsaved_file->Contents = document.toLocal8Bit().data();
	//unsaved_file->Length = document.size();
	if (!unit) return;
	CLANG_REPARSE(unit, NULL);//unsaved_file);
	fprintf(stderr, "line = [%d], column = [%d]\n", line+1, column + tab_count);
	fprintf(stderr, "name = [%s]\n", name);
	CXCodeCompleteResults *res = CLANG_CODE_COMPLETION(unit, name, line+1, column + tab_count);
	if (!res) fprintf(stderr, "ERROR: could not complete\n");
	for (size_t i = 0; i < clang_codeCompleteGetNumDiagnostics(res); i++) {
		const CXDiagnostic &diag = clang_codeCompleteGetDiagnostic(res, i);
		const CXString &s = clang_getDiagnosticSpelling(diag);
		fprintf(stderr, "%s\n", clang_getCString(s));
	}
	unsigned num_results = res->NumResults;
	fprintf(stderr, "num_results = [%d]\n");
	for (unsigned i = 0; i < num_results; i++) {
		const CXCompletionString& str = res->Results[i].CompletionString;
		unsigned chunks = clang_getNumCompletionChunks(str);
		for (unsigned j = 0; j < chunks; j++) {
			const CXString& out = clang_getCompletionChunkText(str, j);
			//std::cout << clang_getCString(out) << " ";
			if (clang_getCompletionChunkKind(str, j) != CXCompletionChunk_TypedText)
				continue;
		}
		//std::cout << std::endl;
	}
	clang_disposeCodeCompleteResults(res);
}
Пример #7
0
std::string diagnostic::spelling()
{
    return string(clang_getDiagnosticSpelling(diag)).str();
}
Пример #8
0
 /** Returns small diagnostic summary */
 inline std::string diagnostic_summary(CXDiagnostic diag) {
     return cx2std(clang_getDiagnosticSpelling(diag));
 }
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());
    }
}
Пример #10
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;
}