AutoTest: Simplify caching for test information

We only need the referencing file in some cases.
First step for refactoring the code parser and the test tree model.

Change-Id: I713212461e4992863ef11a0a634c5d8d786a72a9
Reviewed-by: Niels Weber <niels.weber@theqtcompany.com>
This commit is contained in:
Christian Stenger
2016-01-25 08:40:36 +01:00
parent 9074a8c310
commit 9a0941277b
5 changed files with 72 additions and 109 deletions

View File

@@ -565,13 +565,13 @@ void TestCodeParser::checkDocumentForTestCode(CPlusPlus::Document::Ptr document)
// could not find the class to test, or QTest is not included and QT_TESTLIB_LIB defined // could not find the class to test, or QTest is not included and QT_TESTLIB_LIB defined
// maybe file is only a referenced file // maybe file is only a referenced file
if (m_cppDocMap.contains(fileName)) { if (m_referencingFiles.contains(fileName)) {
const TestInfo info = m_cppDocMap[fileName]; const ReferencingInfo &info = m_referencingFiles[fileName];
CPlusPlus::Snapshot snapshot = modelManager->snapshot(); CPlusPlus::Snapshot snapshot = modelManager->snapshot();
if (snapshot.contains(info.referencingFile())) { if (snapshot.contains(info.referencingFile)) {
checkDocumentForTestCode(snapshot.find(info.referencingFile()).value()); checkDocumentForTestCode(snapshot.find(info.referencingFile).value());
} else { // no referencing file too, so this test case is no more a test case } else { // no referencing file too, so this test case is no more a test case
m_cppDocMap.remove(fileName); m_referencingFiles.remove(fileName);
emit testItemsRemoved(fileName, TestTreeModel::AutoTest); emit testItemsRemoved(fileName, TestTreeModel::AutoTest);
} }
} }
@@ -644,12 +644,7 @@ void TestCodeParser::onCppDocumentUpdated(const CPlusPlus::Document::Ptr &docume
if (!project) if (!project)
return; return;
const QString fileName = document->fileName(); const QString fileName = document->fileName();
if (m_cppDocMap.contains(fileName)) { if (!project->files(ProjectExplorer::Project::AllFiles).contains(fileName)) {
if (m_cppDocMap[fileName].revision() == document->revision()
&& m_cppDocMap[fileName].editorRevision() == document->editorRevision()) {
return;
}
} else if (!project->files(ProjectExplorer::Project::AllFiles).contains(fileName)) {
return; return;
} }
qCDebug(LOG) << "calling scanForTests (onCppDocumentUpdated)"; qCDebug(LOG) << "calling scanForTests (onCppDocumentUpdated)";
@@ -670,22 +665,21 @@ void TestCodeParser::onQmlDocumentUpdated(const QmlJS::Document::Ptr &document)
if (!project) if (!project)
return; return;
const QString fileName = document->fileName(); const QString fileName = document->fileName();
if (m_quickDocMap.contains(fileName)) { if (!project->files(ProjectExplorer::Project::AllFiles).contains(fileName)) {
if ((int)m_quickDocMap[fileName].editorRevision() == document->editorRevision()) {
return;
}
} else if (!project->files(ProjectExplorer::Project::AllFiles).contains(fileName)) {
// what if the file is not listed inside the pro file, but will be used anyway? // what if the file is not listed inside the pro file, but will be used anyway?
return; return;
} }
const CPlusPlus::Snapshot snapshot = CppTools::CppModelManager::instance()->snapshot(); const CPlusPlus::Snapshot snapshot = CppTools::CppModelManager::instance()->snapshot();
if (m_quickDocMap.contains(fileName) if (m_referencingFiles.contains(fileName)) {
&& snapshot.contains(m_quickDocMap[fileName].referencingFile())) { const ReferencingInfo &refInfo = m_referencingFiles.value(fileName);
if (!m_quickDocMap[fileName].referencingFile().isEmpty()) { if (refInfo.type == TestTreeModel::QuickTest
&& snapshot.contains(refInfo.referencingFile)) {
if (!refInfo.referencingFile.isEmpty()) {
qCDebug(LOG) << "calling scanForTests with cached referencing files" qCDebug(LOG) << "calling scanForTests with cached referencing files"
<< "(onQmlDocumentUpdated)"; << "(onQmlDocumentUpdated)";
scanForTests(QStringList(m_quickDocMap[fileName].referencingFile())); scanForTests(QStringList(refInfo.referencingFile));
} }
}
} }
if (m_unnamedQuickDocList.size() == 0) if (m_unnamedQuickDocList.size() == 0)
return; return;
@@ -819,10 +813,8 @@ void TestCodeParser::scanForTests(const QStringList &fileList)
void TestCodeParser::clearCache() void TestCodeParser::clearCache()
{ {
m_cppDocMap.clear(); m_referencingFiles.clear();
m_quickDocMap.clear();
m_unnamedQuickDocList.clear(); m_unnamedQuickDocList.clear();
m_gtestDocMap.clear();
m_gtestDocList.clear(); m_gtestDocList.clear();
emit cacheCleared(); emit cacheCleared();
} }
@@ -830,25 +822,28 @@ void TestCodeParser::clearCache()
void TestCodeParser::removeTestsIfNecessary(const QString &fileName) void TestCodeParser::removeTestsIfNecessary(const QString &fileName)
{ {
// check if this file was listed before and remove if necessary (switched config,...) // check if this file was listed before and remove if necessary (switched config,...)
if (m_cppDocMap.contains(fileName)) { if (m_referencingFiles.contains(fileName)
m_cppDocMap.remove(fileName); && m_referencingFiles.value(fileName).type == TestTreeModel::AutoTest) {
m_referencingFiles.remove(fileName);
emit testItemsRemoved(fileName, TestTreeModel::AutoTest); emit testItemsRemoved(fileName, TestTreeModel::AutoTest);
} else if (m_gtestDocMap.contains(fileName)) { } else if (m_referencingFiles.contains(fileName)
m_gtestDocMap.remove(fileName); && m_referencingFiles.value(fileName).type == TestTreeModel::GoogleTest) {
m_referencingFiles.remove(fileName);
emit testItemsRemoved(fileName, TestTreeModel::GoogleTest); emit testItemsRemoved(fileName, TestTreeModel::GoogleTest);
} else { // handle Qt Quick Tests } else { // handle Qt Quick Tests
QList<QString> toBeRemoved; QList<QString> toBeRemoved;
foreach (const QString &file, m_quickDocMap.keys()) { foreach (const QString &file, m_referencingFiles.keys()) {
if (file == fileName) { if (file == fileName
&& m_referencingFiles.value(file).type == TestTreeModel::QuickTest) {
toBeRemoved.append(file); toBeRemoved.append(file);
continue; continue;
} }
const TestInfo info = m_quickDocMap.value(file); const ReferencingInfo &refInfo = m_referencingFiles.value(file);
if (info.referencingFile() == fileName) if (refInfo.type == TestTreeModel::QuickTest && refInfo.referencingFile == fileName)
toBeRemoved.append(file); toBeRemoved.append(file);
} }
foreach (const QString &file, toBeRemoved) { foreach (const QString &file, toBeRemoved) {
m_quickDocMap.remove(file); m_referencingFiles.remove(file);
emit testItemsRemoved(file, TestTreeModel::QuickTest); emit testItemsRemoved(file, TestTreeModel::QuickTest);
} }
// unnamed Quick Tests must be handled separately // unnamed Quick Tests must be handled separately
@@ -943,7 +938,7 @@ void TestCodeParser::updateUnnamedQuickTests(const QString &fileName, const QStr
const QMap<QString, TestCodeLocationAndType> &functions) const QMap<QString, TestCodeLocationAndType> &functions)
{ {
// if this test case was named before remove it // if this test case was named before remove it
m_quickDocMap.remove(fileName); m_referencingFiles.remove(fileName);
emit testItemsRemoved(fileName, TestTreeModel::QuickTest); emit testItemsRemoved(fileName, TestTreeModel::QuickTest);
removeUnnamedQuickTestsByName(fileName); removeUnnamedQuickTestsByName(fileName);
@@ -966,29 +961,28 @@ void TestCodeParser::updateModelAndCppDocMap(CPlusPlus::Document::Ptr document,
if (ppList.size()) if (ppList.size())
proFile = ppList.at(0)->projectFile; proFile = ppList.at(0)->projectFile;
if (m_cppDocMap.contains(fileName)) { if (m_referencingFiles.contains(fileName)
&& m_referencingFiles.value(fileName).type == TestTreeModel::AutoTest) {
QStringList files = { fileName }; QStringList files = { fileName };
if (fileName != declaringFile) if (fileName != declaringFile)
files << declaringFile; files << declaringFile;
foreach (const QString &file, files) { foreach (const QString &file, files) {
const bool setReferencingFile = (files.size() == 2 && file == declaringFile); const bool setReferencingFile = (files.size() == 2 && file == declaringFile);
TestInfo testInfo(testCaseName, testItem->getChildNames(), ReferencingInfo testInfo;
document->revision(), document->editorRevision());
testInfo.setProFile(proFile);
if (setReferencingFile) if (setReferencingFile)
testInfo.setReferencingFile(fileName); testInfo.referencingFile = fileName;
m_cppDocMap.insert(file, testInfo); testInfo.type = TestTreeModel::AutoTest;
m_referencingFiles.insert(file, testInfo);
} }
emit testItemModified(testItem, TestTreeModel::AutoTest, files); emit testItemModified(testItem, TestTreeModel::AutoTest, files);
} else { } else {
emit testItemCreated(testItem, TestTreeModel::AutoTest); emit testItemCreated(testItem, TestTreeModel::AutoTest);
TestInfo ti(testCaseName, testItem->getChildNames(), ReferencingInfo testInfo;
document->revision(), document->editorRevision()); testInfo.type = TestTreeModel::AutoTest;
ti.setProFile(proFile); m_referencingFiles.insert(fileName, testInfo);
m_cppDocMap.insert(fileName, ti);
if (declaringFile != fileName) { if (declaringFile != fileName) {
ti.setReferencingFile(fileName); testInfo.referencingFile = fileName;
m_cppDocMap.insert(declaringFile, ti); m_referencingFiles.insert(declaringFile, testInfo);
} }
} }
} }
@@ -1004,22 +998,23 @@ void TestCodeParser::updateModelAndQuickDocMap(QmlJS::Document::Ptr document,
if (ppList.size()) if (ppList.size())
proFile = ppList.at(0)->projectFile; proFile = ppList.at(0)->projectFile;
if (m_quickDocMap.contains(fileName)) { if (m_referencingFiles.contains(fileName)
TestInfo testInfo(testItem->name(), testItem->getChildNames(), 0, document->editorRevision()); && m_referencingFiles.value(fileName).type == TestTreeModel::QuickTest) {
testInfo.setReferencingFile(referencingFile); ReferencingInfo testInfo;
testInfo.setProFile(proFile); testInfo.referencingFile = referencingFile;
testInfo.type = TestTreeModel::QuickTest;
emit testItemModified(testItem, TestTreeModel::QuickTest, { fileName }); emit testItemModified(testItem, TestTreeModel::QuickTest, { fileName });
m_quickDocMap.insert(fileName, testInfo); m_referencingFiles.insert(fileName, testInfo);
} else { } else {
// if it was formerly unnamed remove the respective items // if it was formerly unnamed remove the respective items
removeUnnamedQuickTestsByName(fileName); removeUnnamedQuickTestsByName(fileName);
const QString &filePath = testItem->filePath(); const QString &filePath = testItem->filePath();
TestInfo testInfo(testItem->name(), testItem->getChildNames(), 0, document->editorRevision()); ReferencingInfo testInfo;
testInfo.setReferencingFile(referencingFile); testInfo.referencingFile = referencingFile;
testInfo.setProFile(proFile); testInfo.type = TestTreeModel::QuickTest;
emit testItemCreated(testItem, TestTreeModel::QuickTest); emit testItemCreated(testItem, TestTreeModel::QuickTest);
m_quickDocMap.insert(filePath, testInfo); m_referencingFiles.insert(filePath, testInfo);
} }
} }
@@ -1037,8 +1032,9 @@ void TestCodeParser::updateGTests(const CPlusPlus::Document::Ptr &doc,
foreach (const GTestCaseSpec &testSpec, tests.keys()) { foreach (const GTestCaseSpec &testSpec, tests.keys()) {
TestTreeItem *item = constructGTestTreeItem(fileName, testSpec, proFile, tests.value(testSpec)); TestTreeItem *item = constructGTestTreeItem(fileName, testSpec, proFile, tests.value(testSpec));
TestInfo info(item->name(), item->getChildNames(), doc->revision(), doc->editorRevision()); ReferencingInfo testInfo;
info.setProFile(proFile); testInfo.type = TestTreeModel::GoogleTest;
foreach (const TestCodeLocationAndType &testSet, tests.value(testSpec)) { foreach (const TestCodeLocationAndType &testSet, tests.value(testSpec)) {
GTestInfo gtestInfo(testSpec.testCaseName, testSet.m_name, fileName); GTestInfo gtestInfo(testSpec.testCaseName, testSet.m_name, fileName);
if (testSet.m_state & TestTreeItem::Disabled) if (testSet.m_state & TestTreeItem::Disabled)
@@ -1046,7 +1042,7 @@ void TestCodeParser::updateGTests(const CPlusPlus::Document::Ptr &doc,
m_gtestDocList.append(gtestInfo); m_gtestDocList.append(gtestInfo);
} }
emit testItemCreated(item, TestTreeModel::GoogleTest); emit testItemCreated(item, TestTreeModel::GoogleTest);
m_gtestDocMap.insert(fileName, info); m_referencingFiles.insert(fileName, testInfo);
} }
} }
@@ -1072,8 +1068,9 @@ void TestCodeParser::removeGTestsByName(const QString &fileName)
int TestCodeParser::autoTestsCount() const int TestCodeParser::autoTestsCount() const
{ {
int count = 0; int count = 0;
foreach (const QString &file, m_cppDocMap.keys()) { foreach (const QString &file, m_referencingFiles.keys()) {
if (m_cppDocMap.value(file).referencingFile().isEmpty()) const ReferencingInfo &refInfo = m_referencingFiles.value(file);
if (refInfo.type == TestTreeModel::AutoTest && refInfo.referencingFile.isEmpty())
++count; ++count;
} }
return count; return count;
@@ -1081,7 +1078,13 @@ int TestCodeParser::autoTestsCount() const
int TestCodeParser::namedQuickTestsCount() const int TestCodeParser::namedQuickTestsCount() const
{ {
return m_quickDocMap.size(); int count = 0;
foreach (const QString &file, m_referencingFiles.keys()) {
const ReferencingInfo &refInfo = m_referencingFiles.value(file);
if (refInfo.type == TestTreeModel::QuickTest)
++count;
}
return count;
} }
int TestCodeParser::unnamedQuickTestsCount() const int TestCodeParser::unnamedQuickTestsCount() const

View File

@@ -44,7 +44,6 @@ namespace Autotest {
namespace Internal { namespace Internal {
struct TestCodeLocationAndType; struct TestCodeLocationAndType;
class TestInfo;
class UnnamedQuickTestInfo; class UnnamedQuickTestInfo;
class GTestInfo; class GTestInfo;
struct GTestCaseSpec; struct GTestCaseSpec;
@@ -122,9 +121,15 @@ private:
void removeGTestsByName(const QString &fileName); void removeGTestsByName(const QString &fileName);
TestTreeModel *m_model; TestTreeModel *m_model;
QMap<QString, TestInfo> m_cppDocMap;
QMap<QString, TestInfo> m_quickDocMap; // FIXME remove me again
QMap<QString, TestInfo> m_gtestDocMap; struct ReferencingInfo
{
QString referencingFile;
TestTreeModel::Type type;
};
QMap<QString, ReferencingInfo> m_referencingFiles;
QList<UnnamedQuickTestInfo> m_unnamedQuickDocList; QList<UnnamedQuickTestInfo> m_unnamedQuickDocList;
QList<GTestInfo> m_gtestDocList; QList<GTestInfo> m_gtestDocList;
bool m_codeModelParsing; bool m_codeModelParsing;

View File

@@ -28,20 +28,6 @@
namespace Autotest { namespace Autotest {
namespace Internal { namespace Internal {
TestInfo::TestInfo(const QString &className, const QStringList &functions, unsigned revision,
unsigned editorRevision)
: m_className(className),
m_functions(functions),
m_revision(revision),
m_editorRevision(editorRevision)
{
}
TestInfo::~TestInfo()
{
m_functions.clear();
}
UnnamedQuickTestInfo::UnnamedQuickTestInfo(const QString &function, const QString &fileName) UnnamedQuickTestInfo::UnnamedQuickTestInfo(const QString &function, const QString &fileName)
: m_function(function), : m_function(function),
m_fileName(fileName) m_fileName(fileName)

View File

@@ -31,36 +31,6 @@
namespace Autotest { namespace Autotest {
namespace Internal { namespace Internal {
class TestInfo
{
public:
explicit TestInfo(const QString &className = QString(),
const QStringList &functions = QStringList(),
unsigned revision = 0, unsigned editorRevision = 0);
~TestInfo();
const QString testClass() const { return m_className; }
void setTestClass(const QString &className) { m_className = className; }
const QStringList testFunctions() const { return m_functions; }
void setTestFunctions(const QStringList &functions) { m_functions = functions; }
unsigned revision() const { return m_revision; }
void setRevision(unsigned revision) { m_revision = revision; }
unsigned editorRevision() const { return m_editorRevision; }
void setEditorRevision(unsigned editorRevision) { m_editorRevision = editorRevision; }
const QString referencingFile() const { return m_referencingFile; }
void setReferencingFile(const QString &refFile) { m_referencingFile = refFile; }
const QString proFile() const { return m_proFile; }
void setProFile(const QString &proFile) { m_proFile = proFile; }
private:
QString m_className;
QStringList m_functions;
unsigned m_revision;
unsigned m_editorRevision;
QString m_referencingFile;
QString m_proFile;
};
class UnnamedQuickTestInfo { class UnnamedQuickTestInfo {
public: public:
explicit UnnamedQuickTestInfo(const QString &function = QString(), explicit UnnamedQuickTestInfo(const QString &function = QString(),

View File

@@ -39,7 +39,6 @@ namespace Internal {
struct TestCodeLocationAndType; struct TestCodeLocationAndType;
class TestCodeParser; class TestCodeParser;
class TestInfo;
class TestTreeItem; class TestTreeItem;
class TestTreeModel : public Utils::TreeModel class TestTreeModel : public Utils::TreeModel