forked from qt-creator/qt-creator
		
	Add experimental clang code-model plug-in.
Previously known as the wip/clang branch. Contributors (in alphabetical order): - Christian Kamm <christian.d.kamm@nokia.com> - Erik Verbruggen <erik.verbruggen@digia.com> - Leandro Melo <leandro.melo@nokia.com> - Peter Kuemmel <syntheticpp@gmx.net> - Sergey Shambir <sergey.shambir.auto@gmail.com> Change-Id: I4c3ff600a19b6732641c1d5ef28236bf2cc17737 Reviewed-by: hjk <hjk121@nokiamail.com>
This commit is contained in:
		
							
								
								
									
										506
									
								
								src/plugins/clangcodemodel/semanticmarker.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										506
									
								
								src/plugins/clangcodemodel/semanticmarker.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,506 @@
 | 
			
		||||
/****************************************************************************
 | 
			
		||||
**
 | 
			
		||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
 | 
			
		||||
** Contact: http://www.qt-project.org/legal
 | 
			
		||||
**
 | 
			
		||||
** This file is part of Qt Creator.
 | 
			
		||||
**
 | 
			
		||||
** Commercial License Usage
 | 
			
		||||
** Licensees holding valid commercial Qt licenses may use this file in
 | 
			
		||||
** accordance with the commercial license agreement provided with the
 | 
			
		||||
** Software or, alternatively, in accordance with the terms contained in
 | 
			
		||||
** a written agreement between you and Digia.  For licensing terms and
 | 
			
		||||
** conditions see http://qt.digia.com/licensing.  For further information
 | 
			
		||||
** use the contact form at http://qt.digia.com/contact-us.
 | 
			
		||||
**
 | 
			
		||||
** GNU Lesser General Public License Usage
 | 
			
		||||
** Alternatively, this file may be used under the terms of the GNU Lesser
 | 
			
		||||
** General Public License version 2.1 as published by the Free Software
 | 
			
		||||
** Foundation and appearing in the file LICENSE.LGPL included in the
 | 
			
		||||
** packaging of this file.  Please review the following information to
 | 
			
		||||
** ensure the GNU Lesser General Public License version 2.1 requirements
 | 
			
		||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 | 
			
		||||
**
 | 
			
		||||
** In addition, as a special exception, Digia gives you certain additional
 | 
			
		||||
** rights.  These rights are described in the Digia Qt LGPL Exception
 | 
			
		||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 | 
			
		||||
**
 | 
			
		||||
****************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include "semanticmarker.h"
 | 
			
		||||
#include "unit.h"
 | 
			
		||||
#include "utils_p.h"
 | 
			
		||||
#include "cxraii.h"
 | 
			
		||||
 | 
			
		||||
using namespace ClangCodeModel;
 | 
			
		||||
using namespace ClangCodeModel::Internal;
 | 
			
		||||
 | 
			
		||||
static const unsigned ATTACHED_NOTES_LIMIT = 10;
 | 
			
		||||
 | 
			
		||||
SemanticMarker::SemanticMarker()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SemanticMarker::~SemanticMarker()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString SemanticMarker::fileName() const
 | 
			
		||||
{
 | 
			
		||||
    if (!m_unit)
 | 
			
		||||
        return QString();
 | 
			
		||||
 | 
			
		||||
    return m_unit->fileName();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SemanticMarker::setFileName(const QString &fileName)
 | 
			
		||||
{
 | 
			
		||||
    if (this->fileName() == fileName)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    QStringList oldOptions;
 | 
			
		||||
    if (m_unit)
 | 
			
		||||
        oldOptions = m_unit->compilationOptions();
 | 
			
		||||
    m_unit.reset(new Unit(fileName));
 | 
			
		||||
    if (!oldOptions.isEmpty())
 | 
			
		||||
        m_unit->setCompilationOptions(oldOptions);
 | 
			
		||||
 | 
			
		||||
    unsigned clangOpts = clang_defaultEditingTranslationUnitOptions();
 | 
			
		||||
    clangOpts |= CXTranslationUnit_Incomplete;
 | 
			
		||||
    clangOpts |= CXTranslationUnit_DetailedPreprocessingRecord;
 | 
			
		||||
    clangOpts &= ~CXTranslationUnit_CacheCompletionResults;
 | 
			
		||||
    m_unit->setManagementOptions(clangOpts);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SemanticMarker::setCompilationOptions(const QStringList &options)
 | 
			
		||||
{
 | 
			
		||||
    Q_ASSERT(m_unit);
 | 
			
		||||
 | 
			
		||||
    if (m_unit->compilationOptions() == options)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    m_unit->setCompilationOptions(options);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SemanticMarker::reparse(const UnsavedFiles &unsavedFiles)
 | 
			
		||||
{
 | 
			
		||||
    Q_ASSERT(m_unit);
 | 
			
		||||
 | 
			
		||||
    m_unit->setUnsavedFiles(unsavedFiles);
 | 
			
		||||
    if (m_unit->isLoaded())
 | 
			
		||||
        m_unit->reparse();
 | 
			
		||||
    else
 | 
			
		||||
        m_unit->parse();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief Calculate one or several ranges and append diagnostic for each range
 | 
			
		||||
 * Extracted from SemanticMarker::diagnostics() to reuse code
 | 
			
		||||
 */
 | 
			
		||||
