forked from qt-creator/qt-creator
AutoTest: Avoid invalid parse results
If the document gets updated while typing we can get different results when fetching the content and using positions inside the content which might have updated milliseconds later. Beside fetching only once ensure valid parse results by adding an additional check for the used visitor. Change-Id: Id1ba4a139a4dc497be0fbb5cf1f81004f3f8676c Reviewed-by: David Schulz <david.schulz@theqtcompany.com>
This commit is contained in:
@@ -284,9 +284,10 @@ static QString quickTestSrcDir(const CppTools::CppModelManager *cppMM,
|
|||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
static QString testClass(const CppTools::CppModelManager *modelManager,
|
static QString testClass(const CppTools::CppModelManager *modelManager, const QString &fileName)
|
||||||
CPlusPlus::Document::Ptr &document)
|
|
||||||
{
|
{
|
||||||
|
const QByteArray &fileContent = getFileContent(fileName);
|
||||||
|
CPlusPlus::Document::Ptr document = modelManager->document(fileName);
|
||||||
const QList<CPlusPlus::Document::MacroUse> macros = document->macroUses();
|
const QList<CPlusPlus::Document::MacroUse> macros = document->macroUses();
|
||||||
|
|
||||||
foreach (const CPlusPlus::Document::MacroUse ¯o, macros) {
|
foreach (const CPlusPlus::Document::MacroUse ¯o, macros) {
|
||||||
@@ -295,14 +296,13 @@ static QString testClass(const CppTools::CppModelManager *modelManager,
|
|||||||
const QByteArray name = macro.macro().name();
|
const QByteArray name = macro.macro().name();
|
||||||
if (TestUtils::isQTestMacro(name)) {
|
if (TestUtils::isQTestMacro(name)) {
|
||||||
const CPlusPlus::Document::Block arg = macro.arguments().at(0);
|
const CPlusPlus::Document::Block arg = macro.arguments().at(0);
|
||||||
return QLatin1String(getFileContent(document->fileName())
|
return QLatin1String(fileContent.mid(arg.bytesBegin(),
|
||||||
.mid(arg.bytesBegin(), arg.bytesEnd() - arg.bytesBegin()));
|
arg.bytesEnd() - arg.bytesBegin()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// check if one has used a self-defined macro or QTest::qExec() directly
|
// check if one has used a self-defined macro or QTest::qExec() directly
|
||||||
const CPlusPlus::Snapshot snapshot = modelManager->snapshot();
|
const CPlusPlus::Snapshot snapshot = modelManager->snapshot();
|
||||||
const QByteArray fileContent = getFileContent(document->fileName());
|
document = snapshot.preprocessedDocument(fileContent, fileName);
|
||||||
document = snapshot.preprocessedDocument(fileContent, document->fileName());
|
|
||||||
document->check();
|
document->check();
|
||||||
CPlusPlus::AST *ast = document->translationUnit()->ast();
|
CPlusPlus::AST *ast = document->translationUnit()->ast();
|
||||||
TestAstVisitor astVisitor(document);
|
TestAstVisitor astVisitor(document);
|
||||||
@@ -523,7 +523,7 @@ static void checkDocumentForTestCode(QFutureInterface<TestParseResult> futureInt
|
|||||||
} else if (testCaseNames.contains(fileName) // if we do a reparse
|
} else if (testCaseNames.contains(fileName) // if we do a reparse
|
||||||
|| (includesQtTest(document, modelManager)
|
|| (includesQtTest(document, modelManager)
|
||||||
&& qtTestLibDefined(modelManager, fileName))) {
|
&& qtTestLibDefined(modelManager, fileName))) {
|
||||||
QString testCaseName(testClass(modelManager, document));
|
QString testCaseName(testClass(modelManager, fileName));
|
||||||
// we might be in a reparse without the original entry point with the QTest::qExec()
|
// we might be in a reparse without the original entry point with the QTest::qExec()
|
||||||
if (testCaseName.isEmpty())
|
if (testCaseName.isEmpty())
|
||||||
testCaseName = testCaseNames.value(fileName);
|
testCaseName = testCaseNames.value(fileName);
|
||||||
@@ -537,6 +537,10 @@ static void checkDocumentForTestCode(QFutureInterface<TestParseResult> futureInt
|
|||||||
|
|
||||||
TestVisitor visitor(testCaseName);
|
TestVisitor visitor(testCaseName);
|
||||||
visitor.accept(declaringDoc->globalNamespace());
|
visitor.accept(declaringDoc->globalNamespace());
|
||||||
|
|
||||||
|
if (!visitor.resultValid())
|
||||||
|
return;
|
||||||
|
|
||||||
const QMap<QString, TestCodeLocationAndType> testFunctions = visitor.privateSlots();
|
const QMap<QString, TestCodeLocationAndType> testFunctions = visitor.privateSlots();
|
||||||
|
|
||||||
QMap<QString, TestCodeLocationList> dataTags =
|
QMap<QString, TestCodeLocationList> dataTags =
|
||||||
|
|||||||
@@ -73,6 +73,8 @@ bool TestVisitor::visit(CPlusPlus::Class *symbol)
|
|||||||
if (className != m_className)
|
if (className != m_className)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
m_valid = true;
|
||||||
|
|
||||||
if (const auto func = type->asFunctionType()) {
|
if (const auto func = type->asFunctionType()) {
|
||||||
if (func->isSlot() && member->isPrivate()) {
|
if (func->isSlot() && member->isPrivate()) {
|
||||||
const QString name = o.prettyName(func->name());
|
const QString name = o.prettyName(func->name());
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ public:
|
|||||||
virtual ~TestVisitor();
|
virtual ~TestVisitor();
|
||||||
|
|
||||||
QMap<QString, TestCodeLocationAndType> privateSlots() const { return m_privSlots; }
|
QMap<QString, TestCodeLocationAndType> privateSlots() const { return m_privSlots; }
|
||||||
|
bool resultValid() const { return m_valid; }
|
||||||
|
|
||||||
bool visit(CPlusPlus::Class *symbol);
|
bool visit(CPlusPlus::Class *symbol);
|
||||||
|
|
||||||
@@ -59,6 +60,7 @@ private:
|
|||||||
CppTools::SymbolFinder m_symbolFinder;
|
CppTools::SymbolFinder m_symbolFinder;
|
||||||
QString m_className;
|
QString m_className;
|
||||||
QMap<QString, TestCodeLocationAndType> m_privSlots;
|
QMap<QString, TestCodeLocationAndType> m_privSlots;
|
||||||
|
bool m_valid = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TestAstVisitor : public CPlusPlus::ASTVisitor
|
class TestAstVisitor : public CPlusPlus::ASTVisitor
|
||||||
|
|||||||
Reference in New Issue
Block a user