CPlusPlus::Function *CppFunction::function(int line, int column, const QString &fileName)
{
    const CPlusPlus::Snapshot snapshot = CppTools::CppModelManagerInterface::instance()->snapshot();
    const CPlusPlus::Document::Ptr document = snapshot.document(fileName);
    if (!document)
        return 0;

    CPlusPlus::Symbol *symbol = document->lastVisibleSymbolAt(line, column);
    if (!symbol)
        return 0;

    // Find the enclosing function scope (which might be several levels up, or we might be standing on it)
    CPlusPlus::Scope *scope;
    if (symbol->isScope())
        scope = symbol->asScope();
    else
        scope = symbol->enclosingScope();

    while (scope && !scope->isFunction() )
        scope = scope->enclosingScope();

    if (!scope)
        return 0;

    return scope->asFunction();
}
static bool includesQtTest(const CPlusPlus::Document::Ptr &doc,
                           const CppTools::CppModelManager *cppMM)
{
    static QString expectedHeaderPrefix
            = Utils::HostOsInfo::isMacHost()
            ? QLatin1String("QtTest.framework/Headers")
            : QLatin1String("QtTest");

    const QList<CPlusPlus::Document::Include> includes = doc->resolvedIncludes();

    foreach (const CPlusPlus::Document::Include &inc, includes) {
        // TODO this short cut works only for #include <QtTest>
        // bad, as there could be much more different approaches
        if (inc.unresolvedFileName() == QLatin1String("QtTest")
                && inc.resolvedFileName().endsWith(
                    QString::fromLatin1("%1/QtTest").arg(expectedHeaderPrefix))) {
            return true;
        }
    }

    if (cppMM) {
        CPlusPlus::Snapshot snapshot = cppMM->snapshot();
        const QSet<QString> allIncludes = snapshot.allIncludesForDocument(doc->fileName());
        foreach (const QString &include, allIncludes) {

            if (include.endsWith(QString::fromLatin1("%1/qtest.h").arg(expectedHeaderPrefix))) {
                return true;
            }
        }
    }
    return false;
}
static bool includesQtQuickTest(const CPlusPlus::Document::Ptr &doc,
                                const CppTools::CppModelManager *cppMM)
{
    static QString expectedHeaderPrefix
            = Utils::HostOsInfo::isMacHost()
            ? QLatin1String("QtQuickTest.framework/Headers")
            : QLatin1String("QtQuickTest");

    const QList<CPlusPlus::Document::Include> includes = doc->resolvedIncludes();

    foreach (const CPlusPlus::Document::Include &inc, includes) {
        if (inc.unresolvedFileName() == QLatin1String("QtQuickTest/quicktest.h")
                && inc.resolvedFileName().endsWith(
                    QString::fromLatin1("%1/quicktest.h").arg(expectedHeaderPrefix))) {
            return true;
        }
    }

    if (cppMM) {
        foreach (const QString &include, cppMM->snapshot().allIncludesForDocument(doc->fileName())) {
            if (include.endsWith(QString::fromLatin1("%1/quicktest.h").arg(expectedHeaderPrefix)))
                return true;
        }
    }
    return false;
}
void CppTodoItemsScanner::processDocument(CPlusPlus::Document::Ptr doc)
{
    QList<TodoItem> itemList;

    CPlusPlus::TranslationUnit *translationUnit = doc->translationUnit();

    for (unsigned i = 0; i < translationUnit->commentCount(); ++i) {

        // Get comment source
        CPlusPlus::Token token = doc->translationUnit()->commentAt(i);
        QByteArray source = doc->utf8Source().mid(token.begin(), token.length()).trimmed();

        if ((token.kind() == CPlusPlus::T_COMMENT) || (token.kind() == CPlusPlus::T_DOXY_COMMENT)) {
            // Remove trailing "*/"
            source = source.left(source.length() - 2);
        }

        // Process every line of the comment
        // TODO: Do not create QStringList, just iterate through a string tracking line endings.
        const QStringList commentLines =
            QString::fromUtf8(source).split(QLatin1Char('\n'), QString::SkipEmptyParts);
        unsigned lineNumber = 0;
        translationUnit->getPosition(token.begin(), &lineNumber);
        for (int j = 0; j < commentLines.count(); ++j) {
            const QString &commentLine = commentLines.at(j);
            processCommentLine(doc->fileName(), commentLine, lineNumber + j, itemList);
        }
    }
    emit itemsFetched(doc->fileName(), itemList);
}
QString AbstractEditorSupport::functionAt(const CppModelManagerInterface *modelManager,
                                          const QString &fileName,
                                          int line, int column)
{
    const CPlusPlus::Snapshot snapshot = modelManager->snapshot();
    const CPlusPlus::Document::Ptr document = snapshot.document(fileName);
    if (!document)
        return QString();
    if (const CPlusPlus::Symbol *symbol = document->lastVisibleSymbolAt(line, column))
        if (const CPlusPlus::Scope *scope = symbol->enclosingScope())
            if (const CPlusPlus::Scope *functionScope = scope->enclosingFunction())
                if (const CPlusPlus::Symbol *function = functionScope) {
                    const CPlusPlus::Overview o;
                    QString rc = o.prettyName(function->name());
                    // Prepend namespace "Foo::Foo::foo()" up to empty root namespace
                    for (const CPlusPlus::Symbol *owner = function->enclosingNamespace();
                         owner; owner = owner->enclosingNamespace()) {
                        const QString name = o.prettyName(owner->name());
                        if (name.isEmpty()) {
                            break;
                        } else {
                            rc.prepend(QLatin1String("::"));
                            rc.prepend(name);
                        }
                    }
                    return rc;
                }
    return QString();
}
Example #6
0
// Inline helper with integer error return codes.
static inline
int getUninitializedVariablesI(const CPlusPlus::Snapshot &snapshot,
                               const QString &functionName,
                               const QString &file,
                               int line,
                               QStringList *uninitializedVariables)
{
    uninitializedVariables->clear();
    // Find document
    if (snapshot.isEmpty() || functionName.isEmpty() || file.isEmpty() || line < 1)
        return 1;
    const CPlusPlus::Snapshot::const_iterator docIt = snapshot.find(file);
    if (docIt == snapshot.end())
        return 2;
    const CPlusPlus::Document::Ptr doc = docIt.value();
    // Look at symbol at line and find its function. Either it is the
    // function itself or some expression/variable.
    const CPlusPlus::Symbol *symbolAtLine = doc->lastVisibleSymbolAt(line, 0);
    if (!symbolAtLine)
        return 4;
    // First figure out the function to do a safety name check
    // and the innermost scope at cursor position
    const CPlusPlus::Function *function = 0;
    const CPlusPlus::Scope *innerMostScope = 0;
    if (symbolAtLine->isFunction()) {
        function = symbolAtLine->asFunction();
        if (function->memberCount() == 1) // Skip over function block
            if (CPlusPlus::Block *block = function->memberAt(0)->asBlock())
                innerMostScope = block;
    } else {
        if (const CPlusPlus::Scope *functionScope = symbolAtLine->enclosingFunction()) {
            function = functionScope->asFunction();
            innerMostScope = symbolAtLine->isBlock() ?
                             symbolAtLine->asBlock() :
                             symbolAtLine->enclosingBlock();
        }
    }
    if (!function || !innerMostScope)
        return 7;
    // Compare function names with a bit off fuzz,
    // skipping modules from a CDB symbol "lib!foo" or namespaces
    // that the code model does not show at this point
    CPlusPlus::Overview overview;
    const QString name = overview.prettyName(function->name());
    if (!functionName.endsWith(name))
        return 11;
    if (functionName.size() > name.size()) {
        const char previousChar = functionName.at(functionName.size() - name.size() - 1).toLatin1();
        if (previousChar != ':' && previousChar != '!' )
            return 11;
    }
    // Starting from the innermost block scope, collect declarations.
    SeenHash seenHash;
    blockRecursion(overview, innerMostScope, line, uninitializedVariables, &seenHash);
    return 0;
}
void BuiltinEditorDocumentProcessor::onParserFinished(CPlusPlus::Document::Ptr document,
                                                      CPlusPlus::Snapshot snapshot)
{
    if (document.isNull())
        return;

    if (document->fileName() != filePath())
        return; // some other document got updated

    if (document->editorRevision() != revision())
        return; // outdated content, wait for a new document to be parsed

    if (debug) {
        qDebug() << "BuiltinEditorDocumentProcessor: document parsed" << document->fileName()
                 << document->editorRevision();
    }

    // Emit ifdefed out blocks
    const auto ifdefoutBlocks = toTextEditorBlocks(document->skippedBlocks());
    emit ifdefedOutBlocksUpdated(revision(), ifdefoutBlocks);

    // Emit code warnings
    auto codeWarnings = toTextEditorSelections(document->diagnosticMessages(), textDocument());
    emit codeWarningsUpdated(revision(), codeWarnings);

    emit cppDocumentUpdated(document);

    m_documentSnapshot = snapshot;
    const auto source = createSemanticInfoSource(false);
    QTC_CHECK(source.snapshot.contains(document->fileName()));
    m_semanticInfoUpdater.updateDetached(source);
}
Example #8
0
static QString quickTestName(const CPlusPlus::Document::Ptr &doc)
{
    const QList<CPlusPlus::Document::MacroUse> macros = doc->macroUses();

    foreach (const CPlusPlus::Document::MacroUse &macro, macros) {
        if (!macro.isFunctionLike())
            continue;
        const QByteArray name = macro.macro().name();
        if (QuickTestUtils::isQuickTestMacro(name)) {
            CPlusPlus::Document::Block arg = macro.arguments().at(0);
            return QLatin1String(CppParser::getFileContent(doc->fileName())
                                 .mid(arg.bytesBegin(), arg.bytesEnd() - arg.bytesBegin()));
        }
    }
    return QString();
}
Example #9
0
void CppIncludesIterator::fetchMore()
{
    while (!m_queuedPaths.isEmpty() && m_resultQueue.isEmpty()) {
        const QString filePath = *m_queuedPaths.begin();
        m_queuedPaths.remove(filePath);
        CPlusPlus::Document::Ptr doc = m_snapshot.document(filePath);
        if (!doc)
            continue;
        foreach (const QString &includedPath, doc->includedFiles()) {
            if (!m_allResultPaths.contains(includedPath)) {
                m_allResultPaths.insert(includedPath);
                m_queuedPaths.insert(includedPath);
                m_resultQueue.append(includedPath);
            }
        }
    }
}
Example #10
0
// TODO: Can this be improved? This code is ripped from CppEditor, especially CppElementEvaluater
// We cannot depend on this since CppEditor plugin code is internal and requires building the implementation files ourselves
CPlusPlus::Symbol *AnalyzerUtils::findSymbolUnderCursor()
{
    EditorManager *editorManager = EditorManager::instance();
    if (!editorManager)
        return 0;
    IEditor *editor = editorManager->currentEditor();
    if (!editor)
        return 0;
    TextEditor::ITextEditor *textEditor = qobject_cast<TextEditor::ITextEditor *>(editor);
    if (!textEditor)
        return 0;
    TextEditor::BaseTextEditorWidget *editorWidget = qobject_cast<TextEditor::BaseTextEditorWidget *>(editor->widget());
    if (!editorWidget)
        return 0;

    QPlainTextEdit *ptEdit = qobject_cast<QPlainTextEdit *>(editor->widget());
    if (!ptEdit)
        return 0;

    QTextCursor tc;
    tc = ptEdit->textCursor();
    int line = 0;
    int column = 0;
    const int pos = tc.position();
    editorWidget->convertPosition(pos, &line, &column);

    const CPlusPlus::Snapshot &snapshot = CPlusPlus::CppModelManagerInterface::instance()->snapshot();
    CPlusPlus::Document::Ptr doc = snapshot.document(editor->document()->fileName());
    QTC_ASSERT(doc, return 0)

    // fetch the expression's code
    CPlusPlus::ExpressionUnderCursor expressionUnderCursor;
    moveCursorToEndOfName(&tc);
    const QString &expression = expressionUnderCursor(tc);
    CPlusPlus::Scope *scope = doc->scopeAt(line, column);

    CPlusPlus::TypeOfExpression typeOfExpression;
    typeOfExpression.init(doc, snapshot);
    const QList<CPlusPlus::LookupItem> &lookupItems = typeOfExpression(expression.toUtf8(), scope);
    if (lookupItems.isEmpty())
        return 0;

    const CPlusPlus::LookupItem &lookupItem = lookupItems.first(); // ### TODO: select best candidate.
    return lookupItem.declaration();
}
Example #11
0
void CppLocatorData::onDocumentUpdated(const CPlusPlus::Document::Ptr &document)
{
    QMutexLocker locker(&m_pendingDocumentsMutex);

    int i = 0, ei = m_pendingDocuments.size();
    for (; i < ei; ++i) {
        const CPlusPlus::Document::Ptr &doc = m_pendingDocuments.at(i);
        if (doc->fileName() == document->fileName()
                && doc->revision() < document->revision()) {
            m_pendingDocuments[i] = document;
            break;
        }
    }

    if (i == ei)
        m_pendingDocuments.append(document);

    flushPendingDocument(false);
}
bool CppElementEvaluator::matchIncludeFile(const CPlusPlus::Document::Ptr &document, unsigned line)
{
    foreach (const Document::Include &includeFile, document->includes()) {
        if (includeFile.line() == line) {
            m_element = QSharedPointer<CppElement>(new CppInclude(includeFile));
            return true;
        }
    }
    return false;
}
Example #13
0
void CppElementEvaluator::checkDiagnosticMessage(const CPlusPlus::Document::Ptr &document,
                                                 unsigned line)
{
    foreach (const Document::DiagnosticMessage &m, document->diagnosticMessages()) {
        if (m.line() == line) {
            m_diagnosis = m.text();
            break;
        }
    }
}
static bool includesGTest(const CPlusPlus::Document::Ptr &doc,
                          const CppTools::CppModelManager *cppMM)
{
    const QString gtestH = QLatin1String("gtest/gtest.h");
    foreach (const CPlusPlus::Document::Include &inc, doc->resolvedIncludes()) {
        if (inc.resolvedFileName().endsWith(gtestH))
            return true;
    }

    if (cppMM) {
        const CPlusPlus::Snapshot snapshot = cppMM->snapshot();
        foreach (const QString &include, snapshot.allIncludesForDocument(doc->fileName())) {
            if (include.endsWith(gtestH))
                return true;
        }
    }

    return false;
}
bool CppElementEvaluator::matchMacroInUse(const CPlusPlus::Document::Ptr &document, unsigned pos)
{
    foreach (const Document::MacroUse &use, document->macroUses()) {
        if (use.contains(pos)) {
            const unsigned begin = use.begin();
            if (pos < begin + use.macro().name().length()) {
                m_element = QSharedPointer<CppElement>(new CppMacro(use.macro()));
                return true;
            }
        }
    }
    return false;
}
Example #16
0
static bool handleQtQuickTest(QFutureInterface<TestParseResultPtr> futureInterface,
                              CPlusPlus::Document::Ptr document,
                              const Core::Id &id)
{
    const CppTools::CppModelManager *modelManager = CppTools::CppModelManager::instance();
    if (quickTestName(document).isEmpty())
        return false;

    const QString cppFileName = document->fileName();
    QList<CppTools::ProjectPart::Ptr> ppList = modelManager->projectPart(cppFileName);
    if (ppList.isEmpty()) // happens if shutting down while parsing
        return false;
    const QString &proFile = ppList.at(0)->projectFile;

    const QString srcDir = quickTestSrcDir(modelManager, cppFileName);
    if (srcDir.isEmpty())
        return false;

    const QList<QmlJS::Document::Ptr> qmlDocs = scanDirectoryForQuickTestQmlFiles(srcDir);
    bool result = false;
    foreach (const QmlJS::Document::Ptr &qmlJSDoc, qmlDocs)
        result |= checkQmlDocumentForQuickTestCode(futureInterface, qmlJSDoc, id, proFile);
    return result;
}
Example #17
0
GTestVisitor::GTestVisitor(CPlusPlus::Document::Ptr doc)
    : CPlusPlus::ASTVisitor(doc->translationUnit())
    , m_document(doc)
{
}
Example #18
0
void CppLocatorFilter::onDocumentUpdated(CPlusPlus::Document::Ptr doc)
{
    m_searchList[doc->fileName()] = search(doc);
}
Example #19
0
void CppTodoItemsScanner::documentUpdated(CPlusPlus::Document::Ptr doc)
{
    if (shouldProcessFile(doc->fileName()))
        processDocument(doc);
}