diff options
author | Tobias Hunger <tobias.hunger@qt.io> | 2017-02-10 11:16:18 +0100 |
---|---|---|
committer | Tim Jenssen <tim.jenssen@qt.io> | 2017-02-22 16:00:49 +0000 |
commit | f9eab73dad4f56934b12e9f5593bc7d84119217a (patch) | |
tree | 651582bfe9e40ac6e3cbbb730f5ff01a187a500e | |
parent | 62726c3f7793e7e24b0c4b947db78f55e98ac312 (diff) | |
download | qt-creator-f9eab73dad4f56934b12e9f5593bc7d84119217a.tar.gz |
qmake: move over from QmakeProjectNodes to QmakeParserNodes
Change-Id: Iab87e0c248b0f651a1774336c3bddf83baa9d057
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
32 files changed, 438 insertions, 2773 deletions
diff --git a/src/plugins/ios/iosrunconfiguration.cpp b/src/plugins/ios/iosrunconfiguration.cpp index 19a900faf6..093f9100e4 100644 --- a/src/plugins/ios/iosrunconfiguration.cpp +++ b/src/plugins/ios/iosrunconfiguration.cpp @@ -141,7 +141,7 @@ void IosRunConfiguration::deviceChanges() { enabledCheck(); } -void IosRunConfiguration::proFileUpdated(QmakeProFileNode *pro, bool success, +void IosRunConfiguration::proFileUpdated(QmakeProFile *pro, bool success, bool parseInProgress) { if (m_profilePath != pro->filePath()) @@ -193,16 +193,20 @@ FileName IosRunConfiguration::profilePath() const return m_profilePath; } +static QmakeProFile *proFile(const IosRunConfiguration *rc) +{ + QmakeProject *pro = qobject_cast<QmakeProject *>(rc->target()->project()); + QmakeProFile *proFile = pro ? pro->rootProFile() : nullptr; + if (proFile) + proFile = proFile->findProFile(rc->profilePath()); + return proFile; +} + QString IosRunConfiguration::applicationName() const { - QmakeProject *pro = qobject_cast<QmakeProject *>(target()->project()); - const QmakeProFileNode *node = 0; - if (pro) - node = pro->rootProjectNode(); - if (node) - node = node->findProFileFor(profilePath()); - if (node) { - TargetInformation ti = node->targetInformation(); + QmakeProFile *pro = proFile(this); + if (pro) { + TargetInformation ti = pro->targetInformation(); if (ti.valid) return ti.target; } @@ -221,14 +225,9 @@ FileName IosRunConfiguration::bundleDirectory() const QmakeBuildConfiguration *bc = qobject_cast<QmakeBuildConfiguration *>(target()->activeBuildConfiguration()); if (bc) { - QmakeProject *pro = qobject_cast<QmakeProject *>(target()->project()); - const QmakeProFileNode *node = 0; - if (pro) - node = pro->rootProjectNode(); - if (node) - node = node->findProFileFor(profilePath()); - if (node) { - TargetInformation ti = node->targetInformation(); + const QmakeProFile *pro = proFile(this); + if (pro) { + TargetInformation ti = pro->targetInformation(); if (ti.valid) res = ti.buildDir; } diff --git a/src/plugins/ios/iosrunconfiguration.h b/src/plugins/ios/iosrunconfiguration.h index 09919e5b3b..9a33177e8c 100644 --- a/src/plugins/ios/iosrunconfiguration.h +++ b/src/plugins/ios/iosrunconfiguration.h @@ -32,9 +32,7 @@ #include <projectexplorer/runconfiguration.h> #include <utils/fileutils.h> -namespace QmakeProjectManager { -class QmakeProFileNode; -} +namespace QmakeProjectManager { class QmakeProFile; } namespace Ios { namespace Internal { @@ -77,7 +75,7 @@ signals: void localExecutableChanged(); private: - void proFileUpdated(QmakeProjectManager::QmakeProFileNode *pro, bool success, bool parseInProgress); + void proFileUpdated(QmakeProjectManager::QmakeProFile *pro, bool success, bool parseInProgress); void deviceChanges(); void init(); void enabledCheck(); diff --git a/src/plugins/ios/iosrunfactories.cpp b/src/plugins/ios/iosrunfactories.cpp index 729bc0d90e..daa363b9f6 100644 --- a/src/plugins/ios/iosrunfactories.cpp +++ b/src/plugins/ios/iosrunfactories.cpp @@ -99,13 +99,13 @@ QList<Core::Id> IosRunConfigurationFactory::availableCreationIds(Target *parent, return QList<Core::Id>(); QmakeProject *project = static_cast<QmakeProject *>(parent->project()); - QList<QmakeProFileNode *> nodes = project->allProFiles({ ProjectType::ApplicationTemplate, - ProjectType::SharedLibraryTemplate, - ProjectType::AuxTemplate }); + QList<QmakeProFile *> files = project->allProFiles({ ProjectType::ApplicationTemplate, + ProjectType::SharedLibraryTemplate, + ProjectType::AuxTemplate }); if (mode == AutoCreate) - nodes = QmakeProject::nodesWithQtcRunnable(nodes); + files = QmakeProject::proFilesWithQtcRunnable(files); Core::Id baseId(IOS_RC_ID_PREFIX); - return QmakeProject::idsForNodes(baseId, nodes); + return QmakeProject::idsForProFiles(baseId, files); } QString IosRunConfigurationFactory::displayNameForId(Core::Id id) const diff --git a/src/plugins/qmakeandroidsupport/androidextralibrarylistmodel.cpp b/src/plugins/qmakeandroidsupport/androidextralibrarylistmodel.cpp index a96f601a6e..96b5df6e39 100644 --- a/src/plugins/qmakeandroidsupport/androidextralibrarylistmodel.cpp +++ b/src/plugins/qmakeandroidsupport/androidextralibrarylistmodel.cpp @@ -86,20 +86,20 @@ QVariant AndroidExtraLibraryListModel::data(const QModelIndex &index, int role) void AndroidExtraLibraryListModel::activeRunConfigurationChanged() { - const QmakeProjectManager::QmakeProFileNode *node = activeNode(); - if (!node || node->parseInProgress()) { + QmakeProjectManager::QmakeProFile *pro = activeProFile(); + if (!pro || pro->parseInProgress()) { emit enabledChanged(false); return; } m_scope = QLatin1String("contains(ANDROID_TARGET_ARCH,") - + node->singleVariableValue(QmakeProjectManager::Variable::AndroidArch) + + pro->singleVariableValue(QmakeProjectManager::Variable::AndroidArch) + QLatin1Char(')'); bool enabled; beginResetModel(); - if (node->validParse() && node->projectType() == QmakeProjectManager::ProjectType::ApplicationTemplate) { - m_entries = node->variableValue(QmakeProjectManager::Variable::AndroidExtraLibs); + if (pro->validParse() && pro->projectType() == QmakeProjectManager::ProjectType::ApplicationTemplate) { + m_entries = pro->variableValue(QmakeProjectManager::Variable::AndroidExtraLibs); enabled = true; } else { // parsing error or not a application template @@ -111,50 +111,44 @@ void AndroidExtraLibraryListModel::activeRunConfigurationChanged() emit enabledChanged(enabled); } -QmakeProjectManager::QmakeProFileNode *AndroidExtraLibraryListModel::activeNode() const +QmakeProjectManager::QmakeProFile *AndroidExtraLibraryListModel::activeProFile() const { ProjectExplorer::RunConfiguration *rc = m_target->activeRunConfiguration(); QmakeAndroidRunConfiguration *qarc = qobject_cast<QmakeAndroidRunConfiguration *>(rc); if (!qarc) return 0; auto project = static_cast<QmakeProject *>(m_target->project()); - return project->rootProjectNode()->findProFileFor(qarc->proFilePath()); + return project->rootProFile()->findProFile(qarc->proFilePath()); } -void AndroidExtraLibraryListModel::proFileUpdated(QmakeProjectManager::QmakeProFileNode *node) +void AndroidExtraLibraryListModel::proFileUpdated(QmakeProjectManager::QmakeProFile *pro) { - if (node != activeNode()) + if (activeProFile() != pro) return; activeRunConfigurationChanged(); } bool AndroidExtraLibraryListModel::isEnabled() const { - QmakeProjectManager::QmakeProFileNode *node = activeNode(); - if (!node) - return false; - if (node->parseInProgress()) - return false; - if (node->projectType() != QmakeProjectManager::ProjectType::ApplicationTemplate) - return false; - return true; + QmakeProjectManager::QmakeProFile *pro = activeProFile(); + return pro && !pro->parseInProgress() && pro->projectType() == QmakeProjectManager::ProjectType::ApplicationTemplate; } void AndroidExtraLibraryListModel::addEntries(const QStringList &list) { - QmakeProjectManager::QmakeProFileNode *node = activeNode(); - if (!node || node->projectType() != QmakeProjectManager::ProjectType::ApplicationTemplate) + QmakeProjectManager::QmakeProFile *pro = activeProFile(); + if (!pro || pro->projectType() != QmakeProjectManager::ProjectType::ApplicationTemplate) return; beginInsertRows(QModelIndex(), m_entries.size(), m_entries.size() + list.size()); foreach (const QString &path, list) m_entries += QLatin1String("$$PWD/") - + node->filePath().toFileInfo().absoluteDir().relativeFilePath(path); + + pro->filePath().toFileInfo().absoluteDir().relativeFilePath(path); - node->setProVariable(QLatin1String("ANDROID_EXTRA_LIBS"), m_entries, m_scope, - QmakeProjectManager::Internal::ProWriter::ReplaceValues - | QmakeProjectManager::Internal::ProWriter::MultiLine); + pro->setProVariable("ANDROID_EXTRA_LIBS", m_entries, m_scope, + QmakeProjectManager::Internal::ProWriter::ReplaceValues + | QmakeProjectManager::Internal::ProWriter::MultiLine); endInsertRows(); } @@ -166,8 +160,10 @@ bool greaterModelIndexByRow(const QModelIndex &a, const QModelIndex &b) void AndroidExtraLibraryListModel::removeEntries(QModelIndexList list) { - QmakeProjectManager::QmakeProFileNode *node = activeNode(); - if (list.isEmpty() || !node || node->projectType() != QmakeProjectManager::ProjectType::ApplicationTemplate) + QmakeProjectManager::QmakeProFile *pro = activeProFile(); + if (!pro) + return; + if (list.isEmpty() || !pro || pro->projectType() != QmakeProjectManager::ProjectType::ApplicationTemplate) return; std::sort(list.begin(), list.end(), greaterModelIndexByRow); @@ -186,5 +182,5 @@ void AndroidExtraLibraryListModel::removeEntries(QModelIndexList list) endRemoveRows(); } - node->setProVariable(QLatin1String("ANDROID_EXTRA_LIBS"), m_entries, m_scope); + pro->setProVariable(QLatin1String("ANDROID_EXTRA_LIBS"), m_entries, m_scope); } diff --git a/src/plugins/qmakeandroidsupport/androidextralibrarylistmodel.h b/src/plugins/qmakeandroidsupport/androidextralibrarylistmodel.h index f9959d556a..e0b401d473 100644 --- a/src/plugins/qmakeandroidsupport/androidextralibrarylistmodel.h +++ b/src/plugins/qmakeandroidsupport/androidextralibrarylistmodel.h @@ -34,7 +34,7 @@ class RunConfiguration; class Target; } -namespace QmakeProjectManager { class QmakeProFileNode; } +namespace QmakeProjectManager { class QmakeProFile; } namespace QmakeAndroidSupport { @@ -61,9 +61,9 @@ signals: void enabledChanged(bool); private: - void proFileUpdated(QmakeProjectManager::QmakeProFileNode *node); + void proFileUpdated(QmakeProjectManager::QmakeProFile *pro); void activeRunConfigurationChanged(); - QmakeProjectManager::QmakeProFileNode *activeNode() const; + QmakeProjectManager::QmakeProFile *activeProFile() const; ProjectExplorer::Target *m_target; QStringList m_entries; diff --git a/src/plugins/qmakeandroidsupport/createandroidmanifestwizard.cpp b/src/plugins/qmakeandroidsupport/createandroidmanifestwizard.cpp index 2191422681..f1cf7cbdae 100644 --- a/src/plugins/qmakeandroidsupport/createandroidmanifestwizard.cpp +++ b/src/plugins/qmakeandroidsupport/createandroidmanifestwizard.cpp @@ -35,7 +35,6 @@ #include <projectexplorer/target.h> #include <qmakeprojectmanager/qmakeproject.h> -#include <qmakeprojectmanager/qmakenodes.h> #include <proparser/prowriter.h> @@ -55,7 +54,7 @@ using namespace QmakeAndroidSupport::Internal; using namespace Utils; using QmakeProjectManager::QmakeProject; -using QmakeProjectManager::QmakeProFileNode; +using QmakeProjectManager::QmakeProFile; // // NoApplicationProFilePage @@ -74,8 +73,10 @@ NoApplicationProFilePage::NoApplicationProFilePage(CreateAndroidManifestWizard * // // ChooseProFilePage // -ChooseProFilePage::ChooseProFilePage(CreateAndroidManifestWizard *wizard, const QList<QmakeProFileNode *> &nodes, const QmakeProFileNode *select) - : m_wizard(wizard) +ChooseProFilePage::ChooseProFilePage(CreateAndroidManifestWizard *wizard, + const QList<QmakeProFile *> &files, + const QmakeProFile *select) : + m_wizard(wizard) { QFormLayout *fl = new QFormLayout(this); QLabel *label = new QLabel(this); @@ -84,9 +85,9 @@ ChooseProFilePage::ChooseProFilePage(CreateAndroidManifestWizard *wizard, const fl->addRow(label); m_comboBox = new QComboBox(this); - foreach (QmakeProFileNode *node, nodes) { - m_comboBox->addItem(node->displayName(), QVariant::fromValue(static_cast<void *>(node))); // TODO something more? - if (node == select) + for (QmakeProFile *file : files) { + m_comboBox->addItem(file->displayName(), QVariant::fromValue(static_cast<void *>(file))); // TODO something more? + if (file == select) m_comboBox->setCurrentIndex(m_comboBox->count() - 1); } @@ -101,7 +102,7 @@ ChooseProFilePage::ChooseProFilePage(CreateAndroidManifestWizard *wizard, const void ChooseProFilePage::nodeSelected(int index) { Q_UNUSED(index) - m_wizard->setNode(static_cast<QmakeProFileNode *>(m_comboBox->itemData(m_comboBox->currentIndex()).value<void *>())); + m_wizard->setProFile(static_cast<QmakeProFile *>(m_comboBox->itemData(m_comboBox->currentIndex()).value<void *>())); } @@ -152,7 +153,7 @@ ChooseDirectoryPage::ChooseDirectoryPage(CreateAndroidManifestWizard *wizard) void ChooseDirectoryPage::checkPackageSourceDir() { - QString projectDir = m_wizard->node()->filePath().toFileInfo().absolutePath(); + QString projectDir = m_wizard->proFile()->filePath().toFileInfo().absolutePath(); QString newDir = m_androidPackageSourceDir->path(); bool isComplete = QFileInfo(projectDir) != QFileInfo(newDir); @@ -172,13 +173,13 @@ bool ChooseDirectoryPage::isComplete() const void ChooseDirectoryPage::initializePage() { - QString androidPackageDir = m_wizard->node()->singleVariableValue(QmakeProjectManager::Variable::AndroidPackageSourceDir); + QString androidPackageDir = m_wizard->proFile()->singleVariableValue(QmakeProjectManager::Variable::AndroidPackageSourceDir); if (androidPackageDir.isEmpty()) { m_label->setText(tr("Select the Android package source directory.\n\n" "The files in the Android package source directory are copied to the build directory's " "Android directory and the default files are overwritten.")); - m_androidPackageSourceDir->setPath(m_wizard->node()->filePath().toFileInfo().absolutePath().append(QLatin1String("/android"))); + m_androidPackageSourceDir->setPath(m_wizard->proFile()->filePath().toFileInfo().absolutePath().append(QLatin1String("/android"))); connect(m_androidPackageSourceDir, &PathChooser::rawPathChanged, this, &ChooseDirectoryPage::checkPackageSourceDir); } else { @@ -195,40 +196,40 @@ void ChooseDirectoryPage::initializePage() // CreateAndroidManifestWizard // CreateAndroidManifestWizard::CreateAndroidManifestWizard(ProjectExplorer::Target *target) - : m_target(target), m_node(0), m_copyState(Ask) + : m_target(target), m_proFile(0), m_copyState(Ask) { setWindowTitle(tr("Create Android Template Files Wizard")); QmakeProject *project = static_cast<QmakeProject *>(target->project()); - QList<QmakeProFileNode *> nodes = project->applicationProFiles(); + QList<QmakeProFile *> files = project->applicationProFiles(); QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(target->kit()); m_copyGradle = version && version->qtVersion() >= QtSupport::QtVersionNumber(5, 4, 0); - const QmakeProFileNode *currentRunNode = 0; + const QmakeProFile *currentRunNode = nullptr; ProjectExplorer::RunConfiguration *rc = target->activeRunConfiguration(); if (auto qrc = qobject_cast<QmakeAndroidRunConfiguration *>(rc)) - currentRunNode = project->rootProjectNode()->findProFileFor(qrc->proFilePath()); + currentRunNode = project->rootProFile()->findProFile(qrc->proFilePath()); - if (nodes.isEmpty()) { + if (files.isEmpty()) { // oh uhm can't create anything addPage(new NoApplicationProFilePage(this)); - } else if (nodes.size() == 1) { - setNode(nodes.first()); + } else if (files.size() == 1) { + setProFile(files.first()); addPage(new ChooseDirectoryPage(this)); } else { - addPage(new ChooseProFilePage(this, nodes, currentRunNode)); + addPage(new ChooseProFilePage(this, files, currentRunNode)); addPage(new ChooseDirectoryPage(this)); } } -QmakeProjectManager::QmakeProFileNode *CreateAndroidManifestWizard::node() const +QmakeProjectManager::QmakeProFile *CreateAndroidManifestWizard::proFile() const { - return m_node; + return m_proFile; } -void CreateAndroidManifestWizard::setNode(QmakeProjectManager::QmakeProFileNode *node) +void CreateAndroidManifestWizard::setProFile(QmakeProjectManager::QmakeProFile *node) { - m_node = node; + m_proFile = node; } void CreateAndroidManifestWizard::setDirectory(const QString &directory) @@ -334,19 +335,19 @@ void CreateAndroidManifestWizard::createAndroidTemplateFiles() AndroidManager::updateGradleProperties(m_target); } - m_node->addFiles(addedFiles); + m_proFile->addFiles(addedFiles); - if (m_node->singleVariableValue(QmakeProjectManager::Variable::AndroidPackageSourceDir).isEmpty()) { + if (m_proFile->singleVariableValue(QmakeProjectManager::Variable::AndroidPackageSourceDir).isEmpty()) { // and now time for some magic QString value = QLatin1String("$$PWD/") - + m_node->filePath().toFileInfo().absoluteDir().relativeFilePath(m_directory); + + m_proFile->filePath().toFileInfo().absoluteDir().relativeFilePath(m_directory); bool result = - m_node->setProVariable(QLatin1String("ANDROID_PACKAGE_SOURCE_DIR"), QStringList(value)); + m_proFile->setProVariable(QLatin1String("ANDROID_PACKAGE_SOURCE_DIR"), QStringList(value)); if (!result) { QMessageBox::warning(this, tr("Project File not Updated"), tr("Could not update the .pro file %1.") - .arg(m_node->filePath().toUserOutput())); + .arg(m_proFile->filePath().toUserOutput())); } } Core::EditorManager::openEditor(m_directory + QLatin1String("/AndroidManifest.xml")); diff --git a/src/plugins/qmakeandroidsupport/createandroidmanifestwizard.h b/src/plugins/qmakeandroidsupport/createandroidmanifestwizard.h index 96d23a1615..cdd49b247f 100644 --- a/src/plugins/qmakeandroidsupport/createandroidmanifestwizard.h +++ b/src/plugins/qmakeandroidsupport/createandroidmanifestwizard.h @@ -36,7 +36,7 @@ class QFormLayout; QT_END_NAMESPACE namespace ProjectExplorer { class Target; } -namespace QmakeProjectManager { class QmakeProFileNode; } +namespace QmakeProjectManager { class QmakeProFile; } namespace QmakeAndroidSupport { namespace Internal { @@ -56,7 +56,9 @@ class ChooseProFilePage : public QWizardPage { Q_OBJECT public: - ChooseProFilePage(CreateAndroidManifestWizard *wizard, const QList<QmakeProjectManager::QmakeProFileNode *> &nodes, const QmakeProjectManager::QmakeProFileNode *select); + ChooseProFilePage(CreateAndroidManifestWizard *wizard, + const QList<QmakeProjectManager::QmakeProFile *> &nodes, + const QmakeProjectManager::QmakeProFile *select); private: void nodeSelected(int index); private: @@ -90,8 +92,8 @@ class CreateAndroidManifestWizard : public Utils::Wizard public: CreateAndroidManifestWizard(ProjectExplorer::Target *target); - QmakeProjectManager::QmakeProFileNode *node() const; - void setNode(QmakeProjectManager::QmakeProFileNode *node); + QmakeProjectManager::QmakeProFile *proFile() const; + void setProFile(QmakeProjectManager::QmakeProFile *proFile); void accept(); bool copyGradle(); @@ -110,7 +112,7 @@ private: void createAndroidManifestFile(); void createAndroidTemplateFiles(); ProjectExplorer::Target *m_target; - QmakeProjectManager::QmakeProFileNode *m_node; + QmakeProjectManager::QmakeProFile *m_proFile; QString m_directory; CopyState m_copyState; bool m_copyGradle; diff --git a/src/plugins/qmakeandroidsupport/qmakeandroidrunconfiguration.cpp b/src/plugins/qmakeandroidsupport/qmakeandroidrunconfiguration.cpp index 49f1013018..ece47f031a 100644 --- a/src/plugins/qmakeandroidsupport/qmakeandroidrunconfiguration.cpp +++ b/src/plugins/qmakeandroidsupport/qmakeandroidrunconfiguration.cpp @@ -141,7 +141,8 @@ QString QmakeAndroidRunConfiguration::buildSystemTarget() const return qmakeProject()->mapProFilePathToTarget(m_proFilePath); } -void QmakeAndroidRunConfiguration::proFileUpdated(QmakeProjectManager::QmakeProFileNode *pro, bool success, bool parseInProgress) +void QmakeAndroidRunConfiguration::proFileUpdated(QmakeProjectManager::QmakeProFile *pro, + bool success, bool parseInProgress) { QmakeProject *project = qmakeProject(); if (m_proFilePath.isEmpty() && project->rootProjectNode()) diff --git a/src/plugins/qmakeandroidsupport/qmakeandroidrunconfiguration.h b/src/plugins/qmakeandroidsupport/qmakeandroidrunconfiguration.h index 4fbaf29590..f7ff72987c 100644 --- a/src/plugins/qmakeandroidsupport/qmakeandroidrunconfiguration.h +++ b/src/plugins/qmakeandroidsupport/qmakeandroidrunconfiguration.h @@ -30,9 +30,9 @@ #include <utils/fileutils.h> namespace QmakeProjectManager { -class QmakeProFileNode; +class QmakeProFile; class QmakeProject; -} +} // namespace QmakeProjectManager namespace QmakeAndroidSupport { namespace Internal { @@ -61,7 +61,7 @@ protected: QString defaultDisplayName(); private: - void proFileUpdated(QmakeProjectManager::QmakeProFileNode *pro, bool success, bool parseInProgress); + void proFileUpdated(QmakeProjectManager::QmakeProFile *pro, bool success, bool parseInProgress); QmakeProjectManager::QmakeProject *qmakeProject() const; void init(); diff --git a/src/plugins/qmakeandroidsupport/qmakeandroidrunfactories.cpp b/src/plugins/qmakeandroidsupport/qmakeandroidrunfactories.cpp index 6c4a609cfd..74d4f158e9 100644 --- a/src/plugins/qmakeandroidsupport/qmakeandroidrunfactories.cpp +++ b/src/plugins/qmakeandroidsupport/qmakeandroidrunfactories.cpp @@ -84,14 +84,14 @@ QList<Core::Id> QmakeAndroidRunConfigurationFactory::availableCreationIds(Target return QList<Core::Id>(); QmakeProject *project = static_cast<QmakeProject *>(parent->project()); - QList<QmakeProFileNode *> nodes = project->allProFiles({ ProjectType::ApplicationTemplate, - ProjectType::SharedLibraryTemplate }); + QList<QmakeProFile *> files = project->allProFiles({ ProjectType::ApplicationTemplate, + ProjectType::SharedLibraryTemplate }); if (mode == AutoCreate) - nodes = QmakeProject::nodesWithQtcRunnable(nodes); + files = QmakeProject::proFilesWithQtcRunnable(files); const Core::Id base = Core::Id(ANDROID_RC_ID_PREFIX); - return QmakeProject::idsForNodes(base, nodes); + return QmakeProject::idsForProFiles(base, files); } RunConfiguration *QmakeAndroidRunConfigurationFactory::doCreate(Target *parent, Core::Id id) diff --git a/src/plugins/qmakeandroidsupport/qmakeandroidsupport.cpp b/src/plugins/qmakeandroidsupport/qmakeandroidsupport.cpp index 7f961a655e..08cf8d5708 100644 --- a/src/plugins/qmakeandroidsupport/qmakeandroidsupport.cpp +++ b/src/plugins/qmakeandroidsupport/qmakeandroidsupport.cpp @@ -53,14 +53,15 @@ QStringList QmakeAndroidSupport::soLibSearchPath(const ProjectExplorer::Target * if (!project) return res; - foreach (QmakeProFileNode *node, project->allProFiles()) { - TargetInformation info = node->targetInformation(); + foreach (QmakeProFile *file, project->allProFiles()) { + TargetInformation info = file->targetInformation(); res << info.buildDir.toString(); - QString destDir = info.destDir.toString(); + Utils::FileName destDir = info.destDir; if (!destDir.isEmpty()) { - if (QFileInfo(destDir).isRelative()) - destDir = QDir::cleanPath(info.buildDir.toString() + '/' + destDir); - res << destDir; + if (destDir.toFileInfo().isRelative()) + destDir = Utils::FileName::fromString(QDir::cleanPath(info.buildDir.toString() + + '/' + destDir.toString())); + res << destDir.toString(); } } @@ -84,7 +85,7 @@ QStringList QmakeAndroidSupport::projectTargetApplications(const ProjectExplorer QmakeProject *qmakeProject = qobject_cast<QmakeProject *>(target->project()); if (!qmakeProject) return apps; - foreach (QmakeProFileNode *proFile, qmakeProject->applicationProFiles()) { + for (QmakeProFile *proFile : qmakeProject->applicationProFiles()) { if (proFile->projectType() == ProjectType::ApplicationTemplate) { if (proFile->targetInformation().target.startsWith(QLatin1String("lib")) && proFile->targetInformation().target.endsWith(QLatin1String(".so"))) diff --git a/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.cpp b/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.cpp index 629e2f449c..4d36e17cfa 100644 --- a/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.cpp +++ b/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.cpp @@ -121,7 +121,7 @@ QString DesktopQmakeRunConfiguration::disabledReason() const return QString(); } -void DesktopQmakeRunConfiguration::proFileUpdated(QmakeProFileNode *pro, bool success, bool parseInProgress) +void DesktopQmakeRunConfiguration::proFileUpdated(QmakeProFile *pro, bool success, bool parseInProgress) { if (m_proFilePath != pro->filePath()) return; @@ -467,12 +467,16 @@ OutputFormatter *DesktopQmakeRunConfiguration::createOutputFormatter() const QPair<QString, QString> DesktopQmakeRunConfiguration::extractWorkingDirAndExecutable(const QmakeProFileNode *node) const { if (!node) - return qMakePair(QString(), QString()); - TargetInformation ti = node->targetInformation(); + return { }; + + QmakeProFile *pro = node->proFile(); + QTC_ASSERT(pro, return { }); + + TargetInformation ti = pro->targetInformation(); if (!ti.valid) return qMakePair(QString(), QString()); - const QStringList &config = node->variableValue(Variable::Config); + const QStringList &config = pro->variableValue(Variable::Config); QString destDir = ti.destDir.toString(); QString workingDir; @@ -560,10 +564,10 @@ QList<Core::Id> DesktopQmakeRunConfigurationFactory::availableCreationIds(Target return QList<Core::Id>(); QmakeProject *project = static_cast<QmakeProject *>(parent->project()); - QList<QmakeProFileNode *> nodes = project->applicationProFiles(); + QList<QmakeProFile *> files = project->applicationProFiles(); if (mode == AutoCreate) - nodes = QmakeProject::nodesWithQtcRunnable(nodes); - return QmakeProject::idsForNodes(Core::Id(QMAKE_RC_PREFIX), nodes); + files = QmakeProject::proFilesWithQtcRunnable(files); + return QmakeProject::idsForProFiles(Core::Id(QMAKE_RC_PREFIX), files); } QString DesktopQmakeRunConfigurationFactory::displayNameForId(Core::Id id) const diff --git a/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.h b/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.h index 144745b07b..d32cd008a5 100644 --- a/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.h +++ b/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.h @@ -41,6 +41,7 @@ QT_END_NAMESPACE namespace QmakeProjectManager { +class QmakeProFile; class QmakeProFileNode; class QmakeProject; @@ -89,7 +90,7 @@ signals: void effectiveTargetInformationChanged(); private: - void proFileUpdated(QmakeProjectManager::QmakeProFileNode *pro, bool success, bool parseInProgress); + void proFileUpdated(QmakeProjectManager::QmakeProFile *pro, bool success, bool parseInProgress); void proFileEvaluated(); protected: diff --git a/src/plugins/qmakeprojectmanager/findqmakeprofiles.cpp b/src/plugins/qmakeprojectmanager/findqmakeprofiles.cpp deleted file mode 100644 index c0f3a5e9cb..0000000000 --- a/src/plugins/qmakeprojectmanager/findqmakeprofiles.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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 "findqmakeprofiles.h" -#include "qmakenodes.h" - -using namespace QmakeProjectManager; -using namespace QmakeProjectManager::Internal; - -QList<QmakeProFileNode *> FindQmakeProFiles::operator()(ProjectExplorer::ProjectNode *root) -{ - m_proFiles.clear(); - root->accept(this); - return m_proFiles; -} - -void FindQmakeProFiles::visitFolderNode(ProjectExplorer::FolderNode *folderNode) -{ - if (QmakeProFileNode *pro = dynamic_cast<QmakeProFileNode *>(folderNode)) - m_proFiles.append(pro); -} diff --git a/src/plugins/qmakeprojectmanager/findqmakeprofiles.h b/src/plugins/qmakeprojectmanager/findqmakeprofiles.h deleted file mode 100644 index 4a19267b4d..0000000000 --- a/src/plugins/qmakeprojectmanager/findqmakeprofiles.h +++ /dev/null @@ -1,47 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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 <projectexplorer/nodesvisitor.h> - -namespace ProjectExplorer { class ProjectNode; } - -namespace QmakeProjectManager { -class QmakeProFileNode; -namespace Internal { - -class FindQmakeProFiles: protected ProjectExplorer::NodesVisitor -{ -public: - QList<QmakeProFileNode *> operator()(ProjectExplorer::ProjectNode *root); -protected: - void visitFolderNode(ProjectExplorer::FolderNode *folderNode) final; -private: - QList<QmakeProFileNode *> m_proFiles; -}; - -} // namespace Internal -} // namespace QmakeProjectManager diff --git a/src/plugins/qmakeprojectmanager/librarydetailscontroller.cpp b/src/plugins/qmakeprojectmanager/librarydetailscontroller.cpp index 315c916122..d4b6226e53 100644 --- a/src/plugins/qmakeprojectmanager/librarydetailscontroller.cpp +++ b/src/plugins/qmakeprojectmanager/librarydetailscontroller.cpp @@ -25,10 +25,9 @@ #include "librarydetailscontroller.h" #include "ui_librarydetailswidget.h" -#include "findqmakeprofiles.h" -#include "qmakenodes.h" -#include "qmakeparsernodes.h" #include "qmakebuildconfiguration.h" +#include "qmakeparsernodes.h" +#include "qmakeproject.h" #include <projectexplorer/projectexplorer.h> #include <projectexplorer/session.h> @@ -942,8 +941,8 @@ AddLibraryWizard::LinkageType InternalLibraryDetailsController::suggestedLinkage const int currentIndex = libraryDetailsWidget()->libraryComboBox->currentIndex(); AddLibraryWizard::LinkageType type = AddLibraryWizard::NoLinkage; if (currentIndex >= 0) { - QmakeProFileNode *proFileNode = m_proFileNodes.at(currentIndex); - const QStringList configVar = proFileNode->variableValue(Variable::Config); + QmakeProFile *proFile = m_proFiles.at(currentIndex); + const QStringList configVar = proFile->variableValue(Variable::Config); if (configVar.contains(QLatin1String("staticlib")) || configVar.contains(QLatin1String("static"))) type = AddLibraryWizard::StaticLinkage; @@ -958,8 +957,8 @@ AddLibraryWizard::MacLibraryType InternalLibraryDetailsController::suggestedMacL const int currentIndex = libraryDetailsWidget()->libraryComboBox->currentIndex(); AddLibraryWizard::MacLibraryType type = AddLibraryWizard::NoLibraryType; if (currentIndex >= 0) { - QmakeProFileNode *proFileNode = m_proFileNodes.at(currentIndex); - const QStringList configVar = proFileNode->variableValue(Variable::Config); + QmakeProFile *proFile = m_proFiles.at(currentIndex); + const QStringList configVar = proFile->variableValue(Variable::Config); if (configVar.contains(QLatin1String("lib_bundle"))) type = AddLibraryWizard::FrameworkType; else @@ -972,8 +971,8 @@ QString InternalLibraryDetailsController::suggestedIncludePath() const { const int currentIndex = libraryDetailsWidget()->libraryComboBox->currentIndex(); if (currentIndex >= 0) { - QmakeProFileNode *proFileNode = m_proFileNodes.at(currentIndex); - return proFileNode->filePath().toFileInfo().absolutePath(); + QmakeProFile *proFile = m_proFiles.at(currentIndex); + return proFile->filePath().toFileInfo().absolutePath(); } return QString(); } @@ -989,35 +988,35 @@ void InternalLibraryDetailsController::updateWindowsOptionsEnablement() void InternalLibraryDetailsController::updateProFile() { m_rootProjectPath.clear(); - m_proFileNodes.clear(); + m_proFiles.clear(); libraryDetailsWidget()->libraryComboBox->clear(); - const Project *project = SessionManager::projectForFile(Utils::FileName::fromString(proFile())); + const QmakeProject *project + = dynamic_cast<QmakeProject *>(SessionManager::projectForFile(Utils::FileName::fromString(proFile()))); if (!project) return; setIgnoreGuiSignals(true); - ProjectExplorer::ProjectNode *rootProject = project->rootProjectNode(); - m_rootProjectPath = rootProject->filePath().toFileInfo().absolutePath(); + m_rootProjectPath = project->projectDirectory().toString(); + QDir rootDir(m_rootProjectPath); - FindQmakeProFiles findQt4ProFiles; - QList<QmakeProFileNode *> proFiles = findQt4ProFiles(rootProject); - foreach (QmakeProFileNode *proFileNode, proFiles) { - const QString proFilePath = proFileNode->filePath().toString(); - QmakeProjectManager::ProjectType type = proFileNode->projectType(); - if (type == ProjectType::SharedLibraryTemplate || type == ProjectType::StaticLibraryTemplate) { - const QStringList configVar = proFileNode->variableValue(Variable::Config); - if (!configVar.contains(QLatin1String("plugin"))) { - const QString relProFilePath = rootDir.relativeFilePath(proFilePath); - TargetInformation targetInfo = proFileNode->targetInformation(); - const QString itemToolTip = QString::fromLatin1("%1 (%2)").arg(targetInfo.target).arg(relProFilePath); - m_proFileNodes.append(proFileNode); - libraryDetailsWidget()->libraryComboBox->addItem(targetInfo.target); - libraryDetailsWidget()->libraryComboBox->setItemData( - libraryDetailsWidget()->libraryComboBox->count() - 1, - itemToolTip, Qt::ToolTipRole); - } + foreach (QmakeProFile *proFile, project->rootProFile()->allProFiles()) { + QmakeProjectManager::ProjectType type = proFile->projectType(); + if (type != ProjectType::SharedLibraryTemplate && type != ProjectType::StaticLibraryTemplate) + continue; + + const QStringList configVar = proFile->variableValue(Variable::Config); + if (!configVar.contains(QLatin1String("plugin"))) { + const QString relProFilePath = rootDir.relativeFilePath(proFile->filePath().toString()); + TargetInformation targetInfo = proFile->targetInformation(); + const QString itemToolTip = QString::fromLatin1("%1 (%2)").arg(targetInfo.target).arg(relProFilePath); + m_proFiles.append(proFile); + + libraryDetailsWidget()->libraryComboBox->addItem(targetInfo.target); + libraryDetailsWidget()->libraryComboBox->setItemData( + libraryDetailsWidget()->libraryComboBox->count() - 1, + itemToolTip, Qt::ToolTipRole); } } @@ -1031,8 +1030,8 @@ void InternalLibraryDetailsController::slotCurrentLibraryChanged() libraryDetailsWidget()->libraryComboBox->setToolTip( libraryDetailsWidget()->libraryComboBox->itemData( currentIndex, Qt::ToolTipRole).toString()); - QmakeProFileNode *proFileNode = m_proFileNodes.at(currentIndex); - const QStringList configVar = proFileNode->variableValue(Variable::Config); + QmakeProFile *proFile = m_proFiles.at(currentIndex); + const QStringList configVar = proFile->variableValue(Variable::Config); if (Utils::HostOsInfo::isWindowsHost()) { bool useSubfolders = false; if (configVar.contains(QLatin1String("debug_and_release")) @@ -1093,8 +1092,7 @@ QString InternalLibraryDetailsController::snippet() const QDir projectSrcDir(fi.absolutePath()); // project node which we want to link against - QmakeProFileNode *proFileNode = m_proFileNodes.at(currentIndex); - TargetInformation targetInfo = proFileNode->targetInformation(); + TargetInformation targetInfo = m_proFiles.at(currentIndex)->targetInformation(); const QString targetRelativePath = appendSeparator(projectBuildDir.relativeFilePath(targetInfo.buildDir.toString())); const QString includeRelativePath = projectSrcDir.relativeFilePath(libraryDetailsWidget()->includePathChooser->path()); diff --git a/src/plugins/qmakeprojectmanager/librarydetailscontroller.h b/src/plugins/qmakeprojectmanager/librarydetailscontroller.h index 52c6ecbfca..91505a3e13 100644 --- a/src/plugins/qmakeprojectmanager/librarydetailscontroller.h +++ b/src/plugins/qmakeprojectmanager/librarydetailscontroller.h @@ -28,7 +28,7 @@ #include "addlibrarywizard.h" namespace QmakeProjectManager { -class QmakeProFileNode; +class QmakeProFile; namespace Internal { namespace Ui { class LibraryDetailsWidget; } @@ -182,7 +182,7 @@ private: void updateProFile(); QString m_rootProjectPath; - QVector<QmakeProFileNode *> m_proFileNodes; + QVector<QmakeProFile *> m_proFiles; }; } // namespace Internal diff --git a/src/plugins/qmakeprojectmanager/makestep.cpp b/src/plugins/qmakeprojectmanager/makestep.cpp index e43933504b..767d4bf236 100644 --- a/src/plugins/qmakeprojectmanager/makestep.cpp +++ b/src/plugins/qmakeprojectmanager/makestep.cpp @@ -194,14 +194,15 @@ bool MakeStep::init(QList<const BuildStep *> &earlierSteps) QString args; QmakeProjectManager::QmakeProFileNode *subNode = bc->subNodeBuild(); - if (subNode) { - QString makefile = subNode->makefile(); + QmakeProjectManager::QmakeProFile *subProFile = subNode ? subNode->proFile() : nullptr; + if (subProFile) { + QString makefile = subProFile->makefile(); if (makefile.isEmpty()) makefile = QLatin1String("Makefile"); // Use Makefile.Debug and Makefile.Release // for file builds, since the rules for that are // only in those files. - if (subNode->isDebugAndRelease() && bc->fileNodeBuild()) { + if (subProFile->isDebugAndRelease() && bc->fileNodeBuild()) { if (bc->buildType() == QmakeBuildConfiguration::Debug) makefile += QLatin1String(".Debug"); else @@ -223,11 +224,11 @@ bool MakeStep::init(QList<const BuildStep *> &earlierSteps) } Utils::QtcProcess::addArgs(&args, m_userArgs); - if (bc->fileNodeBuild() && subNode) { - QString objectsDir = subNode->objectsDirectory(); + if (bc->fileNodeBuild() && subProFile) { + QString objectsDir = subProFile->objectsDirectory(); if (objectsDir.isEmpty()) { - objectsDir = subNode->buildDir(bc); - if (subNode->isDebugAndRelease()) { + objectsDir = subProFile->buildDir(bc).toString(); + if (subProFile->isDebugAndRelease()) { if (bc->buildType() == QmakeBuildConfiguration::Debug) objectsDir += QLatin1String("/debug"); else @@ -241,7 +242,7 @@ bool MakeStep::init(QList<const BuildStep *> &earlierSteps) relObjectsDir += QLatin1Char('/'); QString objectFile = relObjectsDir + bc->fileNodeBuild()->filePath().toFileInfo().baseName() + - subNode->objectExtension(); + subProFile->objectExtension(); Utils::QtcProcess::addArg(&args, objectFile); } Utils::Environment env = bc->environment(); diff --git a/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp b/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp index b0b9b19717..da72d79093 100644 --- a/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp +++ b/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp @@ -227,7 +227,7 @@ bool QmakeBuildConfiguration::isShadowBuild() const QString QmakeBuildConfiguration::makefile() const { - return static_cast<QmakeProject *>(target()->project())->rootProjectNode()->makefile(); + return static_cast<QmakeProject *>(target()->project())->rootProFile()->makefile(); } BaseQtVersion::QmakeBuildConfigs QmakeBuildConfiguration::qmakeBuildConfiguration() const diff --git a/src/plugins/qmakeprojectmanager/qmakenodes.cpp b/src/plugins/qmakeprojectmanager/qmakenodes.cpp index 5a24ad3758..7245ff979c 100644 --- a/src/plugins/qmakeprojectmanager/qmakenodes.cpp +++ b/src/plugins/qmakeprojectmanager/qmakenodes.cpp @@ -24,424 +24,21 @@ ****************************************************************************/ #include "qmakenodes.h" -#include "qmakeparsernodes.h" #include "qmakeproject.h" -#include "qmakeprojectmanager.h" -#include "qmakeprojectmanagerconstants.h" #include "qmakebuildconfiguration.h" #include "qmakerunconfigurationfactory.h" -#include <projectexplorer/nodesvisitor.h> -#include <projectexplorer/projectexplorer.h> -#include <projectexplorer/projectexplorerconstants.h> -#include <coreplugin/editormanager/editormanager.h> -#include <coreplugin/editormanager/ieditor.h> -#include <coreplugin/fileiconprovider.h> -#include <coreplugin/documentmanager.h> -#include <coreplugin/icore.h> -#include <coreplugin/iversioncontrol.h> -#include <coreplugin/vcsmanager.h> -#include <coreplugin/dialogs/readonlyfilesdialog.h> - -#include <extensionsystem/pluginmanager.h> - -#include <projectexplorer/buildmanager.h> -#include <projectexplorer/projectexplorer.h> #include <projectexplorer/target.h> -#include <projectexplorer/projecttree.h> #include <qtsupport/profilereader.h> -#include <qtsupport/qtkitinformation.h> -#include <cpptools/generatedcodemodelsupport.h> - #include <resourceeditor/resourcenode.h> -#include <cpptools/cppmodelmanager.h> -#include <cpptools/cpptoolsconstants.h> - #include <utils/algorithm.h> -#include <utils/fileutils.h> -#include <utils/hostosinfo.h> -#include <utils/qtcprocess.h> -#include <utils/mimetypes/mimedatabase.h> #include <utils/stringutils.h> -#include <utils/theme/theme.h> -#include <proparser/prowriter.h> -#include <proparser/qmakevfs.h> -#include <proparser/ioutils.h> - -#include <QApplication> -#include <QDebug> -#include <QDir> -#include <QFile> -#include <QFileInfo> -#include <QTextCodec> -#include <QXmlStreamReader> -#include <QMessageBox> -#include <utils/QtConcurrentTools> - -using namespace Core; using namespace ProjectExplorer; using namespace Utils; -using namespace QMakeInternal; - -// Static cached data in struct QmakeNodeStaticData providing information and icons -// for file types and the project. Do some magic via qAddPostRoutine() -// to make sure the icons do not outlive QApplication, triggering warnings on X11. - -struct FileTypeDataStorage { - FileType type; - const char *typeName; - const char *icon; - const char *addFileFilter; -}; - -static const FileTypeDataStorage fileTypeDataStorage[] = { - { FileType::Header, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakePriFileNode", "Headers"), - ProjectExplorer::Constants::FILEOVERLAY_H, "*.h; *.hh; *.hpp; *.hxx;"}, - { FileType::Source, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakePriFileNode", "Sources"), - ProjectExplorer::Constants::FILEOVERLAY_CPP, "*.c; *.cc; *.cpp; *.cp; *.cxx; *.c++;" }, - { FileType::Form, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakePriFileNode", "Forms"), - Constants::FILEOVERLAY_UI, "*.ui;" }, - { FileType::StateChart, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakePriFileNode", "State charts"), - ProjectExplorer::Constants::FILEOVERLAY_SCXML, "*.scxml;" }, - { FileType::Resource, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakePriFileNode", "Resources"), - ProjectExplorer::Constants::FILEOVERLAY_QRC, "*.qrc;" }, - { FileType::QML, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakePriFileNode", "QML"), - ProjectExplorer::Constants::FILEOVERLAY_QML, "*.qml;" }, - { FileType::Unknown, QT_TRANSLATE_NOOP("QmakeProjectManager::QmakePriFileNode", "Other files"), - ProjectExplorer::Constants::FILEOVERLAY_UNKNOWN, "*;" } -}; - -class QmakeNodeStaticData { -public: - class FileTypeData { - public: - FileTypeData(FileType t = FileType::Unknown, - const QString &tN = QString(), - const QString &aff = QString(), - const QIcon &i = QIcon()) : - type(t), typeName(tN), addFileFilter(aff), icon(i) { } - - FileType type; - QString typeName; - QString addFileFilter; - QIcon icon; - }; - - QmakeNodeStaticData(); - - QVector<FileTypeData> fileTypeData; - QIcon projectIcon; -}; - -static void clearQmakeNodeStaticData(); - -QmakeNodeStaticData::QmakeNodeStaticData() -{ - // File type data - const unsigned count = sizeof(fileTypeDataStorage)/sizeof(FileTypeDataStorage); - fileTypeData.reserve(count); - - // Overlay the SP_DirIcon with the custom icons - const QSize desiredSize = QSize(16, 16); - - const QPixmap dirPixmap = qApp->style()->standardIcon(QStyle::SP_DirIcon).pixmap(desiredSize); - for (unsigned i = 0 ; i < count; ++i) { - const QIcon overlayIcon(QLatin1String(fileTypeDataStorage[i].icon)); - QIcon folderIcon; - folderIcon.addPixmap(FileIconProvider::overlayIcon(dirPixmap, overlayIcon)); - const QString desc = QCoreApplication::translate("QmakeProjectManager::QmakePriFileNode", fileTypeDataStorage[i].typeName); - const QString filter = QString::fromUtf8(fileTypeDataStorage[i].addFileFilter); - fileTypeData.push_back(QmakeNodeStaticData::FileTypeData(fileTypeDataStorage[i].type, - desc, filter, folderIcon)); - } - // Project icon - const QIcon projectBaseIcon(ProjectExplorer::Constants::FILEOVERLAY_QT); - const QPixmap projectPixmap = FileIconProvider::overlayIcon(dirPixmap, projectBaseIcon); - projectIcon.addPixmap(projectPixmap); - - qAddPostRoutine(clearQmakeNodeStaticData); -} - -Q_GLOBAL_STATIC(QmakeNodeStaticData, qmakeNodeStaticData) - -static void clearQmakeNodeStaticData() -{ - qmakeNodeStaticData()->fileTypeData.clear(); - qmakeNodeStaticData()->projectIcon = QIcon(); -} - -enum { debug = 0 }; - -using namespace QmakeProjectManager; -using namespace QmakeProjectManager::Internal; namespace QmakeProjectManager { -namespace Internal { -class EvalInput -{ -public: - QString projectDir; - FileName projectFilePath; - QString buildDirectory; - QString sysroot; - QtSupport::ProFileReader *readerExact; - QtSupport::ProFileReader *readerCumulative; - QMakeGlobals *qmakeGlobals; - QMakeVfs *qmakeVfs; -}; - -class PriFileEvalResult -{ -public: - QStringList folders; - QSet<FileName> recursiveEnumerateFiles; - QMap<FileType, QSet<FileName>> foundFiles; -}; - -class IncludedPriFile -{ -public: - ProFile *proFile; - Utils::FileName name; - PriFileEvalResult result; - QMap<Utils::FileName, IncludedPriFile *> children; - - ~IncludedPriFile() - { - qDeleteAll(children); - } -}; - -class EvalResult -{ -public: - enum EvalResultState { EvalAbort, EvalFail, EvalPartial, EvalOk }; - EvalResultState state; - ProjectType projectType; - - QStringList subProjectsNotToDeploy; - QSet<FileName> exactSubdirs; - IncludedPriFile includedFiles; - TargetInformation targetInformation; - InstallsList installsList; - QHash<Variable, QStringList> newVarValues; - QStringList errors; -}; - -class QmakePriFileNodeDocument : public Core::IDocument -{ -public: - QmakePriFileNodeDocument(QmakePriFileNode *qmakePriFile) - : IDocument(nullptr), m_priFile(qmakePriFile) - { - setId("Qmake.PriFile"); - setMimeType(QLatin1String(QmakeProjectManager::Constants::PROFILE_MIMETYPE)); - setFilePath(m_priFile->filePath()); - } - - ReloadBehavior reloadBehavior(ChangeTrigger state, ChangeType type) const override - { - Q_UNUSED(state) - Q_UNUSED(type) - return BehaviorSilent; - } - bool reload(QString *errorString, ReloadFlag flag, ChangeType type) override - { - Q_UNUSED(errorString) - Q_UNUSED(flag) - if (type == TypePermissions) - return true; - m_priFile->scheduleUpdate(); - return true; - } - -private: - QmakePriFileNode *m_priFile; -}; - -class ProVirtualFolderNode : public VirtualFolderNode -{ -public: - ProVirtualFolderNode(InternalNode *node); - - QString displayName() const final { return m_typeName; } - QString addFileFilter() const final { return m_addFileFilter; } - QString tooltip() const final { return QString(); } - -private: - QString m_typeName; - QString m_addFileFilter; -}; - -struct InternalNode -{ - QList<InternalNode *> virtualfolders; - QMap<QString, InternalNode *> subnodes; - FileNameList files; - FileType type = FileType::Unknown; - int priority = Node::DefaultVirtualFolderPriority; - QString displayName; - QString typeName; - QString addFileFilter; - QString fullPath; - QIcon icon; - - ~InternalNode() - { - qDeleteAll(virtualfolders); - qDeleteAll(subnodes); - } - - // Creates: a tree structure from a list of absolute file paths. - // Empty directories are compressed into a single entry with a longer path. - // * project - // * /absolute/path - // * file1 - // * relative - // * path1 - // * file1 - // * file2 - // * path2 - // * file1 - // The function first creates a tree that looks like the directory structure, i.e. - // * / - // * absolute - // * path - // ... - // and afterwards calls compress() which merges directory nodes with single children, i.e. to - // * /absolute/path - void create(const QString &projectDir, const QSet<FileName> &newFilePaths, FileType type) - { - static const QChar separator = QLatin1Char('/'); - const FileName projectDirFileName = FileName::fromString(projectDir); - foreach (const FileName &file, newFilePaths) { - FileName fileWithoutPrefix; - bool isRelative; - if (file.isChildOf(projectDirFileName)) { - isRelative = true; - fileWithoutPrefix = file.relativeChildPath(projectDirFileName); - } else { - isRelative = false; - fileWithoutPrefix = file; - } - QStringList parts = fileWithoutPrefix.toString().split(separator, QString::SkipEmptyParts); - if (!HostOsInfo::isWindowsHost() && !isRelative && parts.count() > 0) - parts[0].prepend(separator); - QStringListIterator it(parts); - InternalNode *currentNode = this; - QString path = (isRelative ? (projectDirFileName.toString() + QLatin1Char('/')) : QString()); - while (it.hasNext()) { - const QString &key = it.next(); - if (it.hasNext()) { // key is directory - path += key; - if (!currentNode->subnodes.contains(path)) { - InternalNode *val = new InternalNode; - val->type = type; - val->fullPath = path; - val->displayName = key; - currentNode->subnodes.insert(path, val); - currentNode = val; - } else { - currentNode = currentNode->subnodes.value(path); - } - path += separator; - } else { // key is filename - currentNode->files.append(file); - } - } - } - this->compress(); - } - - // Removes folder nodes with only a single sub folder in it - void compress() - { - QMap<QString, InternalNode*> newSubnodes; - QMapIterator<QString, InternalNode*> i(subnodes); - while (i.hasNext()) { - i.next(); - i.value()->compress(); - if (i.value()->files.isEmpty() && i.value()->subnodes.size() == 1) { - // replace i.value() by i.value()->subnodes.begin() - QString key = i.value()->subnodes.begin().key(); - InternalNode *keep = i.value()->subnodes.value(key); - keep->displayName = i.value()->displayName + QDir::separator() + keep->displayName; - newSubnodes.insert(key, keep); - i.value()->subnodes.clear(); - delete i.value(); - } else { - newSubnodes.insert(i.key(), i.value()); - } - } - subnodes = newSubnodes; - } - - FolderNode *createFolderNode(InternalNode *node) - { - FolderNode *newNode = nullptr; - if (node->typeName.isEmpty()) - newNode = new FolderNode(FileName::fromString(node->fullPath)); - else - newNode = new ProVirtualFolderNode(node); - - newNode->setDisplayName(node->displayName); - if (!node->icon.isNull()) - newNode->setIcon(node->icon); - return newNode; - } - - // Makes the projectNode's subtree below the given folder match this internal node's subtree - void addSubFolderContents(FolderNode *folder) - { - if (type == FileType::Resource) { - for (const FileName &file : files) { - auto vfs = static_cast<QmakePriFileNode *>(folder->parentProjectNode())->m_project->qmakeVfs(); - QString contents; - // Prefer the cumulative file if it's non-empty, based on the assumption - // that it contains more "stuff". - vfs->readVirtualFile(file.toString(), QMakeVfs::VfsCumulative, &contents); - // If the cumulative evaluation botched the file too much, try the exact one. - if (contents.isEmpty()) - vfs->readVirtualFile(file.toString(), QMakeVfs::VfsExact, &contents); - auto resourceNode = new ResourceEditor::ResourceTopLevelNode(file, contents, folder); - folder->addNode(resourceNode); - resourceNode->addInternalNodes(); - } - } else { - for (const FileName &file : files) - folder->addNode(new FileNode(file, type, false)); - } - - // Virtual - { - for (InternalNode *node : virtualfolders) { - FolderNode *newNode = createFolderNode(node); - folder->addNode(newNode); - node->addSubFolderContents(newNode); - } - } - // Subnodes - { - QMap<QString, InternalNode *>::const_iterator it = subnodes.constBegin(); - QMap<QString, InternalNode *>::const_iterator end = subnodes.constEnd(); - for ( ; it != end; ++it) { - FolderNode *newNode = createFolderNode(it.value()); - folder->addNode(newNode); - it.value()->addSubFolderContents(newNode); - } - } - } -}; - -ProVirtualFolderNode::ProVirtualFolderNode(InternalNode *node) - : VirtualFolderNode(FileName::fromString(node->fullPath), node->priority), - m_typeName(node->typeName), - m_addFileFilter(node->addFileFilter) -{} - -} // Internal /*! \class QmakePriFileNode @@ -449,276 +46,21 @@ ProVirtualFolderNode::ProVirtualFolderNode(InternalNode *node) */ QmakePriFileNode::QmakePriFileNode(QmakeProject *project, QmakeProFileNode *qmakeProFileNode, - const FileName &filePath) - : ProjectNode(filePath), - m_project(project), - m_qmakeProFileNode(qmakeProFileNode), - m_projectFilePath(filePath), - m_projectDir(filePath.toFileInfo().absolutePath()) -{ - Q_ASSERT(project); - m_qmakePriFile = new QmakePriFileNodeDocument(this); - Core::DocumentManager::addDocument(m_qmakePriFile); - - setDisplayName(filePath.toFileInfo().completeBaseName()); - setIcon(qmakeNodeStaticData()->projectIcon); -} - -QmakePriFileNode::~QmakePriFileNode() -{ - watchFolders(QSet<QString>()); - delete m_qmakePriFile; -} - -void QmakePriFileNode::scheduleUpdate() -{ - QtSupport::ProFileCacheManager::instance()->discardFile(m_projectFilePath.toString()); - m_qmakeProFileNode->scheduleUpdate(QmakeProFile::ParseLater); -} - -QStringList QmakePriFileNode::baseVPaths(QtSupport::ProFileReader *reader, const QString &projectDir, const QString &buildDir) -{ - QStringList result; - if (!reader) - return result; - result += reader->absolutePathValues(QLatin1String("VPATH"), projectDir); - result << projectDir; // QMAKE_ABSOLUTE_SOURCE_PATH - result << buildDir; - result.removeDuplicates(); - return result; -} + const FileName &filePath) : + ProjectNode(filePath), + m_project(project), + m_qmakeProFileNode(qmakeProFileNode) +{ } -QStringList QmakePriFileNode::fullVPaths(const QStringList &baseVPaths, QtSupport::ProFileReader *reader, - const QString &qmakeVariable, const QString &projectDir) +QmakePriFile *QmakePriFileNode::priFile() const { - QStringList vPaths; - if (!reader) - return vPaths; - vPaths = reader->absolutePathValues(QLatin1String("VPATH_") + qmakeVariable, projectDir); - vPaths += baseVPaths; - vPaths.removeDuplicates(); - return vPaths; -} - -QSet<FileName> QmakePriFileNode::recursiveEnumerate(const QString &folder) -{ - QSet<FileName> result; - QDir dir(folder); - dir.setFilter(dir.filter() | QDir::NoDotAndDotDot); - foreach (const QFileInfo &file, dir.entryInfoList()) { - if (file.isDir() && !file.isSymLink()) - result += recursiveEnumerate(file.absoluteFilePath()); - else if (!Core::EditorManager::isAutoSaveFile(file.fileName())) - result += FileName(file); - } - return result; -} - -static QStringList fileListForVar( - const QHash<QString, QVector<ProFileEvaluator::SourceFile> > &sourceFiles, - const QString &varName) -{ - const QVector<ProFileEvaluator::SourceFile> &sources = sourceFiles[varName]; - QStringList result; - result.reserve(sources.size()); - foreach (const ProFileEvaluator::SourceFile &sf, sources) - result << sf.fileName; - return result; -} - -void QmakePriFileNode::extractSources( - QHash<const ProFile *, PriFileEvalResult *> proToResult, PriFileEvalResult *fallback, - QVector<ProFileEvaluator::SourceFile> sourceFiles, FileType type) -{ - foreach (const ProFileEvaluator::SourceFile &source, sourceFiles) { - PriFileEvalResult *result = proToResult.value(source.proFile); - if (!result) - result = fallback; - result->foundFiles[type].insert(FileName::fromString(source.fileName)); - } -} - -void QmakePriFileNode::extractInstalls( - QHash<const ProFile *, PriFileEvalResult *> proToResult, PriFileEvalResult *fallback, - const InstallsList &installList) -{ - for (const InstallsItem &item : installList.items) { - for (const ProFileEvaluator::SourceFile &source : item.files) { - auto *result = proToResult.value(source.proFile); - if (!result) - result = fallback; - result->folders << source.fileName; - } - } -} - -void QmakePriFileNode::processValues(PriFileEvalResult &result) -{ - result.folders.removeDuplicates(); - - // Remove non existing items and non folders - QStringList::iterator it = result.folders.begin(); - while (it != result.folders.end()) { - QFileInfo fi(*it); - if (fi.exists()) { - if (fi.isDir()) { - // keep directories - ++it; - } else { - // move files directly to recursiveEnumerateFiles - result.recursiveEnumerateFiles << FileName::fromString(*it); - it = result.folders.erase(it); - } - } else { - // do remove non exsting stuff - it = result.folders.erase(it); - } - } - - foreach (const QString &folder, result.folders) - result.recursiveEnumerateFiles += recursiveEnumerate(folder); - - const QVector<QmakeNodeStaticData::FileTypeData> &fileTypes = qmakeNodeStaticData()->fileTypeData; - for (int i = 0; i < fileTypes.size(); ++i) { - FileType type = fileTypes.at(i).type; - QSet<FileName> &foundFiles = result.foundFiles[type]; - result.recursiveEnumerateFiles.subtract(foundFiles); - QSet<FileName> newFilePaths = filterFilesProVariables(type, foundFiles); - newFilePaths += filterFilesRecursiveEnumerata(type, result.recursiveEnumerateFiles); - foundFiles = newFilePaths; - } -} - -void QmakePriFileNode::update(const Internal::PriFileEvalResult &result) -{ - // add project file node - addNode(new FileNode(m_projectFilePath, FileType::Project, false)); - - m_recursiveEnumerateFiles = result.recursiveEnumerateFiles; - watchFolders(result.folders.toSet()); - - InternalNode contents; - const QVector<QmakeNodeStaticData::FileTypeData> &fileTypes = qmakeNodeStaticData()->fileTypeData; - for (int i = 0; i < fileTypes.size(); ++i) { - FileType type = fileTypes.at(i).type; - const QSet<FileName> &newFilePaths = result.foundFiles.value(type); - // We only need to save this information if - // we are watching folders - if (!result.folders.isEmpty()) - m_files[type] = newFilePaths; - else - m_files[type].clear(); - - if (!newFilePaths.isEmpty()) { - InternalNode *subfolder = new InternalNode; - subfolder->type = type; - subfolder->icon = fileTypes.at(i).icon; - subfolder->fullPath = m_projectDir; - subfolder->typeName = fileTypes.at(i).typeName; - subfolder->addFileFilter = fileTypes.at(i).addFileFilter; - subfolder->priority = Node::DefaultVirtualFolderPriority - i; - subfolder->displayName = fileTypes.at(i).typeName; - contents.virtualfolders.append(subfolder); - // create the hierarchy with subdirectories - subfolder->create(m_projectDir, newFilePaths, type); - } - } - - contents.addSubFolderContents(this); -} - -void QmakePriFileNode::watchFolders(const QSet<QString> &folders) -{ - QSet<QString> toUnwatch = m_watchedFolders; - toUnwatch.subtract(folders); - - QSet<QString> toWatch = folders; - toWatch.subtract(m_watchedFolders); - - if (!toUnwatch.isEmpty()) - m_project->unwatchFolders(toUnwatch.toList(), this); - if (!toWatch.isEmpty()) - m_project->watchFolders(toWatch.toList(), this); - - m_watchedFolders = folders; -} - -bool QmakePriFileNode::folderChanged(const QString &changedFolder, const QSet<FileName> &newFiles) -{ - //qDebug()<<"########## QmakePriFileNode::folderChanged"; - // So, we need to figure out which files changed. - - QSet<FileName> addedFiles = newFiles; - addedFiles.subtract(m_recursiveEnumerateFiles); - - QSet<FileName> removedFiles = m_recursiveEnumerateFiles; - removedFiles.subtract(newFiles); - - foreach (const FileName &file, removedFiles) { - if (!file.isChildOf(FileName::fromString(changedFolder))) - removedFiles.remove(file); - } - - if (addedFiles.isEmpty() && removedFiles.isEmpty()) - return false; - - m_recursiveEnumerateFiles = newFiles; - - // Apply the differences - // per file type - const QVector<QmakeNodeStaticData::FileTypeData> &fileTypes = qmakeNodeStaticData()->fileTypeData; - for (int i = 0; i < fileTypes.size(); ++i) { - FileType type = fileTypes.at(i).type; - QSet<FileName> add = filterFilesRecursiveEnumerata(type, addedFiles); - QSet<FileName> remove = filterFilesRecursiveEnumerata(type, removedFiles); - - if (!add.isEmpty() || !remove.isEmpty()) { - // Scream :) -// qDebug()<<"For type"<<fileTypes.at(i).typeName<<"\n" -// <<"added files"<<add<<"\n" -// <<"removed files"<<remove; - - m_files[type].unite(add); - m_files[type].subtract(remove); - } - } - - // Now apply stuff - InternalNode contents; - for (int i = 0; i < fileTypes.size(); ++i) { - FileType type = fileTypes.at(i).type; - if (!m_files[type].isEmpty()) { - InternalNode *subfolder = new InternalNode; - subfolder->type = type; - subfolder->icon = fileTypes.at(i).icon; - subfolder->fullPath = m_projectDir; - subfolder->typeName = fileTypes.at(i).typeName; - subfolder->priority = Node::DefaultVirtualFolderPriority - i; - subfolder->displayName = fileTypes.at(i).typeName; - contents.virtualfolders.append(subfolder); - // create the hierarchy with subdirectories - subfolder->create(m_projectDir, m_files[type], type); - } - } - - contents.addSubFolderContents(this); - return true; + return m_project->rootProFile()->findPriFile(filePath()); } bool QmakePriFileNode::deploysFolder(const QString &folder) const { - QString f = folder; - const QChar slash = QLatin1Char('/'); - if (!f.endsWith(slash)) - f.append(slash); - - foreach (const QString &wf, m_watchedFolders) { - if (f.startsWith(wf) - && (wf.endsWith(slash) - || (wf.length() < f.length() && f.at(wf.length()) == slash))) - return true; - } - return false; + QmakePriFile *pri = priFile(); + return pri ? pri->deploysFolder(folder) : false; } QList<RunConfiguration *> QmakePriFileNode::runConfigurations() const @@ -729,32 +71,11 @@ QList<RunConfiguration *> QmakePriFileNode::runConfigurations() const return QList<RunConfiguration *>(); } -QList<QmakePriFileNode *> QmakePriFileNode::subProjectNodesExact() const -{ - QList<QmakePriFileNode *> nodes; - foreach (ProjectNode *node, projectNodes()) { - QmakePriFileNode *n = dynamic_cast<QmakePriFileNode *>(node); - if (n && n->includedInExactParse()) - nodes << n; - } - return nodes; -} - QmakeProFileNode *QmakePriFileNode::proFileNode() const { return m_qmakeProFileNode; } -bool QmakePriFileNode::includedInExactParse() const -{ - return m_includedInExactParse; -} - -void QmakePriFileNode::setIncludedInExactParse(bool b) -{ - m_includedInExactParse = b; -} - QList<ProjectAction> QmakePriFileNode::supportedActions(Node *node) const { QList<ProjectAction> actions; @@ -764,8 +85,9 @@ QList<ProjectAction> QmakePriFileNode::supportedActions(Node *node) const while (!(proFileNode = dynamic_cast<const QmakeProFileNode*>(folderNode))) folderNode = folderNode->parentFolderNode(); Q_ASSERT(proFileNode); + const QmakeProFile *pro = proFileNode->proFile(); - switch (proFileNode->projectType()) { + switch (pro ? pro->projectType() : ProjectType::Invalid) { case ProjectType::ApplicationTemplate: case ProjectType::StaticLibraryTemplate: case ProjectType::SharedLibraryTemplate: @@ -775,7 +97,7 @@ QList<ProjectAction> QmakePriFileNode::supportedActions(Node *node) const // work on a subset of the file types according to project type. actions << AddNewFile; - if (m_recursiveEnumerateFiles.contains(node->filePath())) + if (pro && pro->knowsFile(node->filePath())) actions << EraseFile; else actions << RemoveFile; @@ -814,7 +136,6 @@ QList<ProjectAction> QmakePriFileNode::supportedActions(Node *node) const actions << DuplicateFile; } - Target *target = m_project->activeTarget(); QmakeRunConfigurationFactory *factory = QmakeRunConfigurationFactory::find(target); if (factory && !factory->runConfigurationsForNode(target, node).isEmpty()) @@ -825,163 +146,50 @@ QList<ProjectAction> QmakePriFileNode::supportedActions(Node *node) const bool QmakePriFileNode::canAddSubProject(const QString &proFilePath) const { - QFileInfo fi(proFilePath); - if (fi.suffix() == QLatin1String("pro") - || fi.suffix() == QLatin1String("pri")) - return true; - return false; -} - -static QString simplifyProFilePath(const QString &proFilePath) -{ - // if proFilePath is like: _path_/projectName/projectName.pro - // we simplify it to: _path_/projectName - QFileInfo fi(proFilePath); - const QString parentPath = fi.absolutePath(); - QFileInfo parentFi(parentPath); - if (parentFi.fileName() == fi.completeBaseName()) - return parentPath; - return proFilePath; + QmakePriFile *pri = priFile(); + return pri ? pri->canAddSubProject(proFilePath) : false; } bool QmakePriFileNode::addSubProjects(const QStringList &proFilePaths) { - FindAllFilesVisitor visitor; - accept(&visitor); - const FileNameList &allFiles = visitor.filePaths(); - - QStringList uniqueProFilePaths; - foreach (const QString &proFile, proFilePaths) - if (!allFiles.contains(FileName::fromString(proFile))) - uniqueProFilePaths.append(simplifyProFilePath(proFile)); - - QStringList failedFiles; - changeFiles(QLatin1String(Constants::PROFILE_MIMETYPE), uniqueProFilePaths, &failedFiles, AddToProFile); - - return failedFiles.isEmpty(); + QmakePriFile *pri = priFile(); + return pri ? pri->addSubProjects(proFilePaths) : false; } bool QmakePriFileNode::removeSubProjects(const QStringList &proFilePaths) { - QStringList failedOriginalFiles; - changeFiles(QLatin1String(Constants::PROFILE_MIMETYPE), proFilePaths, &failedOriginalFiles, RemoveFromProFile); - - QStringList simplifiedProFiles = Utils::transform(failedOriginalFiles, &simplifyProFilePath); - - QStringList failedSimplifiedFiles; - changeFiles(QLatin1String(Constants::PROFILE_MIMETYPE), simplifiedProFiles, &failedSimplifiedFiles, RemoveFromProFile); - - return failedSimplifiedFiles.isEmpty(); + QmakePriFile *pri = priFile(); + return pri ? pri->removeSubProjects(proFilePaths) : false; } bool QmakePriFileNode::addFiles(const QStringList &filePaths, QStringList *notAdded) { - // If a file is already referenced in the .pro file then we don't add them. - // That ignores scopes and which variable was used to reference the file - // So it's obviously a bit limited, but in those cases you need to edit the - // project files manually anyway. - - FindAllFilesVisitor visitor; - accept(&visitor); - const FileNameList &allFiles = visitor.filePaths(); - - typedef QMap<QString, QStringList> TypeFileMap; - // Split into lists by file type and bulk-add them. - TypeFileMap typeFileMap; - Utils::MimeDatabase mdb; - foreach (const QString &file, filePaths) { - const Utils::MimeType mt = mdb.mimeTypeForFile(file); - typeFileMap[mt.name()] << file; - } - - QStringList failedFiles; - foreach (const QString &type, typeFileMap.keys()) { - const QStringList typeFiles = typeFileMap.value(type); - QStringList qrcFiles; // the list of qrc files referenced from ui files - if (type == QLatin1String(ProjectExplorer::Constants::RESOURCE_MIMETYPE)) { - foreach (const QString &formFile, typeFiles) { - QStringList resourceFiles = formResources(formFile); - foreach (const QString &resourceFile, resourceFiles) - if (!qrcFiles.contains(resourceFile)) - qrcFiles.append(resourceFile); - } - } - - QStringList uniqueQrcFiles; - foreach (const QString &file, qrcFiles) { - if (!allFiles.contains(FileName::fromString(file))) - uniqueQrcFiles.append(file); - } - - QStringList uniqueFilePaths; - foreach (const QString &file, typeFiles) { - if (!allFiles.contains(FileName::fromString(file))) - uniqueFilePaths.append(file); - } - - changeFiles(type, uniqueFilePaths, &failedFiles, AddToProFile); - if (notAdded) - *notAdded += failedFiles; - changeFiles(QLatin1String(ProjectExplorer::Constants::RESOURCE_MIMETYPE), uniqueQrcFiles, &failedFiles, AddToProFile); - if (notAdded) - *notAdded += failedFiles; - } - return failedFiles.isEmpty(); + QmakePriFile *pri = priFile(); + return pri ? pri->addFiles(filePaths, notAdded) : false; } -bool QmakePriFileNode::removeFiles(const QStringList &filePaths, - QStringList *notRemoved) +bool QmakePriFileNode::removeFiles(const QStringList &filePaths, QStringList *notRemoved) { - QStringList failedFiles; - typedef QMap<QString, QStringList> TypeFileMap; - // Split into lists by file type and bulk-add them. - TypeFileMap typeFileMap; - Utils::MimeDatabase mdb; - foreach (const QString &file, filePaths) { - const Utils::MimeType mt = mdb.mimeTypeForFile(file); - typeFileMap[mt.name()] << file; - } - foreach (const QString &type, typeFileMap.keys()) { - const QStringList typeFiles = typeFileMap.value(type); - changeFiles(type, typeFiles, &failedFiles, RemoveFromProFile); - if (notRemoved) - *notRemoved = failedFiles; - } - return failedFiles.isEmpty(); + QmakePriFile *pri = priFile(); + return pri ? pri->removeFiles(filePaths, notRemoved) : false; } bool QmakePriFileNode::deleteFiles(const QStringList &filePaths) { - removeFiles(filePaths); - return true; + QmakePriFile *pri = priFile(); + return pri ? pri->deleteFiles(filePaths) : false; } bool QmakePriFileNode::canRenameFile(const QString &filePath, const QString &newFilePath) { - if (newFilePath.isEmpty()) - return false; - - bool changeProFileOptional = deploysFolder(QFileInfo(filePath).absolutePath()); - if (changeProFileOptional) - return true; - Utils::MimeDatabase mdb; - const Utils::MimeType mt = mdb.mimeTypeForFile(newFilePath); - - return renameFile(filePath, newFilePath, mt.name(), Change::TestOnly); + QmakePriFile *pri = priFile(); + return pri ? pri->canRenameFile(filePath, newFilePath) : false; } bool QmakePriFileNode::renameFile(const QString &filePath, const QString &newFilePath) { - if (newFilePath.isEmpty()) - return false; - - bool changeProFileOptional = deploysFolder(QFileInfo(filePath).absolutePath()); - Utils::MimeDatabase mdb; - const Utils::MimeType mt = mdb.mimeTypeForFile(newFilePath); - - if (renameFile(filePath, newFilePath, mt.name())) - return true; - return changeProFileOptional; + QmakePriFile *pri = priFile(); + return pri ? pri->renameFile(filePath, newFilePath) : false; } FolderNode::AddNewInformation QmakePriFileNode::addNewInformation(const QStringList &files, Node *context) const @@ -990,430 +198,6 @@ FolderNode::AddNewInformation QmakePriFileNode::addNewInformation(const QStringL return FolderNode::AddNewInformation(filePath().fileName(), context && context->parentProjectNode() == this ? 120 : 90); } -bool QmakePriFileNode::priFileWritable(const QString &path) -{ - ReadOnlyFilesDialog roDialog(path, ICore::mainWindow()); - roDialog.setShowFailWarning(true); - return roDialog.exec() != ReadOnlyFilesDialog::RO_Cancel; -} - -bool QmakePriFileNode::saveModifiedEditors() -{ - Core::IDocument *document - = Core::DocumentModel::documentForFilePath(m_projectFilePath.toString()); - if (!document || !document->isModified()) - return true; - - if (!Core::DocumentManager::saveDocument(document)) - return false; - - // force instant reload of ourselves - QtSupport::ProFileCacheManager::instance()->discardFile(m_projectFilePath.toString()); - m_project->projectManager()->notifyChanged(m_projectFilePath); - return true; -} - -QStringList QmakePriFileNode::formResources(const QString &formFile) const -{ - QStringList resourceFiles; - QFile file(formFile); - if (!file.open(QIODevice::ReadOnly)) - return resourceFiles; - - QXmlStreamReader reader(&file); - - QFileInfo fi(formFile); - QDir formDir = fi.absoluteDir(); - while (!reader.atEnd()) { - reader.readNext(); - if (reader.isStartElement()) { - if (reader.name() == QLatin1String("iconset")) { - const QXmlStreamAttributes attributes = reader.attributes(); - if (attributes.hasAttribute(QLatin1String("resource"))) - resourceFiles.append(QDir::cleanPath(formDir.absoluteFilePath( - attributes.value(QLatin1String("resource")).toString()))); - } else if (reader.name() == QLatin1String("include")) { - const QXmlStreamAttributes attributes = reader.attributes(); - if (attributes.hasAttribute(QLatin1String("location"))) - resourceFiles.append(QDir::cleanPath(formDir.absoluteFilePath( - attributes.value(QLatin1String("location")).toString()))); - - } - } - } - - if (reader.hasError()) - qWarning() << "Could not read form file:" << formFile; - - return resourceFiles; -} - -bool QmakePriFileNode::ensureWriteableProFile(const QString &file) -{ - // Ensure that the file is not read only - QFileInfo fi(file); - if (!fi.isWritable()) { - // Try via vcs manager - Core::IVersionControl *versionControl = Core::VcsManager::findVersionControlForDirectory(fi.absolutePath()); - if (!versionControl || !versionControl->vcsOpen(file)) { - bool makeWritable = QFile::setPermissions(file, fi.permissions() | QFile::WriteUser); - if (!makeWritable) { - QMessageBox::warning(Core::ICore::mainWindow(), - QCoreApplication::translate("QmakePriFileNode", "Failed"), - QCoreApplication::translate("QmakePriFileNode", "Could not write project file %1.").arg(file)); - return false; - } - } - } - return true; -} - -QPair<ProFile *, QStringList> QmakePriFileNode::readProFile(const QString &file) -{ - QStringList lines; - ProFile *includeFile = nullptr; - { - QString contents; - { - FileReader reader; - if (!reader.fetch(file, QIODevice::Text)) { - QmakeProject::proFileParseError(reader.errorString()); - return qMakePair(includeFile, lines); - } - const QTextCodec *codec = Core::EditorManager::defaultTextCodec(); - contents = codec->toUnicode(reader.data()); - lines = contents.split(QLatin1Char('\n')); - } - - QMakeVfs vfs; - QtSupport::ProMessageHandler handler; - QMakeParser parser(nullptr, &vfs, &handler); - includeFile = parser.parsedProBlock(QStringRef(&contents), file, 1); - } - return qMakePair(includeFile, lines); -} - -bool QmakePriFileNode::prepareForChange() -{ - return saveModifiedEditors() && ensureWriteableProFile(m_projectFilePath.toString()); -} - -bool QmakePriFileNode::renameFile(const QString &oldName, - const QString &newName, - const QString &mimeType, - Change mode) -{ - if (!prepareForChange()) - return false; - - QPair<ProFile *, QStringList> pair = readProFile(m_projectFilePath.toString()); - ProFile *includeFile = pair.first; - QStringList lines = pair.second; - - if (!includeFile) - return false; - - QDir priFileDir = QDir(m_qmakeProFileNode->m_projectDir); - QStringList notChanged = ProWriter::removeFiles(includeFile, &lines, priFileDir, - QStringList(oldName), varNamesForRemoving()); - - includeFile->deref(); - if (!notChanged.isEmpty()) - return false; - - // We need to re-parse here: The file has changed. - QMakeParser parser(nullptr, nullptr, nullptr); - QString contents = lines.join(QLatin1Char('\n')); - includeFile = parser.parsedProBlock(QStringRef(&contents), - m_projectFilePath.toString(), 1, QMakeParser::FullGrammar); - QTC_ASSERT(includeFile, return false); // The file should still be valid after what we did. - - ProWriter::addFiles(includeFile, &lines, - QStringList(newName), - varNameForAdding(mimeType)); - if (mode == Change::Save) - save(lines); - includeFile->deref(); - return true; -} - -void QmakePriFileNode::changeFiles(const QString &mimeType, - const QStringList &filePaths, - QStringList *notChanged, - ChangeType change, Change mode) -{ - if (filePaths.isEmpty()) - return; - - *notChanged = filePaths; - - // Check for modified editors - if (!prepareForChange()) - return; - - QPair<ProFile *, QStringList> pair = readProFile(m_projectFilePath.toString()); - ProFile *includeFile = pair.first; - QStringList lines = pair.second; - - if (!includeFile) - return; - - if (change == AddToProFile) { - // Use the first variable for adding. - ProWriter::addFiles(includeFile, &lines, filePaths, varNameForAdding(mimeType)); - notChanged->clear(); - } else { // RemoveFromProFile - QDir priFileDir = QDir(m_qmakeProFileNode->m_projectDir); - *notChanged = ProWriter::removeFiles(includeFile, &lines, priFileDir, filePaths, varNamesForRemoving()); - } - - // save file - if (mode == Change::Save) - save(lines); - includeFile->deref(); -} - -bool QmakePriFileNode::setProVariable(const QString &var, const QStringList &values, const QString &scope, int flags) -{ - if (!prepareForChange()) - return false; - - QPair<ProFile *, QStringList> pair = readProFile(m_projectFilePath.toString()); - ProFile *includeFile = pair.first; - QStringList lines = pair.second; - - if (!includeFile) - return false; - - ProWriter::putVarValues(includeFile, &lines, values, var, - ProWriter::PutFlags(flags), - scope); - - save(lines); - includeFile->deref(); - return true; -} - -void QmakePriFileNode::save(const QStringList &lines) -{ - { - FileChangeBlocker changeGuard(m_projectFilePath.toString()); - FileSaver saver(m_projectFilePath.toString(), QIODevice::Text); - const QTextCodec *codec = Core::EditorManager::defaultTextCodec(); - saver.write(codec->fromUnicode(lines.join(QLatin1Char('\n')))); - saver.finalize(Core::ICore::mainWindow()); - } - - // This is a hack. - // We are saving twice in a very short timeframe, once the editor and once the ProFile. - // So the modification time might not change between those two saves. - // We manually tell each editor to reload it's file. - // (The .pro files are notified by the file system watcher.) - QStringList errorStrings; - Core::IDocument *document = Core::DocumentModel::documentForFilePath(m_projectFilePath.toString()); - if (document) { - QString errorString; - if (!document->reload(&errorString, Core::IDocument::FlagReload, Core::IDocument::TypeContents)) - errorStrings << errorString; - } - if (!errorStrings.isEmpty()) - QMessageBox::warning(Core::ICore::mainWindow(), QCoreApplication::translate("QmakePriFileNode", "File Error"), - errorStrings.join(QLatin1Char('\n'))); -} - -QStringList QmakePriFileNode::varNames(FileType type, QtSupport::ProFileReader *readerExact) -{ - QStringList vars; - switch (type) { - case FileType::Header: - vars << QLatin1String("HEADERS"); - vars << QLatin1String("PRECOMPILED_HEADER"); - break; - case FileType::Source: { - vars << QLatin1String("SOURCES"); - QStringList listOfExtraCompilers = readerExact->values(QLatin1String("QMAKE_EXTRA_COMPILERS")); - foreach (const QString &var, listOfExtraCompilers) { - QStringList inputs = readerExact->values(var + QLatin1String(".input")); - foreach (const QString &input, inputs) - // FORMS, RESOURCES, and STATECHARTS are handled below, HEADERS and SOURCES above - if (input != QLatin1String("FORMS") - && input != QLatin1String("STATECHARTS") - && input != QLatin1String("RESOURCES") - && input != QLatin1String("SOURCES") - && input != QLatin1String("HEADERS")) - vars << input; - } - break; - } - case FileType::Resource: - vars << QLatin1String("RESOURCES"); - break; - case FileType::Form: - vars << QLatin1String("FORMS"); - break; - case FileType::StateChart: - vars << QLatin1String("STATECHARTS"); - break; - case FileType::Project: - vars << QLatin1String("SUBDIRS"); - break; - case FileType::QML: - vars << QLatin1String("OTHER_FILES"); - vars << QLatin1String("DISTFILES"); - break; - default: - vars << QLatin1String("OTHER_FILES"); - vars << QLatin1String("DISTFILES"); - vars << QLatin1String("ICON"); - vars << QLatin1String("QMAKE_INFO_PLIST"); - break; - } - return vars; -} - -//! -//! \brief QmakePriFileNode::varNames -//! \param mimeType -//! \return the qmake variable name for the mime type -//! Note: Only used for adding. -//! -QString QmakePriFileNode::varNameForAdding(const QString &mimeType) -{ - if (mimeType == QLatin1String(ProjectExplorer::Constants::CPP_HEADER_MIMETYPE) - || mimeType == QLatin1String(ProjectExplorer::Constants::C_HEADER_MIMETYPE)) { - return QLatin1String("HEADERS"); - } - - if (mimeType == QLatin1String(ProjectExplorer::Constants::CPP_SOURCE_MIMETYPE) - || mimeType == QLatin1String(CppTools::Constants::OBJECTIVE_CPP_SOURCE_MIMETYPE) - || mimeType == QLatin1String(ProjectExplorer::Constants::C_SOURCE_MIMETYPE)) { - return QLatin1String("SOURCES"); - } - - if (mimeType == QLatin1String(ProjectExplorer::Constants::RESOURCE_MIMETYPE)) - return QLatin1String("RESOURCES"); - - if (mimeType == QLatin1String(ProjectExplorer::Constants::FORM_MIMETYPE)) - return QLatin1String("FORMS"); - - if (mimeType == QLatin1String(ProjectExplorer::Constants::QML_MIMETYPE)) - return QLatin1String("DISTFILES"); - - if (mimeType == QLatin1String(ProjectExplorer::Constants::SCXML_MIMETYPE)) - return QLatin1String("STATECHARTS"); - - if (mimeType == QLatin1String(Constants::PROFILE_MIMETYPE)) - return QLatin1String("SUBDIRS"); - - return QLatin1String("DISTFILES"); -} - -//! -//! \brief QmakePriFileNode::varNamesForRemoving -//! \return all qmake variables which are displayed in the project tree -//! Note: Only used for removing. -//! -QStringList QmakePriFileNode::varNamesForRemoving() -{ - QStringList vars; - vars << QLatin1String("HEADERS"); - vars << QLatin1String("OBJECTIVE_HEADERS"); - vars << QLatin1String("PRECOMPILED_HEADER"); - vars << QLatin1String("SOURCES"); - vars << QLatin1String("OBJECTIVE_SOURCES"); - vars << QLatin1String("RESOURCES"); - vars << QLatin1String("FORMS"); - vars << QLatin1String("OTHER_FILES"); - vars << QLatin1String("SUBDIRS"); - vars << QLatin1String("DISTFILES"); - vars << QLatin1String("ICON"); - vars << QLatin1String("QMAKE_INFO_PLIST"); - vars << QLatin1String("STATECHARTS"); - return vars; -} - -QSet<FileName> QmakePriFileNode::filterFilesProVariables(FileType fileType, const QSet<FileName> &files) -{ - if (fileType != FileType::QML && fileType != FileType::Unknown) - return files; - QSet<FileName> result; - if (fileType == FileType::QML) { - foreach (const FileName &file, files) - if (file.toString().endsWith(QLatin1String(".qml"))) - result << file; - } else { - foreach (const FileName &file, files) - if (!file.toString().endsWith(QLatin1String(".qml"))) - result << file; - } - return result; -} - -QSet<FileName> QmakePriFileNode::filterFilesRecursiveEnumerata(FileType fileType, const QSet<FileName> &files) -{ - QSet<FileName> result; - if (fileType != FileType::QML && fileType != FileType::Unknown) - return result; - if (fileType == FileType::QML) { - foreach (const FileName &file, files) - if (file.toString().endsWith(QLatin1String(".qml"))) - result << file; - } else { - foreach (const FileName &file, files) - if (!file.toString().endsWith(QLatin1String(".qml"))) - result << file; - } - return result; -} - -} // namespace QmakeProjectManager - -static ProjectType proFileTemplateTypeToProjectType(ProFileEvaluator::TemplateType type) -{ - switch (type) { - case ProFileEvaluator::TT_Unknown: - case ProFileEvaluator::TT_Application: - return ProjectType::ApplicationTemplate; - case ProFileEvaluator::TT_StaticLibrary: - return ProjectType::StaticLibraryTemplate; - case ProFileEvaluator::TT_SharedLibrary: - return ProjectType::SharedLibraryTemplate; - case ProFileEvaluator::TT_Script: - return ProjectType::ScriptTemplate; - case ProFileEvaluator::TT_Aux: - return ProjectType::AuxTemplate; - case ProFileEvaluator::TT_Subdirs: - return ProjectType::SubDirsTemplate; - default: - return ProjectType::Invalid; - } -} - -namespace { - // feed all files accepted by any of the factories to the callback. - class FindGeneratorSourcesVisitor : public NodesVisitor - { - public: - FindGeneratorSourcesVisitor( - const QList<ProjectExplorer::ExtraCompilerFactory *> &factories, - std::function<void(FileNode *, ProjectExplorer::ExtraCompilerFactory *)> callback) : - factories(factories), callback(callback) {} - - void visitFolderNode(FolderNode *folderNode) final - { - foreach (FileNode *fileNode, folderNode->fileNodes()) { - foreach (ProjectExplorer::ExtraCompilerFactory *factory, factories) { - if (factory->sourceType() == fileNode->fileType()) - callback(fileNode, factory); - } - } - } - - const QList<ProjectExplorer::ExtraCompilerFactory *> factories; - std::function<void(FileNode *, ProjectExplorer::ExtraCompilerFactory *)> callback; - }; -} - QmakeProFileNode *QmakeProFileNode::findProFileFor(const FileName &fileName) const { if (fileName == filePath()) @@ -1425,88 +209,22 @@ QmakeProFileNode *QmakeProFileNode::findProFileFor(const FileName &fileName) con return nullptr; } -QString QmakeProFileNode::makefile() const -{ - return singleVariableValue(Variable::Makefile); -} - -QString QmakeProFileNode::objectExtension() const -{ - if (m_varValues[Variable::ObjectExt].isEmpty()) - return HostOsInfo::isWindowsHost() ? QLatin1String(".obj") : QLatin1String(".o"); - return m_varValues[Variable::ObjectExt].first(); -} - -QString QmakeProFileNode::objectsDirectory() const -{ - return singleVariableValue(Variable::ObjectsDir); -} - -QByteArray QmakeProFileNode::cxxDefines() const -{ - QByteArray result; - foreach (const QString &def, variableValue(Variable::Defines)) { - // 'def' is shell input, so interpret it. - QtcProcess::SplitError error = QtcProcess::SplitOk; - const QStringList args = QtcProcess::splitArgs(def, HostOsInfo::hostOs(), false, &error); - if (error != QtcProcess::SplitOk || args.size() == 0) - continue; - - result += "#define "; - const QString defInterpreted = args.first(); - const int index = defInterpreted.indexOf(QLatin1Char('=')); - if (index == -1) { - result += defInterpreted.toLatin1(); - result += " 1\n"; - } else { - const QString name = defInterpreted.left(index); - const QString value = defInterpreted.mid(index + 1); - result += name.toLatin1(); - result += ' '; - result += value.toLocal8Bit(); - result += '\n'; - } - } - return result; -} - /*! \class QmakeProFileNode Implements abstract ProjectNode class */ -QmakeProFileNode::QmakeProFileNode(QmakeProject *project, - const FileName &filePath) - : QmakePriFileNode(project, this, filePath) -{ - // The slot is a lambda, so that QmakeProFileNode does not need to be - // a qobject. The lifetime of the m_parserFutureWatcher is shorter - // than of this, so this is all safe - QObject::connect(&m_parseFutureWatcher, &QFutureWatcherBase::finished, - [this](){ - applyAsyncEvaluate(); - }); -} +QmakeProFileNode::QmakeProFileNode(QmakeProject *project, const FileName &filePath) : + QmakePriFileNode(project, this, filePath) +{ } -QmakeProFileNode::~QmakeProFileNode() +bool QmakeProFileNode::showInSimpleTree() const { - qDeleteAll(m_extraCompilers); - m_parseFutureWatcher.waitForFinished(); - if (m_readerExact) - applyAsyncEvaluate(); + return showInSimpleTree(projectType()) || m_project->rootProjectNode() == this; } -bool QmakeProFileNode::isParent(QmakeProFileNode *node) +QmakeProFile *QmakeProFileNode::proFile() const { - while ((node = dynamic_cast<QmakeProFileNode *>(node->parentFolderNode()))) { - if (node == this) - return true; - } - return false; -} - -bool QmakeProFileNode::showInSimpleTree() const -{ - return showInSimpleTree(projectType()) || m_project->rootProjectNode() == this; + return m_project->rootProFile()->findProFile(filePath()); } FolderNode::AddNewInformation QmakeProFileNode::addNewInformation(const QStringList &files, Node *context) const @@ -1522,26 +240,16 @@ bool QmakeProFileNode::showInSimpleTree(ProjectType projectType) const || projectType == ProjectType::StaticLibraryTemplate; } -bool QmakeProFileNode::isDebugAndRelease() const -{ - const QStringList configValues = m_varValues.value(Variable::Config); - return configValues.contains(QLatin1String("debug_and_release")); -} - -bool QmakeProFileNode::isQtcRunnable() const -{ - const QStringList configValues = m_varValues.value(Variable::Config); - return configValues.contains(QLatin1String("qtc_runnable")); -} - ProjectType QmakeProFileNode::projectType() const { - return m_projectType; + const QmakeProFile *pro = proFile(); + return pro ? pro->projectType() : ProjectType::Invalid; } QStringList QmakeProFileNode::variableValue(const Variable var) const { - return m_varValues.value(var); + QmakeProFile *pro = proFile(); + return pro ? pro->variableValue(var) : QStringList(); } QString QmakeProFileNode::singleVariableValue(const Variable var) const @@ -1550,704 +258,6 @@ QString QmakeProFileNode::singleVariableValue(const Variable var) const return values.isEmpty() ? QString() : values.first(); } -void QmakeProFileNode::setParseInProgressRecursive(bool b) -{ - setParseInProgress(b); - foreach (ProjectNode *subNode, projectNodes()) { - if (QmakeProFileNode *node = dynamic_cast<QmakeProFileNode *>(subNode)) - node->setParseInProgressRecursive(b); - } -} - -void QmakeProFileNode::setParseInProgress(bool b) -{ - if (m_parseInProgress == b) - return; - m_parseInProgress = b; - emit m_project->proFileUpdated(this, m_validParse, m_parseInProgress); -} - -// Do note the absence of signal emission, always set validParse -// before setParseInProgress, as that will emit the signals -void QmakeProFileNode::setValidParseRecursive(bool b) -{ - m_validParse = b; - foreach (ProjectNode *subNode, projectNodes()) { - if (QmakeProFileNode *node = dynamic_cast<QmakeProFileNode *>(subNode)) - node->setValidParseRecursive(b); - } -} - -bool QmakeProFileNode::validParse() const -{ - return m_validParse; -} - -bool QmakeProFileNode::parseInProgress() const -{ - return m_parseInProgress; -} - -void QmakeProFileNode::scheduleUpdate(QmakeProFile::AsyncUpdateDelay delay) -{ - setParseInProgressRecursive(true); - m_project->scheduleAsyncUpdate(this, delay); -} - -void QmakeProFileNode::asyncUpdate() -{ - m_project->incrementPendingEvaluateFutures(); - setupReader(); - if (!includedInExactParse()) - m_readerExact->setExact(false); - m_parseFutureWatcher.waitForFinished(); - EvalInput input = evalInput(); - QFuture<EvalResult *> future = Utils::runAsync(ProjectExplorerPlugin::sharedThreadPool(), - QThread::LowestPriority, - &QmakeProFileNode::asyncEvaluate, - this, input); - m_parseFutureWatcher.setFuture(future); -} - -EvalInput QmakeProFileNode::evalInput() const -{ - EvalInput input; - input.projectDir = m_projectDir; - input.projectFilePath = m_projectFilePath; - input.buildDirectory = buildDir(); - input.sysroot = m_project->qmakeSysroot(); - input.readerExact = m_readerExact; - input.readerCumulative = m_readerCumulative; - input.qmakeGlobals = m_project->qmakeGlobals(); - input.qmakeVfs = m_project->qmakeVfs(); - return input; -} - -void QmakeProFileNode::setupReader() -{ - Q_ASSERT(!m_readerExact); - Q_ASSERT(!m_readerCumulative); - - m_readerExact = m_project->createProFileReader(this); - - m_readerCumulative = m_project->createProFileReader(this); - m_readerCumulative->setCumulative(true); -} - -static bool evaluateOne( - const EvalInput &input, ProFile *pro, QtSupport::ProFileReader *reader, - bool cumulative, QtSupport::ProFileReader **buildPassReader) -{ - if (!reader->accept(pro, QMakeEvaluator::LoadAll)) - return false; - - QStringList builds = reader->values(QLatin1String("BUILDS")); - if (builds.isEmpty()) { - *buildPassReader = reader; - } else { - QString build = builds.first(); - QHash<QString, QStringList> basevars; - QStringList basecfgs = reader->values(build + QLatin1String(".CONFIG")); - basecfgs += build; - basecfgs += QLatin1String("build_pass"); - basevars[QLatin1String("BUILD_PASS")] = QStringList(build); - QStringList buildname = reader->values(build + QLatin1String(".name")); - basevars[QLatin1String("BUILD_NAME")] = (buildname.isEmpty() ? QStringList(build) : buildname); - - // We don't increase/decrease m_qmakeGlobalsRefCnt here, because the outer profilereaders keep m_qmakeGlobals alive anyway - auto bpReader = new QtSupport::ProFileReader(input.qmakeGlobals, input.qmakeVfs); // needs to access m_qmakeGlobals, m_qmakeVfs - bpReader->setOutputDir(input.buildDirectory); - bpReader->setCumulative(cumulative); - bpReader->setExtraVars(basevars); - bpReader->setExtraConfigs(basecfgs); - - if (bpReader->accept(pro, QMakeEvaluator::LoadAll)) - *buildPassReader = bpReader; - else - delete bpReader; - } - - return true; -} - -EvalResult *QmakeProFileNode::evaluate(const EvalInput &input) -{ - EvalResult *result = new EvalResult; - QtSupport::ProFileReader *exactBuildPassReader = nullptr; - QtSupport::ProFileReader *cumulativeBuildPassReader = nullptr; - ProFile *pro; - if ((pro = input.readerExact->parsedProFile(input.projectFilePath.toString()))) { - bool exactOk = evaluateOne(input, pro, input.readerExact, false, &exactBuildPassReader); - bool cumulOk = evaluateOne(input, pro, input.readerCumulative, true, &cumulativeBuildPassReader); - pro->deref(); - result->state = exactOk ? EvalResult::EvalOk : cumulOk ? EvalResult::EvalPartial : EvalResult::EvalFail; - } else { - result->state = EvalResult::EvalFail; - } - - if (result->state == EvalResult::EvalFail) - return result; - - result->includedFiles.proFile = pro; - result->includedFiles.name = input.projectFilePath; - - QHash<const ProFile *, PriFileEvalResult *> proToResult; - - result->projectType = proFileTemplateTypeToProjectType( - (result->state == EvalResult::EvalOk ? input.readerExact - : input.readerCumulative)->templateType()); - if (result->state == EvalResult::EvalOk) { - if (result->projectType == ProjectType::SubDirsTemplate) { - QStringList errors; - FileNameList subDirs = subDirsPaths(input.readerExact, input.projectDir, &result->subProjectsNotToDeploy, &errors); - result->errors.append(errors); - - foreach (const Utils::FileName &subDirName, subDirs) { - IncludedPriFile *subDir = new IncludedPriFile; - subDir->proFile = nullptr; - subDir->name = subDirName; - result->includedFiles.children.insert(subDirName, subDir); - } - - result->exactSubdirs = subDirs.toSet(); - } - - // Convert ProFileReader::includeFiles to IncludedPriFile structure - QHash<ProFile *, QVector<ProFile *> > includeFiles = input.readerExact->includeFiles(); - QList<IncludedPriFile *> toBuild = { &result->includedFiles }; - while (!toBuild.isEmpty()) { - IncludedPriFile *current = toBuild.takeFirst(); - if (!current->proFile) - continue; // Don't attempt to map subdirs here - QVector<ProFile *> children = includeFiles.value(current->proFile); - foreach (ProFile *child, children) { - const Utils::FileName childName = Utils::FileName::fromString(child->fileName()); - auto it = current->children.find(childName); - if (it == current->children.end()) { - IncludedPriFile *childTree = new IncludedPriFile; - childTree->proFile = child; - childTree->name = childName; - current->children.insert(childName, childTree); - proToResult[child] = &childTree->result; - } - } - toBuild.append(current->children.values()); - } - } - - if (result->projectType == ProjectType::SubDirsTemplate) { - FileNameList subDirs = subDirsPaths(input.readerCumulative, input.projectDir, 0, 0); - foreach (const Utils::FileName &subDirName, subDirs) { - auto it = result->includedFiles.children.find(subDirName); - if (it == result->includedFiles.children.end()) { - IncludedPriFile *subDir = new IncludedPriFile; - subDir->proFile = nullptr; - subDir->name = subDirName; - result->includedFiles.children.insert(subDirName, subDir); - } - } - } - - // Add ProFileReader::includeFiles information from cumulative parse to IncludedPriFile structure - QHash<ProFile *, QVector<ProFile *> > includeFiles = input.readerCumulative->includeFiles(); - QList<IncludedPriFile *> toBuild = { &result->includedFiles }; - while (!toBuild.isEmpty()) { - IncludedPriFile *current = toBuild.takeFirst(); - if (!current->proFile) - continue; // Don't attempt to map subdirs here - QVector<ProFile *> children = includeFiles.value(current->proFile); - foreach (ProFile *child, children) { - const Utils::FileName childName = Utils::FileName::fromString(child->fileName()); - auto it = current->children.find(childName); - if (it == current->children.end()) { - IncludedPriFile *childTree = new IncludedPriFile; - childTree->proFile = child; - childTree->name = childName; - current->children.insert(childName, childTree); - proToResult[child] = &childTree->result; - } - } - toBuild.append(current->children.values()); - } - - auto exactReader = exactBuildPassReader ? exactBuildPassReader : input.readerExact; - auto cumulativeReader = cumulativeBuildPassReader ? cumulativeBuildPassReader : input.readerCumulative; - - QHash<QString, QVector<ProFileEvaluator::SourceFile> > exactSourceFiles; - QHash<QString, QVector<ProFileEvaluator::SourceFile> > cumulativeSourceFiles; - - QStringList baseVPathsExact = baseVPaths(exactReader, input.projectDir, input.buildDirectory); - QStringList baseVPathsCumulative = baseVPaths(cumulativeReader, input.projectDir, input.buildDirectory); - - const QVector<QmakeNodeStaticData::FileTypeData> &fileTypes = qmakeNodeStaticData()->fileTypeData; - for (int i = 0; i < fileTypes.size(); ++i) { - FileType type = fileTypes.at(i).type; - QStringList qmakeVariables = varNames(type, exactReader); - foreach (const QString &qmakeVariable, qmakeVariables) { - QHash<ProString, bool> handled; - if (result->state == EvalResult::EvalOk) { - QStringList vPathsExact = fullVPaths( - baseVPathsExact, exactReader, qmakeVariable, input.projectDir); - auto sourceFiles = exactReader->absoluteFileValues( - qmakeVariable, input.projectDir, vPathsExact, &handled); - exactSourceFiles[qmakeVariable] = sourceFiles; - extractSources(proToResult, &result->includedFiles.result, sourceFiles, type); - } - QStringList vPathsCumulative = fullVPaths( - baseVPathsCumulative, cumulativeReader, qmakeVariable, input.projectDir); - auto sourceFiles = cumulativeReader->absoluteFileValues( - qmakeVariable, input.projectDir, vPathsCumulative, &handled); - cumulativeSourceFiles[qmakeVariable] = sourceFiles; - extractSources(proToResult, &result->includedFiles.result, sourceFiles, type); - } - } - - // This is used for two things: - // - Actual deployment, in which case we need exact values. - // - The project tree, in which case we also want exact values to avoid recursively - // watching bogus paths. However, we accept the values even if the evaluation - // failed, to at least have a best-effort result. - result->installsList = installsList(exactBuildPassReader, input.projectFilePath.toString(), - input.projectDir, input.buildDirectory); - extractInstalls(proToResult, &result->includedFiles.result, result->installsList); - - if (result->state == EvalResult::EvalOk) { - result->targetInformation = targetInformation(input.readerExact, exactBuildPassReader, - input.buildDirectory, input.projectFilePath.toString()); - - // update other variables - result->newVarValues[Variable::Defines] = exactReader->values(QLatin1String("DEFINES")); - result->newVarValues[Variable::IncludePath] = includePaths(exactReader, input.sysroot, - input.buildDirectory, input.projectDir); - result->newVarValues[Variable::CppFlags] = exactReader->values(QLatin1String("QMAKE_CXXFLAGS")); - result->newVarValues[Variable::Source] = - fileListForVar(exactSourceFiles, QLatin1String("SOURCES")) + - fileListForVar(cumulativeSourceFiles, QLatin1String("SOURCES")) + - fileListForVar(exactSourceFiles, QLatin1String("HEADERS")) + - fileListForVar(cumulativeSourceFiles, QLatin1String("HEADERS")) + - fileListForVar(exactSourceFiles, QLatin1String("OBJECTIVE_HEADERS")) + - fileListForVar(cumulativeSourceFiles, QLatin1String("OBJECTIVE_HEADERS")); - result->newVarValues[Variable::UiDir] = QStringList() << uiDirPath(exactReader, input.buildDirectory); - result->newVarValues[Variable::HeaderExtension] = QStringList() << exactReader->value(QLatin1String("QMAKE_EXT_H")); - result->newVarValues[Variable::CppExtension] = QStringList() << exactReader->value(QLatin1String("QMAKE_EXT_CPP")); - result->newVarValues[Variable::MocDir] = QStringList() << mocDirPath(exactReader, input.buildDirectory); - result->newVarValues[Variable::ExactResource] = fileListForVar(exactSourceFiles, QLatin1String("RESOURCES")); - result->newVarValues[Variable::CumulativeResource] = fileListForVar(cumulativeSourceFiles, QLatin1String("RESOURCES")); - result->newVarValues[Variable::PkgConfig] = exactReader->values(QLatin1String("PKGCONFIG")); - result->newVarValues[Variable::PrecompiledHeader] = ProFileEvaluator::sourcesToFiles(exactReader->fixifiedValues( - QLatin1String("PRECOMPILED_HEADER"), input.projectDir, input.buildDirectory)); - result->newVarValues[Variable::LibDirectories] = libDirectories(exactReader); - result->newVarValues[Variable::Config] = exactReader->values(QLatin1String("CONFIG")); - result->newVarValues[Variable::QmlImportPath] = exactReader->absolutePathValues( - QLatin1String("QML_IMPORT_PATH"), input.projectDir); - result->newVarValues[Variable::QmlDesignerImportPath] = exactReader->absolutePathValues( - QLatin1String("QML_DESIGNER_IMPORT_PATH"), input.projectDir); - result->newVarValues[Variable::Makefile] = exactReader->values(QLatin1String("MAKEFILE")); - result->newVarValues[Variable::Qt] = exactReader->values(QLatin1String("QT")); - result->newVarValues[Variable::ObjectExt] = exactReader->values(QLatin1String("QMAKE_EXT_OBJ")); - result->newVarValues[Variable::ObjectsDir] = exactReader->values(QLatin1String("OBJECTS_DIR")); - result->newVarValues[Variable::Version] = exactReader->values(QLatin1String("VERSION")); - result->newVarValues[Variable::TargetExt] = exactReader->values(QLatin1String("TARGET_EXT")); - result->newVarValues[Variable::TargetVersionExt] - = exactReader->values(QLatin1String("TARGET_VERSION_EXT")); - result->newVarValues[Variable::StaticLibExtension] = exactReader->values(QLatin1String("QMAKE_EXTENSION_STATICLIB")); - result->newVarValues[Variable::ShLibExtension] = exactReader->values(QLatin1String("QMAKE_EXTENSION_SHLIB")); - result->newVarValues[Variable::AndroidArch] = exactReader->values(QLatin1String("ANDROID_TARGET_ARCH")); - result->newVarValues[Variable::AndroidDeploySettingsFile] = exactReader->values(QLatin1String("ANDROID_DEPLOYMENT_SETTINGS_FILE")); - result->newVarValues[Variable::AndroidPackageSourceDir] = exactReader->values(QLatin1String("ANDROID_PACKAGE_SOURCE_DIR")); - result->newVarValues[Variable::AndroidExtraLibs] = exactReader->values(QLatin1String("ANDROID_EXTRA_LIBS")); - result->newVarValues[Variable::IsoIcons] = exactReader->values(QLatin1String("ISO_ICONS")); - result->newVarValues[Variable::QmakeProjectName] = exactReader->values(QLatin1String("QMAKE_PROJECT_NAME")); - result->newVarValues[Variable::QmakeCc] = exactReader->values("QMAKE_CC"); - result->newVarValues[Variable::QmakeCxx] = exactReader->values("QMAKE_CXX"); - } - - if (result->state == EvalResult::EvalOk || result->state == EvalResult::EvalPartial) { - - QList<IncludedPriFile *> toExtract = { &result->includedFiles }; - while (!toExtract.isEmpty()) { - IncludedPriFile *current = toExtract.takeFirst(); - processValues(current->result); - toExtract.append(current->children.values()); - } - } - - if (exactBuildPassReader && exactBuildPassReader != input.readerExact) - delete exactBuildPassReader; - if (cumulativeBuildPassReader && cumulativeBuildPassReader != input.readerCumulative) - delete cumulativeBuildPassReader; - - return result; -} - -void QmakeProFileNode::asyncEvaluate(QFutureInterface<EvalResult *> &fi, EvalInput input) -{ - EvalResult *evalResult = evaluate(input); - fi.reportResult(evalResult); -} - -void QmakeProFileNode::applyAsyncEvaluate() -{ - applyEvaluate(m_parseFutureWatcher.result()); - m_project->decrementPendingEvaluateFutures(); -} - -bool sortByNodes(Node *a, Node *b) -{ - return a->filePath() < b->filePath(); -} - -void QmakeProFileNode::applyEvaluate(EvalResult *evalResult) -{ - QScopedPointer<EvalResult> result(evalResult); - if (!m_readerExact) - return; - - if (m_project->asyncUpdateState() == QmakeProject::ShuttingDown) { - cleanupProFileReaders(); - return; - } - - foreach (const QString &error, evalResult->errors) - QmakeProject::proFileParseError(error); - - // we are changing what is executed in that case - if (result->state == EvalResult::EvalFail || m_project->wasEvaluateCanceled()) { - m_validParse = false; - cleanupProFileReaders(); - setValidParseRecursive(false); - setParseInProgressRecursive(false); - - if (result->state == EvalResult::EvalFail) { - QmakeProject::proFileParseError(QCoreApplication::translate("QmakeProFileNode", "Error while parsing file %1. Giving up.") - .arg(m_projectFilePath.toUserOutput())); - if (m_projectType == ProjectType::Invalid) - return; - - // delete files && folders && projects - makeEmpty(); - m_projectType = ProjectType::Invalid; - } - return; - } - - if (debug) - qDebug() << "QmakeProFileNode - updating files for file " << m_projectFilePath; - - if (result->projectType != m_projectType) { - // probably all subfiles/projects have changed anyway - // delete files && folders && projects - foreach (ProjectNode *projectNode, projectNodes()) { - if (QmakeProFileNode *qmakeProFileNode = dynamic_cast<QmakeProFileNode *>(projectNode)) { - qmakeProFileNode->setValidParseRecursive(false); - qmakeProFileNode->setParseInProgressRecursive(false); - } - } - - makeEmpty(); - m_projectType = result->projectType; - } - - // - // Add/Remove pri files, sub projects - // - - QString buildDirectory = buildDir(); - - QList<QPair<QmakePriFileNode *, IncludedPriFile *>> toCompare; - - toCompare.append(qMakePair(this, &result->includedFiles)); - - makeEmpty(); - - while (!toCompare.isEmpty()) { - QmakePriFileNode *pn = toCompare.first().first; - IncludedPriFile *tree = toCompare.first().second; - toCompare.pop_front(); - - for (IncludedPriFile *priFile : tree->children) { - // Loop preventation, make sure that exact same node is not in our parent chain - bool loop = false; - Node *n = pn; - while ((n = n->parentFolderNode())) { - if (dynamic_cast<QmakePriFileNode *>(n) && n->filePath() == priFile->name) { - loop = true; - break; - } - } - - if (loop) - continue; // Do nothing - - if (priFile->proFile) { - QmakePriFileNode *qmakePriFileNode = new QmakePriFileNode(m_project, this, priFile->name); - pn->addNode(qmakePriFileNode); - qmakePriFileNode->setIncludedInExactParse( - (result->state == EvalResult::EvalOk) && pn->includedInExactParse()); - qmakePriFileNode->update(priFile->result); - toCompare.append(qMakePair(qmakePriFileNode, priFile)); - } else { - QmakeProFileNode *qmakeProFileNode = new QmakeProFileNode(m_project, priFile->name); - pn->addNode(qmakeProFileNode); - qmakeProFileNode->setIncludedInExactParse( - result->exactSubdirs.contains(qmakeProFileNode->filePath()) - && pn->includedInExactParse()); - qmakeProFileNode->setParseInProgress(true); - qmakeProFileNode->asyncUpdate(); - } - } - } - - QmakePriFileNode::update(result->includedFiles.result); - - m_validParse = (result->state == EvalResult::EvalOk); - if (m_validParse) { - // update TargetInformation - m_qmakeTargetInformation = result->targetInformation; - - m_subProjectsNotToDeploy = result->subProjectsNotToDeploy; - m_installsList = result->installsList; - - if (m_varValues != result->newVarValues) - m_varValues = result->newVarValues; - - const QString projectName = singleVariableValue(Variable::QmakeProjectName); - if (projectName.isEmpty()) - setDisplayName(m_projectFilePath.toFileInfo().completeBaseName()); - else - setDisplayName(projectName); - } // result == EvalOk - - setParseInProgress(false); - - updateGeneratedFiles(buildDirectory); - - cleanupProFileReaders(); - ProjectNode::emitTreeChanged(); -} - -void QmakeProFileNode::cleanupProFileReaders() -{ - m_project->destroyProFileReader(m_readerExact); - m_project->destroyProFileReader(m_readerCumulative); - - m_readerExact = nullptr; - m_readerCumulative = nullptr; -} - -QString QmakeProFileNode::uiDirPath(QtSupport::ProFileReader *reader, const QString &buildDir) -{ - QString path = reader->value(QLatin1String("UI_DIR")); - if (QFileInfo(path).isRelative()) - path = QDir::cleanPath(buildDir + QLatin1Char('/') + path); - return path; -} - -QString QmakeProFileNode::mocDirPath(QtSupport::ProFileReader *reader, const QString &buildDir) -{ - QString path = reader->value(QLatin1String("MOC_DIR")); - if (QFileInfo(path).isRelative()) - path = QDir::cleanPath(buildDir + QLatin1Char('/') + path); - return path; -} - -QString QmakeProFileNode::sysrootify(const QString &path, const QString &sysroot, - const QString &baseDir, const QString &outputDir) -{ -#ifdef Q_OS_WIN - Qt::CaseSensitivity cs = Qt::CaseInsensitive; -#else - Qt::CaseSensitivity cs = Qt::CaseSensitive; -#endif - if (sysroot.isEmpty() || path.startsWith(sysroot, cs) - || path.startsWith(baseDir, cs) || path.startsWith(outputDir, cs)) { - return path; - } - QString sysrooted = QDir::cleanPath(sysroot + path); - return !IoUtils::exists(sysrooted) ? path : sysrooted; -} - -QStringList QmakeProFileNode::includePaths(QtSupport::ProFileReader *reader, const QString &sysroot, - const QString &buildDir, const QString &projectDir) -{ - QStringList paths; - foreach (const QString &cxxflags, reader->values(QLatin1String("QMAKE_CXXFLAGS"))) { - if (cxxflags.startsWith(QLatin1String("-I"))) - paths.append(cxxflags.mid(2)); - } - - foreach (const ProFileEvaluator::SourceFile &el, - reader->fixifiedValues(QLatin1String("INCLUDEPATH"), projectDir, buildDir)) { - paths << sysrootify(el.fileName, sysroot, projectDir, buildDir); - } - // paths already contains moc dir and ui dir, due to corrrectly parsing uic.prf and moc.prf - // except if those directories don't exist at the time of parsing - // thus we add those directories manually (without checking for existence) - paths << mocDirPath(reader, buildDir) << uiDirPath(reader, buildDir); - paths.removeDuplicates(); - return paths; -} - -QStringList QmakeProFileNode::libDirectories(QtSupport::ProFileReader *reader) -{ - QStringList result; - foreach (const QString &str, reader->values(QLatin1String("LIBS"))) { - if (str.startsWith(QLatin1String("-L"))) - result.append(str.mid(2)); - } - return result; -} - -FileNameList QmakeProFileNode::subDirsPaths(QtSupport::ProFileReader *reader, - const QString &projectDir, - QStringList *subProjectsNotToDeploy, - QStringList *errors) -{ - FileNameList subProjectPaths; - - const QStringList subDirVars = reader->values(QLatin1String("SUBDIRS")); - - foreach (const QString &subDirVar, subDirVars) { - // Special case were subdir is just an identifier: - // "SUBDIR = subid - // subid.subdir = realdir" - // or - // "SUBDIR = subid - // subid.file = realdir/realfile.pro" - - QString realDir; - const QString subDirKey = subDirVar + QLatin1String(".subdir"); - const QString subDirFileKey = subDirVar + QLatin1String(".file"); - if (reader->contains(subDirKey)) - realDir = reader->value(subDirKey); - else if (reader->contains(subDirFileKey)) - realDir = reader->value(subDirFileKey); - else - realDir = subDirVar; - QFileInfo info(realDir); - if (!info.isAbsolute()) - info.setFile(projectDir + QLatin1Char('/') + realDir); - realDir = info.filePath(); - - QString realFile; - if (info.isDir()) - realFile = QString::fromLatin1("%1/%2.pro").arg(realDir, info.fileName()); - else - realFile = realDir; - - if (QFile::exists(realFile)) { - realFile = QDir::cleanPath(realFile); - subProjectPaths << FileName::fromString(realFile); - if (subProjectsNotToDeploy && !subProjectsNotToDeploy->contains(realFile) - && reader->values(subDirVar + QLatin1String(".CONFIG")) - .contains(QLatin1String("no_default_target"))) { - subProjectsNotToDeploy->append(realFile); - } - } else { - if (errors) - errors->append(QCoreApplication::translate("QmakeProFileNode", "Could not find .pro file for subdirectory \"%1\" in \"%2\".") - .arg(subDirVar).arg(realDir)); - } - } - - return Utils::filteredUnique(subProjectPaths); -} - -TargetInformation QmakeProFileNode::targetInformation(QtSupport::ProFileReader *reader, QtSupport::ProFileReader *readerBuildPass, const QString &buildDir, const QString &projectFilePath) -{ - TargetInformation result; - if (!reader || !readerBuildPass) - return result; - - QStringList builds = reader->values(QLatin1String("BUILDS")); - if (!builds.isEmpty()) { - QString build = builds.first(); - result.buildTarget = reader->value(build + QLatin1String(".target")); - } - - // BUILD DIR - result.buildDir = FileName::fromString(buildDir); - - if (readerBuildPass->contains(QLatin1String("DESTDIR"))) - result.destDir = FileName::fromString(readerBuildPass->value(QLatin1String("DESTDIR"))); - - // Target - result.target = readerBuildPass->value(QLatin1String("TARGET")); - if (result.target.isEmpty()) - result.target = QFileInfo(projectFilePath).baseName(); - - result.valid = true; - - return result; -} - -TargetInformation QmakeProFileNode::targetInformation() const -{ - return m_qmakeTargetInformation; -} - -InstallsList QmakeProFileNode::installsList(const QtSupport::ProFileReader *reader, const QString &projectFilePath, - const QString &projectDir, const QString &buildDir) -{ - InstallsList result; - if (!reader) - return result; - const QStringList &itemList = reader->values(QLatin1String("INSTALLS")); - if (itemList.isEmpty()) - return result; - - const QString installPrefix - = reader->propertyValue(QLatin1String("QT_INSTALL_PREFIX")); - const QString devInstallPrefix - = reader->propertyValue(QLatin1String("QT_INSTALL_PREFIX/dev")); - bool fixInstallPrefix = (installPrefix != devInstallPrefix); - - foreach (const QString &item, itemList) { - bool active = !reader->values(item + QLatin1String(".CONFIG")) - .contains(QLatin1String("no_default_install")); - const QString pathVar = item + QLatin1String(".path"); - const QStringList &itemPaths = reader->values(pathVar); - if (itemPaths.count() != 1) { - qDebug("Invalid RHS: Variable '%s' has %d values.", - qPrintable(pathVar), itemPaths.count()); - if (itemPaths.isEmpty()) { - qDebug("%s: Ignoring INSTALLS item '%s', because it has no path.", - qPrintable(projectFilePath), qPrintable(item)); - continue; - } - } - - QString itemPath = itemPaths.last(); - if (fixInstallPrefix && itemPath.startsWith(installPrefix)) { - // This is a hack for projects which install into $$[QT_INSTALL_*], - // in particular Qt itself, examples being most relevant. - // Projects which implement their own install path policy must - // parametrize their INSTALLS themselves depending on the intended - // installation/deployment mode. - itemPath.replace(0, installPrefix.length(), devInstallPrefix); - } - if (item == QLatin1String("target")) { - if (active) - result.targetPath = itemPath; - } else { - const auto &itemFiles = reader->fixifiedValues( - item + QLatin1String(".files"), projectDir, buildDir); - result.items << InstallsItem(itemPath, itemFiles, active); - } - } - return result; -} - -InstallsList QmakeProFileNode::installsList() const -{ - return m_installsList; -} - -QString QmakeProFileNode::sourceDir() const -{ - return m_projectDir; -} - QString QmakeProFileNode::buildDir(QmakeBuildConfiguration *bc) const { const QDir srcDirRoot(m_project->projectDirectory().toString()); @@ -2259,74 +269,4 @@ QString QmakeProFileNode::buildDir(QmakeBuildConfiguration *bc) const return QDir::cleanPath(QDir(bc->buildDirectory().toString()).absoluteFilePath(relativeDir)); } -QStringList QmakeProFileNode::generatedFiles(const QString &buildDir, - const ProjectExplorer::FileNode *sourceFile) const -{ - // The mechanism for finding the file names is rather crude, but as we - // cannot parse QMAKE_EXTRA_COMPILERS and qmake has facilities to put - // ui_*.h files into a special directory, or even change the .h suffix, we - // cannot help doing this here. - switch (sourceFile->fileType()) { - case FileType::Form: { - FileName location; - auto it = m_varValues.constFind(Variable::UiDir); - if (it != m_varValues.constEnd() && !it.value().isEmpty()) - location = FileName::fromString(it.value().front()); - else - location = FileName::fromString(buildDir); - if (location.isEmpty()) - return QStringList(); - location.appendPath(QLatin1String("ui_") - + sourceFile->filePath().toFileInfo().completeBaseName() - + singleVariableValue(Variable::HeaderExtension)); - return QStringList(QDir::cleanPath(location.toString())); - } - case FileType::StateChart: { - if (buildDir.isEmpty()) - return QStringList(); - QString location = QDir::cleanPath(FileName::fromString(buildDir).appendPath( - sourceFile->filePath().toFileInfo().completeBaseName()).toString()); - return QStringList({location + singleVariableValue(Variable::HeaderExtension), - location + singleVariableValue(Variable::CppExtension)}); - } - default: - // TODO: Other types will be added when adapters for their compilers become available. - return QStringList(); - } -} - -QList<ExtraCompiler *> QmakeProFileNode::extraCompilers() const -{ - return m_extraCompilers; -} - -void QmakeProFileNode::updateGeneratedFiles(const QString &buildDir) -{ - // We can do this because other plugins are not supposed to keep the compilers around. - qDeleteAll(m_extraCompilers); - m_extraCompilers.clear(); - - // Only those project types can have generated files for us - if (m_projectType != ProjectType::ApplicationTemplate - && m_projectType != ProjectType::SharedLibraryTemplate - && m_projectType != ProjectType::StaticLibraryTemplate) { - return; - } - - QList<ExtraCompilerFactory *> factories = - ProjectExplorer::ExtraCompilerFactory::extraCompilerFactories(); - - FindGeneratorSourcesVisitor filesVisitor(factories, [&]( - FileNode *file, ExtraCompilerFactory *factory) { - QStringList generated = generatedFiles(buildDir, file); - if (!generated.isEmpty()) { - FileNameList fileNames = Utils::transform(generated, [](const QString &name) { - return FileName::fromString(name); - }); - m_extraCompilers.append(factory->create(m_project, file->filePath(), fileNames)); - } - }); - - // Find all generated files - accept(&filesVisitor); -} +} // namespace QmakeProjectManager diff --git a/src/plugins/qmakeprojectmanager/qmakenodes.h b/src/plugins/qmakeprojectmanager/qmakenodes.h index edb6abfae5..c3c6ff1a8a 100644 --- a/src/plugins/qmakeprojectmanager/qmakenodes.h +++ b/src/plugins/qmakeprojectmanager/qmakenodes.h @@ -27,22 +27,13 @@ #include "qmakeprojectmanager_global.h" #include "qmakeparsernodes.h" -#include "proparser/prowriter.h" -#include "proparser/profileevaluator.h" -#include <coreplugin/idocument.h> #include <projectexplorer/projectnodes.h> -#include <cpptools/generatedcodemodelsupport.h> -#include <QHash> #include <QStringList> #include <QMap> -#include <QFutureWatcher> namespace Utils { class FileName; } - -namespace QtSupport { class ProFileReader; } - namespace ProjectExplorer { class RunConfiguration; } namespace QmakeProjectManager { @@ -51,24 +42,18 @@ class QmakeProFileNode; class QmakeProject; namespace Internal { -class QmakePriFileNodeDocument; struct InternalNode; - -class EvalInput; -class EvalResult; class PriFileEvalResult; -} - -class InstallsList; +} // namespace Internal // Implements ProjectNode for qmake .pri files class QMAKEPROJECTMANAGER_EXPORT QmakePriFileNode : public ProjectExplorer::ProjectNode { public: - QmakePriFileNode(QmakeProject *project, QmakeProFileNode *qmakeProFileNode, const Utils::FileName &filePath); - ~QmakePriFileNode() override; + QmakePriFileNode(QmakeProject *project, QmakeProFileNode *qmakeProFileNode, + const Utils::FileName &filePath); - void update(const Internal::PriFileEvalResult &result); + QmakePriFile *priFile() const; // ProjectNode interface QList<ProjectExplorer::ProjectAction> supportedActions(Node *node) const override; @@ -87,89 +72,16 @@ public: bool renameFile(const QString &filePath, const QString &newFilePath) override; AddNewInformation addNewInformation(const QStringList &files, Node *context) const override; - bool setProVariable(const QString &var, const QStringList &values, - const QString &scope = QString(), - int flags = QmakeProjectManager::Internal::ProWriter::ReplaceValues); - - bool folderChanged(const QString &changedFolder, const QSet<Utils::FileName> &newFiles); - bool deploysFolder(const QString &folder) const override; QList<ProjectExplorer::RunConfiguration *> runConfigurations() const override; QmakeProFileNode *proFileNode() const; - QList<QmakePriFileNode*> subProjectNodesExact() const; - - // Set by parent - bool includedInExactParse() const; - - static QSet<Utils::FileName> recursiveEnumerate(const QString &folder); protected: - void setIncludedInExactParse(bool b); - static QStringList varNames(ProjectExplorer::FileType type, QtSupport::ProFileReader *readerExact); - static QStringList varNamesForRemoving(); - static QString varNameForAdding(const QString &mimeType); - static QSet<Utils::FileName> filterFilesProVariables(ProjectExplorer::FileType fileType, const QSet<Utils::FileName> &files); - static QSet<Utils::FileName> filterFilesRecursiveEnumerata(ProjectExplorer::FileType fileType, const QSet<Utils::FileName> &files); - - enum ChangeType { - AddToProFile, - RemoveFromProFile - }; - - enum class Change { Save, TestOnly }; - bool renameFile(const QString &oldName, - const QString &newName, - const QString &mimeType, - Change mode = Change::Save); - void changeFiles(const QString &mimeType, - const QStringList &filePaths, - QStringList *notChanged, - ChangeType change, - Change mode = Change::Save); + QmakeProject *m_project; private: - void scheduleUpdate(); - - bool prepareForChange(); - static bool ensureWriteableProFile(const QString &file); - static QPair<ProFile *, QStringList> readProFile(const QString &file); - static QPair<ProFile *, QStringList> readProFileFromContents(const QString &contents); - void save(const QStringList &lines); - bool priFileWritable(const QString &absoluteFilePath); - bool saveModifiedEditors(); - QStringList formResources(const QString &formFile) const; - static QStringList baseVPaths(QtSupport::ProFileReader *reader, const QString &projectDir, const QString &buildDir); - static QStringList fullVPaths(const QStringList &baseVPaths, QtSupport::ProFileReader *reader, const QString &qmakeVariable, const QString &projectDir); - static void extractSources( - QHash<const ProFile *, Internal::PriFileEvalResult *> proToResult, - Internal::PriFileEvalResult *fallback, - QVector<ProFileEvaluator::SourceFile> sourceFiles, ProjectExplorer::FileType type); - static void extractInstalls( - QHash<const ProFile *, Internal::PriFileEvalResult *> proToResult, - Internal::PriFileEvalResult *fallback, - const InstallsList &installList); - static void processValues(Internal::PriFileEvalResult &result); - void watchFolders(const QSet<QString> &folders); - - QmakeProject *m_project; QmakeProFileNode *m_qmakeProFileNode; - Utils::FileName m_projectFilePath; - QString m_projectDir; - - Internal::QmakePriFileNodeDocument *m_qmakePriFile; - - // Memory is cheap... - QMap<ProjectExplorer::FileType, QSet<Utils::FileName> > m_files; - QSet<Utils::FileName> m_recursiveEnumerateFiles; - QSet<QString> m_watchedFolders; - bool m_includedInExactParse = true; - - // managed by QmakeProFileNode - friend class QmakeProjectManager::QmakeProFileNode; - friend class Internal::QmakePriFileNodeDocument; // for scheduling updates on modified - // internal temporary subtree representation - friend struct Internal::InternalNode; }; // Implements ProjectNode for qmake .pro files @@ -177,9 +89,8 @@ class QMAKEPROJECTMANAGER_EXPORT QmakeProFileNode : public QmakePriFileNode { public: QmakeProFileNode(QmakeProject *project, const Utils::FileName &filePath); - ~QmakeProFileNode() override; - bool isParent(QmakeProFileNode *node); + QmakeProFile *proFile() const; bool showInSimpleTree() const override; @@ -190,84 +101,11 @@ public: QStringList variableValue(const Variable var) const; QString singleVariableValue(const Variable var) const; - bool isSubProjectDeployable(const QString &filePath) const { - return !m_subProjectsNotToDeploy.contains(filePath); - } - - QString sourceDir() const; QString buildDir(QmakeBuildConfiguration *bc = nullptr) const; - QStringList generatedFiles(const QString &buildDirectory, - const ProjectExplorer::FileNode *sourceFile) const; - QList<ProjectExplorer::ExtraCompiler *> extraCompilers() const; - QmakeProFileNode *findProFileFor(const Utils::FileName &string) const; - TargetInformation targetInformation() const; - - InstallsList installsList() const; - - QString makefile() const; - QString objectExtension() const; - QString objectsDirectory() const; - QByteArray cxxDefines() const; - - void scheduleUpdate(QmakeProFile::AsyncUpdateDelay delay); - - bool validParse() const; - bool parseInProgress() const; bool showInSimpleTree(ProjectType projectType) const; - bool isDebugAndRelease() const; - bool isQtcRunnable() const; - - void setParseInProgressRecursive(bool b); - - void asyncUpdate(); - -private: - void setParseInProgress(bool b); - void setValidParseRecursive(bool b); - - void applyAsyncEvaluate(); - - void setupReader(); - Internal::EvalInput evalInput() const; - - static Internal::EvalResult *evaluate(const Internal::EvalInput &input); - void applyEvaluate(Internal::EvalResult *parseResult); - - void asyncEvaluate(QFutureInterface<Internal::EvalResult *> &fi, Internal::EvalInput input); - void cleanupProFileReaders(); - - using VariablesHash = QHash<Variable, QStringList>; - - void updateGeneratedFiles(const QString &buildDir); - - static QString uiDirPath(QtSupport::ProFileReader *reader, const QString &buildDir); - static QString mocDirPath(QtSupport::ProFileReader *reader, const QString &buildDir); - static QString sysrootify(const QString &path, const QString &sysroot, const QString &baseDir, const QString &outputDir); - static QStringList includePaths(QtSupport::ProFileReader *reader, const QString &sysroot, const QString &buildDir, const QString &projectDir); - static QStringList libDirectories(QtSupport::ProFileReader *reader); - static Utils::FileNameList subDirsPaths(QtSupport::ProFileReader *reader, const QString &projectDir, QStringList *subProjectsNotToDeploy, QStringList *errors); - - static TargetInformation targetInformation(QtSupport::ProFileReader *reader, QtSupport::ProFileReader *readerBuildPass, const QString &buildDir, const QString &projectFilePath); - static InstallsList installsList(const QtSupport::ProFileReader *reader, const QString &projectFilePath, const QString &projectDir, const QString &buildDir); - - bool m_validParse = false; - bool m_parseInProgress = false; - - ProjectType m_projectType = ProjectType::Invalid; - VariablesHash m_varValues; - QList<ProjectExplorer::ExtraCompiler *> m_extraCompilers; - - TargetInformation m_qmakeTargetInformation; - QStringList m_subProjectsNotToDeploy; - InstallsList m_installsList; - - // Async stuff - QFutureWatcher<Internal::EvalResult *> m_parseFutureWatcher; - QtSupport::ProFileReader *m_readerExact = nullptr; - QtSupport::ProFileReader *m_readerCumulative = nullptr; }; } // namespace QmakeProjectManager diff --git a/src/plugins/qmakeprojectmanager/qmakeparsernodes.cpp b/src/plugins/qmakeprojectmanager/qmakeparsernodes.cpp index bcee8b7c87..d1589c3124 100644 --- a/src/plugins/qmakeprojectmanager/qmakeparsernodes.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeparsernodes.cpp @@ -370,12 +370,10 @@ void QmakePriFile::watchFolders(const QSet<QString> &folders) QSet<QString> toWatch = folders; toWatch.subtract(m_watchedFolders); -#if 0 // Enable again! if (!toUnwatch.isEmpty()) m_project->unwatchFolders(toUnwatch.toList(), this); if (!toWatch.isEmpty()) m_project->watchFolders(toWatch.toList(), this); -#endif m_watchedFolders = folders; } @@ -1166,9 +1164,7 @@ void QmakeProFile::setParseInProgress(bool b) if (m_parseInProgress == b) return; m_parseInProgress = b; -#if 0 emit m_project->proFileUpdated(this, m_validParse, m_parseInProgress); -#endif } // Do note the absence of signal emission, always set validParse @@ -1195,9 +1191,7 @@ bool QmakeProFile::parseInProgress() const void QmakeProFile::scheduleUpdate(QmakeProFile::AsyncUpdateDelay delay) { setParseInProgressRecursive(true); -#if 0 m_project->scheduleAsyncUpdate(this, delay); -#endif } void QmakeProFile::asyncUpdate() @@ -1234,12 +1228,10 @@ void QmakeProFile::setupReader() Q_ASSERT(!m_readerExact); Q_ASSERT(!m_readerCumulative); -#if 0 m_readerExact = m_project->createProFileReader(this); m_readerCumulative = m_project->createProFileReader(this); m_readerCumulative->setCumulative(true); -#endif } static bool evaluateOne(const QmakeEvalInput &input, ProFile *pro, @@ -1869,17 +1861,16 @@ FileName QmakeProFile::buildDir(QmakeBuildConfiguration *bc) const return FileName::fromString(QDir::cleanPath(QDir(bc->buildDirectory().toString()).absoluteFilePath(relativeDir))); } -FileNameList QmakeProFile::generatedFiles(const Utils::FileName &buildDir, - const Utils::FileName &sourceFile) const +FileNameList QmakeProFile::generatedFiles(const FileName &buildDir, + const FileName &sourceFile, + const FileType &sourceFileType) const { // The mechanism for finding the file names is rather crude, but as we // cannot parse QMAKE_EXTRA_COMPILERS and qmake has facilities to put // ui_*.h files into a special directory, or even change the .h suffix, we // cannot help doing this here. - Utils::MimeDatabase mdb; - MimeType sourceFileType = mdb.mimeTypeForFile(sourceFile.toString()); - if (sourceFileType.matchesName(ProjectExplorer::Constants::FORM_MIMETYPE)) { + if (sourceFileType == FileType::Form) { FileName location; auto it = m_varValues.constFind(Variable::UiDir); if (it != m_varValues.constEnd() && !it.value().isEmpty()) @@ -1892,7 +1883,7 @@ FileNameList QmakeProFile::generatedFiles(const Utils::FileName &buildDir, + sourceFile.toFileInfo().completeBaseName() + singleVariableValue(Variable::HeaderExtension)); return { Utils::FileName::fromString(QDir::cleanPath(location.toString())) }; - } else if (sourceFileType.matchesName(ProjectExplorer::Constants::SCXML_MIMETYPE)) { + } else if (sourceFileType == FileType::StateChart) { if (buildDir.isEmpty()) return { }; FileName location = buildDir; @@ -1912,6 +1903,17 @@ QList<ExtraCompiler *> QmakeProFile::extraCompilers() const return m_extraCompilers; } +void QmakeProFile::setupExtraCompiler(const FileName &buildDir, + const FileType &fileType, ExtraCompilerFactory *factory) +{ + foreach (const FileName &fn, files(fileType)) { + const FileNameList generated = generatedFiles(buildDir, fn, fileType); + if (!generated.isEmpty()) { + m_extraCompilers.append(factory->create(m_project, fn, generated)); + } + } +} + void QmakeProFile::updateGeneratedFiles(const FileName &buildDir) { // We can do this because other plugins are not supposed to keep the compilers around. @@ -1925,22 +1927,15 @@ void QmakeProFile::updateGeneratedFiles(const FileName &buildDir) return; } - QList<ExtraCompilerFactory *> factories = + const QList<ExtraCompilerFactory *> factories = ProjectExplorer::ExtraCompilerFactory::extraCompilerFactories(); -#if 0 - FindGeneratorSourcesVisitor filesVisitor(factories, [&]( - FileNode *file, ExtraCompilerFactory *factory) { - QStringList generated = generatedFiles(buildDir, file); - if (!generated.isEmpty()) { - FileNameList fileNames = Utils::transform(generated, [](const QString &name) { - return FileName::fromString(name); - }); - m_extraCompilers.append(factory->create(m_project, file->filePath(), fileNames)); - } - }); - - // Find all generated files - accept(&filesVisitor); -#endif + ExtraCompilerFactory *formFactory + = Utils::findOrDefault(factories, Utils::equal(&ExtraCompilerFactory::sourceType, FileType::Form)); + if (formFactory) + setupExtraCompiler(buildDir, FileType::Form, formFactory); + ExtraCompilerFactory *scxmlFactory + = Utils::findOrDefault(factories, Utils::equal(&ExtraCompilerFactory::sourceType, FileType::StateChart)); + if (scxmlFactory) + setupExtraCompiler(buildDir, FileType::StateChart, scxmlFactory); } diff --git a/src/plugins/qmakeprojectmanager/qmakeparsernodes.h b/src/plugins/qmakeprojectmanager/qmakeparsernodes.h index 4a4295a9c6..527e0dbc68 100644 --- a/src/plugins/qmakeprojectmanager/qmakeparsernodes.h +++ b/src/plugins/qmakeprojectmanager/qmakeparsernodes.h @@ -211,7 +211,6 @@ private: static void processValues(Internal::QmakePriFileEvalResult &result); void watchFolders(const QSet<QString> &folders); - QmakeProject *m_project = nullptr; QmakeProFile *m_qmakeProFile = nullptr; QmakePriFile *m_parent = nullptr; @@ -225,8 +224,7 @@ private: QSet<QString> m_watchedFolders; bool m_includedInExactParse = true; - // managed by QmakeProFile - friend class QmakeProjectManager::QmakeProFile; + friend class QmakeProFile; }; class QMAKEPROJECTMANAGER_EXPORT TargetInformation @@ -297,7 +295,8 @@ public: Utils::FileName buildDir(QmakeBuildConfiguration *bc = nullptr) const; Utils::FileNameList generatedFiles(const Utils::FileName &buildDirectory, - const Utils::FileName &sourceFile) const; + const Utils::FileName &sourceFile, + const ProjectExplorer::FileType &sourceFileType) const; QList<ProjectExplorer::ExtraCompiler *> extraCompilers() const; TargetInformation targetInformation() const; @@ -349,6 +348,10 @@ private: static TargetInformation targetInformation(QtSupport::ProFileReader *reader, QtSupport::ProFileReader *readerBuildPass, const Utils::FileName &buildDir, const Utils::FileName &projectFilePath); static InstallsList installsList(const QtSupport::ProFileReader *reader, const QString &projectFilePath, const QString &projectDir, const QString &buildDir); + void setupExtraCompiler(const Utils::FileName &buildDir, + const ProjectExplorer::FileType &fileType, + ProjectExplorer::ExtraCompilerFactory *factory); + bool m_validParse = false; bool m_parseInProgress = false; diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.cpp b/src/plugins/qmakeprojectmanager/qmakeproject.cpp index 66100b329a..a38b386ce4 100644 --- a/src/plugins/qmakeprojectmanager/qmakeproject.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeproject.cpp @@ -30,9 +30,9 @@ #include "qmakebuildinfo.h" #include "qmakestep.h" #include "qmakenodes.h" +#include "qmakenodetreebuilder.h" #include "qmakeprojectmanagerconstants.h" #include "qmakebuildconfiguration.h" -#include "findqmakeprofiles.h" #include <utils/algorithm.h> #include <coreplugin/editormanager/editormanager.h> @@ -47,6 +47,7 @@ #include <projectexplorer/buildmanager.h> #include <projectexplorer/buildtargetinfo.h> #include <projectexplorer/deploymentdata.h> +#include <projectexplorer/nodesvisitor.h> #include <projectexplorer/toolchain.h> #include <projectexplorer/headerpath.h> #include <projectexplorer/target.h> @@ -92,8 +93,8 @@ class CentralizedFolderWatcher : public QObject public: CentralizedFolderWatcher(QmakeProject *parent); - void watchFolders(const QList<QString> &folders, QmakePriFileNode *node); - void unwatchFolders(const QList<QString> &folders, QmakePriFileNode *node); + void watchFolders(const QList<QString> &folders, QmakePriFile *file); + void unwatchFolders(const QList<QString> &folders, QmakePriFile *file); private: void folderChanged(const QString &folder); @@ -103,7 +104,7 @@ private: QmakeProject *m_project; QSet<QString> recursiveDirs(const QString &folder); QFileSystemWatcher m_watcher; - QMultiMap<QString, QmakePriFileNode *> m_map; + QMultiMap<QString, QmakePriFile *> m_map; QSet<QString> m_recursiveWatchedFolders; QTimer m_compressTimer; @@ -265,6 +266,7 @@ QmakeProject::QmakeProject(QmakeManager *manager, const QString &fileName) : connect(&m_asyncUpdateTimer, &QTimer::timeout, this, &QmakeProject::asyncUpdate); setRootProjectNode(new QmakeProFileNode(this, projectFilePath())); + m_rootProFile = std::make_unique<QmakeProFile>(this, projectFilePath()); connect(BuildManager::instance(), &BuildManager::buildQueueFinished, this, &QmakeProject::buildFinished); @@ -282,6 +284,7 @@ QmakeProject::~QmakeProject() // Make sure root node (and associated readers) are shut hown before proceeding setRootProjectNode(nullptr); + m_rootProFile.reset(); projectManager()->unregisterProject(this); delete m_projectFiles; @@ -290,6 +293,11 @@ QmakeProject::~QmakeProject() delete m_qmakeVfs; } +QmakeProFile *QmakeProject::rootProFile() const +{ + return m_rootProFile.get(); +} + void QmakeProject::updateFileList() { QmakeProjectFiles newFiles; @@ -370,12 +378,11 @@ void QmakeProject::updateCppCodeModel() qtVersionForPart = ProjectPart::Qt5; } - FindQmakeProFiles findQmakeProFiles; - const QList<QmakeProFileNode *> proFiles = findQmakeProFiles(rootProjectNode()); + const QList<QmakeProFile *> proFiles = rootProFile()->allProFiles(); QList<ProjectExplorer::ExtraCompiler *> generators; CppTools::RawProjectParts rpps; - foreach (QmakeProFileNode *pro, proFiles) { + for (const QmakeProFile *pro : proFiles) { warnOnToolChainMismatch(pro); CppTools::RawProjectPart rpp; @@ -435,18 +442,18 @@ void QmakeProject::updateQmlJSCodeModel() QmlJS::ModelManagerInterface::ProjectInfo projectInfo = modelManager->defaultProjectInfoForProject(this); - FindQmakeProFiles findQt4ProFiles; - QList<QmakeProFileNode *> proFiles = findQt4ProFiles(rootProjectNode()); + const QList<QmakeProFile *> proFiles = rootProFile()->allProFiles(); projectInfo.importPaths.clear(); bool hasQmlLib = false; - foreach (QmakeProFileNode *node, proFiles) { - foreach (const QString &path, node->variableValue(Variable::QmlImportPath)) + for (QmakeProFile *file : proFiles) { + for (const QString &path : file->variableValue(Variable::QmlImportPath)) { projectInfo.importPaths.maybeInsert(FileName::fromString(path), QmlJS::Dialect::Qml); - const QStringList &exactResources = node->variableValue(Variable::ExactResource); - const QStringList &cumulativeResources = node->variableValue(Variable::CumulativeResource); + } + const QStringList &exactResources = file->variableValue(Variable::ExactResource); + const QStringList &cumulativeResources = file->variableValue(Variable::CumulativeResource); projectInfo.activeResourceFiles.append(exactResources); projectInfo.allResourceFiles.append(exactResources); projectInfo.allResourceFiles.append(cumulativeResources); @@ -461,7 +468,7 @@ void QmakeProject::updateQmlJSCodeModel() projectInfo.resourceFileContents[rc] = contents; } if (!hasQmlLib) { - QStringList qtLibs = node->variableValue(Variable::Qt); + QStringList qtLibs = file->variableValue(Variable::Qt); hasQmlLib = qtLibs.contains(QLatin1String("declarative")) || qtLibs.contains(QLatin1String("qml")) || qtLibs.contains(QLatin1String("quick")); @@ -487,7 +494,7 @@ void QmakeProject::updateRunConfigurations() activeTarget()->updateDefaultRunConfigurations(); } -void QmakeProject::scheduleAsyncUpdate(QmakeProFileNode *node, QmakeProFile::AsyncUpdateDelay delay) +void QmakeProject::scheduleAsyncUpdate(QmakeProFile *file, QmakeProFile::AsyncUpdateDelay delay) { if (m_asyncUpdateState == ShuttingDown) return; @@ -499,7 +506,7 @@ void QmakeProject::scheduleAsyncUpdate(QmakeProFileNode *node, QmakeProFile::Asy return; } - node->setParseInProgressRecursive(true); + file->setParseInProgressRecursive(true); setAllBuildConfigurationsEnabled(false); if (m_asyncUpdateState == AsyncFullUpdatePending) { @@ -510,16 +517,15 @@ void QmakeProject::scheduleAsyncUpdate(QmakeProFileNode *node, QmakeProFile::Asy // Add the node m_asyncUpdateState = AsyncPartialUpdatePending; - QList<QmakeProFileNode *>::iterator it; bool add = true; - it = m_partialEvaluate.begin(); + auto it = m_partialEvaluate.begin(); while (it != m_partialEvaluate.end()) { - if (*it == node) { + if (*it == file) { add = false; break; - } else if (node->isParent(*it)) { // We already have the parent in the list, nothing to do + } else if (file->isParent(*it)) { // We already have the parent in the list, nothing to do it = m_partialEvaluate.erase(it); - } else if ((*it)->isParent(node)) { // The node is the parent of a child already in the list + } else if ((*it)->isParent(file)) { // The node is the parent of a child already in the list add = false; break; } else { @@ -528,7 +534,7 @@ void QmakeProject::scheduleAsyncUpdate(QmakeProFileNode *node, QmakeProFile::Asy } if (add) - m_partialEvaluate.append(node); + m_partialEvaluate.append(file); // Cancel running code model update m_cppCodeModelUpdater->cancel(); @@ -556,7 +562,7 @@ void QmakeProject::scheduleAsyncUpdate(QmakeProFile::AsyncUpdateDelay delay) return; } - rootProjectNode()->setParseInProgressRecursive(true); + rootProFile()->setParseInProgressRecursive(true); setAllBuildConfigurationsEnabled(false); if (m_asyncUpdateState == AsyncUpdateInProgress) { @@ -594,6 +600,7 @@ void QmakeProject::decrementPendingEvaluateFutures() m_asyncUpdateFutureInterface->setProgressValue(m_asyncUpdateFutureInterface->progressValue() + 1); if (m_pendingEvaluateFuturesCount == 0) { // We are done! + QmakeNodeTreeBuilder::buildTree(rootProFile(), rootProjectNode()); m_asyncUpdateFutureInterface->reportFinished(); delete m_asyncUpdateFutureInterface; @@ -602,7 +609,7 @@ void QmakeProject::decrementPendingEvaluateFutures() // TODO clear the profile cache ? if (m_asyncUpdateState == AsyncFullUpdatePending || m_asyncUpdateState == AsyncPartialUpdatePending) { - rootProjectNode()->setParseInProgressRecursive(true); + rootProFile()->setParseInProgressRecursive(true); setAllBuildConfigurationsEnabled(false); startAsyncTimer(QmakeProFile::ParseLater); } else if (m_asyncUpdateState != ShuttingDown){ @@ -644,10 +651,10 @@ void QmakeProject::asyncUpdate() m_asyncUpdateFutureInterface->reportStarted(); if (m_asyncUpdateState == AsyncFullUpdatePending) { - rootProjectNode()->asyncUpdate(); + rootProFile()->asyncUpdate(); } else { - foreach (QmakeProFileNode *node, m_partialEvaluate) - node->asyncUpdate(); + foreach (QmakeProFile *file, m_partialEvaluate) + file->asyncUpdate(); } m_partialEvaluate.clear(); @@ -722,17 +729,17 @@ static FileNode *fileNodeOf(QmakeProFileNode *in, const FileName &fileName) QStringList QmakeProject::filesGeneratedFrom(const QString &input) const { - // Look in sub-profiles as SessionManager::projectForFile returns - // the top-level project only. if (!rootProjectNode()) - return QStringList(); + return { }; if (const FileNode *file = fileNodeOf(rootProjectNode(), FileName::fromString(input))) { - QmakeProFileNode *pro = static_cast<QmakeProFileNode *>(file->parentFolderNode()); - return pro->generatedFiles(pro->buildDir(), file); - } else { - return QStringList(); + const QmakeProFileNode *pro = static_cast<QmakeProFileNode *>(file->parentFolderNode()); + if (const QmakeProFile *proFile = pro->proFile()) + return Utils::transform(proFile->generatedFiles(FileName::fromString(pro->buildDir()), + file->filePath(), file->fileType()), + &FileName::toString); } + return { }; } void QmakeProject::proFileParseError(const QString &errorMessage) @@ -740,13 +747,14 @@ void QmakeProject::proFileParseError(const QString &errorMessage) Core::MessageManager::write(errorMessage); } -QtSupport::ProFileReader *QmakeProject::createProFileReader(const QmakeProFileNode *qmakeProFileNode, QmakeBuildConfiguration *bc) +QtSupport::ProFileReader *QmakeProject::createProFileReader(const QmakeProFile *qmakeProFileNode, + QmakeBuildConfiguration *bc) { if (!m_qmakeGlobals) { m_qmakeGlobals = new QMakeGlobals; m_qmakeGlobalsRefCnt = 0; - Kit *k; + Kit *k = nullptr; Environment env = Environment::systemEnvironment(); QStringList qmakeArgs; if (!bc) @@ -771,7 +779,8 @@ QtSupport::ProFileReader *QmakeProject::createProFileReader(const QmakeProFileNo m_qmakeGlobals->qmake_abslocation = QDir::cleanPath(qtVersion->qmakeCommand().toString()); qtVersion->applyProperties(m_qmakeGlobals); } - m_qmakeGlobals->setDirectories(rootProjectNode()->sourceDir(), rootProjectNode()->buildDir()); + m_qmakeGlobals->setDirectories(rootProFile()->sourceDir().toString(), + rootProFile()->buildDir().toString()); Environment::const_iterator eit = env.constBegin(), eend = env.constEnd(); for (; eit != eend; ++eit) @@ -799,7 +808,7 @@ QtSupport::ProFileReader *QmakeProject::createProFileReader(const QmakeProFileNo auto reader = new QtSupport::ProFileReader(m_qmakeGlobals, m_qmakeVfs); - reader->setOutputDir(qmakeProFileNode->buildDir()); + reader->setOutputDir(qmakeProFileNode->buildDir().toString()); return reader; } @@ -841,74 +850,67 @@ QmakeProFileNode *QmakeProject::rootProjectNode() const bool QmakeProject::validParse(const FileName &proFilePath) const { - if (!rootProjectNode()) + if (!rootProFile()) return false; - const QmakeProFileNode *node = rootProjectNode()->findProFileFor(proFilePath); - return node && node->validParse(); + const QmakeProFile *pro = rootProFile()->findProFile(proFilePath); + return pro && pro->validParse(); } bool QmakeProject::parseInProgress(const FileName &proFilePath) const { - if (!rootProjectNode()) + if (!rootProFile()) return false; - const QmakeProFileNode *node = rootProjectNode()->findProFileFor(proFilePath); - return node && node->parseInProgress(); + const QmakeProFile *pro = rootProFile()->findProFile(proFilePath); + return pro && pro->parseInProgress(); } -void QmakeProject::collectAllProFiles(QList<QmakeProFileNode *> &list, QmakeProFileNode *node, Parsing parse, - const QList<ProjectType> &projectTypes) +QList<QmakeProFile *> +QmakeProject::collectAllProFiles(QmakeProFile *file, Parsing parse, + const QList<ProjectType> &projectTypes) { - if (parse == ExactAndCumulativeParse || node->includedInExactParse()) - if (projectTypes.isEmpty() || projectTypes.contains(node->projectType())) - list.append(node); - foreach (ProjectNode *n, node->projectNodes()) { - QmakeProFileNode *qmakeProFileNode = dynamic_cast<QmakeProFileNode *>(n); + QList<QmakeProFile *> result; + if (parse == ExactAndCumulativeParse || file->includedInExactParse()) + if (projectTypes.isEmpty() || projectTypes.contains(file->projectType())) + result.append(file); + + for (QmakePriFile *f : file->children()) { + auto qmakeProFileNode = dynamic_cast<QmakeProFile *>(f); if (qmakeProFileNode) - collectAllProFiles(list, qmakeProFileNode, parse, projectTypes); + result.append(collectAllProFiles(qmakeProFileNode, parse, projectTypes)); } + + return result; } -QList<QmakeProFileNode *> QmakeProject::applicationProFiles(Parsing parse) const +QList<QmakeProFile *> QmakeProject::applicationProFiles(Parsing parse) const { return allProFiles({ ProjectType::ApplicationTemplate, ProjectType::ScriptTemplate }, parse); } -QList<QmakeProFileNode *> QmakeProject::allProFiles(const QList<ProjectType> &projectTypes, Parsing parse) const +QList<QmakeProFile *> QmakeProject::allProFiles(const QList<ProjectType> &projectTypes, Parsing parse) const { - QList<QmakeProFileNode *> list; - if (!rootProjectNode()) + QList<QmakeProFile *> list; + if (!rootProFile()) return list; - collectAllProFiles(list, rootProjectNode(), parse, projectTypes); + list = collectAllProFiles(rootProFile(), parse, projectTypes); return list; } bool QmakeProject::hasApplicationProFile(const FileName &path) const { - if (path.isEmpty()) - return false; - - QList<QmakeProFileNode *> list = applicationProFiles(); - foreach (QmakeProFileNode * node, list) - if (node->filePath() == path) - return true; - return false; + const QList<QmakeProFile *> list = applicationProFiles(); + return Utils::contains(list, Utils::equal(&QmakeProFile::filePath, path)); } -QList<QmakeProFileNode *> QmakeProject::nodesWithQtcRunnable(QList<QmakeProFileNode *> nodes) +QList<QmakeProFile *> QmakeProject::proFilesWithQtcRunnable(QList<QmakeProFile *> files) { - std::function<bool (QmakeProFileNode *)> hasQtcRunnable = [](QmakeProFileNode *node) { - return node->isQtcRunnable(); - }; - - if (anyOf(nodes, hasQtcRunnable)) - erase(nodes, std::not1(hasQtcRunnable)); - return nodes; + return Utils::filtered(files, [](const QmakeProFile *f) { return f->isQtcRunnable(); }); } -QList<Core::Id> QmakeProject::idsForNodes(Core::Id base, const QList<QmakeProFileNode *> &nodes) +QList<Core::Id> QmakeProject::idsForProFiles(Core::Id base, const QList<QmakeProFile *> &files) { - return Utils::transform(nodes, [&base](QmakeProFileNode *node) { - return base.withSuffix(node->filePath().toString()); + return Utils::transform(files, [&base](QmakeProFile *f) { + return base.withSuffix(f->filePath().toString()); }); } @@ -941,30 +943,15 @@ void QmakeProject::setAllBuildConfigurationsEnabled(bool enabled) } } -bool QmakeProject::hasSubNode(QmakePriFileNode *root, const FileName &path) +QList<QmakeProFile *> QmakeProject::findProFiles(const FileName &fileName, QmakeProFile *root) { - if (root->filePath() == path) - return true; - foreach (FolderNode *fn, root->folderNodes()) { - if (dynamic_cast<QmakeProFileNode *>(fn)) { - // we aren't interested in pro file nodes - } else if (QmakePriFileNode *qt4prifilenode = dynamic_cast<QmakePriFileNode *>(fn)) { - if (hasSubNode(qt4prifilenode, path)) - return true; - } - } - return false; -} - -QList<QmakeProFileNode *> QmakeProject::findProFile(const FileName &fileName, QmakeProFileNode *root) -{ - QList<QmakeProFileNode *> result; - if (hasSubNode(root, fileName)) + QList<QmakeProFile *> result; + if (root->filePath() == fileName) result.append(root); - foreach (FolderNode *fn, root->folderNodes()) { - if (QmakeProFileNode *qt4proFileNode = dynamic_cast<QmakeProFileNode *>(fn)) - result.append(findProFile(fileName, qt4proFileNode)); + for (QmakePriFile *fn : root->children()) { + if (auto pro = dynamic_cast<QmakeProFile *>(fn)) + result.append(findProFiles(fileName, pro)); } return result; @@ -973,27 +960,27 @@ QList<QmakeProFileNode *> QmakeProject::findProFile(const FileName &fileName, Qm void QmakeProject::notifyChanged(const FileName &name) { if (files(QmakeProject::SourceFiles).contains(name.toString())) { - const QList<QmakeProFileNode *> list = findProFile(name, rootProjectNode()); - foreach (QmakeProFileNode *node, list) { + const QList<QmakeProFile *> list = findProFiles(name, rootProFile()); + for (QmakeProFile *file : list) { QtSupport::ProFileCacheManager::instance()->discardFile(name.toString()); - node->scheduleUpdate(QmakeProFile::ParseNow); + file->scheduleUpdate(QmakeProFile::ParseNow); } } } -void QmakeProject::watchFolders(const QStringList &l, QmakePriFileNode *node) +void QmakeProject::watchFolders(const QStringList &l, QmakePriFile *file) { if (l.isEmpty()) return; if (!m_centralizedFolderWatcher) m_centralizedFolderWatcher = new Internal::CentralizedFolderWatcher(this); - m_centralizedFolderWatcher->watchFolders(l, node); + m_centralizedFolderWatcher->watchFolders(l, file); } -void QmakeProject::unwatchFolders(const QStringList &l, QmakePriFileNode *node) +void QmakeProject::unwatchFolders(const QStringList &l, QmakePriFile *file) { if (m_centralizedFolderWatcher && !l.isEmpty()) - m_centralizedFolderWatcher->unwatchFolders(l, node); + m_centralizedFolderWatcher->unwatchFolders(l, file); } ///////////// @@ -1024,7 +1011,7 @@ QSet<QString> CentralizedFolderWatcher::recursiveDirs(const QString &folder) return result; } -void CentralizedFolderWatcher::watchFolders(const QList<QString> &folders, QmakePriFileNode *node) +void CentralizedFolderWatcher::watchFolders(const QList<QString> &folders, QmakePriFile *file) { m_watcher.addPaths(folders); @@ -1033,7 +1020,7 @@ void CentralizedFolderWatcher::watchFolders(const QList<QString> &folders, Qmake QString folder = f; if (!folder.endsWith(slash)) folder.append(slash); - m_map.insert(folder, node); + m_map.insert(folder, file); // Support for recursive watching // we add the recursive directories we find @@ -1044,14 +1031,14 @@ void CentralizedFolderWatcher::watchFolders(const QList<QString> &folders, Qmake } } -void CentralizedFolderWatcher::unwatchFolders(const QList<QString> &folders, QmakePriFileNode *node) +void CentralizedFolderWatcher::unwatchFolders(const QList<QString> &folders, QmakePriFile *file) { const QChar slash = QLatin1Char('/'); foreach (const QString &f, folders) { QString folder = f; if (!folder.endsWith(slash)) folder.append(slash); - m_map.remove(folder, node); + m_map.remove(folder, file); if (!m_map.contains(folder)) m_watcher.removePath(folder); @@ -1107,15 +1094,13 @@ void CentralizedFolderWatcher::delayedFolderChanged(const QString &folder) while (true) { if (!dir.endsWith(slash)) dir.append(slash); - QList<QmakePriFileNode *> nodes = m_map.values(dir); - if (!nodes.isEmpty()) { + QList<QmakePriFile *> files = m_map.values(dir); + if (!files.isEmpty()) { // Collect all the files QSet<FileName> newFiles; - newFiles += QmakePriFileNode::recursiveEnumerate(folder); - foreach (QmakePriFileNode *node, nodes) { - newOrRemovedFiles = newOrRemovedFiles - || node->folderChanged(folder, newFiles); - } + newFiles += QmakePriFile::recursiveEnumerate(folder); + foreach (QmakePriFile *file, files) + newOrRemovedFiles = newOrRemovedFiles || file->folderChanged(folder, newFiles); } // Chop off last part, and break if there's nothing to chop off @@ -1214,52 +1199,50 @@ void QmakeProject::updateBuildSystemData() Target *const target = activeTarget(); if (!target) return; - const QmakeProFileNode * const rootNode = rootProjectNode(); - if (!rootNode || rootNode->parseInProgress()) + const QmakeProFile *const file = rootProFile(); + if (!file || file->parseInProgress()) return; DeploymentData deploymentData; - collectData(rootNode, deploymentData); + collectData(file, deploymentData); target->setDeploymentData(deploymentData); BuildTargetInfoList appTargetList; - foreach (const QmakeProFileNode * const node, applicationProFiles()) { - appTargetList.list << BuildTargetInfo(node->targetInformation().target, - FileName::fromString(executableFor(node)), - node->filePath()); + for (const QmakeProFile * const file : applicationProFiles()) { + appTargetList.list << BuildTargetInfo(file->targetInformation().target, + FileName::fromString(executableFor(file)), + file->filePath()); } target->setApplicationTargets(appTargetList); } -void QmakeProject::collectData(const QmakeProFileNode *node, DeploymentData &deploymentData) +void QmakeProject::collectData(const QmakeProFile *file, DeploymentData &deploymentData) { - if (!node->isSubProjectDeployable(node->filePath().toString())) + if (!file->isSubProjectDeployable(file->filePath())) return; - const InstallsList &installsList = node->installsList(); - foreach (const InstallsItem &item, installsList.items) { + const InstallsList &installsList = file->installsList(); + for (const InstallsItem &item : installsList.items) { if (!item.active) continue; foreach (const auto &localFile, item.files) deploymentData.addFile(localFile.fileName, item.path); } - switch (node->projectType()) { + switch (file->projectType()) { case ProjectType::ApplicationTemplate: if (!installsList.targetPath.isEmpty()) - collectApplicationData(node, deploymentData); + collectApplicationData(file, deploymentData); break; case ProjectType::SharedLibraryTemplate: case ProjectType::StaticLibraryTemplate: - collectLibraryData(node, deploymentData); + collectLibraryData(file, deploymentData); break; case ProjectType::SubDirsTemplate: - foreach (const ProjectNode * const subProject, node->subProjectNodesExact()) { - const QmakeProFileNode * const qt4SubProject - = dynamic_cast<const QmakeProFileNode *>(subProject); - if (!qt4SubProject) - continue; - collectData(qt4SubProject, deploymentData); + for (const QmakePriFile *const subPriFile : file->subPriFilesExact()) { + auto subProFile = dynamic_cast<const QmakeProFile *>(subPriFile); + if (subProFile) + collectData(subProFile, deploymentData); } break; default: @@ -1267,26 +1250,26 @@ void QmakeProject::collectData(const QmakeProFileNode *node, DeploymentData &dep } } -void QmakeProject::collectApplicationData(const QmakeProFileNode *node, DeploymentData &deploymentData) +void QmakeProject::collectApplicationData(const QmakeProFile *file, DeploymentData &deploymentData) { - QString executable = executableFor(node); + QString executable = executableFor(file); if (!executable.isEmpty()) - deploymentData.addFile(executable, node->installsList().targetPath, + deploymentData.addFile(executable, file->installsList().targetPath, DeployableFile::TypeExecutable); } -static QString destDirFor(const TargetInformation &ti) +static FileName destDirFor(const TargetInformation &ti) { if (ti.destDir.isEmpty()) - return ti.buildDir.toString(); + return ti.buildDir; if (QDir::isRelativePath(ti.destDir.toString())) - return QDir::cleanPath(ti.buildDir.toString() + '/' + ti.destDir.toString()); - return ti.destDir.toString(); + return FileName::fromString(QDir::cleanPath(ti.buildDir.toString() + '/' + ti.destDir.toString())); + return ti.destDir; } -void QmakeProject::collectLibraryData(const QmakeProFileNode *node, DeploymentData &deploymentData) +void QmakeProject::collectLibraryData(const QmakeProFile *file, DeploymentData &deploymentData) { - const QString targetPath = node->installsList().targetPath; + const QString targetPath = file->installsList().targetPath; if (targetPath.isEmpty()) return; const Kit * const kit = activeTarget()->kit(); @@ -1294,16 +1277,16 @@ void QmakeProject::collectLibraryData(const QmakeProFileNode *node, DeploymentDa if (!toolchain) return; - TargetInformation ti = node->targetInformation(); + TargetInformation ti = file->targetInformation(); QString targetFileName = ti.target; - const QStringList config = node->variableValue(Variable::Config); + const QStringList config = file->variableValue(Variable::Config); const bool isStatic = config.contains(QLatin1String("static")); const bool isPlugin = config.contains(QLatin1String("plugin")); switch (toolchain->targetAbi().os()) { case Abi::WindowsOS: { - QString targetVersionExt = node->singleVariableValue(Variable::TargetVersionExt); + QString targetVersionExt = file->singleVariableValue(Variable::TargetVersionExt); if (targetVersionExt.isEmpty()) { - const QString version = node->singleVariableValue(Variable::Version); + const QString version = file->singleVariableValue(Variable::Version); if (!version.isEmpty()) { targetVersionExt = version.left(version.indexOf(QLatin1Char('.'))); if (targetVersionExt == QLatin1String("0")) @@ -1312,31 +1295,30 @@ void QmakeProject::collectLibraryData(const QmakeProFileNode *node, DeploymentDa } targetFileName += targetVersionExt + QLatin1Char('.'); targetFileName += QLatin1String(isStatic ? "lib" : "dll"); - deploymentData.addFile(destDirFor(ti) + QLatin1Char('/') + targetFileName, targetPath); + deploymentData.addFile(destDirFor(ti).toString() + '/' + targetFileName, targetPath); break; } case Abi::DarwinOS: { - QString destDir = destDirFor(ti); + FileName destDir = destDirFor(ti); if (config.contains(QLatin1String("lib_bundle"))) { - destDir.append(QLatin1Char('/')).append(ti.target) - .append(QLatin1String(".framework")); + destDir.appendPath(ti.target + ".framework"); } else { if (!(isPlugin && config.contains(QLatin1String("no_plugin_name_prefix")))) targetFileName.prepend(QLatin1String("lib")); if (!isPlugin) { targetFileName += QLatin1Char('.'); - const QString version = node->singleVariableValue(Variable::Version); + const QString version = file->singleVariableValue(Variable::Version); QString majorVersion = version.left(version.indexOf(QLatin1Char('.'))); if (majorVersion.isEmpty()) majorVersion = QLatin1String("1"); targetFileName += majorVersion; } targetFileName += QLatin1Char('.'); - targetFileName += node->singleVariableValue(isStatic + targetFileName += file->singleVariableValue(isStatic ? Variable::StaticLibExtension : Variable::ShLibExtension); } - deploymentData.addFile(destDir + QLatin1Char('/') + targetFileName, targetPath); + deploymentData.addFile(destDir.toString() + '/' + targetFileName, targetPath); break; } case Abi::LinuxOS: @@ -1350,14 +1332,14 @@ void QmakeProject::collectLibraryData(const QmakeProFileNode *node, DeploymentDa targetFileName += QLatin1Char('a'); } else { targetFileName += QLatin1String("so"); - deploymentData.addFile(destDirFor(ti) + QLatin1Char('/') + targetFileName, targetPath); + deploymentData.addFile(destDirFor(ti).toString() + '/' + targetFileName, targetPath); if (!isPlugin) { - QString version = node->singleVariableValue(Variable::Version); + QString version = file->singleVariableValue(Variable::Version); if (version.isEmpty()) version = QLatin1String("1.0.0"); targetFileName += QLatin1Char('.'); while (true) { - deploymentData.addFile(destDirFor(ti) + QLatin1Char('/') + deploymentData.addFile(destDirFor(ti).toString() + '/' + targetFileName + version, targetPath); const QString tmpVersion = version.left(version.lastIndexOf(QLatin1Char('.'))); if (tmpVersion == version) @@ -1382,7 +1364,7 @@ bool QmakeProject::matchesKit(const Kit *kit) }); } -static Utils::FileName getFullPathOf(const QmakeProFileNode *pro, Variable variable, +static Utils::FileName getFullPathOf(const QmakeProFile *pro, Variable variable, const BuildConfiguration *bc) { // Take last non-flag value, to cover e.g. '@echo $< && $$QMAKE_CC' or 'ccache gcc' @@ -1420,7 +1402,7 @@ void QmakeProject::testToolChain(ToolChain *tc, const Utils::FileName &path) con } } -void QmakeProject::warnOnToolChainMismatch(const QmakeProFileNode *pro) const +void QmakeProject::warnOnToolChainMismatch(const QmakeProFile *pro) const { const Target *t = activeTarget(); const BuildConfiguration *bc = t ? t->activeBuildConfiguration() : nullptr; @@ -1433,30 +1415,24 @@ void QmakeProject::warnOnToolChainMismatch(const QmakeProFileNode *pro) const getFullPathOf(pro, Variable::QmakeCxx, bc)); } -QString QmakeProject::executableFor(const QmakeProFileNode *node) +QString QmakeProject::executableFor(const QmakeProFile *file) { - const Kit * const kit = activeTarget()->kit(); - const ToolChain * const toolchain = ToolChainKitInformation::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID); - if (!toolchain) + const Kit *const kit = activeTarget() ? activeTarget()->kit() : nullptr; + const ToolChain *const tc = ToolChainKitInformation::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID); + if (!tc) return QString(); - TargetInformation ti = node->targetInformation(); + TargetInformation ti = file->targetInformation(); QString target; - switch (toolchain->targetAbi().os()) { - case Abi::DarwinOS: - if (node->variableValue(Variable::Config).contains(QLatin1String("app_bundle"))) { + if (tc->targetAbi().os() == Abi::DarwinOS) { + if (file->variableValue(Variable::Config).contains(QLatin1String("app_bundle"))) target = ti.target + QLatin1String(".app/Contents/MacOS/") + ti.target; - break; - } - // else fall through - default: { - QString extension = node->singleVariableValue(Variable::TargetExt); + } else { + QString extension = file->singleVariableValue(Variable::TargetExt); target = ti.target + extension; - break; - } } - return QDir(destDirFor(ti)).absoluteFilePath(target); + return QDir(destDirFor(ti).toString()).absoluteFilePath(target); } void QmakeProject::emitBuildDirectoryInitialized() @@ -1478,9 +1454,8 @@ QmakeProject::AsyncUpdateState QmakeProject::asyncUpdateState() const QString QmakeProject::mapProFilePathToTarget(const FileName &proFilePath) { - const QmakeProjectManager::QmakeProFileNode *root = rootProjectNode(); - const QmakeProjectManager::QmakeProFileNode *node = root ? root->findProFileFor(proFilePath) : nullptr; - return node ? node->targetInformation().target : QString(); + const QmakeProFile *pro = rootProFile()->findProFile(proFilePath); + return pro ? pro->targetInformation().target : QString(); } } // namespace QmakeProjectManager diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.h b/src/plugins/qmakeprojectmanager/qmakeproject.h index d0f1fecd0a..37cac81309 100644 --- a/src/plugins/qmakeprojectmanager/qmakeproject.h +++ b/src/plugins/qmakeprojectmanager/qmakeproject.h @@ -64,6 +64,8 @@ public: QmakeProject(QmakeManager *manager, const QString &proFile); ~QmakeProject() final; + QmakeProFile *rootProFile() const; + QString displayName() const final; QmakeManager *projectManager() const final; @@ -77,18 +79,18 @@ public: virtual QStringList filesGeneratedFrom(const QString &file) const final; enum Parsing {ExactParse, ExactAndCumulativeParse }; - QList<QmakeProFileNode *> allProFiles(const QList<ProjectType> &projectTypes = QList<ProjectType>(), - Parsing parse = ExactParse) const; - QList<QmakeProFileNode *> applicationProFiles(Parsing parse = ExactParse) const; + QList<QmakeProFile *> allProFiles(const QList<ProjectType> &projectTypes = QList<ProjectType>(), + Parsing parse = ExactParse) const; + QList<QmakeProFile *> applicationProFiles(Parsing parse = ExactParse) const; bool hasApplicationProFile(const Utils::FileName &path) const; - static QList<QmakeProFileNode *> nodesWithQtcRunnable(QList<QmakeProFileNode *> nodes); - static QList<Core::Id> idsForNodes(Core::Id base, const QList<QmakeProFileNode *> &nodes); + static QList<QmakeProFile *> proFilesWithQtcRunnable(QList<QmakeProFile *> nodes); + static QList<Core::Id> idsForProFiles(Core::Id base, const QList<QmakeProFile *> &files); void notifyChanged(const Utils::FileName &name); /// \internal - QtSupport::ProFileReader *createProFileReader(const QmakeProFileNode *qmakeProFileNode, + QtSupport::ProFileReader *createProFileReader(const QmakeProFile *qmakeProFileNode, QmakeBuildConfiguration *bc = nullptr); /// \internal QMakeGlobals *qmakeGlobals(); @@ -100,7 +102,7 @@ public: void destroyProFileReader(QtSupport::ProFileReader *reader); /// \internal - void scheduleAsyncUpdate(QmakeProjectManager::QmakeProFileNode *node, + void scheduleAsyncUpdate(QmakeProFile *file, QmakeProFile::AsyncUpdateDelay delay = QmakeProFile::ParseLater); /// \internal void incrementPendingEvaluateFutures(); @@ -113,8 +115,8 @@ public: void updateFileList(); void updateCodeModels(); - void watchFolders(const QStringList &l, QmakePriFileNode *node); - void unwatchFolders(const QStringList &l, QmakePriFileNode *node); + void watchFolders(const QStringList &l, QmakePriFile *file); + void unwatchFolders(const QStringList &l, QmakePriFile *file); bool needsConfiguration() const final; @@ -139,7 +141,7 @@ public: QString mapProFilePathToTarget(const Utils::FileName &proFilePath); signals: - void proFileUpdated(QmakeProjectManager::QmakeProFileNode *node, bool, bool); + void proFileUpdated(QmakeProjectManager::QmakeProFile *pro, bool, bool); void buildDirectoryInitialized(); void proFilesEvaluated(); @@ -157,29 +159,28 @@ private: void setAllBuildConfigurationsEnabled(bool enabled); - QString executableFor(const QmakeProFileNode *node); + QString executableFor(const QmakeProFile *file); void updateRunConfigurations(); void updateCppCodeModel(); void updateQmlJSCodeModel(); - static void collectAllProFiles(QList<QmakeProFileNode *> &list, QmakeProFileNode *node, Parsing parse, - const QList<ProjectType> &projectTypes); - static QList<QmakeProFileNode *> findProFile(const Utils::FileName &fileName, QmakeProFileNode *root); - static bool hasSubNode(QmakePriFileNode *root, const Utils::FileName &path); + static QList<QmakeProFile *> collectAllProFiles(QmakeProFile *file, Parsing parse, + const QList<ProjectType> &projectTypes); + static QList<QmakeProFile *> findProFiles(const Utils::FileName &fileName, QmakeProFile *root); static bool equalFileList(const QStringList &a, const QStringList &b); void updateBuildSystemData(); - void collectData(const QmakeProFileNode *node, ProjectExplorer::DeploymentData &deploymentData); - void collectApplicationData(const QmakeProFileNode *node, + void collectData(const QmakeProFile *file, ProjectExplorer::DeploymentData &deploymentData); + void collectApplicationData(const QmakeProFile *file, ProjectExplorer::DeploymentData &deploymentData); - void collectLibraryData(const QmakeProFileNode *node, + void collectLibraryData(const QmakeProFile *file, ProjectExplorer::DeploymentData &deploymentData); void startAsyncTimer(QmakeProFile::AsyncUpdateDelay delay); bool matchesKit(const ProjectExplorer::Kit *kit); - void warnOnToolChainMismatch(const QmakeProFileNode *pro) const; + void warnOnToolChainMismatch(const QmakeProFile *pro) const; void testToolChain(ProjectExplorer::ToolChain *tc, const Utils::FileName &path) const; mutable QSet<const QPair<Utils::FileName, Utils::FileName>> m_toolChainWarnings; @@ -188,6 +189,8 @@ private: QString m_oldQtIncludePath; QString m_oldQtLibsPath; + std::unique_ptr<QmakeProFile> m_rootProFile; + // cached lists of all of files Internal::QmakeProjectFiles *m_projectFiles = nullptr; @@ -204,7 +207,7 @@ private: int m_pendingEvaluateFuturesCount = 0; AsyncUpdateState m_asyncUpdateState = Base; bool m_cancelEvaluate = false; - QList<QmakeProFileNode *> m_partialEvaluate; + QList<QmakeProFile *> m_partialEvaluate; CppTools::CppProjectUpdater *m_cppCodeModelUpdater = nullptr; diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectconfigwidget.cpp b/src/plugins/qmakeprojectmanager/qmakeprojectconfigwidget.cpp index 7ba94adea8..8a71762ef3 100644 --- a/src/plugins/qmakeprojectmanager/qmakeprojectconfigwidget.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeprojectconfigwidget.cpp @@ -210,7 +210,7 @@ void QmakeProjectConfigWidget::updateProblemLabel() } QmakeProject *p = static_cast<QmakeProject *>(m_buildConfiguration->target()->project()); - if (p->rootProjectNode()->parseInProgress() || !p->rootProjectNode()->validParse()) { + if (p->rootProFile()->parseInProgress() || !p->rootProFile()->validParse()) { setProblemLabel(QString()); return; } diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.pro b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.pro index 48c7e6f21f..850febd4d1 100644 --- a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.pro +++ b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.pro @@ -44,7 +44,6 @@ HEADERS += \ qmakeparser.h \ addlibrarywizard.h \ librarydetailscontroller.h \ - findqmakeprofiles.h \ qmakeprojectmanager_global.h \ desktopqmakerunconfiguration.h \ profilecompletionassist.h \ @@ -88,7 +87,6 @@ SOURCES += \ qmakeparser.cpp \ addlibrarywizard.cpp \ librarydetailscontroller.cpp \ - findqmakeprofiles.cpp \ desktopqmakerunconfiguration.cpp \ profilecompletionassist.cpp \ makefileparse.cpp diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.qbs b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.qbs index 5b0d3137da..3e6bff6572 100644 --- a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.qbs +++ b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.qbs @@ -27,7 +27,6 @@ Project { "addlibrarywizard.cpp", "addlibrarywizard.h", "desktopqmakerunconfiguration.cpp", "desktopqmakerunconfiguration.h", "externaleditors.cpp", "externaleditors.h", - "findqmakeprofiles.cpp", "findqmakeprofiles.h", "librarydetailscontroller.cpp", "librarydetailscontroller.h", "librarydetailswidget.ui", "makestep.cpp", "makestep.h", "makestep.ui", diff --git a/src/plugins/qmakeprojectmanager/qmakestep.cpp b/src/plugins/qmakeprojectmanager/qmakestep.cpp index 50f99b1e45..d8bb0ce023 100644 --- a/src/plugins/qmakeprojectmanager/qmakestep.cpp +++ b/src/plugins/qmakeprojectmanager/qmakestep.cpp @@ -224,8 +224,9 @@ bool QMakeStep::init(QList<const BuildStep *> &earlierSteps) QString makefile = workingDirectory; if (qmakeBc->subNodeBuild()) { - if (!qmakeBc->subNodeBuild()->makefile().isEmpty()) - makefile.append(qmakeBc->subNodeBuild()->makefile()); + QmakeProFile *pro = qmakeBc->subNodeBuild()->proFile(); + if (pro && !pro->makefile().isEmpty()) + makefile.append(pro->makefile()); else makefile.append(QLatin1String("/Makefile")); } else if (!qmakeBc->makefile().isEmpty()) { diff --git a/src/plugins/qmldesigner/documentmanager.cpp b/src/plugins/qmldesigner/documentmanager.cpp index de2b6cc7a9..59412263ac 100644 --- a/src/plugins/qmldesigner/documentmanager.cpp +++ b/src/plugins/qmldesigner/documentmanager.cpp @@ -369,7 +369,10 @@ bool DocumentManager::setIsoIconsQmakeVariableValue(const QString &proPath, cons } int flags = QmakeProjectManager::Internal::ProWriter::ReplaceValues | QmakeProjectManager::Internal::ProWriter::MultiLine; - return proNode->setProVariable("ISO_ICONS", value, QString(), flags); + QmakeProjectManager::QmakeProFile *pro = proNode->proFile(); + if (pro) + return pro->setProVariable("ISO_ICONS", value, QString(), flags); + return false; } void DocumentManager::findPathToIsoProFile(bool *iconResourceFileAlreadyExists, QString *resourceFilePath, diff --git a/src/plugins/qnx/qnxrunconfigurationfactory.cpp b/src/plugins/qnx/qnxrunconfigurationfactory.cpp index 7f95b20eb0..5d82aeabca 100644 --- a/src/plugins/qnx/qnxrunconfigurationfactory.cpp +++ b/src/plugins/qnx/qnxrunconfigurationfactory.cpp @@ -53,16 +53,16 @@ QList<Core::Id> QnxRunConfigurationFactory::availableCreationIds(ProjectExplorer if (!canHandle(parent)) return QList<Core::Id>(); - QmakeProject *qt4Project = qobject_cast<QmakeProject *>(parent->project()); - if (!qt4Project) + auto project = qobject_cast<QmakeProject *>(parent->project()); + if (!project) return QList<Core::Id>(); - QList<QmakeProjectManager::QmakeProFileNode *> nodes = qt4Project->applicationProFiles(); + QList<QmakeProjectManager::QmakeProFile *> files = project->applicationProFiles(); if (mode == AutoCreate) - nodes = QmakeProject::nodesWithQtcRunnable(nodes); + files = QmakeProject::proFilesWithQtcRunnable(files); - return QmakeProject::idsForNodes(Core::Id(Constants::QNX_QNX_RUNCONFIGURATION_PREFIX), - nodes); + return QmakeProject::idsForProFiles(Core::Id(Constants::QNX_QNX_RUNCONFIGURATION_PREFIX), + files); } QString QnxRunConfigurationFactory::displayNameForId(Core::Id id) const @@ -92,16 +92,14 @@ bool QnxRunConfigurationFactory::canCreate(ProjectExplorer::Target *parent, Core ProjectExplorer::RunConfiguration *QnxRunConfigurationFactory::doCreate(ProjectExplorer::Target *parent, Core::Id id) { const Utils::FileName projectFilePath = pathFromId(id); - const QmakeProjectManager::QmakeProject * const qt4Project - = qobject_cast<QmakeProjectManager::QmakeProject *>(parent->project()); - QTC_ASSERT(qt4Project, return 0); - foreach (const QmakeProjectManager::QmakeProFileNode * const node, - qt4Project->applicationProFiles()) { - if (node->filePath() == projectFilePath) - return new QnxRunConfiguration(parent, id, node->targetInformation().target); + auto project = qobject_cast<QmakeProjectManager::QmakeProject *>(parent->project()); + QTC_ASSERT(project, return nullptr); + for (const QmakeProjectManager::QmakeProFile *file : project->applicationProFiles()) { + if (file->filePath() == projectFilePath) + return new QnxRunConfiguration(parent, id, file->targetInformation().target); } QTC_CHECK(false); - return 0; + return nullptr; } bool QnxRunConfigurationFactory::canRestore(ProjectExplorer::Target *parent, const QVariantMap &map) const diff --git a/src/plugins/winrt/winrtrunfactories.cpp b/src/plugins/winrt/winrtrunfactories.cpp index c668a7a0cd..d510517e0d 100644 --- a/src/plugins/winrt/winrtrunfactories.cpp +++ b/src/plugins/winrt/winrtrunfactories.cpp @@ -38,7 +38,7 @@ using namespace ProjectExplorer; using QmakeProjectManager::QmakeProject; -using QmakeProjectManager::QmakeProFileNode; +using QmakeProjectManager::QmakeProFile; namespace WinRt { namespace Internal { @@ -66,10 +66,10 @@ QList<Core::Id> WinRtRunConfigurationFactory::availableCreationIds(Target *paren return QList<Core::Id>(); QmakeProject *project = static_cast<QmakeProject *>(parent->project()); - QList<QmakeProFileNode *> nodes = project->applicationProFiles(); + QList<QmakeProFile *> files = project->applicationProFiles(); if (mode == AutoCreate) - nodes = QmakeProject::nodesWithQtcRunnable(nodes); - return QmakeProject::idsForNodes(Core::Id(Constants::WINRT_RC_PREFIX), nodes); + files = QmakeProject::proFilesWithQtcRunnable(files); + return QmakeProject::idsForProFiles(Core::Id(Constants::WINRT_RC_PREFIX), files); } QString WinRtRunConfigurationFactory::displayNameForId(Core::Id id) const |