AutoTest: Speed up scanning for tests

Especially Qt and Quick tests scanning takes some time,
so do some additional pre-filtering of files before
parsing them to reduce the number of files to process.
Depending on the structure of the project this can
significantly reduce the scan time.

Task-number: QTCREATORBUG-29301
Change-Id: I629beedcc02502d98d84e29282e1cd7b265cfcf0
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: David Schulz <david.schulz@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
Christian Stenger
2023-08-23 15:59:38 +02:00
parent a6e779606d
commit 322336a488
6 changed files with 54 additions and 4 deletions

View File

@@ -5,6 +5,7 @@
#include <coreplugin/editormanager/editormanager.h>
#include <cppeditor/cppmodelmanager.h>
#include <projectexplorer/projectmanager.h>
#include <utils/textfileformat.h>
#include <utils/algorithm.h>
@@ -105,6 +106,31 @@ bool CppParser::precompiledHeaderContains(const CPlusPlus::Snapshot &snapshot,
});
}
std::optional<QSet<FilePath>> CppParser::filesContainingMacro(const QByteArray &macroName)
{
// safety net to avoid adding some option
static const bool noPrefilter = qtcEnvironmentVariableIsSet("QTC_AUTOTEST_DISABLE_PREFILTER");
if (noPrefilter)
return std::nullopt;
QSet<FilePath> result;
CppEditor::ProjectInfo::ConstPtr infos = CppEditor::CppModelManager::projectInfo(
ProjectExplorer::ProjectManager::startupProject());
if (!infos)
return std::nullopt;
const auto projectParts = infos->projectParts();
for (const auto &pp : projectParts) {
if (!pp->selectedForBuilding)
continue;
const ProjectExplorer::Macros macros = pp->projectMacros;
if (Utils::anyOf(pp->projectMacros, Utils::equal(&ProjectExplorer::Macro::key, macroName)))
result.unite(Utils::transform<QSet>(pp->files, &CppEditor::ProjectFile::path));
}
return std::make_optional(result);
}
void CppParser::release()
{
m_cppSnapshot = CPlusPlus::Snapshot();

View File

@@ -9,6 +9,8 @@
#include <cppeditor/cppworkingcopy.h>
#include <qmljs/qmljsdocument.h>
#include <optional>
QT_BEGIN_NAMESPACE
template <class T>
class QPromise;
@@ -76,6 +78,9 @@ public:
static bool precompiledHeaderContains(const CPlusPlus::Snapshot &snapshot,
const Utils::FilePath &filePath,
const QRegularExpression &headerFileRegex);
// returns all files of the startup project whose ProjectPart has the given \a macroName
// set as a project define
static std::optional<QSet<Utils::FilePath>> filesContainingMacro(const QByteArray &macroName);
protected:
CPlusPlus::Snapshot m_cppSnapshot;

View File

@@ -295,6 +295,9 @@ static bool isQObject(const CPlusPlus::Document::Ptr &declaringDoc)
bool QtTestParser::processDocument(QPromise<TestParseResultPtr> &promise,
const FilePath &fileName)
{
if (!m_prefilteredFiles.contains(fileName))
return false;
CPlusPlus::Document::Ptr doc = document(fileName);
if (doc.isNull())
return false;
@@ -418,6 +421,12 @@ void QtTestParser::init(const QSet<FilePath> &filesToParse, bool fullParse)
m_testCases = QTestUtils::testCaseNamesForFiles(framework(), filesToParse);
m_alternativeFiles = QTestUtils::alternativeFiles(framework(), filesToParse);
}
if (std::optional<QSet<Utils::FilePath>> prefiltered = filesContainingMacro("QT_TESTLIB_LIB"))
m_prefilteredFiles = prefiltered->intersect(filesToParse);
else
m_prefilteredFiles = filesToParse;
CppParser::init(filesToParse, fullParse);
}
@@ -425,6 +434,7 @@ void QtTestParser::release()
{
m_testCases.clear();
m_alternativeFiles.clear();
m_prefilteredFiles.clear();
CppParser::release();
}

View File

@@ -57,6 +57,7 @@ private:
const QString &projectFile) const;
QHash<Utils::FilePath, TestCases> m_testCases;
QMultiHash<Utils::FilePath, Utils::FilePath> m_alternativeFiles;
QSet<Utils::FilePath> m_prefilteredFiles;
};
} // namespace Internal

View File

@@ -28,8 +28,7 @@
using namespace QmlJS;
using namespace Utils;
namespace Autotest {
namespace Internal {
namespace Autotest::Internal {
TestTreeItem *QuickTestParseResult::createTestTreeItem() const
{
@@ -359,6 +358,11 @@ void QuickTestParser::init(const QSet<FilePath> &filesToParse, bool fullParse)
m_checkForDerivedTests = theQtTestFramework().quickCheckForDerivedTests();
if (std::optional<QSet<Utils::FilePath>> prefiltered = filesContainingMacro("QT_QMLTEST_LIB"))
m_prefilteredFiles = prefiltered->intersect(filesToParse);
else
m_prefilteredFiles = filesToParse;
CppParser::init(filesToParse, fullParse);
}
@@ -366,6 +370,7 @@ void QuickTestParser::release()
{
m_qmlSnapshot = Snapshot();
m_proFilesForQmlFiles.clear();
m_prefilteredFiles.clear();
CppParser::release();
}
@@ -384,6 +389,9 @@ bool QuickTestParser::processDocument(QPromise<TestParseResultPtr> &promise,
m_checkForDerivedTests);
}
if (!m_prefilteredFiles.contains(fileName))
return false;
CPlusPlus::Document::Ptr cppdoc = document(fileName);
if (cppdoc.isNull() || !includesQtQuickTest(cppdoc, m_cppSnapshot))
return false;
@@ -396,5 +404,4 @@ FilePath QuickTestParser::projectFileForMainCppFile(const FilePath &fileName) co
return m_mainCppFiles.contains(fileName) ? m_mainCppFiles.value(fileName) : FilePath();
}
} // namespace Internal
} // namespace Autotest
} // namespace Autotest::Internal

View File

@@ -44,6 +44,7 @@ private:
QFileSystemWatcher m_directoryWatcher;
QMap<QString, QMap<QString, QDateTime> > m_watchedFiles;
QMap<Utils::FilePath, Utils::FilePath> m_mainCppFiles;
QSet<Utils::FilePath> m_prefilteredFiles;
bool m_checkForDerivedTests = false;
};