void TestDUChain::testInclude() { TestFile header("int foo() { return 42; }\n", "h"); // NOTE: header is _not_ explictly being parsed, instead the impl job does that TestFile impl("#include \"" + header.url().byteArray() + "\"\n" "int main() { return foo(); }", "cpp", &header); impl.parse(TopDUContext::AllDeclarationsContextsAndUses); auto implCtx = impl.topContext(); QVERIFY(implCtx); DUChainReadLocker lock; QCOMPARE(implCtx->localDeclarations().size(), 1); auto headerCtx = DUChain::self()->chainForDocument(header.url()); QVERIFY(headerCtx); QVERIFY(!headerCtx->parsingEnvironmentFile()->needsUpdate()); QCOMPARE(headerCtx->localDeclarations().size(), 1); QVERIFY(implCtx->imports(headerCtx, CursorInRevision(0, 10))); Declaration* foo = headerCtx->localDeclarations().first(); QCOMPARE(foo->uses().size(), 1); QCOMPARE(foo->uses().begin().key(), impl.url()); QCOMPARE(foo->uses().begin()->size(), 1); QCOMPARE(foo->uses().begin()->first(), RangeInRevision(1, 20, 1, 23)); }
void TestDUChainMultipleFiles::testUpdateForeach() { TopDUContext::Features features = TopDUContext::AllDeclarationsContextsAndUses; TestProject* project = new TestProject; m_projectController->clearProjects(); m_projectController->addProject(project); TestFile f("<?\n$k = null;\nforeach(array() as $i => $k) {}\n", "php", project); f.parse(features); f.waitForParsed(); QVERIFY(f.topContext()); { DUChainWriteLocker lock; QVERIFY(f.topContext()->problems().isEmpty()); QCOMPARE(f.topContext()->findDeclarations(Identifier("k")).count(), 1); Declaration* kDec = f.topContext()->findDeclarations(Identifier("k")).first(); QCOMPARE(kDec->rangeInCurrentRevision().start.line, 1); QCOMPARE(kDec->rangeInCurrentRevision().start.column, 0); QCOMPARE(kDec->uses().count(), 1); QCOMPARE(kDec->uses().begin()->count(), 1); QCOMPARE(kDec->uses().begin()->begin()->start.line, 2); } // delete $k = null; line f.setFileContents("<?\nforeach(array() as $i => $k) {}\n"); f.parse(static_cast<TopDUContext::Features>(features | TopDUContext::ForceUpdate)); f.waitForParsed(); QVERIFY(f.topContext()); { DUChainWriteLocker lock; QVERIFY(f.topContext()->problems().isEmpty()); QCOMPARE(f.topContext()->findDeclarations(Identifier("k")).count(), 1); Declaration* kDec = f.topContext()->findDeclarations(Identifier("k")).first(); QCOMPARE(kDec->rangeInCurrentRevision().start.line, 1); QCOMPARE(kDec->rangeInCurrentRevision().start.column, 25); QCOMPARE(kDec->uses().count(), 0); } }
void TestDUChain::testBaseClasses() { TestFile file("class Base {}; class Inherited : public Base {};", "cpp"); QVERIFY(file.parseAndWait()); DUChainReadLocker lock; DUContext* top = file.topContext().data(); QVERIFY(top); QCOMPARE(top->localDeclarations().count(), 2); Declaration* baseDecl = top->localDeclarations().first(); QCOMPARE(baseDecl->identifier(), Identifier("Base")); ClassDeclaration* inheritedDecl = dynamic_cast<ClassDeclaration*>(top->localDeclarations()[1]); QCOMPARE(inheritedDecl->identifier(), Identifier("Inherited")); QVERIFY(inheritedDecl); QCOMPARE(inheritedDecl->baseClassesSize(), 1u); QCOMPARE(baseDecl->uses().count(), 1); QCOMPARE(baseDecl->uses().first().count(), 1); QCOMPARE(baseDecl->uses().first().first(), RangeInRevision(0, 40, 0, 44)); }
QList<RenameAction*> AdaptSignatureAssistant::getRenameActions(const Signature &newSignature, const QList<int> &oldPositions) const { Q_ASSERT(DUChain::lock()->currentThreadHasReadLock()); QList<RenameAction*> renameActions; if (!m_otherSideContext) { return renameActions; } for (int i = newSignature.parameters.size() - 1; i >= 0; --i) { if (oldPositions[i] == -1) { continue; //new parameter } Declaration *renamedDecl = m_otherSideContext->localDeclarations()[oldPositions[i]]; if (newSignature.parameters[i].second != m_oldSignature.parameters[oldPositions[i]].second) { QMap<IndexedString, QList<RangeInRevision> > uses = renamedDecl->uses(); if (!uses.isEmpty()) { renameActions << new RenameAction(renamedDecl->identifier(), newSignature.parameters[i].second, RevisionedFileRanges::convert(uses)); } } } return renameActions; }