Ejemplo n.º 1
0
std::vector<SourceRange> Diagnostic::ranges() const
{
    std::vector<SourceRange> ranges;
    const uint rangesCount = clang_getDiagnosticNumRanges(cxDiagnostic);
    ranges.reserve(rangesCount);

    for (uint index = 0; index < rangesCount; ++index) {
        const SourceRange sourceRange(clang_getDiagnosticRange(cxDiagnostic, index));

        if (sourceRange.isValid())
            ranges.push_back(SourceRange(clang_getDiagnosticRange(cxDiagnostic, index)));
    }

    return ranges;
}
Ejemplo n.º 2
0
source_range diagnostic::get_range(unsigned idx)
{
    return { clang_getDiagnosticRange(diag, idx) };
}
Ejemplo n.º 3
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;
}