diff options
Diffstat (limited to 'src/plugins/autotest/qtest/qttestparser.cpp')
-rw-r--r-- | src/plugins/autotest/qtest/qttestparser.cpp | 171 |
1 files changed, 97 insertions, 74 deletions
diff --git a/src/plugins/autotest/qtest/qttestparser.cpp b/src/plugins/autotest/qtest/qttestparser.cpp index 29e861a927..d1c27723fc 100644 --- a/src/plugins/autotest/qtest/qttestparser.cpp +++ b/src/plugins/autotest/qtest/qttestparser.cpp @@ -81,7 +81,7 @@ static bool includesQtTest(const CPlusPlus::Document::Ptr &doc, const CPlusPlus: return false; } -static bool qtTestLibDefined(const QString &fileName) +static bool qtTestLibDefined(const Utils::FilePath &fileName) { const QList<CppTools::ProjectPart::Ptr> parts = CppTools::CppModelManager::instance()->projectPart(fileName); @@ -93,10 +93,11 @@ static bool qtTestLibDefined(const QString &fileName) return false; } -QString QtTestParser::testClass(const CppTools::CppModelManager *modelManager, const QString &fileName) const +QString QtTestParser::testClass(const CppTools::CppModelManager *modelManager, + const Utils::FilePath &fileName) const { const QByteArray &fileContent = getFileContent(fileName); - CPlusPlus::Document::Ptr document = modelManager->document(fileName); + CPlusPlus::Document::Ptr document = modelManager->document(fileName.toString()); if (document.isNull()) return QString(); @@ -124,7 +125,7 @@ QString QtTestParser::testClass(const CppTools::CppModelManager *modelManager, c static CPlusPlus::Document::Ptr declaringDocument(CPlusPlus::Document::Ptr doc, const CPlusPlus::Snapshot &snapshot, const QString &testCaseName, - const QStringList &alternativeFiles = {}, + const Utils::FilePaths &alternativeFiles = {}, int *line = nullptr, int *column = nullptr) { @@ -136,7 +137,7 @@ static CPlusPlus::Document::Ptr declaringDocument(CPlusPlus::Document::Ptr doc, doc->globalNamespace()); // fallback for inherited functions if (lookupItems.size() == 0 && !alternativeFiles.isEmpty()) { - for (const QString &alternativeFile : alternativeFiles) { + for (const Utils::FilePath &alternativeFile : alternativeFiles) { if (snapshot.contains(alternativeFile)) { CPlusPlus::Document::Ptr document = snapshot.document(alternativeFile); CPlusPlus::TypeOfExpression typeOfExpr; // we need a new one with no bindings @@ -181,7 +182,7 @@ static QSet<QString> filesWithDataFunctionDefinitions( QHash<QString, QtTestCodeLocationList> QtTestParser::checkForDataTags(const QString &fileName) const { - const QByteArray fileContent = getFileContent(fileName); + const QByteArray fileContent = getFileContent(Utils::FilePath::fromString(fileName)); CPlusPlus::Document::Ptr document = m_cppSnapshot.preprocessedDocument(fileContent, fileName); document->check(); CPlusPlus::AST *ast = document->translationUnit()->ast(); @@ -278,7 +279,7 @@ static bool isQObject(const CPlusPlus::Document::Ptr &declaringDoc) } bool QtTestParser::processDocument(QFutureInterface<TestParseResultPtr> futureInterface, - const QString &fileName) + const Utils::FilePath &fileName) { CPlusPlus::Document::Ptr doc = document(fileName); if (doc.isNull()) @@ -293,84 +294,106 @@ bool QtTestParser::processDocument(QFutureInterface<TestParseResultPtr> futureIn if (testCaseName.isEmpty()) testCaseName = oldTestCaseName; if (!testCaseName.isEmpty()) { - int line = 0; - int column = 0; - const QStringList &alternativeFiles = m_alternativeFiles.values(fileName); - CPlusPlus::Document::Ptr declaringDoc = declaringDocument(doc, m_cppSnapshot, testCaseName, - alternativeFiles, &line, &column); - if (declaringDoc.isNull()) - return false; - - TestVisitor visitor(testCaseName, m_cppSnapshot); - visitor.accept(declaringDoc->globalNamespace()); - if (!visitor.resultValid()) - return false; + TestCaseData data; + Utils::optional<bool> earlyReturn = fillTestCaseData(testCaseName, doc, data); + if (earlyReturn.has_value()) + return earlyReturn.value(); - QMap<QString, QtTestCodeLocationAndType> testFunctions = visitor.privateSlots(); - // gather appropriate information of base classes as well and merge into already found - // functions - but only as far as QtTest can handle this appropriate - fetchAndMergeBaseTestFunctions( - visitor.baseClasses(), testFunctions, declaringDoc, m_cppSnapshot); - - // handle tests that are not runnable without more information (plugin unit test of QC) - if (testFunctions.isEmpty() && testCaseName == "QObject" && isQObject(declaringDoc)) - return true; // we did not handle it, but we do not expect any test defined there either - - const QSet<QString> &files = filesWithDataFunctionDefinitions(testFunctions); - - QHash<QString, QtTestCodeLocationList> dataTags; - for (const QString &file : files) - Utils::addToHash(&dataTags, checkForDataTags(file)); - - QtTestParseResult *parseResult = new QtTestParseResult(framework()); - parseResult->itemType = TestTreeItem::TestCase; - parseResult->fileName = declaringDoc->fileName(); - parseResult->name = testCaseName; - parseResult->displayName = testCaseName; - parseResult->line = line; - parseResult->column = column; QList<CppTools::ProjectPart::Ptr> projectParts = modelManager->projectPart(fileName); if (projectParts.isEmpty()) // happens if shutting down while parsing return false; - parseResult->proFile = projectParts.first()->projectFile; - QMap<QString, QtTestCodeLocationAndType>::ConstIterator it = testFunctions.begin(); - const QMap<QString, QtTestCodeLocationAndType>::ConstIterator end = testFunctions.end(); - for ( ; it != end; ++it) { - const QtTestCodeLocationAndType &location = it.value(); - QString functionName = it.key(); - functionName = functionName.mid(functionName.lastIndexOf(':') + 1); - QtTestParseResult *func = new QtTestParseResult(framework()); - func->itemType = location.m_type; - func->name = testCaseName + "::" + functionName; - func->displayName = functionName; - func->fileName = location.m_name; - func->line = location.m_line; - func->column = location.m_column; - func->setInherited(location.m_inherited); - - const QtTestCodeLocationList &tagLocations = tagLocationsFor(func, dataTags); - for (const QtTestCodeLocationAndType &tag : tagLocations) { - QtTestParseResult *dataTag = new QtTestParseResult(framework()); - dataTag->itemType = tag.m_type; - dataTag->name = tag.m_name; - dataTag->displayName = tag.m_name; - dataTag->fileName = testFunctions.value(it.key() + "_data").m_name; - dataTag->line = tag.m_line; - dataTag->column = tag.m_column; - dataTag->setInherited(tag.m_inherited); - - func->children.append(dataTag); - } - parseResult->children.append(func); - } + QtTestParseResult *parseResult + = createParseResult(testCaseName, data, projectParts.first()->projectFile); futureInterface.reportResult(TestParseResultPtr(parseResult)); return true; } return false; } -void QtTestParser::init(const QStringList &filesToParse, bool fullParse) +Utils::optional<bool> QtTestParser::fillTestCaseData( + const QString &testCaseName, const CPlusPlus::Document::Ptr &doc, + TestCaseData &data) const +{ + const Utils::FilePath filePath = Utils::FilePath::fromString(doc->fileName()); + const Utils::FilePaths &alternativeFiles = m_alternativeFiles.values(filePath); + CPlusPlus::Document::Ptr declaringDoc = declaringDocument(doc, m_cppSnapshot, testCaseName, + alternativeFiles, + &(data.line), &(data.column)); + if (declaringDoc.isNull()) + return false; + + TestVisitor visitor(testCaseName, m_cppSnapshot); + visitor.accept(declaringDoc->globalNamespace()); + if (!visitor.resultValid()) + return false; + + data.testFunctions = visitor.privateSlots(); + // gather appropriate information of base classes as well and merge into already found + // functions - but only as far as QtTest can handle this appropriate + fetchAndMergeBaseTestFunctions( + visitor.baseClasses(), data.testFunctions, declaringDoc, m_cppSnapshot); + + // handle tests that are not runnable without more information (plugin unit test of QC) + if (data.testFunctions.isEmpty() && testCaseName == "QObject" && isQObject(declaringDoc)) + return true; // we did not handle it, but we do not expect any test defined there either + + const QSet<QString> &files = filesWithDataFunctionDefinitions(data.testFunctions); + + for (const QString &file : files) + Utils::addToHash(&(data.dataTags), checkForDataTags(file)); + + data.fileName = Utils::FilePath::fromString(declaringDoc->fileName()); + data.valid = true; + return Utils::optional<bool>(); +} + +QtTestParseResult *QtTestParser::createParseResult( + const QString &testCaseName, const TestCaseData &data, const QString &projectFile) const +{ + QtTestParseResult *parseResult = new QtTestParseResult(framework()); + parseResult->itemType = TestTreeItem::TestCase; + parseResult->fileName = data.fileName; + parseResult->name = testCaseName; + parseResult->displayName = testCaseName; + parseResult->line = data.line; + parseResult->column = data.column; + parseResult->proFile = Utils::FilePath::fromString(projectFile); + QMap<QString, QtTestCodeLocationAndType>::ConstIterator it = data.testFunctions.begin(); + const QMap<QString, QtTestCodeLocationAndType>::ConstIterator end = data.testFunctions.end(); + for ( ; it != end; ++it) { + const QtTestCodeLocationAndType &location = it.value(); + QString functionName = it.key(); + functionName = functionName.mid(functionName.lastIndexOf(':') + 1); + QtTestParseResult *func = new QtTestParseResult(framework()); + func->itemType = location.m_type; + func->name = testCaseName + "::" + functionName; + func->displayName = functionName; + func->fileName = Utils::FilePath::fromString(location.m_name); + func->line = location.m_line; + func->column = location.m_column; + func->setInherited(location.m_inherited); + + const QtTestCodeLocationList &tagLocations = tagLocationsFor(func, data.dataTags); + for (const QtTestCodeLocationAndType &tag : tagLocations) { + QtTestParseResult *dataTag = new QtTestParseResult(framework()); + dataTag->itemType = tag.m_type; + dataTag->name = tag.m_name; + dataTag->displayName = tag.m_name; + dataTag->fileName = Utils::FilePath::fromString( + data.testFunctions.value(it.key() + "_data").m_name); + dataTag->line = tag.m_line; + dataTag->column = tag.m_column; + dataTag->setInherited(tag.m_inherited); + + func->children.append(dataTag); + } + parseResult->children.append(func); + } + return parseResult; +} + +void QtTestParser::init(const Utils::FilePaths &filesToParse, bool fullParse) { if (!fullParse) { // in a full parse cached information might lead to wrong results m_testCaseNames = QTestUtils::testCaseNamesForFiles(framework(), filesToParse); |