forked from qt-creator/qt-creator
CPlusPlus: Add more usage tags
To be used in subsequent patches. Change-Id: Id7140aa39bb2adba343cc12b0273c90f3c12abeb Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -226,6 +226,7 @@ public:
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (const auto declarator = (*it)->asDeclarator()) {
|
if (const auto declarator = (*it)->asDeclarator()) {
|
||||||
|
Usage::Tags tags;
|
||||||
if (containsToken(declarator->core_declarator)) {
|
if (containsToken(declarator->core_declarator)) {
|
||||||
if (declarator->initializer && declarator->equal_token
|
if (declarator->initializer && declarator->equal_token
|
||||||
&& (!declarator->postfix_declarator_list
|
&& (!declarator->postfix_declarator_list
|
||||||
@@ -233,17 +234,47 @@ public:
|
|||||||
|| !declarator->postfix_declarator_list->value->asFunctionDeclarator())) {
|
|| !declarator->postfix_declarator_list->value->asFunctionDeclarator())) {
|
||||||
return {Usage::Tag::Declaration, Usage::Tag::Write};
|
return {Usage::Tag::Declaration, Usage::Tag::Write};
|
||||||
}
|
}
|
||||||
return Usage::Tag::Declaration;
|
tags = Usage::Tag::Declaration;
|
||||||
}
|
if (declarator->postfix_declarator_list
|
||||||
if (const auto decl = (*(it + 1))->asSimpleDeclaration()) {
|
&& declarator->postfix_declarator_list->value) {
|
||||||
if (decl->symbols && decl->symbols->value) {
|
if (const FunctionDeclaratorAST * const funcDecl = declarator
|
||||||
return checkPotentialWrite(
|
->postfix_declarator_list->value->asFunctionDeclarator()) {
|
||||||
getTagsFromLhsAndRhs(decl->symbols->value->type(),
|
for (SpecifierListAST *iter = funcDecl->cv_qualifier_list; iter;
|
||||||
declarator->initializer, it + 1),
|
iter = iter->next) {
|
||||||
it + 1);
|
if (!iter->value)
|
||||||
|
continue;
|
||||||
|
if (const auto simpleSpec = iter->value->asSimpleSpecifier();
|
||||||
|
simpleSpec && simpleSpec->specifier_token) {
|
||||||
|
const Control * const ctl = m_findUsages->control();
|
||||||
|
const Identifier * const id = m_findUsages->translationUnit()
|
||||||
|
->tokenAt(simpleSpec->specifier_token).identifier;
|
||||||
|
if (id && (id->equalTo(ctl->cpp11Override())
|
||||||
|
|| id->equalTo(ctl->cpp11Final()))) {
|
||||||
|
tags |= Usage::Tag::Override;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {};
|
if (const auto decl = (*(it + 1))->asSimpleDeclaration()) {
|
||||||
|
if (tags.toInt() && decl->qt_invokable_token)
|
||||||
|
return tags |= Usage::Tag::MocInvokable;
|
||||||
|
if (decl->symbols && decl->symbols->value) {
|
||||||
|
if (!tags) {
|
||||||
|
return checkPotentialWrite(
|
||||||
|
getTagsFromLhsAndRhs(decl->symbols->value->type(),
|
||||||
|
declarator->initializer, it + 1),
|
||||||
|
it + 1);
|
||||||
|
}
|
||||||
|
if (const auto func = decl->symbols->value->type()->asFunctionType()) {
|
||||||
|
if (func->isSignal() || func->isSlot() || func->isInvokable())
|
||||||
|
return tags |= Usage::Tag::MocInvokable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tags;
|
||||||
}
|
}
|
||||||
if (const auto retStmt = (*it)->asReturnStatement()) {
|
if (const auto retStmt = (*it)->asReturnStatement()) {
|
||||||
for (auto funcIt = it + 1; funcIt != m_astPath.rend(); ++funcIt) {
|
for (auto funcIt = it + 1; funcIt != m_astPath.rend(); ++funcIt) {
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ public:
|
|||||||
Read = 1 << 1,
|
Read = 1 << 1,
|
||||||
Write = 1 << 2,
|
Write = 1 << 2,
|
||||||
WritableRef = 1 << 3,
|
WritableRef = 1 << 3,
|
||||||
|
Override = 1 << 4,
|
||||||
|
MocInvokable = 1 << 5,
|
||||||
};
|
};
|
||||||
using Tags = QFlags<Tag>;
|
using Tags = QFlags<Tag>;
|
||||||
|
|
||||||
|
|||||||
@@ -397,7 +397,17 @@ static Usage::Tags getUsageType(const ClangdAstPath &path)
|
|||||||
return Usage::Tag::WritableRef;
|
return Usage::Tag::WritableRef;
|
||||||
return Usage::Tag::Read;
|
return Usage::Tag::Read;
|
||||||
}
|
}
|
||||||
return Usage::Tag::Declaration;
|
Usage::Tags tags = Usage::Tag::Declaration;
|
||||||
|
const auto children = pathIt->children().value_or(QList<ClangdAstNode>());
|
||||||
|
for (const ClangdAstNode &child : children) {
|
||||||
|
if (child.role() == "attribute") {
|
||||||
|
if (child.kind() == "Override" || child.kind() == "Final")
|
||||||
|
tags |= Usage::Tag::Override;
|
||||||
|
else if (child.kind() == "Annotate" && child.arcanaContains("qt_"))
|
||||||
|
tags |= Usage::Tag::MocInvokable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tags;
|
||||||
}
|
}
|
||||||
if (pathIt->kind() == "MemberInitializer")
|
if (pathIt->kind() == "MemberInitializer")
|
||||||
return pathIt == path.rbegin() ? Usage::Tag::Write : Usage::Tag::Read;
|
return pathIt == path.rbegin() ? Usage::Tag::Write : Usage::Tag::Read;
|
||||||
|
|||||||
@@ -219,7 +219,7 @@ void ClangdTestFindReferences::test_data()
|
|||||||
makeItem(5, 21, Initialization), makeItem(45, 16, Usage::Tag::Read)};
|
makeItem(5, 21, Initialization), makeItem(45, 16, Usage::Tag::Read)};
|
||||||
|
|
||||||
ItemList pureVirtualRefs{makeItem(17, 17, Usage::Tag::Declaration),
|
ItemList pureVirtualRefs{makeItem(17, 17, Usage::Tag::Declaration),
|
||||||
makeItem(21, 9, Usage::Tag::Declaration)};
|
makeItem(21, 9, {Usage::Tag::Declaration, Usage::Tag::Override})};
|
||||||
QTest::newRow("pure virtual declaration") << "defs.h" << 420 << pureVirtualRefs;
|
QTest::newRow("pure virtual declaration") << "defs.h" << 420 << pureVirtualRefs;
|
||||||
|
|
||||||
QTest::newRow("pointer variable") << "main.cpp" << 52 << ItemList{
|
QTest::newRow("pointer variable") << "main.cpp" << 52 << ItemList{
|
||||||
|
|||||||
@@ -116,6 +116,8 @@ private Q_SLOTS:
|
|||||||
|
|
||||||
void variadicMacros();
|
void variadicMacros();
|
||||||
void writableRefs();
|
void writableRefs();
|
||||||
|
void mocInvokables();
|
||||||
|
void virtualOverride();
|
||||||
};
|
};
|
||||||
|
|
||||||
void tst_FindUsages::dump(const QList<Usage> &usages) const
|
void tst_FindUsages::dump(const QList<Usage> &usages) const
|
||||||
@@ -724,7 +726,16 @@ void tst_FindUsages::qproperty_1()
|
|||||||
QCOMPARE(findUsages.usages().size(), 2);
|
QCOMPARE(findUsages.usages().size(), 2);
|
||||||
QCOMPARE(findUsages.usages().at(0).tags, Usage::Tags());
|
QCOMPARE(findUsages.usages().at(0).tags, Usage::Tags());
|
||||||
QCOMPARE(findUsages.usages().at(1).tags, Usage::Tag::Declaration);
|
QCOMPARE(findUsages.usages().at(1).tags, Usage::Tag::Declaration);
|
||||||
QCOMPARE(findUsages.references().size(), 2);
|
|
||||||
|
Declaration *xChangedSignal = tst->memberAt(3)->asDeclaration();
|
||||||
|
QVERIFY(xChangedSignal);
|
||||||
|
QCOMPARE(xChangedSignal->identifier()->chars(), "xChanged");
|
||||||
|
findUsages(xChangedSignal);
|
||||||
|
QCOMPARE(findUsages.usages().size(), 3);
|
||||||
|
QCOMPARE(findUsages.usages().at(0).tags, Usage::Tags());
|
||||||
|
QCOMPARE(findUsages.usages().at(1).tags, Usage::Tags());
|
||||||
|
QCOMPARE(findUsages.usages().at(2).tags,
|
||||||
|
(Usage::Tags{Usage::Tag::Declaration, Usage::Tag::MocInvokable}));
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_FindUsages::instantiateTemplateWithNestedClass()
|
void tst_FindUsages::instantiateTemplateWithNestedClass()
|
||||||
@@ -2343,5 +2354,137 @@ int main()
|
|||||||
QCOMPARE(find.usages().at(2).tags, Usage::Tag::Read);
|
QCOMPARE(find.usages().at(2).tags, Usage::Tag::Read);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_FindUsages::mocInvokables()
|
||||||
|
{
|
||||||
|
const QByteArray src =
|
||||||
|
R"(
|
||||||
|
class O : public QObject {
|
||||||
|
public:
|
||||||
|
void aPublicFunction();
|
||||||
|
Q_SLOT void aSlot();
|
||||||
|
Q_SIGNAL void aSignal();
|
||||||
|
Q_INVOKABLE void anInvokable();
|
||||||
|
public slots:
|
||||||
|
void anotherSlot();
|
||||||
|
signals:
|
||||||
|
void anotherSignal();
|
||||||
|
private slots:
|
||||||
|
void yetAnotherSlot();
|
||||||
|
private:
|
||||||
|
void aPrivateFunction();
|
||||||
|
};
|
||||||
|
)";
|
||||||
|
|
||||||
|
Document::Ptr doc = Document::create("mocInvokables");
|
||||||
|
doc->setUtf8Source(src);
|
||||||
|
doc->parse();
|
||||||
|
doc->check();
|
||||||
|
|
||||||
|
QVERIFY(doc->diagnosticMessages().isEmpty());
|
||||||
|
QVERIFY(doc->globalSymbolCount() >= 1);
|
||||||
|
|
||||||
|
Snapshot snapshot;
|
||||||
|
snapshot.insert(doc);
|
||||||
|
|
||||||
|
Class *s = doc->globalSymbolAt(0)->asClass();
|
||||||
|
QVERIFY(s);
|
||||||
|
QCOMPARE(s->name()->identifier()->chars(), "O");
|
||||||
|
QCOMPARE(s->memberCount(), 8);
|
||||||
|
|
||||||
|
const Usage::Tags invokable{Usage::Tag::Declaration, Usage::Tag::MocInvokable};
|
||||||
|
|
||||||
|
Declaration *sv = s->memberAt(0)->asDeclaration();
|
||||||
|
QVERIFY(sv);
|
||||||
|
QCOMPARE(sv->name()->identifier()->chars(), "aPublicFunction");
|
||||||
|
FindUsages find(src, doc, snapshot, true);
|
||||||
|
find(sv);
|
||||||
|
QCOMPARE(find.usages().size(), 1);
|
||||||
|
QCOMPARE(find.usages().at(0).tags, Usage::Tag::Declaration);
|
||||||
|
|
||||||
|
sv = s->memberAt(1)->asDeclaration();
|
||||||
|
QVERIFY(sv);
|
||||||
|
QCOMPARE(sv->name()->identifier()->chars(), "aSlot");
|
||||||
|
find(sv);
|
||||||
|
QCOMPARE(find.usages().size(), 1);
|
||||||
|
QCOMPARE(find.usages().at(0).tags, invokable);
|
||||||
|
|
||||||
|
sv = s->memberAt(2)->asDeclaration();
|
||||||
|
QVERIFY(sv);
|
||||||
|
QCOMPARE(sv->name()->identifier()->chars(), "aSignal");
|
||||||
|
find(sv);
|
||||||
|
QCOMPARE(find.usages().size(), 1);
|
||||||
|
QCOMPARE(find.usages().at(0).tags, invokable);
|
||||||
|
|
||||||
|
sv = s->memberAt(3)->asDeclaration();
|
||||||
|
QVERIFY(sv);
|
||||||
|
QCOMPARE(sv->name()->identifier()->chars(), "anInvokable");
|
||||||
|
find(sv);
|
||||||
|
QCOMPARE(find.usages().size(), 1);
|
||||||
|
QCOMPARE(find.usages().at(0).tags, invokable);
|
||||||
|
|
||||||
|
sv = s->memberAt(4)->asDeclaration();
|
||||||
|
QVERIFY(sv);
|
||||||
|
QCOMPARE(sv->name()->identifier()->chars(), "anotherSlot");
|
||||||
|
find(sv);
|
||||||
|
QCOMPARE(find.usages().size(), 1);
|
||||||
|
QCOMPARE(find.usages().at(0).tags, invokable);
|
||||||
|
|
||||||
|
sv = s->memberAt(5)->asDeclaration();
|
||||||
|
QVERIFY(sv);
|
||||||
|
QCOMPARE(sv->name()->identifier()->chars(), "anotherSignal");
|
||||||
|
find(sv);
|
||||||
|
QCOMPARE(find.usages().size(), 1);
|
||||||
|
QCOMPARE(find.usages().at(0).tags, invokable);
|
||||||
|
|
||||||
|
sv = s->memberAt(6)->asDeclaration();
|
||||||
|
QVERIFY(sv);
|
||||||
|
QCOMPARE(sv->name()->identifier()->chars(), "yetAnotherSlot");
|
||||||
|
find(sv);
|
||||||
|
QCOMPARE(find.usages().size(), 1);
|
||||||
|
QCOMPARE(find.usages().at(0).tags, invokable);
|
||||||
|
|
||||||
|
sv = s->memberAt(7)->asDeclaration();
|
||||||
|
QVERIFY(sv);
|
||||||
|
QCOMPARE(sv->name()->identifier()->chars(), "aPrivateFunction");
|
||||||
|
find(sv);
|
||||||
|
QCOMPARE(find.usages().size(), 1);
|
||||||
|
QCOMPARE(find.usages().at(0).tags, Usage::Tag::Declaration);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_FindUsages::virtualOverride()
|
||||||
|
{
|
||||||
|
const QByteArray src =
|
||||||
|
R"(
|
||||||
|
struct Base { virtual void foo(); };
|
||||||
|
struct Derived : public Base { void foo() override; };
|
||||||
|
)";
|
||||||
|
|
||||||
|
Document::Ptr doc = Document::create("virtualOverride");
|
||||||
|
doc->setUtf8Source(src);
|
||||||
|
doc->parse();
|
||||||
|
doc->check();
|
||||||
|
|
||||||
|
QVERIFY(doc->diagnosticMessages().isEmpty());
|
||||||
|
QVERIFY(doc->globalSymbolCount() >= 2);
|
||||||
|
|
||||||
|
Snapshot snapshot;
|
||||||
|
snapshot.insert(doc);
|
||||||
|
|
||||||
|
Class *s = doc->globalSymbolAt(1)->asClass();
|
||||||
|
QVERIFY(s);
|
||||||
|
QCOMPARE(s->name()->identifier()->chars(), "Derived");
|
||||||
|
QCOMPARE(s->memberCount(), 1);
|
||||||
|
|
||||||
|
Declaration *sv = s->memberAt(0)->asDeclaration();
|
||||||
|
QVERIFY(sv);
|
||||||
|
QCOMPARE(sv->name()->identifier()->chars(), "foo");
|
||||||
|
|
||||||
|
FindUsages find(src, doc, snapshot, true);
|
||||||
|
find(sv);
|
||||||
|
QCOMPARE(find.usages().size(), 1);
|
||||||
|
QCOMPARE(find.usages().at(0).tags,
|
||||||
|
(Usage::Tags{Usage::Tag::Declaration, Usage::Tag::Override}));
|
||||||
|
}
|
||||||
|
|
||||||
QTEST_APPLESS_MAIN(tst_FindUsages)
|
QTEST_APPLESS_MAIN(tst_FindUsages)
|
||||||
#include "tst_findusages.moc"
|
#include "tst_findusages.moc"
|
||||||
|
|||||||
Reference in New Issue
Block a user