diff options
Diffstat (limited to 'src/plugins/projectexplorer/project.cpp')
-rw-r--r-- | src/plugins/projectexplorer/project.cpp | 160 |
1 files changed, 147 insertions, 13 deletions
diff --git a/src/plugins/projectexplorer/project.cpp b/src/plugins/projectexplorer/project.cpp index fbd4f9e28fd..c021d9b1a64 100644 --- a/src/plugins/projectexplorer/project.cpp +++ b/src/plugins/projectexplorer/project.cpp @@ -11,15 +11,17 @@ #include "environmentaspect.h" #include "kit.h" #include "kitinformation.h" +#include "msvctoolchain.h" #include "projectexplorer.h" #include "projectexplorerconstants.h" #include "projectexplorertr.h" +#include "projectmanager.h" #include "projectnodes.h" #include "runconfiguration.h" #include "runconfigurationaspects.h" -#include "session.h" #include "target.h" #include "taskhub.h" +#include "toolchainmanager.h" #include "userfileaccessor.h" #include <coreplugin/idocument.h> @@ -273,7 +275,7 @@ void Project::addTarget(std::unique_ptr<Target> &&t) // check activeTarget: if (!activeTarget()) - SessionManager::setActiveTarget(this, pointer, SetActive::Cascade); + setActiveTarget(pointer, SetActive::Cascade); } Target *Project::addTargetForDefaultKit() @@ -309,7 +311,7 @@ bool Project::removeTarget(Target *target) auto keep = take(d->m_targets, target); if (target == d->m_activeTarget) { Target *newActiveTarget = (d->m_targets.size() == 0 ? nullptr : d->m_targets.at(0).get()); - SessionManager::setActiveTarget(this, newActiveTarget, SetActive::Cascade); + setActiveTarget(newActiveTarget, SetActive::Cascade); } emit removedTarget(target); @@ -326,7 +328,7 @@ Target *Project::activeTarget() const return d->m_activeTarget; } -void Project::setActiveTarget(Target *target) +void Project::setActiveTargetHelper(Target *target) { if (d->m_activeTarget == target) return; @@ -414,6 +416,29 @@ Target *Project::target(Kit *k) const return findOrDefault(d->m_targets, equal(&Target::kit, k)); } +void Project::setActiveTarget(Target *target, SetActive cascade) +{ + if (isShuttingDown()) + return; + + setActiveTargetHelper(target); + + if (!target) // never cascade setting no target + return; + + if (cascade != SetActive::Cascade || !ProjectManager::isProjectConfigurationCascading()) + return; + + Utils::Id kitId = target->kit()->id(); + for (Project *otherProject : ProjectManager::projects()) { + if (otherProject == this) + continue; + if (Target *otherTarget = Utils::findOrDefault(otherProject->targets(), + [kitId](Target *t) { return t->kit()->id() == kitId; })) + otherProject->setActiveTargetHelper(otherTarget); + } +} + Tasks Project::projectIssues(const Kit *k) const { Tasks result; @@ -445,12 +470,12 @@ bool Project::copySteps(Target *sourceTarget, Target *newTarget) sourceBc->buildSystem()->name())); newTarget->addBuildConfiguration(newBc); if (sourceTarget->activeBuildConfiguration() == sourceBc) - SessionManager::setActiveBuildConfiguration(newTarget, newBc, SetActive::NoCascade); + newTarget->setActiveBuildConfiguration(newBc, SetActive::NoCascade); } if (!newTarget->activeBuildConfiguration()) { QList<BuildConfiguration *> bcs = newTarget->buildConfigurations(); if (!bcs.isEmpty()) - SessionManager::setActiveBuildConfiguration(newTarget, bcs.first(), SetActive::NoCascade); + newTarget->setActiveBuildConfiguration(bcs.first(), SetActive::NoCascade); } for (DeployConfiguration *sourceDc : sourceTarget->deployConfigurations()) { @@ -462,12 +487,12 @@ bool Project::copySteps(Target *sourceTarget, Target *newTarget) newDc->setDisplayName(sourceDc->displayName()); newTarget->addDeployConfiguration(newDc); if (sourceTarget->activeDeployConfiguration() == sourceDc) - SessionManager::setActiveDeployConfiguration(newTarget, newDc, SetActive::NoCascade); + newTarget->setActiveDeployConfiguration(newDc, SetActive::NoCascade); } if (!newTarget->activeBuildConfiguration()) { QList<DeployConfiguration *> dcs = newTarget->deployConfigurations(); if (!dcs.isEmpty()) - SessionManager::setActiveDeployConfiguration(newTarget, dcs.first(), SetActive::NoCascade); + newTarget->setActiveDeployConfiguration(dcs.first(), SetActive::NoCascade); } for (RunConfiguration *sourceRc : sourceTarget->runConfigurations()) { @@ -846,6 +871,34 @@ const Node *Project::nodeForFilePath(const FilePath &filePath, return nullptr; } +FilePaths Project::binariesForSourceFile(const FilePath &sourceFile) const +{ + if (!rootProjectNode()) + return {}; + const QList<Node *> fileNodes = rootProjectNode()->findNodes([&sourceFile](Node *n) { + return n->filePath() == sourceFile; + }); + FilePaths binaries; + for (const Node * const fileNode : fileNodes) { + for (ProjectNode *projectNode = fileNode->parentProjectNode(); projectNode; + projectNode = projectNode->parentProjectNode()) { + if (!projectNode->isProduct()) + continue; + if (projectNode->productType() == ProductType::App + || projectNode->productType() == ProductType::Lib) { + const QList<Node *> binaryNodes = projectNode->findNodes([](Node *n) { + return n->asFileNode() && (n->asFileNode()->fileType() == FileType::App + || n->asFileNode()->fileType() == FileType::Lib); + + }); + binaries << Utils::transform(binaryNodes, &Node::filePath); + } + break; + } + } + return binaries; +} + void Project::setProjectLanguages(Context language) { if (d->m_projectLanguages == language) @@ -1130,7 +1183,7 @@ void Project::addVariablesToMacroExpander(const QByteArray &prefix, }); expander->registerVariable(fullPrefix + "Kit:Name", //: %1 is something like "Active project" - Tr::tr("%1: The name the active kit.").arg(descriptor), + Tr::tr("%1: The name of the active kit.").arg(descriptor), [targetGetter]() -> QString { if (const Target *const target = targetGetter()) return target->kit()->displayName(); @@ -1435,8 +1488,7 @@ void ProjectExplorerPlugin::testProject_multipleBuildConfigs() Target * const target = theProject.project()->activeTarget(); QVERIFY(target); QCOMPARE(target->buildConfigurations().size(), 6); - SessionManager::setActiveBuildConfiguration(target, target->buildConfigurations().at(1), - SetActive::Cascade); + target->setActiveBuildConfiguration(target->buildConfigurations().at(1), SetActive::Cascade); BuildSystem * const bs = theProject.project()->activeTarget()->buildSystem(); QVERIFY(bs); QCOMPARE(bs, target->activeBuildConfiguration()->buildSystem()); @@ -1452,12 +1504,94 @@ void ProjectExplorerPlugin::testProject_multipleBuildConfigs() } QVERIFY(!bs->isWaitingForParse() && !bs->isParsing()); - QCOMPARE(SessionManager::startupProject(), theProject.project()); + QCOMPARE(ProjectManager::startupProject(), theProject.project()); QCOMPARE(ProjectTree::currentProject(), theProject.project()); QVERIFY(EditorManager::openEditor(projectDir.pathAppended("main.cpp"))); QVERIFY(ProjectTree::currentNode()); ProjectTree::instance()->expandAll(); - SessionManager::closeAllProjects(); // QTCREATORBUG-25655 + ProjectManager::closeAllProjects(); // QTCREATORBUG-25655 +} + +void ProjectExplorerPlugin::testSourceToBinaryMapping() +{ + // Find suitable kit. + Kit * const kit = findOr(KitManager::kits(), nullptr, [](const Kit *k) { + return k->isValid() && ToolChainKitAspect::cxxToolChain(k); + }); + if (!kit) + QSKIP("The test requires at least one kit with a toolchain."); + + const auto toolchain = ToolChainKitAspect::cxxToolChain(kit); + QVERIFY(toolchain); + if (const auto msvcToolchain = dynamic_cast<Internal::MsvcToolChain *>(toolchain)) { + while (!msvcToolchain->environmentInitialized()) { + QSignalSpy parsingFinishedSpy(ToolChainManager::instance(), + &ToolChainManager::toolChainUpdated); + QVERIFY(parsingFinishedSpy.wait(10000)); + } + } + + // Copy project from qrc. + QTemporaryDir * const tempDir = TemporaryDirectory::masterTemporaryDirectory(); + QVERIFY(tempDir->isValid()); + const FilePath projectDir = FilePath::fromString(tempDir->path() + "/multi-target-project"); + if (!projectDir.exists()) { + const auto result = FilePath(":/projectexplorer/testdata/multi-target-project") + .copyRecursively(projectDir); + QVERIFY2(result, qPrintable(result.error())); + const QFileInfoList files = QDir(projectDir.toString()).entryInfoList(QDir::Files); + for (const QFileInfo &f : files) + QFile(f.absoluteFilePath()).setPermissions(f.permissions() | QFile::WriteUser); + } + + // Load Project. + QFETCH(QString, projectFileName); + const auto theProject = openProject(projectDir.pathAppended(projectFileName)); + if (theProject.errorMessage().contains("text/")) { + QSKIP("This test requires the presence of the qmake/cmake/qbs project managers " + "to be fully functional"); + } + + QVERIFY2(theProject, qPrintable(theProject.errorMessage())); + theProject.project()->configureAsExampleProject(kit); + QCOMPARE(theProject.project()->targets().size(), 1); + Target * const target = theProject.project()->activeTarget(); + QVERIFY(target); + BuildSystem * const bs = target->buildSystem(); + QVERIFY(bs); + QCOMPARE(bs, target->activeBuildConfiguration()->buildSystem()); + if (bs->isWaitingForParse() || bs->isParsing()) { + QSignalSpy parsingFinishedSpy(bs, &BuildSystem::parsingFinished); + QVERIFY(parsingFinishedSpy.wait(10000)); + } + QVERIFY(!bs->isWaitingForParse() && !bs->isParsing()); + + if (QLatin1String(QTest::currentDataTag()) == QLatin1String("qbs")) { + BuildManager::buildProjectWithoutDependencies(theProject.project()); + if (BuildManager::isBuilding()) { + QSignalSpy buildingFinishedSpy(BuildManager::instance(), &BuildManager::buildQueueFinished); + QVERIFY(buildingFinishedSpy.wait(10000)); + } + QVERIFY(!BuildManager::isBuilding()); + QSignalSpy projectUpdateSpy(theProject.project(), &Project::fileListChanged); + QVERIFY(projectUpdateSpy.wait(5000)); + } + + // Check mapping + const auto binariesForSource = [&](const QString &fileName) { + return theProject.project()->binariesForSourceFile(projectDir.pathAppended(fileName)); + }; + QCOMPARE(binariesForSource("multi-target-project-main.cpp").size(), 1); + QCOMPARE(binariesForSource("multi-target-project-lib.cpp").size(), 1); + QCOMPARE(binariesForSource("multi-target-project-shared.h").size(), 2); +} + +void ProjectExplorerPlugin::testSourceToBinaryMapping_data() +{ + QTest::addColumn<QString>("projectFileName"); + QTest::addRow("cmake") << "CMakeLists.txt"; + QTest::addRow("qbs") << "multi-target-project.qbs"; + QTest::addRow("qmake") << "multi-target-project.pro"; } #endif // WITH_TESTS |