예제 #1
0
QList<ProblemPointer> TestProblems::parse(const QByteArray& code)
{
    ClangIndex index;
    ClangParsingEnvironment environment;
    environment.setTranslationUnitUrl(IndexedString(FileName));
    ParseSession session(ParseSessionData::Ptr(new ParseSessionData({UnsavedFile(FileName, {code})},
                                                                    &index, environment)));
    return session.problemsForFile(session.mainFile());
}
예제 #2
0
void TestDUChain::testParsingEnvironment()
{
    const TopDUContext::Features features = TopDUContext::AllDeclarationsContextsAndUses;

    IndexedTopDUContext indexed;
    ClangParsingEnvironment lastEnv;
    {
        TestFile file("int main() {}\n", "cpp");
        auto astFeatures = static_cast<TopDUContext::Features>(features | TopDUContext::AST);
        file.parse(astFeatures);
        file.setKeepDUChainData(true);
        QVERIFY(file.waitForParsed());

        DUChainWriteLocker lock;
        auto top = file.topContext();
        QVERIFY(top);
        auto sessionData = ParseSessionData::Ptr(dynamic_cast<ParseSessionData*>(top->ast().data()));
        lock.unlock();
        ParseSession session(sessionData);
        lock.lock();
        QVERIFY(session.data());
        QVERIFY(top);

        auto envFile = QExplicitlySharedDataPointer<ClangParsingEnvironmentFile>(
            dynamic_cast<ClangParsingEnvironmentFile*>(file.topContext()->parsingEnvironmentFile().data()));

        QCOMPARE(envFile->features(), astFeatures);
        QVERIFY(envFile->featuresSatisfied(astFeatures));
        QCOMPARE(envFile->environmentQuality(), ClangParsingEnvironment::Source);

        // if no environment is given, no update should be triggered
        QVERIFY(!envFile->needsUpdate());

        // same env should also not trigger a reparse
        ClangParsingEnvironment env = session.environment();
        QCOMPARE(env.quality(), ClangParsingEnvironment::Source);
        QVERIFY(!envFile->needsUpdate(&env));

        // but changing the environment should trigger an update
        env.addIncludes(Path::List() << Path("/foo/bar/baz"));
        QVERIFY(envFile->needsUpdate(&env));
        envFile->setEnvironment(env);
        QVERIFY(!envFile->needsUpdate(&env));

        // setting the environment quality higher should require an update
        env.setQuality(ClangParsingEnvironment::BuildSystem);
        QVERIFY(envFile->needsUpdate(&env));
        envFile->setEnvironment(env);
        QVERIFY(!envFile->needsUpdate(&env));

        // changing defines requires an update
        env.addDefines(QHash<QString, QString>{ { "foo", "bar" } });
        QVERIFY(envFile->needsUpdate(&env));

        // but only when changing the defines for the envFile's TU
        const auto barTU = IndexedString("bar.cpp");
        const auto oldTU = env.translationUnitUrl();
        env.setTranslationUnitUrl(barTU);
        QCOMPARE(env.translationUnitUrl(), barTU);
        QVERIFY(!envFile->needsUpdate(&env));
        env.setTranslationUnitUrl(oldTU);
        QVERIFY(envFile->needsUpdate(&env));

        // update it again
        envFile->setEnvironment(env);
        QVERIFY(!envFile->needsUpdate(&env));
        lastEnv = env;

        // now compare against a lower quality environment
        // in such a case, we do not want to trigger an update
        env.setQuality(ClangParsingEnvironment::Unknown);
        env.setTranslationUnitUrl(barTU);
        QVERIFY(!envFile->needsUpdate(&env));

        // even when the environment changes
        env.addIncludes(Path::List() << Path("/lalalala"));
        QVERIFY(!envFile->needsUpdate(&env));

        indexed = top->indexed();
    }

    DUChain::self()->storeToDisk();

    {
        DUChainWriteLocker lock;
        QVERIFY(!DUChain::self()->isInMemory(indexed.index()));
        QVERIFY(indexed.data());
        QVERIFY(DUChain::self()->environmentFileForDocument(indexed));
        auto envFile = QExplicitlySharedDataPointer<ClangParsingEnvironmentFile>(
            dynamic_cast<ClangParsingEnvironmentFile*>(DUChain::self()->environmentFileForDocument(indexed).data()));
        QVERIFY(envFile);

        QCOMPARE(envFile->features(), features);
        QVERIFY(envFile->featuresSatisfied(features));
        QVERIFY(!envFile->needsUpdate(&lastEnv));
        DUChain::self()->removeDocumentChain(indexed.data());
    }
}