static void appendDiagnostic(const CXDiagnostic &diag,
 | 
			
		||||
                             const CXSourceLocation &cxLocation,
 | 
			
		||||
                             Diagnostic::Severity severity,
 | 
			
		||||
                             const QString &spelling,
 | 
			
		||||
                             QList<Diagnostic> &diagnostics)
 | 
			
		||||
{
 | 
			
		||||
    const unsigned rangeCount = clang_getDiagnosticNumRanges(diag);
 | 
			
		||||
    bool expandLocation = true;
 | 
			
		||||
 | 
			
		||||
    for (unsigned i = 0; i < rangeCount; ++i) {
 | 
			
		||||
        CXSourceRange r = clang_getDiagnosticRange(diag, i);
 | 
			
		||||
        const SourceLocation &spellBegin = Internal::getSpellingLocation(clang_getRangeStart(r));
 | 
			
		||||
        const SourceLocation &spellEnd = Internal::getSpellingLocation(clang_getRangeEnd(r));
 | 
			
		||||
        unsigned length = spellEnd.offset() - spellBegin.offset();
 | 
			
		||||
 | 
			
		||||
        // File name can be empty due clang bug
 | 
			
		||||
        if (!spellBegin.fileName().isEmpty()) {
 | 
			
		||||
            Diagnostic d(severity, spellBegin, length, spelling);
 | 
			
		||||
            diagnostics.append(d);
 | 
			
		||||
            expandLocation = false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (expandLocation) {
 | 
			
		||||
        const SourceLocation &location = Internal::getExpansionLocation(cxLocation);
 | 
			
		||||
        Diagnostic d(severity, location, 0, spelling);
 | 
			
		||||
        diagnostics.append(d);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QList<Diagnostic> SemanticMarker::diagnostics() const
 | 
			
		||||
{
 | 
			
		||||
    QList<Diagnostic> diagnostics;
 | 
			
		||||
    if (!m_unit || !m_unit->isLoaded())
 | 
			
		||||
        return diagnostics;
 | 
			
		||||
 | 
			
		||||
    const unsigned diagCount = m_unit->getNumDiagnostics();
 | 
			
		||||
    for (unsigned i = 0; i < diagCount; ++i) {
 | 
			
		||||
        ScopedCXDiagnostic diag(m_unit->getDiagnostic(i));
 | 
			
		||||
 | 
			
		||||
        Diagnostic::Severity severity = static_cast<Diagnostic::Severity>(clang_getDiagnosticSeverity(diag));
 | 
			
		||||
        if (severity == Diagnostic::Ignored || severity == Diagnostic::Note)
 | 
			
		||||
            continue;
 | 
			
		||||
 | 
			
		||||
        CXSourceLocation cxLocation = clang_getDiagnosticLocation(diag);
 | 
			
		||||
        QString spelling = Internal::getQString(clang_getDiagnosticSpelling(diag));
 | 
			
		||||
 | 
			
		||||
        // Attach messages with Diagnostic::Note severity
 | 
			
		||||
        ScopedCXDiagnosticSet cxChildren(clang_getChildDiagnostics(diag));
 | 
			
		||||
        const unsigned numChildren = clang_getNumDiagnosticsInSet(cxChildren);
 | 
			
		||||
        const unsigned size = qMin(ATTACHED_NOTES_LIMIT, numChildren);
 | 
			
		||||
        for (unsigned di = 0; di < size; ++di) {
 | 
			
		||||
            ScopedCXDiagnostic child(clang_getDiagnosticInSet(cxChildren, di));
 | 
			
		||||
            spelling.append(QLatin1String("\n  "));
 | 
			
		||||
            spelling.append(Internal::getQString(clang_getDiagnosticSpelling(child)));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Fatal error may occur in another file, but it breaks whole parsing
 | 
			
		||||
        // Typical fatal error is unresolved #include
 | 
			
		||||
        if (severity == Diagnostic::Fatal) {
 | 
			
		||||
            for (unsigned di = 0; di < numChildren; ++di) {
 | 
			
		||||
                ScopedCXDiagnostic child(clang_getDiagnosticInSet(cxChildren, di));
 | 
			
		||||
                appendDiagnostic(child, clang_getDiagnosticLocation(child), Diagnostic::Warning, spelling, diagnostics);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        appendDiagnostic(diag, cxLocation, severity, spelling, diagnostics);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return diagnostics;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QList<TextEditor::BlockRange> SemanticMarker::ifdefedOutBlocks() const
 | 
			
		||||
{
 | 
			
		||||
    QList<TextEditor::BlockRange> blocks;
 | 
			
		||||
 | 
			
		||||
    if (!m_unit || !m_unit->isLoaded())
 | 
			
		||||
        return blocks;
 | 
			
		||||
 | 
			
		||||
#if CINDEX_VERSION_MINOR >= 21
 | 
			
		||||
    CXSourceRangeList *skippedRanges = clang_getSkippedRanges(m_unit->clangTranslationUnit(),
 | 
			
		||||
                                                              m_unit->getFile());
 | 
			
		||||
    blocks.reserve(skippedRanges->count);
 | 
			
		||||
    for (unsigned i = 0; i < skippedRanges->count; ++i) {
 | 
			
		||||
        const CXSourceRange &r = skippedRanges->ranges[i];
 | 
			
		||||
        const SourceLocation &spellBegin = Internal::getSpellingLocation(clang_getRangeStart(r));
 | 
			
		||||
        if (spellBegin.fileName() != fileName())
 | 
			
		||||
            continue;
 | 
			
		||||
        const SourceLocation &spellEnd = Internal::getSpellingLocation(clang_getRangeEnd(r));
 | 
			
		||||
        const int begin = spellBegin.offset() + 1;
 | 
			
		||||
        const int end = spellEnd.offset() - spellEnd.column();
 | 
			
		||||
        blocks.append(TextEditor::BlockRange(begin, end));
 | 
			
		||||
    }
 | 
			
		||||
    clang_disposeSourceRangeList(skippedRanges);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    return blocks;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
static void add(QList<SourceMarker> &markers,
 | 
			
		||||
                const CXSourceRange &extent,
 | 
			
		||||
                SourceMarker::Kind kind)
 | 
			
		||||
{
 | 
			
		||||
    CXSourceLocation start = clang_getRangeStart(extent);
 | 
			
		||||
    CXSourceLocation end = clang_getRangeEnd(extent);
 | 
			
		||||
    const SourceLocation &location = Internal::getExpansionLocation(start);
 | 
			
		||||
    const SourceLocation &locationEnd = Internal::getExpansionLocation(end);
 | 
			
		||||
 | 
			
		||||
    if (location.offset() < locationEnd.offset()) {
 | 
			
		||||
        const unsigned length = locationEnd.offset() - location.offset();
 | 
			
		||||
        markers.append(SourceMarker(location, length, kind));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Selects correct highlighting for cursor that is reference
 | 
			
		||||
 * @return SourceMarker::Unknown if cannot select highlighting
 | 
			
		||||
 */
 | 
			
		||||
static SourceMarker::Kind getKindByReferencedCursor(const CXCursor &cursor)
 | 
			
		||||
{
 | 
			
		||||
    const CXCursor referenced = clang_getCursorReferenced(cursor);
 | 
			
		||||
    switch (clang_getCursorKind(referenced)) {
 | 
			
		||||
    case CXCursor_EnumConstantDecl:
 | 
			
		||||
        return SourceMarker::Enumeration;
 | 
			
		||||
 | 
			
		||||
    case CXCursor_FieldDecl:
 | 
			
		||||
    case CXCursor_ObjCIvarDecl:
 | 
			
		||||
    case CXCursor_ObjCPropertyDecl:
 | 
			
		||||
        return SourceMarker::Field;
 | 
			
		||||
 | 
			
		||||
    case CXCursor_FunctionDecl:
 | 
			
		||||
    case CXCursor_FunctionTemplate:
 | 
			
		||||
    case CXCursor_Constructor:
 | 
			
		||||
        return SourceMarker::Function;
 | 
			
		||||
 | 
			
		||||
    case CXCursor_VarDecl:
 | 
			
		||||
    case CXCursor_ParmDecl:
 | 
			
		||||
    case CXCursor_NonTypeTemplateParameter:
 | 
			
		||||
        return SourceMarker::Local;
 | 
			
		||||
 | 
			
		||||
    case CXCursor_CXXMethod:
 | 
			
		||||
        if (clang_CXXMethod_isVirtual(referenced))
 | 
			
		||||
            return SourceMarker::VirtualMethod;
 | 
			
		||||
        else
 | 
			
		||||
            return SourceMarker::Function;
 | 
			
		||||
 | 
			
		||||
    case CXCursor_ObjCClassMethodDecl:
 | 
			
		||||
    case CXCursor_ObjCInstanceMethodDecl:
 | 
			
		||||
        // calling method as property, e.h. "layer.shouldRasterize = YES"
 | 
			
		||||
        return SourceMarker::Field;
 | 
			
		||||
 | 
			
		||||
    case CXCursor_UnexposedDecl:
 | 
			
		||||
        // NSObject "self" method which is a pseudo keyword
 | 
			
		||||
        if (clang_getCursorLanguage(referenced) == CXLanguage_ObjC)
 | 
			
		||||
            return SourceMarker::PseudoKeyword;
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    return SourceMarker::Unknown;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const QSet<QString> ObjcPseudoKeywords = QSet<QString>()
 | 
			
		||||
        << QLatin1String("end")
 | 
			
		||||
        << QLatin1String("try")
 | 
			
		||||
        << QLatin1String("defs")
 | 
			
		||||
        << QLatin1String("throw")
 | 
			
		||||
        << QLatin1String("class")
 | 
			
		||||
        << QLatin1String("catch")
 | 
			
		||||
        << QLatin1String("encode")
 | 
			
		||||
        << QLatin1String("public")
 | 
			
		||||
        << QLatin1String("dynamic")
 | 
			
		||||
        << QLatin1String("finally")
 | 
			
		||||
        << QLatin1String("package")
 | 
			
		||||
        << QLatin1String("private")
 | 
			
		||||
        << QLatin1String("optional")
 | 
			
		||||
        << QLatin1String("property")
 | 
			
		||||
        << QLatin1String("protocol")
 | 
			
		||||
        << QLatin1String("required")
 | 
			
		||||
        << QLatin1String("selector")
 | 
			
		||||
        << QLatin1String("interface")
 | 
			
		||||
        << QLatin1String("protected")
 | 
			
		||||
        << QLatin1String("synthesize")
 | 
			
		||||
        << QLatin1String("not_keyword")
 | 
			
		||||
        << QLatin1String("synchronized")
 | 
			
		||||
        << QLatin1String("implementation")
 | 
			
		||||
        << QLatin1String("compatibility_alias")
 | 
			
		||||
           ;
 | 
			
		||||
 | 
			
		||||
} // Anonymous namespace
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief SemanticMarker::sourceMarkersInRange
 | 
			
		||||
 * @param firstLine - first line where to generate highlighting markers
 | 
			
		||||
 * @param lastLine - last line where to generate highlighting markers
 | 
			
		||||
 *
 | 
			
		||||
 * There still two kinds of problems:
 | 
			
		||||
 *    - clang_annotateTokens() can return wrong cursor, and it's normal behavior
 | 
			
		||||
 *    - some cases no handled
 | 
			
		||||
 *
 | 
			
		||||
 * Problems caused by wrong cursors:
 | 
			
		||||
 *    - range-based for from C++ 2011
 | 
			
		||||
 *    - identifiers in some compound statements have type DeclStmt
 | 
			
		||||
 *      or CompoundStmt which refers to top-level construction.
 | 
			
		||||
 *    - CXCursor_ObjCIvarDecl mapped to field, but instance variable have
 | 
			
		||||
 *      incorrect cursor kind if it declared in private interface
 | 
			
		||||
 *          @interface MyApplication() {
 | 
			
		||||
 *              NSArray* _items;
 | 
			
		||||
 *          }
 | 
			
		||||
 *
 | 
			
		||||
 * Missed cases:
 | 
			
		||||
 *    - global variables highlighted as locals
 | 
			
		||||
 *    - appropriate marker had not been selected for listed cursors:
 | 
			
		||||
 *          CXCursor_ObjCProtocolExpr, CXCursor_ObjCEncodeExpr,
 | 
			
		||||
 *          CXCursor_ObjCDynamicDecl, CXCursor_ObjCBridgedCastExpr,
 | 
			
		||||
 *          CXCursor_ObjCSuperClassRef
 | 
			
		||||
 *    - template members of template classes&functions always highlighted
 | 
			
		||||
 *      as members, even if they are functions - no way to differ found.
 | 
			
		||||
 *    - @1, @{}, @[]
 | 
			
		||||
 */
 | 
			
		||||
QList<SourceMarker> SemanticMarker::sourceMarkersInRange(unsigned firstLine,
 | 
			
		||||
                                                         unsigned lastLine)
 | 
			
		||||
{
 | 
			
		||||
    Q_ASSERT(m_unit);
 | 
			
		||||
 | 
			
		||||
    QList<SourceMarker> result;
 | 
			
		||||
 | 
			
		||||
    if (!m_unit->isLoaded())
 | 
			
		||||
        return result;
 | 
			
		||||
 | 
			
		||||
    // Highlighting called asynchronously, and a few lines at the end can be deleted for this time.
 | 
			
		||||
    CXSourceRange unitRange = clang_getCursorExtent(m_unit->getTranslationUnitCursor());
 | 
			
		||||
    SourceLocation unitEnd = getExpansionLocation(clang_getRangeEnd(unitRange));
 | 
			
		||||
    if (lastLine > unitEnd.line())
 | 
			
		||||
        lastLine = unitEnd.line();
 | 
			
		||||
 | 
			
		||||
    if (firstLine > lastLine)
 | 
			
		||||
        return result;
 | 
			
		||||
 | 
			
		||||
    IdentifierTokens idTokens(*m_unit, firstLine, lastLine);
 | 
			
		||||
 | 
			
		||||
    const CXSourceRange *atTokenExtent = 0;
 | 
			
		||||
    for (unsigned i = 0; i < idTokens.count(); ++i) {
 | 
			
		||||
        const CXToken &tok = idTokens.token(i);
 | 
			
		||||
        CXTokenKind kind = clang_getTokenKind(tok);
 | 
			
		||||
        if (atTokenExtent) {
 | 
			
		||||
            if (CXToken_Literal == kind) {
 | 
			
		||||
                if (m_unit->getTokenSpelling(tok).startsWith(QLatin1Char('"')))
 | 
			
		||||
                    add(result, *atTokenExtent, SourceMarker::ObjCString);
 | 
			
		||||
                atTokenExtent = 0;
 | 
			
		||||
                continue;
 | 
			
		||||
            } else {
 | 
			
		||||
                add(result, *atTokenExtent, SourceMarker::PseudoKeyword);
 | 
			
		||||
                atTokenExtent = 0;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const CXSourceRange &tokenExtent = idTokens.extent(i);
 | 
			
		||||
 | 
			
		||||
        if (CXToken_Keyword == kind) {
 | 
			
		||||
            QString spell = m_unit->getTokenSpelling(tok);
 | 
			
		||||
            if (ObjcPseudoKeywords.contains(spell))
 | 
			
		||||
                add(result, tokenExtent, SourceMarker::PseudoKeyword);
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (CXToken_Punctuation == kind) {
 | 
			
		||||
            static const QLatin1String at("@");
 | 
			
		||||
            if (m_unit->getTokenSpelling(tok) == at)
 | 
			
		||||
                atTokenExtent = &tokenExtent;
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (CXToken_Identifier != kind)
 | 
			
		||||
            continue;
 | 
			
		||||
 | 
			
		||||
        const CXCursor &cursor = idTokens.cursor(i);
 | 
			
		||||
        const CXCursorKind cursorKind = clang_getCursorKind(cursor);
 | 
			
		||||
        if (clang_isInvalid(cursorKind))
 | 
			
		||||
            continue;
 | 
			
		||||
 | 
			
		||||
        switch (cursorKind) {
 | 
			
		||||
        case CXCursor_EnumConstantDecl:
 | 
			
		||||
            add(result, tokenExtent, SourceMarker::Enumeration);
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case CXCursor_ClassDecl:
 | 
			
		||||
        case CXCursor_UnionDecl:
 | 
			
		||||
        case CXCursor_ClassTemplate:
 | 
			
		||||
        case CXCursor_ClassTemplatePartialSpecialization:
 | 
			
		||||
        case CXCursor_EnumDecl:
 | 
			
		||||
        case CXCursor_Namespace:
 | 
			
		||||
        case CXCursor_NamespaceRef:
 | 
			
		||||
        case CXCursor_NamespaceAlias:
 | 
			
		||||
        case CXCursor_StructDecl:
 | 
			
		||||
        case CXCursor_TemplateRef:
 | 
			
		||||
        case CXCursor_TypeRef:
 | 
			
		||||
        case CXCursor_TypedefDecl:
 | 
			
		||||
        case CXCursor_Constructor:
 | 
			
		||||
        case CXCursor_TemplateTypeParameter:
 | 
			
		||||
        case CXCursor_TemplateTemplateParameter:
 | 
			
		||||
        case CXCursor_UnexposedDecl: /* friend class MyClass; */
 | 
			
		||||
            add(result, tokenExtent, SourceMarker::Type);
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case CXCursor_ParmDecl:
 | 
			
		||||
        case CXCursor_VariableRef:
 | 
			
		||||
        case CXCursor_VarDecl:
 | 
			
		||||
        case CXCursor_NonTypeTemplateParameter:
 | 
			
		||||
            add(result, tokenExtent, SourceMarker::Local);
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case CXCursor_MemberRefExpr:
 | 
			
		||||
        case CXCursor_MemberRef:
 | 
			
		||||
        case CXCursor_DeclRefExpr:
 | 
			
		||||
        case CXCursor_CallExpr: {
 | 
			
		||||
            SourceMarker::Kind kind = getKindByReferencedCursor(cursor);
 | 
			
		||||
            if (kind == SourceMarker::Unknown && cursorKind == CXCursor_MemberRefExpr) {
 | 
			
		||||
                /* template class member in template function */
 | 
			
		||||
                kind = SourceMarker::Field;
 | 
			
		||||
            }
 | 
			
		||||
            if (kind != SourceMarker::Unknown)
 | 
			
		||||
                add(result, tokenExtent, kind);
 | 
			
		||||
        } break;
 | 
			
		||||
 | 
			
		||||
        case CXCursor_FieldDecl:
 | 
			
		||||
            add(result, tokenExtent, SourceMarker::Field);
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case CXCursor_Destructor:
 | 
			
		||||
        case CXCursor_CXXMethod: {
 | 
			
		||||
            if (clang_CXXMethod_isVirtual(cursor))
 | 
			
		||||
                add(result, tokenExtent, SourceMarker::VirtualMethod);
 | 
			
		||||
            else
 | 
			
		||||
                add(result, tokenExtent, SourceMarker::Function);
 | 
			
		||||
        } break;
 | 
			
		||||
 | 
			
		||||
        case CXCursor_CXXOverrideAttr:
 | 
			
		||||
        case CXCursor_CXXFinalAttr:
 | 
			
		||||
        case CXCursor_AnnotateAttr: // 'annotate' in '__attribute__((annotate("AnyComment")))'
 | 
			
		||||
        case CXCursor_UnexposedAttr: // 'align' in '__declspec(align(8))'
 | 
			
		||||
            add(result, tokenExtent, SourceMarker::PseudoKeyword);
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case CXCursor_FunctionDecl:
 | 
			
		||||
        case CXCursor_FunctionTemplate:
 | 
			
		||||
        case CXCursor_OverloadedDeclRef:
 | 
			
		||||
            add(result, tokenExtent, SourceMarker::Function);
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case CXCursor_ObjCInstanceMethodDecl:
 | 
			
		||||
        case CXCursor_ObjCClassMethodDecl:
 | 
			
		||||
        case CXCursor_ObjCSelectorExpr:
 | 
			
		||||
            add(result, tokenExtent, SourceMarker::ObjectiveCMessage);
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case CXCursor_ObjCMessageExpr: {
 | 
			
		||||
            static const QLatin1String super("super");
 | 
			
		||||
            if (m_unit->getTokenSpelling(tok) == super)
 | 
			
		||||
                add(result, tokenExtent, SourceMarker::PseudoKeyword);
 | 
			
		||||
            else
 | 
			
		||||
                add(result, tokenExtent, SourceMarker::ObjectiveCMessage);
 | 
			
		||||
        } break;
 | 
			
		||||
 | 
			
		||||
        case CXCursor_ObjCCategoryDecl:
 | 
			
		||||
        case CXCursor_ObjCCategoryImplDecl:
 | 
			
		||||
        case CXCursor_ObjCImplementationDecl:
 | 
			
		||||
        case CXCursor_ObjCInterfaceDecl:
 | 
			
		||||
        case CXCursor_ObjCProtocolDecl:
 | 
			
		||||
        case CXCursor_ObjCProtocolRef:
 | 
			
		||||
        case CXCursor_ObjCClassRef:
 | 
			
		||||
        case CXCursor_ObjCSuperClassRef:
 | 
			
		||||
        case CXCursor_TypeAliasDecl: // C++11 type alias: 'using value_t = T'
 | 
			
		||||
            add(result, tokenExtent, SourceMarker::Type);
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case CXCursor_ObjCSynthesizeDecl:
 | 
			
		||||
        case CXCursor_ObjCDynamicDecl:
 | 
			
		||||
        case CXCursor_ObjCPropertyDecl:
 | 
			
		||||
        case CXCursor_ObjCIvarDecl:
 | 
			
		||||
            add(result, tokenExtent, SourceMarker::Field);
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case CXCursor_MacroDefinition:
 | 
			
		||||
        case CXCursor_MacroExpansion:
 | 
			
		||||
            add(result, tokenExtent, SourceMarker::Macro);
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case CXCursor_LabelRef:
 | 
			
		||||
        case CXCursor_LabelStmt:
 | 
			
		||||
            add(result, tokenExtent, SourceMarker::Label);
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        default:
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Unit SemanticMarker::unit() const
 | 
			
		||||
{
 | 
			
		||||
    return *m_unit;
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user