void CppEditorSupport::onDocumentUpdated(Document::Ptr doc)
{
    if (doc.isNull())
        return;

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

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

    // Update the ifdeffed-out blocks:
    if (m_highlightingSupport && !m_highlightingSupport->hightlighterHandlesIfdefedOutBlocks()) {
        QList<Document::Block> skippedBlocks = doc->skippedBlocks();
        QList<BlockRange> ifdefedOutBlocks;
        ifdefedOutBlocks.reserve(skippedBlocks.size());
        foreach (const Document::Block &block, skippedBlocks)
            ifdefedOutBlocks.append(BlockRange(block.begin(), block.end()));
        setIfdefedOutBlocks(ifdefedOutBlocks);
    }
void CppPreprocessor::mergeEnvironment(Document::Ptr doc)
{
    if (!doc)
        return;

    const QString fn = doc->fileName();

    if (m_processed.contains(fn))
        return;

    m_processed.insert(fn);

    foreach (const Document::Include &incl, doc->resolvedIncludes()) {
        const QString includedFile = incl.resolvedFileName();

        if (Document::Ptr includedDoc = m_snapshot.document(includedFile))
            mergeEnvironment(includedDoc);
        else if (!m_included.contains(includedFile))
            run(includedFile);
    }

    m_env.addMacros(doc->definedMacros());
}
/*!
    Should insert at line 4, column 1, with "protected\n" as prefix and "\n" suffix.
 */
void CppToolsPlugin::test_codegen_protected_between_public_and_private()
{
    const QByteArray src = "\n"
            "class Foo\n" // line 1
            "{\n"
            "public:\n"   // line 3
            "private:\n"  // line 4
            "};\n"        // line 5
            "\n";

    Document::Ptr doc = Document::create(QLatin1String("protected_betwee_public_and_private"));
    doc->setUtf8Source(src);
    doc->parse();
    doc->check();

    QCOMPARE(doc->diagnosticMessages().size(), 0);
    QCOMPARE(doc->globalSymbolCount(), 1U);

    Class *foo = doc->globalSymbolAt(0)->asClass();
    QVERIFY(foo);
    QCOMPARE(foo->line(), 1U);
    QCOMPARE(foo->column(), 7U);

    Snapshot snapshot;
    snapshot.insert(doc);
    CppRefactoringChanges changes(snapshot);
    InsertionPointLocator find(changes);
    InsertionLocation loc = find.methodDeclarationInClass(
                doc->fileName(),
                foo,
                InsertionPointLocator::Protected);
    QVERIFY(loc.isValid());
    QCOMPARE(loc.prefix(), QLatin1String("protected:\n"));
    QCOMPARE(loc.suffix(), QLatin1String("\n"));
    QCOMPARE(loc.column(), 1U);
    QCOMPARE(loc.line(), 4U);
}
void CppToolsPlugin::test_codegen_definition_member_specific_file()
{
    const QByteArray srcText = "\n"
            "class Foo\n"  // line 1
            "{\n"
            "void foo();\n" // line 3
            "void bar();\n" // line 4
            "void baz();\n" // line 5
            "};\n"
            "\n"
            "void Foo::bar()\n"
            "{\n"
            "\n"
            "}\n";

    const QByteArray dstText = QString::fromLatin1(
                "\n"
                "#include \"%1/file.h\"\n" // line 1
                "int x;\n"
                "\n"
                "void Foo::foo()\n" // line 4
                "{\n"
                "\n"
                "}\n" // line 7
                "\n"
                "int y;\n").arg(QDir::tempPath()).toLatin1();

    Document::Ptr src = Document::create(QDir::tempPath() + QLatin1String("/file.h"));
    Utils::FileSaver srcSaver(src->fileName());
    srcSaver.write(srcText);
    srcSaver.finalize();
    src->setUtf8Source(srcText);
    src->parse();
    src->check();
    QCOMPARE(src->diagnosticMessages().size(), 0);
    QCOMPARE(src->globalSymbolCount(), 2U);

    Document::Ptr dst = Document::create(QDir::tempPath() + QLatin1String("/file.cpp"));
    dst->addIncludeFile(Document::Include(QLatin1String("file.h"), src->fileName(), 1,
                                          Client::IncludeLocal));
    Utils::FileSaver dstSaver(dst->fileName());
    dstSaver.write(dstText);
    dstSaver.finalize();
    dst->setUtf8Source(dstText);
    dst->parse();
    dst->check();
    QCOMPARE(dst->diagnosticMessages().size(), 0);
    QCOMPARE(dst->globalSymbolCount(), 3U);

    Snapshot snapshot;
    snapshot.insert(src);
    snapshot.insert(dst);

    Class *foo = src->globalSymbolAt(0)->asClass();
    QVERIFY(foo);
    QCOMPARE(foo->line(), 1U);
    QCOMPARE(foo->column(), 7U);
    QCOMPARE(foo->memberCount(), 3U);
    Declaration *decl = foo->memberAt(2)->asDeclaration();
    QVERIFY(decl);
    QCOMPARE(decl->line(), 5U);
    QCOMPARE(decl->column(), 6U);

    CppRefactoringChanges changes(snapshot);
    InsertionPointLocator find(changes);
    QList<InsertionLocation> locList = find.methodDefinition(decl, true, dst->fileName());
    QVERIFY(locList.size() == 1);
    InsertionLocation loc = locList.first();
    QCOMPARE(loc.fileName(), dst->fileName());
    QCOMPARE(loc.line(), 7U);
    QCOMPARE(loc.column(), 2U);
    QCOMPARE(loc.prefix(), QLatin1String("\n\n"));
    QCOMPARE(loc.suffix(), QString());
}
Example #5
0
void LocatorData::onDocumentUpdated(const Document::Ptr &doc)
{
    QList<Entry> entries = FunctionFinder().run(doc);
    QMutexLocker l(&m_mutex);
    m_entries.insert(doc->fileName(), entries);
}
void CppCurrentDocumentFilter::onDocumentUpdated(Document::Ptr doc)
{
    if (m_currentFileName == doc->fileName())
        m_itemsOfCurrentDoc.clear();
}
bool QtCreatorIntegration::navigateToSlot(const QString &objectName,
                                          const QString &signalSignature,
                                          const QStringList &parameterNames,
                                          QString *errorMessage)
{
    typedef QMap<int, Document::Ptr> DocumentMap;

    const Utils::FileName currentUiFile = FormEditorW::activeEditor()->document()->filePath();
#if 0
    return Designer::Internal::navigateToSlot(currentUiFile.toString(), objectName,
                                              signalSignature, parameterNames, errorMessage);
#endif
    // TODO: we should pass to findDocumentsIncluding an absolute path to generated .h file from ui.
    // Currently we are guessing the name of ui_<>.h file and pass the file name only to the findDocumentsIncluding().
    // The idea is that the .pro file knows if the .ui files is inside, and the .pro file knows it will
    // be generating the ui_<>.h file for it, and the .pro file knows what the generated file's name and its absolute path will be.
    // So we should somehow get that info from project manager (?)
    const QFileInfo fi = currentUiFile.toFileInfo();
    const QString uiFolder = fi.absolutePath();
    const QString uicedName = "ui_" + fi.completeBaseName() + ".h";

    // Retrieve code model snapshot restricted to project of ui file or the working copy.
    Snapshot docTable = CppTools::CppModelManager::instance()->snapshot();
    Snapshot newDocTable;
    const Project *uiProject = SessionManager::projectForFile(currentUiFile);
    if (uiProject) {
        for (Snapshot::const_iterator i = docTable.begin(), ei = docTable.end(); i != ei; ++i) {
            const Project *project = SessionManager::projectForFile(i.key());
            if (project == uiProject)
                newDocTable.insert(i.value());
        }
    } else {
        const CppTools::WorkingCopy workingCopy =
                CppTools::CppModelManager::instance()->workingCopy();
        const Utils::FileName configFileName =
                Utils::FileName::fromString(CppTools::CppModelManager::configurationFileName());
        QHashIterator<Utils::FileName, QPair<QByteArray, unsigned> > it = workingCopy.iterator();
        while (it.hasNext()) {
            it.next();
            const Utils::FileName &fileName = it.key();
            if (fileName != configFileName)
                newDocTable.insert(docTable.document(fileName));
        }
    }
    docTable = newDocTable;

    // take all docs, find the ones that include the ui_xx.h.
    // Sort into a map, putting the ones whose path closely matches the ui-folder path
    // first in case there are project subdirectories that contain identical file names.
    const QList<Document::Ptr> docList = findDocumentsIncluding(docTable, uicedName, true); // change to false when we know the absolute path to generated ui_<>.h file
    DocumentMap docMap;
    for (const Document::Ptr &d : docList) {
        const QFileInfo docFi(d->fileName());
        docMap.insert(qAbs(docFi.absolutePath().compare(uiFolder, Qt::CaseInsensitive)), d);
    }

    if (Designer::Constants::Internal::debug)
        qDebug() << Q_FUNC_INFO << objectName << signalSignature << "Looking for " << uicedName << " returned " << docList.size();
    if (docMap.isEmpty()) {
        *errorMessage = tr("No documents matching \"%1\" could be found.\nRebuilding the project might help.").arg(uicedName);
        return false;
    }

    QDesignerFormWindowInterface *fwi = FormEditorW::activeWidgetHost()->formWindow();

    const QString uiClass = uiClassName(fwi->mainContainer()->objectName());

    if (Designer::Constants::Internal::debug)
        qDebug() << "Checking docs for " << uiClass;

    // Find the class definition (ui class defined as member or base class)
    // in the file itself or in the directly included files (order 1).
    QString namespaceName;
    const Class *cl = 0;
    Document::Ptr doc;

    for (const Document::Ptr &d : qAsConst(docMap)) {
        LookupContext context(d, docTable);
        const ClassDocumentPtrPair cd = findClassRecursively(context, uiClass, 1u , &namespaceName);
        if (cd.first) {
            cl = cd.first;
            doc = cd.second;
            break;
        }
    }
    if (!cl) {
        *errorMessage = msgClassNotFound(uiClass, docList);
        return false;
    }

    Overview o;
    const QString className = namespaceName + o.prettyName(cl->name());
    if (Designer::Constants::Internal::debug)
        qDebug() << "Found class  " << className << doc->fileName();

    const QString functionName = "on_" + objectName + '_' + signalSignature;
    const QString functionNameWithParameterNames = addParameterNames(functionName, parameterNames);

    if (Designer::Constants::Internal::debug)
        qDebug() << Q_FUNC_INFO << "Found " << uiClass << doc->fileName() << " checking " << functionName  << functionNameWithParameterNames;

    int line = 0;
    Document::Ptr sourceDoc;

    if (Function *fun = findDeclaration(cl, functionName)) {
        sourceDoc = findDefinition(fun, &line);
        if (!sourceDoc) {
            // add function definition to cpp file
            sourceDoc = addDefinition(docTable, doc->fileName(), className, functionNameWithParameterNames, &line);
        }
    } else {
        // add function declaration to cl
        CppTools::WorkingCopy workingCopy =
            CppTools::CppModelManager::instance()->workingCopy();
        const QString fileName = doc->fileName();
        getParsedDocument(fileName, workingCopy, docTable);
        addDeclaration(docTable, fileName, cl, functionNameWithParameterNames);

        // add function definition to cpp file
        sourceDoc = addDefinition(docTable, fileName, className, functionNameWithParameterNames, &line);
    }

    if (!sourceDoc) {
        *errorMessage = tr("Unable to add the method definition.");
        return false;
    }

    // jump to function definition, position within code
    Core::EditorManager::openEditorAt(sourceDoc->fileName(), line + 2, indentation);

    return true;
}
bool QtCreatorIntegration::navigateToSlot(const QString &objectName,
                                          const QString &signalSignature,
                                          const QStringList &parameterNames,
                                          QString *errorMessage)
{
    const EditorData ed = m_few->activeEditor();
    QTC_ASSERT(ed, return false)
    const QString currentUiFile = ed.formWindowEditor->file()->fileName();
#if 0
    return Designer::Internal::navigateToSlot(currentUiFile, objectName, signalSignature, parameterNames, errorMessage);
#endif
    // TODO: we should pass to findDocumentsIncluding an absolute path to generated .h file from ui.
    // Currently we are guessing the name of ui_<>.h file and pass the file name only to the findDocumentsIncluding().
    // The idea is that the .pro file knows if the .ui files is inside, and the .pro file knows it will
    // be generating the ui_<>.h file for it, and the .pro file knows what the generated file's name and its absolute path will be.
    // So we should somehow get that info from project manager (?)
    const QFileInfo fi(currentUiFile);
    const QString uicedName = QLatin1String("ui_") + fi.completeBaseName() + QLatin1String(".h");

    // Retrieve code model snapshot restricted to project of ui file.
    const ProjectExplorer::Project *uiProject = ProjectExplorer::ProjectExplorerPlugin::instance()->session()->projectForFile(currentUiFile);
    if (!uiProject) {
        *errorMessage = tr("Internal error: No project could be found for %1.").arg(currentUiFile);
        return false;
    }
    CPlusPlus::Snapshot docTable = CppModelManagerInterface::instance()->snapshot();
    CPlusPlus::Snapshot newDocTable;

    for  (CPlusPlus::Snapshot::iterator it = docTable.begin(); it != docTable.end(); ++it) {
        const ProjectExplorer::Project *project = ProjectExplorer::ProjectExplorerPlugin::instance()->session()->projectForFile(it.key());
        if (project == uiProject)
            newDocTable.insert(it.value());
    }

    docTable = newDocTable;

    // take all docs, find the ones that include the ui_xx.h.
    QList<Document::Ptr> docList = findDocumentsIncluding(docTable, uicedName, true); // change to false when we know the absolute path to generated ui_<>.h file

    if (Designer::Constants::Internal::debug)
        qDebug() << Q_FUNC_INFO << objectName << signalSignature << "Looking for " << uicedName << " returned " << docList.size();
    if (docList.isEmpty()) {
        *errorMessage = tr("No documents matching '%1' could be found.\nRebuilding the project might help.").arg(uicedName);
        return false;
    }

    QDesignerFormWindowInterface *fwi = ed.widgetHost->formWindow();

    const QString uiClass = uiClassName(fwi->mainContainer()->objectName());

    if (Designer::Constants::Internal::debug)
        qDebug() << "Checking docs for " << uiClass;

    // Find the class definition (ui class defined as member or base class)
    // in the file itself or in the directly included files (order 1).
    QString namespaceName;
    const Class *cl = 0;
    Document::Ptr doc;

    foreach (const Document::Ptr &d, docList) {
        const ClassDocumentPtrPair cd = findClassRecursively(docTable, d, uiClass, 1u , &namespaceName);
        if (cd.first) {
            cl = cd.first;
            doc = cd.second;
            break;
        }
    }
    if (!cl) {
        *errorMessage = msgClassNotFound(uiClass, docList);
        return false;
    }

    Overview o;
    const QString className = namespaceName + o.prettyName(cl->name());
    if (Designer::Constants::Internal::debug)
        qDebug() << "Found class  " << className << doc->fileName();

    const QString functionName = QLatin1String("on_") + objectName + QLatin1Char('_') + signalSignature;
    const QString functionNameWithParameterNames = addParameterNames(functionName, parameterNames);

    if (Designer::Constants::Internal::debug)
        qDebug() << Q_FUNC_INFO << "Found " << uiClass << doc->fileName() << " checking " << functionName  << functionNameWithParameterNames;

    int line = 0;
    Document::Ptr sourceDoc;

    if (Function *fun = findDeclaration(cl, functionName)) {
        sourceDoc = findDefinition(fun, &line);
        if (!sourceDoc) {
            // add function definition to cpp file
            sourceDoc = addDefinition(docTable, doc->fileName(), className, functionNameWithParameterNames, &line);
        }
    } else {
        // add function declaration to cl
        CppModelManagerInterface::WorkingCopy workingCopy =
            CppModelManagerInterface::instance()->workingCopy();
        const QString fileName = doc->fileName();
        getParsedDocument(fileName, workingCopy, docTable);
        addDeclaration(docTable, fileName, cl, functionNameWithParameterNames);

        // add function definition to cpp file
        sourceDoc = addDefinition(docTable, fileName, className, functionNameWithParameterNames, &line);
    }

    if (!sourceDoc) {
        *errorMessage = tr("Unable to add the method definition.");
        return false;
    }

    // jump to function definition, position within code
    TextEditor::BaseTextEditorWidget::openEditorAt(sourceDoc->fileName(), line + 2, indentation);

    return true;
}
Example #9
0
void Snapshot::insert(Document::Ptr doc)
{
    if (doc)
        _documents.insert(doc->fileName(), doc);
}
QmlJSRefactoringFile::QmlJSRefactoringFile(TextEditor::TextEditorWidget *editor, Document::Ptr document)
    : RefactoringFile(editor)
    , m_qmljsDocument(document)
{
    m_fileName = document->fileName();
}
void CppCurrentDocumentFilter::onDocumentUpdated(Document::Ptr doc)
{
    QMutexLocker locker(&m_mutex);
    if (m_currentFileName == doc->fileName())
        m_itemsOfCurrentDoc.clear();
}