diff --git a/autotests/syntaxrepository_test.cpp b/autotests/syntaxrepository_test.cpp --- a/autotests/syntaxrepository_test.cpp +++ b/autotests/syntaxrepository_test.cpp @@ -148,6 +148,27 @@ QCOMPARE(def.foldingIgnoreList(), QStringList() << QLatin1String("(?:\\s+|\\s*#.*)")); } + void testIncludedDefinitions() + { + auto def = m_repo.definitionForName(QLatin1String("C++")); + QVERIFY(def.isValid()); + auto defs = def.includedDefinitions(); + + const QStringList expectedDefinitionNames = { + QStringLiteral("C++"), + QStringLiteral("ISO C++"), + QStringLiteral("GCCExtensions"), + QStringLiteral("Doxygen"), + QStringLiteral("Alerts"), + QStringLiteral("Modelines") + }; + QStringList definitionNames; + for (auto d : defs) { + definitionNames.push_back(d.name()); + } + QCOMPARE(definitionNames, expectedDefinitionNames); + } + void testReload() { auto def = m_repo.definitionForName(QLatin1String("QML")); diff --git a/src/lib/definition.h b/src/lib/definition.h --- a/src/lib/definition.h +++ b/src/lib/definition.h @@ -172,6 +172,15 @@ */ QStringList foldingIgnoreList() const; + /** + * Returns a list of Definitions that are referenced with the IncludeRules rule. + * The returned list includes this Definition as well as any recursively used + * Definition. + * + * @since 5.49 + */ + QVector includedDefinitions() const; + private: friend class DefinitionData; friend class DefinitionRef; diff --git a/src/lib/definition.cpp b/src/lib/definition.cpp --- a/src/lib/definition.cpp +++ b/src/lib/definition.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -186,6 +187,33 @@ return d->foldingIgnoreList; } +QVector Definition::includedDefinitions() const +{ + d->load(); + + QVector definitions; + + QQueue queue; + queue.enqueue(*this); + while (!queue.isEmpty()) { + const auto definition = queue.dequeue(); + definitions.push_back(definition); + + // Iterate all context rules to find associated Definitions. This will + // automatically catch other Definitions referenced with IncludeRuldes. + foreach (const auto & context, definition.d->contexts) { + foreach (const auto &rule, context->rules()) { + if ((!definitions.contains(rule->definition())) && + (!queue.contains(rule->definition()))) + { + queue.enqueue(rule->definition()); + } + } + } + } + return definitions; +} + Context* DefinitionData::initialContext() const { Q_ASSERT(!contexts.isEmpty());