forked from qt-creator/qt-creator
AutoTest: Re-implement catch parser
The AST handling is limited and fails for other macros that will be added later on. Replace the parser by using a lexer. Change-Id: Ia11f0a05eec770c703180935a64615e5090b314c Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -21,7 +21,8 @@ add_qtc_plugin(AutoTest
|
|||||||
boost/boosttestsettings.cpp boost/boosttestsettings.h
|
boost/boosttestsettings.cpp boost/boosttestsettings.h
|
||||||
boost/boosttestsettingspage.cpp boost/boosttestsettingspage.h boost/boosttestsettingspage.ui
|
boost/boosttestsettingspage.cpp boost/boosttestsettingspage.h boost/boosttestsettingspage.ui
|
||||||
boost/boosttesttreeitem.cpp boost/boosttesttreeitem.h
|
boost/boosttesttreeitem.cpp boost/boosttesttreeitem.h
|
||||||
catch/catchconfiguration.h catch/catchconfiguration.cpp
|
catch/catchcodeparser.cpp catch/catchcodeparser.h
|
||||||
|
catch/catchconfiguration.cpp catch/catchconfiguration.h
|
||||||
catch/catchframework.h catch/catchframework.cpp catch/catchoutputreader.h
|
catch/catchframework.h catch/catchframework.cpp catch/catchoutputreader.h
|
||||||
catch/catchoutputreader.cpp catch/catchresult.h catch/catchresult.cpp catch/catchtestparser.h
|
catch/catchoutputreader.cpp catch/catchresult.h catch/catchresult.cpp catch/catchtestparser.h
|
||||||
catch/catchtestparser.cpp catch/catchtreeitem.h catch/catchtreeitem.cpp
|
catch/catchtestparser.cpp catch/catchtreeitem.h catch/catchtreeitem.cpp
|
||||||
|
@@ -27,6 +27,7 @@ SOURCES += \
|
|||||||
testtreeitemdelegate.cpp \
|
testtreeitemdelegate.cpp \
|
||||||
testtreemodel.cpp \
|
testtreemodel.cpp \
|
||||||
testtreeview.cpp \
|
testtreeview.cpp \
|
||||||
|
catch/catchcodeparser.cpp \
|
||||||
catch/catchconfiguration.cpp \
|
catch/catchconfiguration.cpp \
|
||||||
catch/catchframework.cpp \
|
catch/catchframework.cpp \
|
||||||
catch/catchoutputreader.cpp \
|
catch/catchoutputreader.cpp \
|
||||||
@@ -97,6 +98,7 @@ HEADERS += \
|
|||||||
testtreeitemdelegate.h \
|
testtreeitemdelegate.h \
|
||||||
testtreemodel.h \
|
testtreemodel.h \
|
||||||
testtreeview.h \
|
testtreeview.h \
|
||||||
|
catch/catchcodeparser.h \
|
||||||
catch/catchconfiguration.h \
|
catch/catchconfiguration.h \
|
||||||
catch/catchframework.h \
|
catch/catchframework.h \
|
||||||
catch/catchoutputreader.h \
|
catch/catchoutputreader.h \
|
||||||
|
170
src/plugins/autotest/catch/catchcodeparser.cpp
Normal file
170
src/plugins/autotest/catch/catchcodeparser.cpp
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2020 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "catchcodeparser.h"
|
||||||
|
|
||||||
|
#include <cplusplus/Token.h>
|
||||||
|
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
|
#include <QRegularExpression>
|
||||||
|
|
||||||
|
namespace Autotest {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
using namespace CPlusPlus;
|
||||||
|
|
||||||
|
CatchCodeParser::CatchCodeParser(const QByteArray &source, const LanguageFeatures &features,
|
||||||
|
const Document::Ptr &doc, const Snapshot &snapshot)
|
||||||
|
: m_source(source)
|
||||||
|
, m_features(features)
|
||||||
|
, m_doc(doc)
|
||||||
|
, m_snapshot(snapshot)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static TestCodeLocationAndType locationAndTypeFromToken(const Token &tkn)
|
||||||
|
{
|
||||||
|
TestCodeLocationAndType locationAndType;
|
||||||
|
locationAndType.m_type = TestTreeItem::TestFunction;
|
||||||
|
locationAndType.m_line = tkn.lineno;
|
||||||
|
locationAndType.m_column = 0;
|
||||||
|
return locationAndType;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Tokens tokensForSource(const QByteArray &source, const LanguageFeatures &features)
|
||||||
|
{
|
||||||
|
SimpleLexer lexer;
|
||||||
|
lexer.setPreprocessorMode(false); // or true? does not make a difference so far..
|
||||||
|
lexer.setLanguageFeatures(features);
|
||||||
|
return lexer(QString::fromUtf8(source));
|
||||||
|
}
|
||||||
|
|
||||||
|
static QStringList parseTags(const QString &tagsString)
|
||||||
|
{
|
||||||
|
QStringList tagsList;
|
||||||
|
|
||||||
|
const QRegularExpression tagRegEx("\\[(.*?)\\]",QRegularExpression::CaseInsensitiveOption);
|
||||||
|
int pos = 0;
|
||||||
|
QRegularExpressionMatch it = tagRegEx.match(tagsString, pos);
|
||||||
|
while (it.hasMatch()) {
|
||||||
|
tagsList.append(it.captured(1));
|
||||||
|
pos += it.capturedLength();
|
||||||
|
it = tagRegEx.match(tagsString, pos);
|
||||||
|
}
|
||||||
|
return tagsList;
|
||||||
|
}
|
||||||
|
|
||||||
|
TestCodeLocationList CatchCodeParser::findTests()
|
||||||
|
{
|
||||||
|
m_tokens = tokensForSource(m_source, m_features);
|
||||||
|
m_currentIndex = 0;
|
||||||
|
for ( ; m_currentIndex < m_tokens.size(); ++m_currentIndex) {
|
||||||
|
const Token &token = m_tokens.at(m_currentIndex);
|
||||||
|
if (token.kind() == T_IDENTIFIER)
|
||||||
|
handleIdentifier();
|
||||||
|
}
|
||||||
|
return m_testCases;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CatchCodeParser::handleIdentifier()
|
||||||
|
{
|
||||||
|
QTC_ASSERT(m_currentIndex < m_tokens.size(), return);
|
||||||
|
const Token &token = m_tokens.at(m_currentIndex);
|
||||||
|
const QByteArray &identifier = m_source.mid(int(token.bytesBegin()), int(token.bytes()));
|
||||||
|
if (identifier == "TEST_CASE") {
|
||||||
|
handleTestCase(false);
|
||||||
|
} else if (identifier == "SCENARIO") {
|
||||||
|
handleTestCase(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CatchCodeParser::handleTestCase(bool isScenario)
|
||||||
|
{
|
||||||
|
if (!skipCommentsUntil(T_LPAREN))
|
||||||
|
return;
|
||||||
|
|
||||||
|
Token token = m_tokens.at(m_currentIndex);
|
||||||
|
TestCodeLocationAndType locationAndType = locationAndTypeFromToken(token);
|
||||||
|
|
||||||
|
Kind stoppedAt;
|
||||||
|
++m_currentIndex;
|
||||||
|
QString testCaseName = getStringLiteral(stoppedAt);
|
||||||
|
QString tagsString; // TODO: use them
|
||||||
|
|
||||||
|
if (stoppedAt == T_COMMA) {
|
||||||
|
++m_currentIndex;
|
||||||
|
tagsString = getStringLiteral(stoppedAt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stoppedAt != T_RPAREN)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (isScenario)
|
||||||
|
testCaseName.prepend("Scenario: "); // use a flag?
|
||||||
|
|
||||||
|
locationAndType.m_name = testCaseName;
|
||||||
|
m_testCases.append(locationAndType);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CatchCodeParser::getStringLiteral(Kind &stoppedAtKind)
|
||||||
|
{
|
||||||
|
QByteArray captured;
|
||||||
|
int end = m_tokens.size();
|
||||||
|
while (m_currentIndex < end) {
|
||||||
|
const Token token = m_tokens.at(m_currentIndex);
|
||||||
|
Kind kind = token.kind();
|
||||||
|
if (kind == T_STRING_LITERAL) {
|
||||||
|
// store the string without its quotes
|
||||||
|
captured.append(m_source.mid(token.bytesBegin() + 1, token.bytes() - 2));
|
||||||
|
} else if (kind == T_RPAREN || kind == T_COMMA) {
|
||||||
|
stoppedAtKind = kind;
|
||||||
|
return QString::fromUtf8(captured);
|
||||||
|
} else if (!token.isComment()) { // comments are okay - but anything else will cancel
|
||||||
|
stoppedAtKind = kind;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
++m_currentIndex;
|
||||||
|
}
|
||||||
|
stoppedAtKind = T_ERROR;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CatchCodeParser::skipCommentsUntil(Kind nextExpectedKind)
|
||||||
|
{
|
||||||
|
for (int index = m_currentIndex + 1, end = m_tokens.size(); index < end; ++index) {
|
||||||
|
const Token &token = m_tokens.at(index);
|
||||||
|
if (token.isComment())
|
||||||
|
continue;
|
||||||
|
if (token.kind() != nextExpectedKind)
|
||||||
|
break;
|
||||||
|
m_currentIndex = index;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Autotest
|
63
src/plugins/autotest/catch/catchcodeparser.h
Normal file
63
src/plugins/autotest/catch/catchcodeparser.h
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2020 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "catchtreeitem.h"
|
||||||
|
|
||||||
|
#include <cplusplus/CppDocument.h>
|
||||||
|
#include <cplusplus/SimpleLexer.h>
|
||||||
|
|
||||||
|
#include <QByteArray>
|
||||||
|
|
||||||
|
namespace Autotest {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class CatchCodeParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CatchCodeParser(const QByteArray &source, const CPlusPlus::LanguageFeatures &features,
|
||||||
|
const CPlusPlus::Document::Ptr &doc, const CPlusPlus::Snapshot &snapshot);
|
||||||
|
virtual ~CatchCodeParser() = default;
|
||||||
|
TestCodeLocationList findTests();
|
||||||
|
private:
|
||||||
|
void handleIdentifier();
|
||||||
|
void handleTestCase(bool isScenario);
|
||||||
|
|
||||||
|
QString getStringLiteral(CPlusPlus::Kind &stoppedAtKind);
|
||||||
|
bool skipCommentsUntil(CPlusPlus::Kind nextExpectedKind); // moves currentIndex if succeeds
|
||||||
|
|
||||||
|
const QByteArray &m_source;
|
||||||
|
const CPlusPlus::LanguageFeatures &m_features;
|
||||||
|
const CPlusPlus::Document::Ptr &m_doc;
|
||||||
|
const CPlusPlus::Snapshot &m_snapshot;
|
||||||
|
CPlusPlus::Tokens m_tokens;
|
||||||
|
int m_currentIndex = 0;
|
||||||
|
TestCodeLocationList m_testCases;
|
||||||
|
int m_lineNo = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Autotest
|
@@ -24,12 +24,11 @@
|
|||||||
|
|
||||||
#include "catchtestparser.h"
|
#include "catchtestparser.h"
|
||||||
|
|
||||||
|
#include "catchcodeparser.h"
|
||||||
#include "catchtreeitem.h"
|
#include "catchtreeitem.h"
|
||||||
|
|
||||||
#include <cpptools/cppmodelmanager.h>
|
#include <cpptools/cppmodelmanager.h>
|
||||||
#include <cpptools/projectpart.h>
|
#include <cpptools/projectpart.h>
|
||||||
#include <cplusplus/LookupContext.h>
|
|
||||||
#include <cplusplus/Overview.h>
|
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
@@ -37,12 +36,6 @@
|
|||||||
namespace Autotest {
|
namespace Autotest {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
struct CatchTestCaseSpec
|
|
||||||
{
|
|
||||||
QString name;
|
|
||||||
QStringList tags;
|
|
||||||
};
|
|
||||||
|
|
||||||
static bool isCatchTestCaseMacro(const QString ¯oName)
|
static bool isCatchTestCaseMacro(const QString ¯oName)
|
||||||
{
|
{
|
||||||
const QStringList validTestCaseMacros = {
|
const QStringList validTestCaseMacros = {
|
||||||
@@ -59,123 +52,6 @@ static bool isCatchMacro(const QString ¯oName)
|
|||||||
return isCatchTestCaseMacro(macroName) || validSectionMacros.contains(macroName);
|
return isCatchTestCaseMacro(macroName) || validSectionMacros.contains(macroName);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline QString stringLiteralToQString(const CPlusPlus::StringLiteral *literal)
|
|
||||||
{
|
|
||||||
return QString::fromLatin1(literal->chars(), int(literal->size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
static QStringList parseTags(const QString &tagsString)
|
|
||||||
{
|
|
||||||
QStringList tagsList;
|
|
||||||
|
|
||||||
const QRegularExpression tagRegEx("\\[(.*?)\\]",QRegularExpression::CaseInsensitiveOption);
|
|
||||||
int pos = 0;
|
|
||||||
QRegularExpressionMatch it = tagRegEx.match(tagsString, pos);
|
|
||||||
while (it.hasMatch()) {
|
|
||||||
tagsList.append(it.captured(1));
|
|
||||||
pos += it.capturedLength();
|
|
||||||
it = tagRegEx.match(tagsString, pos);
|
|
||||||
}
|
|
||||||
return tagsList;
|
|
||||||
}
|
|
||||||
|
|
||||||
class CatchTestVisitor : public CPlusPlus::ASTVisitor
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit CatchTestVisitor(CPlusPlus::Document::Ptr doc)
|
|
||||||
: CPlusPlus::ASTVisitor(doc->translationUnit()) , m_document(doc) {}
|
|
||||||
bool visit(CPlusPlus::FunctionDefinitionAST *ast) override;
|
|
||||||
|
|
||||||
QMap<CatchTestCaseSpec, TestCodeLocationAndType> testFunctions() const { return m_testFunctions; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool isValidTestCase(unsigned int macroTokenIndex, QString &testCaseName, QStringList &tags);
|
|
||||||
|
|
||||||
CPlusPlus::Document::Ptr m_document;
|
|
||||||
CPlusPlus::Overview m_overview;
|
|
||||||
QMap<CatchTestCaseSpec, TestCodeLocationAndType> m_testFunctions;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool CatchTestVisitor::visit(CPlusPlus::FunctionDefinitionAST *ast)
|
|
||||||
{
|
|
||||||
if (!ast || !ast->declarator || !ast->declarator->core_declarator)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
CPlusPlus::DeclaratorIdAST *id = ast->declarator->core_declarator->asDeclaratorId();
|
|
||||||
if (!id || !id->name)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const QString prettyName = m_overview.prettyName(id->name->name);
|
|
||||||
if (!isCatchTestCaseMacro(prettyName))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
QString testName;
|
|
||||||
QStringList tags;
|
|
||||||
if (!isValidTestCase(ast->firstToken(), testName, tags))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
CatchTestCaseSpec spec;
|
|
||||||
spec.name = testName;
|
|
||||||
if (prettyName == "SCENARIO")
|
|
||||||
spec.name.prepend("Scenario: "); // TODO maybe better as a flag?
|
|
||||||
|
|
||||||
spec.tags = tags;
|
|
||||||
|
|
||||||
TestCodeLocationAndType location;
|
|
||||||
location.m_type = TestTreeItem::TestCase;
|
|
||||||
location.m_name = m_document->fileName();
|
|
||||||
getTokenStartPosition(ast->firstToken(), &location.m_line, &location.m_column);
|
|
||||||
|
|
||||||
m_testFunctions.insert(spec, location);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CatchTestVisitor::isValidTestCase(unsigned int macroTokenIndex, QString &testCaseName, QStringList &tags)
|
|
||||||
{
|
|
||||||
QTC_ASSERT(testCaseName.isEmpty(), return false);
|
|
||||||
QTC_ASSERT(tags.isEmpty(), return false);
|
|
||||||
|
|
||||||
unsigned int end = tokenCount();
|
|
||||||
++macroTokenIndex;
|
|
||||||
|
|
||||||
enum ParseMode { TestCaseMode, TagsMode, Ignored } mode = TestCaseMode;
|
|
||||||
QString captured;
|
|
||||||
while (macroTokenIndex < end) {
|
|
||||||
CPlusPlus::Token token = tokenAt(macroTokenIndex);
|
|
||||||
if (token.kind() == CPlusPlus::T_RPAREN) {
|
|
||||||
if (mode == TagsMode)
|
|
||||||
tags = parseTags(captured);
|
|
||||||
else
|
|
||||||
testCaseName = captured;
|
|
||||||
break;
|
|
||||||
} else if (token.kind() == CPlusPlus::T_COMMA) {
|
|
||||||
if (mode == TestCaseMode) {
|
|
||||||
mode = TagsMode;
|
|
||||||
testCaseName = captured;
|
|
||||||
captured = QString();
|
|
||||||
} else if (mode == TagsMode) {
|
|
||||||
mode = Ignored;
|
|
||||||
}
|
|
||||||
} else if (token.kind() == CPlusPlus::T_STRING_LITERAL) {
|
|
||||||
if (mode != Ignored)
|
|
||||||
captured += stringLiteralToQString(stringLiteral(macroTokenIndex));
|
|
||||||
}
|
|
||||||
++macroTokenIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
return !testCaseName.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator<(const CatchTestCaseSpec &spec1, const CatchTestCaseSpec &spec2)
|
|
||||||
{
|
|
||||||
if (spec1.name != spec2.name)
|
|
||||||
return spec1.name < spec2.name;
|
|
||||||
if (spec1.tags != spec2.tags)
|
|
||||||
return spec1.tags < spec2.tags;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool includesCatchHeader(const CPlusPlus::Document::Ptr &doc,
|
static bool includesCatchHeader(const CPlusPlus::Document::Ptr &doc,
|
||||||
const CPlusPlus::Snapshot &snapshot)
|
const CPlusPlus::Snapshot &snapshot)
|
||||||
{
|
{
|
||||||
@@ -217,37 +93,30 @@ static bool handleCatchDocument(QFutureInterface<TestParseResultPtr> futureInter
|
|||||||
const CppTools::CppModelManager *modelManager = CppTools::CppModelManager::instance();
|
const CppTools::CppModelManager *modelManager = CppTools::CppModelManager::instance();
|
||||||
const QString &filePath = doc->fileName();
|
const QString &filePath = doc->fileName();
|
||||||
const QByteArray &fileContent = CppParser::getFileContent(filePath);
|
const QByteArray &fileContent = CppParser::getFileContent(filePath);
|
||||||
CPlusPlus::Document::Ptr document = snapshot.preprocessedDocument(fileContent, filePath);
|
|
||||||
document->check();
|
|
||||||
CPlusPlus::AST *ast = document->translationUnit()->ast();
|
|
||||||
CatchTestVisitor visitor(document);
|
|
||||||
visitor.accept(ast);
|
|
||||||
|
|
||||||
QMap<CatchTestCaseSpec, TestCodeLocationAndType> result = visitor.testFunctions();
|
const QList<CppTools::ProjectPart::Ptr> projectParts = modelManager->projectPart(filePath);
|
||||||
QString proFile;
|
if (projectParts.isEmpty()) // happens if shutting down while parsing
|
||||||
const QList<CppTools::ProjectPart::Ptr> &ppList = modelManager->projectPart(filePath);
|
|
||||||
if (ppList.size())
|
|
||||||
proFile = ppList.first()->projectFile;
|
|
||||||
else
|
|
||||||
return false;
|
return false;
|
||||||
|
QString proFile;
|
||||||
|
const CppTools::ProjectPart::Ptr projectPart = projectParts.first();
|
||||||
|
proFile = projectPart->projectFile;
|
||||||
|
|
||||||
|
CatchCodeParser codeParser(fileContent, projectPart->languageFeatures, doc, snapshot);
|
||||||
|
const TestCodeLocationList foundTests = codeParser.findTests();
|
||||||
|
|
||||||
CatchParseResult *parseResult = new CatchParseResult(framework);
|
CatchParseResult *parseResult = new CatchParseResult(framework);
|
||||||
parseResult->itemType = TestTreeItem::TestCase;
|
parseResult->itemType = TestTreeItem::TestCase;
|
||||||
parseResult->fileName = filePath;
|
parseResult->fileName = filePath;
|
||||||
parseResult->name = filePath;
|
parseResult->name = filePath;
|
||||||
parseResult->displayName = filePath;
|
parseResult->displayName = filePath;
|
||||||
QList<CppTools::ProjectPart::Ptr> projectParts = modelManager->projectPart(doc->fileName());
|
|
||||||
if (projectParts.isEmpty()) // happens if shutting down while parsing
|
|
||||||
return false;
|
|
||||||
parseResult->proFile = projectParts.first()->projectFile;
|
parseResult->proFile = projectParts.first()->projectFile;
|
||||||
|
|
||||||
for (const auto &testSpec : result.keys()) {
|
for (const TestCodeLocationAndType & testLocation : foundTests) {
|
||||||
const TestCodeLocationAndType &testLocation = result.value(testSpec);
|
|
||||||
CatchParseResult *testCase = new CatchParseResult(framework);
|
CatchParseResult *testCase = new CatchParseResult(framework);
|
||||||
testCase->fileName = filePath;
|
testCase->fileName = filePath;
|
||||||
testCase->name = testSpec.name;
|
testCase->name = testLocation.m_name;
|
||||||
testCase->proFile = proFile;
|
testCase->proFile = proFile;
|
||||||
testCase->itemType = TestTreeItem::TestFunction;
|
testCase->itemType = testLocation.m_type;
|
||||||
testCase->line = testLocation.m_line;
|
testCase->line = testLocation.m_line;
|
||||||
testCase->column = testLocation.m_column;
|
testCase->column = testLocation.m_column;
|
||||||
|
|
||||||
@@ -256,7 +125,7 @@ static bool handleCatchDocument(QFutureInterface<TestParseResultPtr> futureInter
|
|||||||
|
|
||||||
futureInterface.reportResult(TestParseResultPtr(parseResult));
|
futureInterface.reportResult(TestParseResultPtr(parseResult));
|
||||||
|
|
||||||
return !result.keys().isEmpty();
|
return !foundTests.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CatchTestParser::processDocument(QFutureInterface<TestParseResultPtr> futureInterface, const QString &fileName)
|
bool CatchTestParser::processDocument(QFutureInterface<TestParseResultPtr> futureInterface, const QString &fileName)
|
||||||
|
Reference in New Issue
Block a user