Commit 7c06e4b7 authored by Christian Stenger's avatar Christian Stenger
Browse files

Be more generic regarding supported project types



This removes the hard dependency on QmakeProjectManager.
Furthermore now unneeded code is removed and some parts
of the parsing are slightly modified to support other
project types than qmake based projects.

Change-Id: I1c23056d5a444ddea857e10fdb71264eb6ecc269
Reviewed-by: default avatarChristian Kandeler <christian.kandeler@theqtcompany.com>
Reviewed-by: default avatarNiels Weber <niels.weber@theqtcompany.com>
parent 4fbc020d
......@@ -7,11 +7,14 @@ QtcCommercialPlugin {
Depends { name: "CppTools" }
Depends { name: "CPlusPlus" }
Depends { name: "ProjectExplorer" }
Depends { name: "QmakeProjectManager" }
Depends { name: "QmlJS" }
Depends { name: "QmlJSTools" }
Depends { name: "Utils" }
pluginTestDepends: [
"QmakeProjectManager"
]
Depends {
name: "QtSupport"
condition: project.testsEnabled
......
......@@ -4,8 +4,7 @@ QTC_PLUGIN_DEPENDS += \
coreplugin \
projectexplorer \
cpptools \
qmljstools \
qmakeprojectmanager
qmljstools
CONFIG(licensechecker): QTC_PLUGIN_DEPENDS += licensechecker
......@@ -14,4 +13,8 @@ QTC_LIB_DEPENDS += \
qmljs \
utils
QTC_TEST_DEPENDS += \
qmakeprojectmanager \
qtsupport
#QTC_PLUGIN_RECOMMENDS += \
......@@ -33,11 +33,9 @@
#include <cpptools/cppmodelmanager.h>
#include <cpptools/cppworkingcopy.h>
#include <projectexplorer/project.h>
#include <projectexplorer/session.h>
#include <qmakeprojectmanager/qmakeproject.h>
#include <qmakeprojectmanager/qmakeprojectmanagerconstants.h>
#include <qmljs/parser/qmljsast_p.h>
#include <qmljs/qmljsdialect.h>
#include <qmljstools/qmljsmodelmanager.h>
......@@ -46,8 +44,10 @@
#include <utils/qtcassert.h>
#include <utils/textfileformat.h>
#include <QDirIterator>
#include <QFuture>
#include <QFutureInterface>
#include <QTimer>
namespace Autotest {
namespace Internal {
......@@ -58,8 +58,9 @@ TestCodeParser::TestCodeParser(TestTreeModel *parent)
m_codeModelParsing(false),
m_fullUpdatePostponed(false),
m_partialUpdatePostponed(false),
m_dirty(true),
m_dirty(false),
m_waitForParseTaskFinish(false),
m_singleShotScheduled(false),
m_parserState(Disabled)
{
// connect to ProgressManager to postpone test parsing when CppModelManager is parsing
......@@ -105,26 +106,22 @@ void TestCodeParser::setState(State state)
void TestCodeParser::emitUpdateTestTree()
{
if (m_singleShotScheduled)
return;
m_singleShotScheduled = true;
QTimer::singleShot(1000, this, SLOT(updateTestTree()));
}
void TestCodeParser::updateTestTree()
{
m_singleShotScheduled = false;
if (m_codeModelParsing) {
m_fullUpdatePostponed = true;
return;
}
if (ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject()) {
if (auto qmakeProject = qobject_cast<QmakeProjectManager::QmakeProject *>(project)) {
if (qmakeProject->asyncUpdateState() != QmakeProjectManager::QmakeProject::Base) {
m_fullUpdatePostponed = true;
return;
}
connect(qmakeProject, &QmakeProjectManager::QmakeProject::proFilesEvaluated,
this, &TestCodeParser::onProFileEvaluated, Qt::UniqueConnection);
}
} else
if (!ProjectExplorer::SessionManager::startupProject())
return;
m_fullUpdatePostponed = false;
......@@ -369,6 +366,10 @@ static TestTreeItem constructTestTreeItem(const QString &fileName,
/****** end of helpers ******/
// used internally to indicate a parse that failed due to having triggered a parse for a file that
// is not (yet) part of the CppModelManager's snapshot
static bool parsingHasFailed;
void performParse(QFutureInterface<void> &futureInterface, QStringList list,
TestCodeParser *testCodeParser)
{
......@@ -383,6 +384,9 @@ void performParse(QFutureInterface<void> &futureInterface, QStringList list,
CPlusPlus::Document::Ptr doc = snapshot.find(file).value();
futureInterface.setProgressValue(++progressValue);
testCodeParser->checkDocumentForTestCode(doc);
} else {
parsingHasFailed |= (CppTools::ProjectFile::classify(file)
!= CppTools::ProjectFile::Unclassified);
}
}
futureInterface.setProgressValue(list.size());
......@@ -618,6 +622,7 @@ void TestCodeParser::scanForTests(const QStringList &fileList)
if (postponed(fileList))
return;
m_postponedFiles.clear();
bool isFullParse = fileList.isEmpty();
bool isSmallChange = !isFullParse && fileList.size() < 6;
QStringList list;
......@@ -631,6 +636,7 @@ void TestCodeParser::scanForTests(const QStringList &fileList)
m_parserState = PartialParse;
}
parsingHasFailed = false;
if (isSmallChange) { // no need to do this async or should we do this always async?
CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance();
CPlusPlus::Snapshot snapshot = cppMM->snapshot();
......@@ -638,9 +644,12 @@ void TestCodeParser::scanForTests(const QStringList &fileList)
if (snapshot.contains(file)) {
CPlusPlus::Document::Ptr doc = snapshot.find(file).value();
checkDocumentForTestCode(doc);
} else {
parsingHasFailed |= (CppTools::ProjectFile::classify(file)
!= CppTools::ProjectFile::Unclassified);
}
}
emit onFinished();
onFinished();
return;
}
......@@ -699,34 +708,6 @@ void TestCodeParser::removeTestsIfNecessary(const QString &fileName)
}
}
void TestCodeParser::removeTestsIfNecessaryByProFile(const QString &proFile)
{
QList<QString> fList;
foreach (const QString &fileName, m_cppDocMap.keys()) {
if (m_cppDocMap[fileName].proFile() == proFile)
fList.append(fileName);
}
foreach (const QString &fileName, fList) {
m_cppDocMap.remove(fileName);
emit testItemsRemoved(fileName, TestTreeModel::AutoTest);
}
fList.clear();
foreach (const QString &fileName, m_quickDocMap.keys()) {
if (m_quickDocMap[fileName].proFile() == proFile)
fList.append(fileName);
}
foreach (const QString &fileName, fList) {
m_quickDocMap.remove(fileName);
emit testItemsRemoved(fileName, TestTreeModel::QuickTest);
}
// handle unnamed Quick Tests
const QSet<QString> &filePaths = m_model->qmlFilesForProFile(proFile);
foreach (const QString &fileName, filePaths) {
removeUnnamedQuickTestsByName(fileName);
emit unnamedQuickTestsRemoved(fileName);
}
}
void TestCodeParser::onTaskStarted(Core::Id type)
{
if (type == CppTools::Constants::TASK_INDEX)
......@@ -762,7 +743,11 @@ void TestCodeParser::onFinished()
break;
case FullParse:
m_parserState = Idle;
emit parsingFinished();
m_dirty = parsingHasFailed;
if (m_partialUpdatePostponed || m_fullUpdatePostponed || parsingHasFailed)
emit partialParsingFinished();
else
emit parsingFinished();
m_dirty = false;
break;
case Disabled: // can happen if all Test related widgets become hidden while parsing
......@@ -784,14 +769,13 @@ void TestCodeParser::onPartialParsingFinished()
updateTestTree();
} else if (m_partialUpdatePostponed) {
m_partialUpdatePostponed = false;
QStringList tmp;
foreach (const QString &file, m_postponedFiles)
tmp << file;
m_postponedFiles.clear();
scanForTests(tmp);
scanForTests(m_postponedFiles.toList());
} else {
m_dirty = false;
emit parsingFinished();
m_dirty |= m_codeModelParsing;
if (m_dirty)
emit parsingFailed();
else if (!m_singleShotScheduled)
emit parsingFinished();
}
}
......@@ -887,28 +871,6 @@ void TestCodeParser::removeUnnamedQuickTestsByName(const QString &fileName)
}
}
void TestCodeParser::onProFileEvaluated()
{
ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject();
if (!project)
return;
CppTools::CppModelManager *modelManager = CppTools::CppModelManager::instance();
const QList<CppTools::ProjectPart::Ptr> pp = modelManager->projectInfo(project).projectParts();
foreach (const CppTools::ProjectPart::Ptr &p, pp) {
if (!p->selectedForBuilding)
removeTestsIfNecessaryByProFile(p->projectFile);
else {
QStringList files;
foreach (auto projectFile, p->files)
files.append(projectFile.path);
// avoid illegal parser state when respective widgets became hidden while evaluating
setState(Idle);
scanForTests(files);
}
}
}
#ifdef WITH_TESTS
int TestCodeParser::autoTestsCount() const
{
......
......@@ -56,6 +56,7 @@ public:
virtual ~TestCodeParser();
void setState(State state);
State state() const { return m_parserState; }
void setDirty() { m_dirty = true; }
#ifdef WITH_TESTS
int autoTestsCount() const;
......@@ -74,6 +75,7 @@ signals:
void unnamedQuickTestsRemoved(const QString &filePath);
void parsingStarted();
void parsingFinished();
void parsingFailed();
void partialParsingFinished();
public slots:
......@@ -87,14 +89,12 @@ public slots:
void onStartupProjectChanged(ProjectExplorer::Project *);
void onProjectPartsUpdated(ProjectExplorer::Project *project);
void removeFiles(const QStringList &files);
void onProFileEvaluated();
private:
bool postponed(const QStringList &fileList);
void scanForTests(const QStringList &fileList = QStringList());
void clearCache();
void removeTestsIfNecessary(const QString &fileName);
void removeTestsIfNecessaryByProFile(const QString &proFile);
void onTaskStarted(Core::Id type);
void onAllTasksFinished(Core::Id type);
......@@ -117,6 +117,7 @@ private:
bool m_partialUpdatePostponed;
bool m_dirty;
bool m_waitForParseTaskFinish;
bool m_singleShotScheduled;
QSet<QString> m_postponedFiles;
State m_parserState;
};
......
......@@ -75,6 +75,8 @@ TestNavigationWidget::TestNavigationWidget(QWidget *parent) :
this, &TestNavigationWidget::onParsingStarted);
connect(m_model->parser(), &TestCodeParser::parsingFinished,
this, &TestNavigationWidget::onParsingFinished);
connect(m_model->parser(), &TestCodeParser::parsingFailed,
this, &TestNavigationWidget::onParsingFinished);
connect(m_progressTimer, &QTimer::timeout,
m_progressIndicator, &Utils::ProgressIndicator::show);
}
......
......@@ -96,6 +96,10 @@ TestTreeModel::~TestTreeModel()
void TestTreeModel::enableParsing()
{
m_refCounter.ref();
if (!m_connectionsInitialized)
m_parser->setDirty();
m_parser->setState(TestCodeParser::Idle);
if (m_connectionsInitialized)
return;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment