summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Stenger <christian.stenger@qt.io>2021-06-04 14:28:03 +0200
committerChristian Stenger <christian.stenger@qt.io>2021-06-07 12:05:37 +0000
commit9db6569c43bd2acfb453b5e67f13d7f0ee4448a6 (patch)
tree941c842f26d35875a1115529c1cdfe58405087c4 /src
parent684c5f75293634bac7a315ca62bf917e93af28f9 (diff)
downloadqt-creator-9db6569c43bd2acfb453b5e67f13d7f0ee4448a6.tar.gz
AutoTest: Take precompiled headers into account
Test frameworks might be added to the precompiled headers. This in turn would make some pre-checks whether a file has to be processed or not fail. Fixes: QTCREATORBUG-25821 Change-Id: Iff69c1a83889cb6f79a3e3f9b2e59c5383989ccd Reviewed-by: Christian Stenger <christian.stenger@qt.io> Reviewed-by: David Schulz <david.schulz@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/plugins/autotest/boost/boosttestparser.cpp4
-rw-r--r--src/plugins/autotest/catch/catchtestparser.cpp19
-rw-r--r--src/plugins/autotest/gtest/gtestparser.cpp19
-rw-r--r--src/plugins/autotest/itestparser.cpp37
-rw-r--r--src/plugins/autotest/itestparser.h10
-rw-r--r--src/plugins/autotest/qtest/qttestparser.cpp24
-rw-r--r--src/plugins/autotest/quick/quicktestparser.cpp42
7 files changed, 143 insertions, 12 deletions
diff --git a/src/plugins/autotest/boost/boosttestparser.cpp b/src/plugins/autotest/boost/boosttestparser.cpp
index 53a1443430..c285d49b39 100644
--- a/src/plugins/autotest/boost/boosttestparser.cpp
+++ b/src/plugins/autotest/boost/boosttestparser.cpp
@@ -84,7 +84,9 @@ static bool includesBoostTest(const CPlusPlus::Document::Ptr &doc,
return true;
}
- return false;
+ return CppParser::precompiledHeaderContains(snapshot,
+ Utils::FilePath::fromString(doc->fileName()),
+ boostTestHpp);
}
static bool hasBoostTestMacros(const CPlusPlus::Document::Ptr &doc)
diff --git a/src/plugins/autotest/catch/catchtestparser.cpp b/src/plugins/autotest/catch/catchtestparser.cpp
index a95e1f2905..933fda35fd 100644
--- a/src/plugins/autotest/catch/catchtestparser.cpp
+++ b/src/plugins/autotest/catch/catchtestparser.cpp
@@ -86,6 +86,12 @@ static bool includesCatchHeader(const CPlusPlus::Document::Ptr &doc,
}
}
+ for (const QString &catchHeader : catchHeaders) {
+ if (CppParser::precompiledHeaderContains(snapshot,
+ Utils::FilePath::fromString(doc->fileName()),
+ catchHeader))
+ return true;
+ }
return false;
}
@@ -109,13 +115,24 @@ bool CatchTestParser::processDocument(QFutureInterface<TestParseResultPtr> futur
const Utils::FilePath &fileName)
{
CPlusPlus::Document::Ptr doc = document(fileName);
- if (doc.isNull() || !includesCatchHeader(doc, m_cppSnapshot) || !hasCatchNames(doc))
+ if (doc.isNull() || !includesCatchHeader(doc, m_cppSnapshot))
return false;
const CppTools::CppModelManager *modelManager = CppTools::CppModelManager::instance();
const QString &filePath = doc->fileName();
const QByteArray &fileContent = getFileContent(fileName);
+ if (!hasCatchNames(doc)) {
+ const QRegularExpression regex("\\b(SCENARIO|(TEMPLATE_(PRODUCT_)?)?TEST_CASE(_METHOD)?|"
+ "TEMPLATE_TEST_CASE(_METHOD)?_SIG|"
+ "TEMPLATE_PRODUCT_TEST_CASE(_METHOD)?_SIG|"
+ "TEMPLATE_LIST_TEST_CASE_METHOD|METHOD_AS_TEST_CASE|"
+ "REGISTER_TEST_CASE)");
+ if (!regex.match(QString::fromUtf8(fileContent)).hasMatch())
+ return false;
+ }
+
+
const QList<CppTools::ProjectPart::Ptr> projectParts = modelManager->projectPart(fileName);
if (projectParts.isEmpty()) // happens if shutting down while parsing
return false;
diff --git a/src/plugins/autotest/gtest/gtestparser.cpp b/src/plugins/autotest/gtest/gtestparser.cpp
index 4975bc66da..35f00e2c94 100644
--- a/src/plugins/autotest/gtest/gtestparser.cpp
+++ b/src/plugins/autotest/gtest/gtestparser.cpp
@@ -32,6 +32,9 @@
#include <cpptools/cppmodelmanager.h>
#include <cpptools/projectpart.h>
+#include <QRegularExpression>
+#include <QRegularExpressionMatch>
+
namespace Autotest {
namespace Internal {
@@ -69,7 +72,9 @@ static bool includesGTest(const CPlusPlus::Document::Ptr &doc,
return true;
}
- return false;
+ return CppParser::precompiledHeaderContains(snapshot,
+ Utils::FilePath::fromString(doc->fileName()),
+ gtestH);
}
static bool hasGTestNames(const CPlusPlus::Document::Ptr &document)
@@ -91,12 +96,18 @@ bool GTestParser::processDocument(QFutureInterface<TestParseResultPtr> futureInt
const Utils::FilePath &fileName)
{
CPlusPlus::Document::Ptr doc = document(fileName);
- if (doc.isNull() || !includesGTest(doc, m_cppSnapshot) || !hasGTestNames(doc))
+ if (doc.isNull() || !includesGTest(doc, m_cppSnapshot))
return false;
- const CppTools::CppModelManager *modelManager = CppTools::CppModelManager::instance();
- const QString &filePath = doc->fileName();
const QByteArray &fileContent = getFileContent(fileName);
+ if (!hasGTestNames(doc)) {
+ const QRegularExpression regex("\\b(TEST(_[FP])?|TYPED_TEST(_P)?|(GTEST_TEST))");
+ if (!regex.match(QString::fromUtf8(fileContent)).hasMatch())
+ return false;
+ }
+
+ const QString &filePath = doc->fileName();
+ const CppTools::CppModelManager *modelManager = CppTools::CppModelManager::instance();
CPlusPlus::Document::Ptr document = m_cppSnapshot.preprocessedDocument(fileContent, fileName);
document->check();
CPlusPlus::AST *ast = document->translationUnit()->ast();
diff --git a/src/plugins/autotest/itestparser.cpp b/src/plugins/autotest/itestparser.cpp
index 740f029e4c..cd0f2591dd 100644
--- a/src/plugins/autotest/itestparser.cpp
+++ b/src/plugins/autotest/itestparser.cpp
@@ -28,6 +28,10 @@
#include <coreplugin/editormanager/editormanager.h>
#include <cpptools/cppmodelmanager.h>
#include <utils/textfileformat.h>
+#include <utils/algorithm.h>
+
+#include <QRegularExpression>
+#include <QRegularExpressionMatch>
namespace Autotest {
@@ -69,6 +73,39 @@ QByteArray CppParser::getFileContent(const Utils::FilePath &filePath) const
return fileContent;
}
+bool precompiledHeaderContains(const CPlusPlus::Snapshot &snapshot,
+ const Utils::FilePath &filePath,
+ const std::function<bool(const QString &)> &checker)
+{
+ const CppTools::CppModelManager *modelManager = CppTools::CppModelManager::instance();
+ const QList<CppTools::ProjectPart::Ptr> projectParts = modelManager->projectPart(filePath);
+ if (projectParts.isEmpty())
+ return false;
+ const QStringList precompiledHeaders = projectParts.first()->precompiledHeaders;
+ auto headerContains = [&](const QString &header){
+ return Utils::anyOf(snapshot.allIncludesForDocument(header), checker);
+ };
+ return Utils::anyOf(precompiledHeaders, headerContains);
+}
+
+bool CppParser::precompiledHeaderContains(const CPlusPlus::Snapshot &snapshot,
+ const Utils::FilePath &filePath,
+ const QString &headerFilePath)
+{
+ return Autotest::precompiledHeaderContains(snapshot, filePath, [&](const QString &include) {
+ return include.endsWith(headerFilePath);
+ });
+}
+
+bool CppParser::precompiledHeaderContains(const CPlusPlus::Snapshot &snapshot,
+ const Utils::FilePath &filePath,
+ const QRegularExpression &headerFileRegex)
+{
+ return Autotest::precompiledHeaderContains(snapshot, filePath, [&](const QString &include) {
+ return headerFileRegex.match(include).hasMatch();
+ });
+}
+
void CppParser::release()
{
m_cppSnapshot = CPlusPlus::Snapshot();
diff --git a/src/plugins/autotest/itestparser.h b/src/plugins/autotest/itestparser.h
index e089c030d4..a3cb0cb8b4 100644
--- a/src/plugins/autotest/itestparser.h
+++ b/src/plugins/autotest/itestparser.h
@@ -33,6 +33,10 @@
#include <QFutureInterface>
+QT_BEGIN_NAMESPACE
+class QRegularExpression;
+QT_END_NAMESPACE
+
namespace Autotest {
class ITestFramework;
@@ -85,6 +89,12 @@ public:
CPlusPlus::Document::Ptr document(const Utils::FilePath &fileName);
+ static bool precompiledHeaderContains(const CPlusPlus::Snapshot &snapshot,
+ const Utils::FilePath &filePath,
+ const QString &headerFilePath);
+ static bool precompiledHeaderContains(const CPlusPlus::Snapshot &snapshot,
+ const Utils::FilePath &filePath,
+ const QRegularExpression &headerFileRegex);
protected:
CPlusPlus::Snapshot m_cppSnapshot;
CppTools::WorkingCopy m_workingCopy;
diff --git a/src/plugins/autotest/qtest/qttestparser.cpp b/src/plugins/autotest/qtest/qttestparser.cpp
index 387b6e0879..a42d341eff 100644
--- a/src/plugins/autotest/qtest/qttestparser.cpp
+++ b/src/plugins/autotest/qtest/qttestparser.cpp
@@ -32,6 +32,8 @@
#include <cplusplus/TypeOfExpression.h>
#include <utils/algorithm.h>
+#include <QRegularExpressionMatchIterator>
+
namespace Autotest {
namespace Internal {
@@ -78,6 +80,14 @@ static bool includesQtTest(const CPlusPlus::Document::Ptr &doc, const CPlusPlus:
return true;
}
}
+
+ for (const QString &prefix : expectedHeaderPrefixes) {
+ if (CppParser::precompiledHeaderContains(snapshot,
+ Utils::FilePath::fromString(doc->fileName()),
+ QString("%1/qtest.h").arg(prefix))) {
+ return true;
+ }
+ }
return false;
}
@@ -120,7 +130,19 @@ TestCases QtTestParser::testCases(const CppTools::CppModelManager *modelManager,
CPlusPlus::AST *ast = document->translationUnit()->ast();
TestAstVisitor astVisitor(document, m_cppSnapshot);
astVisitor.accept(ast);
- return astVisitor.testCases();
+ if (!astVisitor.testCases().isEmpty())
+ return astVisitor.testCases();
+
+ // check pch usage - might give false positives, but we can't do better without cost
+ TestCases result;
+ const QRegularExpression regex("\\bQTEST_(APPLESS_|GUILESS_)?MAIN"
+ "\\s*\\(\\s*([[:alnum:]]+)\\s*\\)");
+ QRegularExpressionMatchIterator it = regex.globalMatch(QString::fromUtf8(fileContent));
+ while (it.hasNext()) {
+ const QRegularExpressionMatch match = it.next();
+ result.append({match.captured(2), false});
+ }
+ return result;
}
static CPlusPlus::Document::Ptr declaringDocument(CPlusPlus::Document::Ptr doc,
diff --git a/src/plugins/autotest/quick/quicktestparser.cpp b/src/plugins/autotest/quick/quicktestparser.cpp
index fdd045bb31..598f8a2e79 100644
--- a/src/plugins/autotest/quick/quicktestparser.cpp
+++ b/src/plugins/autotest/quick/quicktestparser.cpp
@@ -87,6 +87,14 @@ static bool includesQtQuickTest(const CPlusPlus::Document::Ptr &doc,
return true;
}
}
+
+ for (const QString &prefix : expectedHeaderPrefixes) {
+ if (CppParser::precompiledHeaderContains(snapshot,
+ Utils::FilePath::fromString(doc->fileName()),
+ QString("%1/quicktest.h").arg(prefix))) {
+ return true;
+ }
+ }
return false;
}
@@ -115,6 +123,7 @@ static QString quickTestSrcDir(const CppTools::CppModelManager *cppMM,
QString QuickTestParser::quickTestName(const CPlusPlus::Document::Ptr &doc) const
{
const QList<CPlusPlus::Document::MacroUse> macros = doc->macroUses();
+ const Utils::FilePath filePath = Utils::FilePath::fromString(doc->fileName());
for (const CPlusPlus::Document::MacroUse &macro : macros) {
if (!macro.isFunctionLike())
@@ -122,22 +131,45 @@ QString QuickTestParser::quickTestName(const CPlusPlus::Document::Ptr &doc) cons
const QByteArray name = macro.macro().name();
if (QuickTestUtils::isQuickTestMacro(name)) {
CPlusPlus::Document::Block arg = macro.arguments().at(0);
- return QLatin1String(getFileContent(Utils::FilePath::fromString(doc->fileName()))
+ return QLatin1String(getFileContent(filePath)
.mid(int(arg.bytesBegin()), int(arg.bytesEnd() - arg.bytesBegin())));
}
}
+
+ const QByteArray &fileContent = getFileContent(filePath);
// check for using quick_test_main() directly
- const QString fileName = doc->fileName();
- const QByteArray &fileContent = getFileContent(Utils::FilePath::fromString(fileName));
- CPlusPlus::Document::Ptr document = m_cppSnapshot.preprocessedDocument(fileContent, fileName);
+ CPlusPlus::Document::Ptr document = m_cppSnapshot.preprocessedDocument(fileContent, filePath);
if (document.isNull())
return QString();
document->check();
CPlusPlus::AST *ast = document->translationUnit()->ast();
QuickTestAstVisitor astVisitor(document, m_cppSnapshot);
astVisitor.accept(ast);
- return astVisitor.testBaseName();
+ if (!astVisitor.testBaseName().isEmpty())
+ return astVisitor.testBaseName();
+
+ // check for precompiled headers
+ static QStringList expectedHeaderPrefixes
+ = Utils::HostOsInfo::isMacHost()
+ ? QStringList({"QtQuickTest.framework/Headers", "QtQuickTest"})
+ : QStringList({"QtQuickTest"});
+ bool pchIncludes = false;
+ for (const QString &prefix : expectedHeaderPrefixes) {
+ if (CppParser::precompiledHeaderContains(m_cppSnapshot, filePath,
+ QString("%1/quicktest.h").arg(prefix))) {
+ pchIncludes = true;
+ break;
+ }
+ }
+
+ if (pchIncludes) {
+ const QRegularExpression regex("\\bQUICK_TEST_(MAIN|OPENGL_MAIN|MAIN_WITH_SETUP)");
+ const QRegularExpressionMatch match = regex.match(QString::fromUtf8(fileContent));
+ if (match.hasMatch())
+ return match.captured(); // we do not care for the name, just return something non-empty
+ }
+ return {};
}
QList<Document::Ptr> QuickTestParser::scanDirectoryForQuickTestQmlFiles(const QString &srcDir)