From 3a4592609c510dd18041cf3635d4c14477c585a6 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 9 Jul 2018 10:43:31 +0200 Subject: AutoTest: Handle direct usage of quick_test_main If users need to register additional QML types before Qt5.12 they need to bend the Quick tests magic a bit and use quick_test_main or quick_test_main_with_setup directly. The plugin supports something similar for QTest::qExec, so allow this for Quick tests as well. Task-number: QTCREATORBUG-20746 Change-Id: I672f8410914c6cc77abc901998f419dda35755ae Reviewed-by: Ivan Donchevskii --- src/plugins/autotest/quick/quicktestparser.cpp | 18 ++++++++-- src/plugins/autotest/quick/quicktestvisitors.cpp | 44 ++++++++++++++++++++++++ src/plugins/autotest/quick/quicktestvisitors.h | 16 +++++++++ 3 files changed, 75 insertions(+), 3 deletions(-) diff --git a/src/plugins/autotest/quick/quicktestparser.cpp b/src/plugins/autotest/quick/quicktestparser.cpp index 91c1bfb36e..6e9b4ae82e 100644 --- a/src/plugins/autotest/quick/quicktestparser.cpp +++ b/src/plugins/autotest/quick/quicktestparser.cpp @@ -108,7 +108,8 @@ static QString quickTestSrcDir(const CppTools::CppModelManager *cppMM, return QString(); } -static QString quickTestName(const CPlusPlus::Document::Ptr &doc) +static QString quickTestName(const CPlusPlus::Document::Ptr &doc, + const CPlusPlus::Snapshot &snapshot) { const QList macros = doc->macroUses(); @@ -122,7 +123,18 @@ static QString quickTestName(const CPlusPlus::Document::Ptr &doc) .mid(arg.bytesBegin(), arg.bytesEnd() - arg.bytesBegin())); } } - return QString(); + + // check for using quick_test_main() directly + const QString fileName = doc->fileName(); + const QByteArray &fileContent = CppParser::getFileContent(fileName); + CPlusPlus::Document::Ptr document = snapshot.preprocessedDocument(fileContent, fileName); + if (document.isNull()) + return QString(); + document->check(); + CPlusPlus::AST *ast = document->translationUnit()->ast(); + QuickTestAstVisitor astVisitor(document, snapshot); + astVisitor.accept(ast); + return astVisitor.testBaseName(); } QList QuickTestParser::scanDirectoryForQuickTestQmlFiles(const QString &srcDir) const @@ -215,7 +227,7 @@ bool QuickTestParser::handleQtQuickTest(QFutureInterface fut const Core::Id &id) { const CppTools::CppModelManager *modelManager = CppTools::CppModelManager::instance(); - if (quickTestName(document).isEmpty()) + if (quickTestName(document, m_cppSnapshot).isEmpty()) return false; const QString cppFileName = document->fileName(); diff --git a/src/plugins/autotest/quick/quicktestvisitors.cpp b/src/plugins/autotest/quick/quicktestvisitors.cpp index 9e4752821b..cbc5f9b2a2 100644 --- a/src/plugins/autotest/quick/quicktestvisitors.cpp +++ b/src/plugins/autotest/quick/quicktestvisitors.cpp @@ -25,6 +25,7 @@ #include "quicktestvisitors.h" +#include #include #include #include @@ -161,5 +162,48 @@ bool TestQmlVisitor::visit(QmlJS::AST::StringLiteral *ast) return false; } +/************************************** QuickTestAstVisitor *************************************/ + +QuickTestAstVisitor::QuickTestAstVisitor(CPlusPlus::Document::Ptr doc, + const CPlusPlus::Snapshot &snapshot) + : ASTVisitor(doc->translationUnit()) + , m_currentDoc(doc) + , m_snapshot(snapshot) +{ +} + +bool QuickTestAstVisitor::visit(CPlusPlus::CallAST *ast) +{ + if (m_currentDoc.isNull()) + return false; + + if (const auto expressionAST = ast->base_expression) { + if (const auto idExpressionAST = expressionAST->asIdExpression()) { + if (const auto simpleNameAST = idExpressionAST->name->asSimpleName()) { + const CPlusPlus::Overview o; + const QString prettyName = o.prettyName(simpleNameAST->name); + if (prettyName == "quick_test_main" || prettyName == "quick_test_main_with_setup") { + if (auto expressionListAST = ast->expression_list) { + // third argument is the one we need, so skip current and next + expressionListAST = expressionListAST->next; // argv + expressionListAST = expressionListAST ? expressionListAST->next : nullptr; // testcase literal + + if (expressionListAST && expressionListAST->value) { + const auto *stringLitAST = expressionListAST->value->asStringLiteral(); + const auto *string + = translationUnit()->stringLiteral(stringLitAST->literal_token); + if (string) { + m_testBaseName = QString::fromUtf8(string->chars(), + int(string->size())); + } + } + } + } + } + } + } + return false; +} + } // namespace Internal } // namespace Autotest diff --git a/src/plugins/autotest/quick/quicktestvisitors.h b/src/plugins/autotest/quick/quicktestvisitors.h index f131339475..025ce0198d 100644 --- a/src/plugins/autotest/quick/quicktestvisitors.h +++ b/src/plugins/autotest/quick/quicktestvisitors.h @@ -27,6 +27,8 @@ #include "quicktesttreeitem.h" +#include +#include #include #include @@ -65,5 +67,19 @@ private: bool m_expectTestCaseName = false; }; +class QuickTestAstVisitor : public CPlusPlus::ASTVisitor +{ +public: + QuickTestAstVisitor(CPlusPlus::Document::Ptr doc, const CPlusPlus::Snapshot &snapshot); + + bool visit(CPlusPlus::CallAST *ast) override; + + QString testBaseName() const { return m_testBaseName; } +private: + QString m_testBaseName; + CPlusPlus::Document::Ptr m_currentDoc; + CPlusPlus::Snapshot m_snapshot; +}; + } // namespace Internal } // namespace Autotest -- cgit v1.2.3