diff options
author | Christian Kandeler <[email protected]> | 2021-05-07 16:10:07 +0200 |
---|---|---|
committer | Christian Kandeler <[email protected]> | 2021-08-13 12:35:49 +0000 |
commit | 33108795d6b2dd1e91942efb3c1c27ad23342295 (patch) | |
tree | 084d21ac56db3c55c84f242acc8400f2e68cd81c /src | |
parent | 3143ba79e3d954e006f261cc0a535724a4fdc08a (diff) |
CppTools: Turn some classes into pure value types
ProjectInfo, ProjectPart and ProjectUpdateInfo used to carry pointers
to Project and/or Toolchain, even though they were used in contexts
where these pointers were either unsafe to access or not guaranteed to
be valid anymore, which made their use difficult and error-prone.
We turn these classes into pure value types by copying in all relevant
information before the first async operation takes place.
Fixes: QTCREATORBUG-25678
Change-Id: I1914b0dbda6c7dfba6c95e5e92f2d69977755590
Reviewed-by: Jarek Kobus <[email protected]>
Diffstat (limited to 'src')
58 files changed, 1092 insertions, 966 deletions
diff --git a/src/plugins/autotest/autotestunittests.cpp b/src/plugins/autotest/autotestunittests.cpp index 3ce4c69a284..27badd7beb2 100644 --- a/src/plugins/autotest/autotestunittests.cpp +++ b/src/plugins/autotest/autotestunittests.cpp @@ -109,8 +109,7 @@ void AutoTestUnitTests::testCodeParser() QFETCH(int, expectedDataTagsCount); CppTools::Tests::ProjectOpenerAndCloser projectManager; - const CppTools::ProjectInfo projectInfo = projectManager.open(projectFilePath, true, m_kit); - QVERIFY(projectInfo.isValid()); + QVERIFY(projectManager.open(projectFilePath, true, m_kit)); QSignalSpy parserSpy(m_model->parser(), SIGNAL(parsingFinished())); QSignalSpy modelUpdateSpy(m_model, SIGNAL(sweepingDone())); @@ -160,8 +159,7 @@ void AutoTestUnitTests::testCodeParserSwitchStartup() CppTools::Tests::ProjectOpenerAndCloser projectManager; for (int i = 0; i < projectFilePaths.size(); ++i) { qDebug() << "Opening project" << projectFilePaths.at(i); - CppTools::ProjectInfo projectInfo = projectManager.open(projectFilePaths.at(i), true, m_kit); - QVERIFY(projectInfo.isValid()); + QVERIFY(projectManager.open(projectFilePaths.at(i), true, m_kit)); QSignalSpy parserSpy(m_model->parser(), SIGNAL(parsingFinished())); QSignalSpy modelUpdateSpy(m_model, SIGNAL(sweepingDone())); @@ -208,8 +206,7 @@ void AutoTestUnitTests::testCodeParserGTest() QFETCH(QString, projectFilePath); CppTools::Tests::ProjectOpenerAndCloser projectManager; - CppTools::ProjectInfo projectInfo = projectManager.open(projectFilePath, true, m_kit); - QVERIFY(projectInfo.isValid()); + QVERIFY(projectManager.open(projectFilePath, true, m_kit)); QSignalSpy parserSpy(m_model->parser(), SIGNAL(parsingFinished())); QSignalSpy modelUpdateSpy(m_model, SIGNAL(sweepingDone())); @@ -258,8 +255,9 @@ void AutoTestUnitTests::testCodeParserBoostTest() QFETCH(QString, projectFilePath); QFETCH(QString, extension); CppTools::Tests::ProjectOpenerAndCloser projectManager; - CppTools::ProjectInfo projectInfo = projectManager.open(projectFilePath, true, m_kit); - QVERIFY(projectInfo.isValid()); + const CppTools::ProjectInfo::Ptr projectInfo + = projectManager.open(projectFilePath, true, m_kit); + QVERIFY(projectInfo); QSignalSpy parserSpy(m_model->parser(), SIGNAL(parsingFinished())); QSignalSpy modelUpdateSpy(m_model, SIGNAL(sweepingDone())); @@ -268,10 +266,7 @@ void AutoTestUnitTests::testCodeParserBoostTest() QCOMPARE(m_model->boostTestNamesCount(), 5); - - auto project = projectInfo.project(); - QVERIFY(project); - const Utils::FilePath basePath = project->projectFilePath().absolutePath(); + const Utils::FilePath basePath = projectInfo->projectRoot(); QVERIFY(!basePath.isEmpty()); QMap<QString, int> expectedSuitesAndTests; diff --git a/src/plugins/autotest/gtest/gtesttreeitem.cpp b/src/plugins/autotest/gtest/gtesttreeitem.cpp index a52b8b63e54..fcdc98316dc 100644 --- a/src/plugins/autotest/gtest/gtesttreeitem.cpp +++ b/src/plugins/autotest/gtest/gtesttreeitem.cpp @@ -524,9 +524,11 @@ QSet<QString> internalTargets(const TestTreeItem &item) QSet<QString> result; const auto cppMM = CppTools::CppModelManager::instance(); const auto projectInfo = cppMM->projectInfo(ProjectExplorer::SessionManager::startupProject()); + if (!projectInfo) + return {}; const Utils::FilePath filePath = item.filePath(); const QString file = filePath.toString(); - const QVector<CppTools::ProjectPart::Ptr> projectParts = projectInfo.projectParts(); + const QVector<CppTools::ProjectPart::Ptr> projectParts = projectInfo->projectParts(); if (projectParts.isEmpty()) return cppMM->dependingInternalTargets(item.filePath()); for (const CppTools::ProjectPart::Ptr &projectPart : projectParts) { diff --git a/src/plugins/autotest/loadprojectscenario.cpp b/src/plugins/autotest/loadprojectscenario.cpp index 40e9173493d..2013d1a5821 100644 --- a/src/plugins/autotest/loadprojectscenario.cpp +++ b/src/plugins/autotest/loadprojectscenario.cpp @@ -92,8 +92,8 @@ bool LoadProjectScenario::loadProject() CppTools::Tests::ProjectOpenerAndCloser projectManager; // This code must trigger a call to PluginManager::finishScenario() at some later point. - const CppTools::ProjectInfo projectInfo = projectManager.open(projectFilePath, true, m_kit); - return projectInfo.isValid(); + const CppTools::ProjectInfo::Ptr projectInfo = projectManager.open(projectFilePath, true, m_kit); + return projectInfo.get(); } } // namespace Internal diff --git a/src/plugins/autotest/quick/quicktesttreeitem.cpp b/src/plugins/autotest/quick/quicktesttreeitem.cpp index 1be0e7153b9..e80432674ff 100644 --- a/src/plugins/autotest/quick/quicktesttreeitem.cpp +++ b/src/plugins/autotest/quick/quicktesttreeitem.cpp @@ -389,7 +389,9 @@ QSet<QString> internalTargets(const Utils::FilePath &proFile) QSet<QString> result; const auto cppMM = CppTools::CppModelManager::instance(); const auto projectInfo = cppMM->projectInfo(ProjectExplorer::SessionManager::startupProject()); - for (const CppTools::ProjectPart::Ptr &projectPart : projectInfo.projectParts()) { + if (!projectInfo) + return {}; + for (const CppTools::ProjectPart::Ptr &projectPart : projectInfo->projectParts()) { if (projectPart->buildTargetType != ProjectExplorer::BuildTargetType::Executable) continue; if (projectPart->projectFile == proFile.toString()) diff --git a/src/plugins/baremetal/debugservers/uvsc/uvproject.cpp b/src/plugins/baremetal/debugservers/uvsc/uvproject.cpp index fccd07eb1d4..7620ace8599 100644 --- a/src/plugins/baremetal/debugservers/uvsc/uvproject.cpp +++ b/src/plugins/baremetal/debugservers/uvsc/uvproject.cpp @@ -90,8 +90,10 @@ static void extractAllFiles(const DebuggerRunTool *runTool, QStringList &include FilePaths &headers, FilePaths &sources, FilePaths &assemblers) { const auto project = runTool->runControl()->project(); - const CppTools::ProjectInfo info = CppModelManager::instance()->projectInfo(project); - const QVector<ProjectPart::Ptr> parts = info.projectParts(); + const CppTools::ProjectInfo::Ptr info = CppModelManager::instance()->projectInfo(project); + if (!info) + return; + const QVector<ProjectPart::Ptr> parts = info->projectParts(); for (const ProjectPart::Ptr &part : parts) { for (const ProjectFile &file : qAsConst(part->files)) { if (!file.active) diff --git a/src/plugins/clangcodemodel/clangcodemodelplugin.cpp b/src/plugins/clangcodemodel/clangcodemodelplugin.cpp index bc92b1bbab7..bb055a1e922 100644 --- a/src/plugins/clangcodemodel/clangcodemodelplugin.cpp +++ b/src/plugins/clangcodemodel/clangcodemodelplugin.cpp @@ -76,10 +76,15 @@ void ClangCodeModelPlugin::generateCompilationDB() if (!target) return; + const auto projectInfo = CppModelManager::instance()->projectInfo(target->project()); + if (!projectInfo) + return; + QFuture<GenerateCompilationDbResult> task - = QtConcurrent::run(&Internal::generateCompilationDB, - CppModelManager::instance()->projectInfo(target->project()), - CompilationDbPurpose::Project); + = QtConcurrent::run(&Internal::generateCompilationDB, projectInfo, + CompilationDbPurpose::Project, + warningsConfigForProject(target->project()), + optionsForProject(target->project())); Core::ProgressManager::addTask(task, tr("Generating Compilation DB"), "generate compilation db"); m_generatorWatcher.setFuture(task); } @@ -89,8 +94,8 @@ static bool isDBGenerationEnabled(ProjectExplorer::Project *project) using namespace CppTools; if (!project) return false; - ProjectInfo projectInfo = CppModelManager::instance()->projectInfo(project); - return projectInfo.isValid() && !projectInfo.projectParts().isEmpty(); + const ProjectInfo::Ptr projectInfo = CppModelManager::instance()->projectInfo(project); + return projectInfo && !projectInfo->projectParts().isEmpty(); } ClangCodeModelPlugin::~ClangCodeModelPlugin() diff --git a/src/plugins/clangcodemodel/clangdclient.cpp b/src/plugins/clangcodemodel/clangdclient.cpp index 60decc87fdf..cb1d17556b0 100644 --- a/src/plugins/clangcodemodel/clangdclient.cpp +++ b/src/plugins/clangcodemodel/clangdclient.cpp @@ -735,9 +735,10 @@ ClangdClient::ClangdClient(Project *project, const Utils::FilePath &jsonDbDir) setActivateDocumentAutomatically(true); if (!project) { QJsonObject initOptions; - const auto clangOptions = createClangOptions( - *CppTools::CppModelManager::instance()->fallbackProjectPart(), {}); - initOptions.insert("fallbackFlags", QJsonArray::fromStringList(clangOptions.second)); + const QStringList clangOptions = createClangOptions( + *CppTools::CppModelManager::instance()->fallbackProjectPart(), {}, + warningsConfigForProject(nullptr), optionsForProject(nullptr)); + initOptions.insert("fallbackFlags", QJsonArray::fromStringList(clangOptions)); setInitializationOptions(initOptions); } ClientCapabilities caps = Client::defaultClientCapabilities(); diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp index 9306d8c67e9..c1b825a0731 100644 --- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp +++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp @@ -26,6 +26,7 @@ #include "clangeditordocumentprocessor.h" #include "clangbackendcommunicator.h" +#include "clangprojectsettings.h" #include "clangdiagnostictooltipwidget.h" #include "clangfixitoperation.h" #include "clangfixitoperationsextractor.h" @@ -463,11 +464,14 @@ void ClangEditorDocumentProcessor::updateBackendDocument(CppTools::ProjectPart & return; } - const auto clangOptions = createClangOptions(projectPart, filePath()); - m_diagnosticConfigId = clangOptions.first; + ProjectExplorer::Project * const project = CppTools::projectForProjectPart(projectPart); + const CppTools::ClangDiagnosticConfig config = warningsConfigForProject(project); + const QStringList clangOptions = createClangOptions(projectPart, filePath(), config, + optionsForProject(project)); + m_diagnosticConfigId = config.id(); m_communicator.documentsOpened( - {fileContainerWithOptionsAndDocumentContent(clangOptions.second, projectPart.headerPaths)}); + {fileContainerWithOptionsAndDocumentContent(clangOptions, projectPart.headerPaths)}); setLastSentDocumentRevision(filePath(), revision()); } diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp index 12d70c80002..730db89d73d 100644 --- a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp +++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp @@ -48,7 +48,6 @@ #include <cpptools/cppmodelmanager.h> #include <cpptools/cpptoolsreuse.h> #include <cpptools/editordocumenthandle.h> -#include <cpptools/projectinfo.h> #include <languageclient/languageclientmanager.h> @@ -275,7 +274,7 @@ void ClangModelManagerSupport::connectToWidgetsMarkContextMenuRequested(QWidget } void ClangModelManagerSupport::updateLanguageClient(ProjectExplorer::Project *project, - const CppTools::ProjectInfo &projectInfo) + const CppTools::ProjectInfo::Ptr &projectInfo) { if (!CppTools::ClangdProjectSettings(project).settings().useClangd) return; @@ -300,7 +299,8 @@ void ClangModelManagerSupport::updateLanguageClient(ProjectExplorer::Project *pr return; if (!CppTools::ClangdProjectSettings(project).settings().useClangd) return; - if (cppModelManager()->projectInfo(project) != projectInfo) + const CppTools::ProjectInfo::Ptr newProjectInfo = cppModelManager()->projectInfo(project); + if (!newProjectInfo || *newProjectInfo != *projectInfo) return; if (getJsonDbDir() != jsonDbDir) return; @@ -320,7 +320,9 @@ void ClangModelManagerSupport::updateLanguageClient(ProjectExplorer::Project *pr return; if (!CppTools::ClangdProjectSettings(project).settings().useClangd) return; - if (cppModelManager()->projectInfo(project) != projectInfo) + const CppTools::ProjectInfo::Ptr newProjectInfo + = cppModelManager()->projectInfo(project); + if (!newProjectInfo || *newProjectInfo != *projectInfo) return; // Acquaint the client with all open C++ documents for this project. @@ -361,7 +363,9 @@ void ClangModelManagerSupport::updateLanguageClient(ProjectExplorer::Project *pr }); auto future = Utils::runAsync(&Internal::generateCompilationDB, projectInfo, - CompilationDbPurpose::CodeModel); + CompilationDbPurpose::CodeModel, + warningsConfigForProject(project), + optionsForProject(project)); generatorWatcher->setFuture(future); m_generatorSynchronizer.addFuture(future); } @@ -576,7 +580,7 @@ static ClangEditorDocumentProcessors clangProcessorsWithProject(const ProjectExplorer::Project *project) { return ::Utils::filtered(clangProcessors(), [project](ClangEditorDocumentProcessor *p) { - return p->hasProjectPart() && p->projectPart()->project == project; + return p->hasProjectPart() && p->projectPart()->belongsToProject(project); }); } @@ -611,13 +615,13 @@ void ClangModelManagerSupport::onAboutToRemoveProject(ProjectExplorer::Project * void ClangModelManagerSupport::onProjectPartsUpdated(ProjectExplorer::Project *project) { QTC_ASSERT(project, return); - const CppTools::ProjectInfo projectInfo = cppModelManager()->projectInfo(project); - QTC_ASSERT(projectInfo.isValid(), return); + const CppTools::ProjectInfo::Ptr projectInfo = cppModelManager()->projectInfo(project); + QTC_ASSERT(projectInfo, return); updateLanguageClient(project, projectInfo); QStringList projectPartIds; - for (const CppTools::ProjectPart::Ptr &projectPart : projectInfo.projectParts()) + for (const CppTools::ProjectPart::Ptr &projectPart : projectInfo->projectParts()) projectPartIds.append(projectPart->id()); onProjectPartsRemoved(projectPartIds); } diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.h b/src/plugins/clangcodemodel/clangmodelmanagersupport.h index 6844aaedf49..5110d22b77a 100644 --- a/src/plugins/clangcodemodel/clangmodelmanagersupport.h +++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.h @@ -29,6 +29,7 @@ #include "clanguiheaderondiskmanager.h" #include <cpptools/cppmodelmanagersupport.h> +#include <cpptools/projectinfo.h> #include <utils/futuresynchronizer.h> #include <utils/id.h> @@ -129,7 +130,7 @@ private: void connectToWidgetsMarkContextMenuRequested(QWidget *editorWidget); void updateLanguageClient(ProjectExplorer::Project *project, - const CppTools::ProjectInfo &projectInfo); + const CppTools::ProjectInfo::Ptr &projectInfo); ClangdClient *createClient(ProjectExplorer::Project *project, const Utils::FilePath &jsonDbDir); void claimNonProjectSources(ClangdClient *fallbackClient); diff --git a/src/plugins/clangcodemodel/clangtextmark.cpp b/src/plugins/clangcodemodel/clangtextmark.cpp index 52b0d32f955..1db01923591 100644 --- a/src/plugins/clangcodemodel/clangtextmark.cpp +++ b/src/plugins/clangcodemodel/clangtextmark.cpp @@ -88,7 +88,7 @@ ProjectExplorer::Project *projectForCurrentEditor() if (auto processor = ClangEditorDocumentProcessor::get(filePath)) { if (ProjectPart::Ptr projectPart = processor->projectPart()) - return projectPart->project; + return projectForProjectPart(*projectPart); } return nullptr; diff --git a/src/plugins/clangcodemodel/clangutils.cpp b/src/plugins/clangcodemodel/clangutils.cpp index fe9f071ec7f..52a23a1b31c 100644 --- a/src/plugins/clangcodemodel/clangutils.cpp +++ b/src/plugins/clangcodemodel/clangutils.cpp @@ -296,30 +296,10 @@ QString diagnosticCategoryPrefixRemoved(const QString &text) return text; } -static FilePath compilerPath(const CppTools::ProjectPart &projectPart) -{ - Target *target = projectPart.project->activeTarget(); - if (!target) - return FilePath(); - - ToolChain *toolchain = ToolChainKitAspect::cxxToolChain(target->kit()); - - return toolchain->compilerCommand(); -} - -static FilePath buildDirectory(const ProjectExplorer::Project &project) -{ - if (auto *target = project.activeTarget()) { - if (auto *bc = target->activeBuildConfiguration()) - return bc->buildDirectory(); - } - return {}; -} - static QStringList projectPartArguments(const ProjectPart &projectPart) { QStringList args; - args << compilerPath(projectPart).toString(); + args << projectPart.compilerFilePath.toString(); args << "-c"; if (projectPart.toolchainType != ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID) { args << "--target=" + projectPart.toolChainTargetTriple; @@ -350,7 +330,9 @@ static QJsonObject createFileObject(const FilePath &buildDir, const QStringList &arguments, const ProjectPart &projectPart, const ProjectFile &projFile, - CompilationDbPurpose purpose) + CompilationDbPurpose purpose, + const ClangDiagnosticConfig &warningsConfig, + const QStringList &projectOptions) { QJsonObject fileObject; fileObject["file"] = projFile.path; @@ -376,7 +358,8 @@ static QJsonObject createFileObject(const FilePath &buildDir, } } else { // TODO: Do we really need to re-calculate the project part options per source file? - args = QJsonArray::fromStringList(createClangOptions(projectPart, projFile.path).second); + args = QJsonArray::fromStringList(createClangOptions(projectPart, projFile.path, + warningsConfig, projectOptions)); args.prepend("clang"); // TODO: clang-cl for MSVC targets? Does it matter at all what we put here? } @@ -386,10 +369,12 @@ static QJsonObject createFileObject(const FilePath &buildDir, return fileObject; } -GenerateCompilationDbResult generateCompilationDB(CppTools::ProjectInfo projectInfo, - CompilationDbPurpose purpose) +GenerateCompilationDbResult generateCompilationDB(const CppTools::ProjectInfo::Ptr projectInfo, + CompilationDbPurpose purpose, + const ClangDiagnosticConfig &warningsConfig, + const QStringList &projectOptions) { - const FilePath buildDir = buildDirectory(*projectInfo.project()); + const FilePath buildDir = projectInfo->buildRoot(); QTC_ASSERT(!buildDir.isEmpty(), return GenerateCompilationDbResult(QString(), QCoreApplication::translate("ClangUtils", "Could not retrieve build directory."))); @@ -405,13 +390,13 @@ GenerateCompilationDbResult generateCompilationDB(CppTools::ProjectInfo projectI } compileCommandsFile.write("["); - for (ProjectPart::Ptr projectPart : projectInfo.projectParts()) { + for (ProjectPart::Ptr projectPart : projectInfo->projectParts()) { QStringList args; if (purpose == CompilationDbPurpose::Project) args = projectPartArguments(*projectPart); for (const ProjectFile &projFile : projectPart->files) { const QJsonObject json = createFileObject(buildDir, args, *projectPart, projFile, - purpose); + purpose, warningsConfig, projectOptions); if (compileCommandsFile.size() > 1) compileCommandsFile.write(","); compileCommandsFile.write('\n' + QJsonDocument(json).toJson().trimmed()); @@ -495,9 +480,12 @@ static ClangProjectSettings &getProjectSettings(ProjectExplorer::Project *projec class FileOptionsBuilder { public: - FileOptionsBuilder(const QString &filePath, const CppTools::ProjectPart &projectPart) + FileOptionsBuilder(const QString &filePath, const CppTools::ProjectPart &projectPart, + const ClangDiagnosticConfig &warningsConfig, + const QStringList &projectOptions) : m_filePath(filePath) , m_projectPart(projectPart) + , m_warningsConfig(warningsConfig) , m_builder(projectPart) { // Determine the driver mode from toolchain and flags. @@ -507,12 +495,11 @@ public: addLanguageOptions(); addGlobalDiagnosticOptions(); // Before addDiagnosticOptions() so users still can overwrite. addDiagnosticOptions(); - addGlobalOptions(); + m_options.append(projectOptions); addPrecompiledHeaderOptions(); } const QStringList &options() const { return m_options; } - const ::Utils::Id &diagnosticConfigId() const { return m_diagnosticConfigId; } CppTools::UseBuildSystemWarnings useBuildSystemWarnings() const { return m_useBuildSystemWarnings; @@ -539,25 +526,11 @@ private: void addDiagnosticOptions() { - if (m_projectPart.project) { - ClangProjectSettings &projectSettings = getProjectSettings(m_projectPart.project); - if (!projectSettings.useGlobalConfig()) { - const ::Utils::Id warningConfigId = projectSettings.warningConfigId(); - const CppTools::ClangDiagnosticConfigsModel configsModel - = CppTools::diagnosticConfigsModel(); - if (configsModel.hasConfigWithId(warningConfigId)) { - addDiagnosticOptionsForConfig(configsModel.configWithId(warningConfigId)); - return; - } - } - } - - addDiagnosticOptionsForConfig(CppTools::codeModelSettings()->clangDiagnosticConfig()); + addDiagnosticOptionsForConfig(m_warningsConfig); } void addDiagnosticOptionsForConfig(const CppTools::ClangDiagnosticConfig &diagnosticConfig) { - m_diagnosticConfigId = diagnosticConfig.id(); m_useBuildSystemWarnings = diagnosticConfig.useBuildSystemWarnings() ? CppTools::UseBuildSystemWarnings::Yes : CppTools::UseBuildSystemWarnings::No; @@ -573,14 +546,6 @@ private: m_options += CppTools::ClangDiagnosticConfigsModel::globalDiagnosticOptions(); } - void addGlobalOptions() - { - if (!m_projectPart.project) - m_options.append(ClangProjectSettings::globalCommandLineOptions()); - else - m_options.append(getProjectSettings(m_projectPart.project).commandLineOptions()); - } - void addPrecompiledHeaderOptions() { using namespace CppTools; @@ -600,8 +565,8 @@ private: private: const QString &m_filePath; const CppTools::ProjectPart &m_projectPart; + const ClangDiagnosticConfig &m_warningsConfig; - ::Utils::Id m_diagnosticConfigId; CppTools::UseBuildSystemWarnings m_useBuildSystemWarnings = CppTools::UseBuildSystemWarnings::No; CppTools::CompilerOptionsBuilder m_builder; bool m_isClMode = false; @@ -609,17 +574,38 @@ private: }; } // namespace -QPair<Utils::Id, QStringList> createClangOptions(const CppTools::ProjectPart &projectPart, - const QString &filePath) +QStringList createClangOptions(const ProjectPart &projectPart, const QString &filePath, + const ClangDiagnosticConfig &warningsConfig, + const QStringList &projectOptions) { - QPair<Utils::Id, QStringList> value; - const FileOptionsBuilder fileOptions(filePath, projectPart); - value.first = fileOptions.diagnosticConfigId(); + const FileOptionsBuilder fileOptions(filePath, projectPart, warningsConfig, projectOptions); LibClangOptionsBuilder optionsBuilder(projectPart, fileOptions.useBuildSystemWarnings()); const QStringList projectPartOptions = optionsBuilder.build(CppTools::ProjectFile::Unsupported, UsePrecompiledHeaders::No); - value.second = projectPartOptions + fileOptions.options(); - return value; + return projectPartOptions + fileOptions.options(); +} + +ClangDiagnosticConfig warningsConfigForProject(Project *project) +{ + if (project) { + ClangProjectSettings &projectSettings = ClangModelManagerSupport::instance() + ->projectSettings(project); + if (!projectSettings.useGlobalConfig()) { + const Utils::Id warningConfigId = projectSettings.warningConfigId(); + const CppTools::ClangDiagnosticConfigsModel configsModel + = CppTools::diagnosticConfigsModel(); + if (configsModel.hasConfigWithId(warningConfigId)) + return configsModel.configWithId(warningConfigId); + } + } + return CppTools::codeModelSettings()->clangDiagnosticConfig(); +} + +const QStringList optionsForProject(ProjectExplorer::Project *project) +{ + if (project) + return getProjectSettings(project).commandLineOptions(); + return ClangProjectSettings::globalCommandLineOptions(); } } // namespace Internal diff --git a/src/plugins/clangcodemodel/clangutils.h b/src/plugins/clangcodemodel/clangutils.h index 22ae56b4b58..e381654d083 100644 --- a/src/plugins/clangcodemodel/clangutils.h +++ b/src/plugins/clangcodemodel/clangutils.h @@ -27,7 +27,7 @@ #include <cplusplus/Icons.h> -#include <cpptools/projectpart.h> +#include <cpptools/projectinfo.h> #include <cpptools/compileroptionsbuilder.h> #include <QPair> @@ -38,20 +38,26 @@ class QTextBlock; QT_END_NAMESPACE namespace CppTools { +class ClangDiagnosticConfig; class CppEditorDocumentHandle; -class ProjectInfo; } namespace ClangBackEnd { class TokenInfoContainer; } +namespace ProjectExplorer { class Project; } + namespace ClangCodeModel { namespace Internal { CppTools::CppEditorDocumentHandle *cppDocument(const QString &filePath); void setLastSentDocumentRevision(const QString &filePath, uint revision); -QPair<Utils::Id, QStringList> createClangOptions(const CppTools::ProjectPart &projectPart, - const QString &filePath); +CppTools::ClangDiagnosticConfig warningsConfigForProject(ProjectExplorer::Project *project); +const QStringList optionsForProject(ProjectExplorer::Project *project); + +QStringList createClangOptions(const CppTools::ProjectPart &projectPart, const QString &filePath, + const CppTools::ClangDiagnosticConfig &warningsConfig, + const QStringList &projectOptions); CppTools::ProjectPart::Ptr projectPartForFile(const QString &filePath); CppTools::ProjectPart::Ptr projectPartForFileBasedOnProcessor(const QString &filePath); @@ -79,8 +85,9 @@ public: }; enum class CompilationDbPurpose { Project, CodeModel }; -GenerateCompilationDbResult generateCompilationDB(CppTools::ProjectInfo projectInfo, - CompilationDbPurpose purpose); +GenerateCompilationDbResult generateCompilationDB(const CppTools::ProjectInfo::Ptr projectInfo, + CompilationDbPurpose purpose, const CppTools::ClangDiagnosticConfig &warningsConfig, + const QStringList &projectOptions); class DiagnosticTextInfo { diff --git a/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp b/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp index a1a57f74985..fc8c995214c 100644 --- a/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp +++ b/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp @@ -246,31 +246,33 @@ bool OpenEditorAtCursorPosition::waitUntil(const std::function<bool ()> &conditi return false; } -CppTools::ProjectPart::Ptr createProjectPart(const QStringList &files, +CppTools::ProjectPart::Ptr createProjectPart(const Utils::FilePath &projectFilePath, + const QStringList &files, const ProjectExplorer::Macros ¯os) { using namespace CppTools; - ProjectPart::Ptr projectPart(new ProjectPart); - projectPart->projectFile = QLatin1String("myproject.project"); - foreach (const QString &file, files) - projectPart->files.append(ProjectFile(file, ProjectFile::classify(file))); - projectPart->qtVersion = ::Utils::QtVersion::None; - projectPart->projectMacros = macros; - - return projectPart; + ProjectExplorer::RawProjectPart rpp; + rpp.setProjectFileLocation("myproject.project"); + rpp.setQtVersion(Utils::QtVersion::None); + rpp.setMacros(macros); + const auto projectFiles = Utils::transform<ProjectFiles>(files, [](const QString &f) { + return ProjectFile(f, ProjectFile::classify(f)); + }); + return ProjectPart::create(projectFilePath, rpp, {}, projectFiles); } -CppTools::ProjectInfo createProjectInfo(ProjectExplorer::Project *project, - const QStringList &files, - const ProjectExplorer::Macros ¯os) +CppTools::ProjectInfo::Ptr createProjectInfo(ProjectExplorer::Project *project, + const QStringList &files, + const ProjectExplorer::Macros ¯os) { using namespace CppTools; - QTC_ASSERT(project, return ProjectInfo()); + QTC_ASSERT(project, return {}); - const CppTools::ProjectPart::Ptr projectPart = createProjectPart(files, macros); - ProjectInfo projectInfo = ProjectInfo(project); - projectInfo.appendProjectPart(projectPart); + const CppTools::ProjectPart::Ptr projectPart = createProjectPart(project->projectFilePath(), + files, macros); + const auto projectInfo = ProjectInfo::create( + {project, ProjectExplorer::KitInfo(nullptr), {}, {}}, {projectPart}); return projectInfo; } @@ -290,9 +292,9 @@ public: bool load() { m_project = m_helper.createProject(QLatin1String("testProject")); - const CppTools::ProjectInfo projectInfo = createProjectInfo(m_project, - m_projectFiles, - m_projectMacros); + const CppTools::ProjectInfo::Ptr projectInfo = createProjectInfo(m_project, + m_projectFiles, + m_projectMacros); const QSet<QString> filesIndexedAfterLoading = m_helper.updateProjectInfo(projectInfo); return m_projectFiles.size() == filesIndexedAfterLoading.size(); } @@ -300,15 +302,14 @@ public: bool updateProject(const ProjectExplorer::Macros &updatedProjectMacros) { QTC_ASSERT(m_project, return false); - const CppTools::ProjectInfo updatedProjectInfo = createProjectInfo(m_project, - m_projectFiles, - updatedProjectMacros); + const CppTools::ProjectInfo::Ptr updatedProjectInfo + = createProjectInfo(m_project, m_projectFiles, updatedProjectMacros); return updateProjectInfo(updatedProjectInfo); } private: - bool updateProjectInfo(const CppTools::ProjectInfo &projectInfo) + bool updateProjectInfo(const CppTools::ProjectInfo::Ptr &projectInfo) { const QSet<QString> filesIndexedAfterLoading = m_helper.updateProjectInfo(projectInfo); return m_projectFiles.size() == filesIndexedAfterLoading.size(); @@ -720,8 +721,7 @@ void ClangCodeCompletionTest::testCompleteProjectDependingCodeInGeneratedUiFile( // Open project const QString projectFilePath = testDir.absolutePath("qt-widgets-app.pro"); CppTools::Tests::ProjectOpenerAndCloser projectManager; - const CppTools::ProjectInfo projectInfo = projectManager.open(projectFilePath, true); - QVERIFY(projectInfo.isValid()); + QVERIFY(projectManager.open(projectFilePath, true)); QVERIFY(monitorGeneratedUiFile.waitUntilGenerated()); // Open file with ui object diff --git a/src/plugins/clangtools/clangselectablefilesdialog.cpp b/src/plugins/clangtools/clangselectablefilesdialog.cpp index 6fa105e896f..0999c5aee68 100644 --- a/src/plugins/clangtools/clangselectablefilesdialog.cpp +++ b/src/plugins/clangtools/clangselectablefilesdialog.cpp @@ -264,14 +264,14 @@ private: } }; -SelectableFilesDialog::SelectableFilesDialog(const ProjectInfo &projectInfo, +SelectableFilesDialog::SelectableFilesDialog(Project *project, const FileInfoProviders &fileInfoProviders, int initialProviderIndex) : QDialog(nullptr) , m_ui(new Ui::SelectableFilesDialog) , m_filesModel(new SelectableFilesModel) , m_fileInfoProviders(fileInfoProviders) - , m_project(projectInfo.project()) + , m_project(project) , m_analyzeButton(new QPushButton(tr("Analyze"), this)) { m_ui->setupUi(this); diff --git a/src/plugins/clangtools/clangselectablefilesdialog.h b/src/plugins/clangtools/clangselectablefilesdialog.h index dbd0125d8bb..d12680cae30 100644 --- a/src/plugins/clangtools/clangselectablefilesdialog.h +++ b/src/plugins/clangtools/clangselectablefilesdialog.h @@ -47,7 +47,7 @@ class SelectableFilesDialog : public QDialog Q_OBJECT public: - explicit SelectableFilesDialog(const CppTools::ProjectInfo &projectInfo, + explicit SelectableFilesDialog(ProjectExplorer::Project *project, const FileInfoProviders &fileInfoProviders, int initialProviderIndex); ~SelectableFilesDialog() override; diff --git a/src/plugins/clangtools/clangtool.cpp b/src/plugins/clangtools/clangtool.cpp index 53eb9b0ca9a..5690c2767dc 100644 --- a/src/plugins/clangtools/clangtool.cpp +++ b/src/plugins/clangtools/clangtool.cpp @@ -736,17 +736,17 @@ FileInfos ClangTool::collectFileInfos(Project *project, FileSelection fileSelect return {}; } - auto projectInfo = CppTools::CppModelManager::instance()->projectInfo(project); - QTC_ASSERT(projectInfo.isValid(), return FileInfos()); + const auto projectInfo = CppTools::CppModelManager::instance()->projectInfo(project); + QTC_ASSERT(projectInfo, return FileInfos()); - const FileInfos allFileInfos = sortedFileInfos(projectInfo.projectParts()); + const FileInfos allFileInfos = sortedFileInfos(projectInfo->projectParts()); if (selectionType && *selectionType == FileSelectionType::AllFiles) return allFileInfos; if (selectionType && *selectionType == FileSelectionType::AskUser) { static int initialProviderIndex = 0; - SelectableFilesDialog dialog(projectInfo, + SelectableFilesDialog dialog(project, fileInfoProviders(project, allFileInfos), initialProviderIndex); if (dialog.exec() == QDialog::Rejected) @@ -875,7 +875,7 @@ static bool canAnalyzeProject(Project *project) const bool projectSupportsLanguage = project->projectLanguages().contains(c) || project->projectLanguages().contains(cxx); return projectSupportsLanguage - && CppModelManager::instance()->projectInfo(project).isValid() + && CppModelManager::instance()->projectInfo(project) && ToolChainKitAspect::cxxToolChain(target->kit()); } return false; diff --git a/src/plugins/clangtools/clangtoolruncontrol.cpp b/src/plugins/clangtools/clangtoolruncontrol.cpp index 4a8cbcfbf4b..f2febea4c2f 100644 --- a/src/plugins/clangtools/clangtoolruncontrol.cpp +++ b/src/plugins/clangtools/clangtoolruncontrol.cpp @@ -135,7 +135,7 @@ AnalyzeUnit::AnalyzeUnit(const FileInfo &fileInfo, AnalyzeUnits ClangToolRunWorker::unitsToAnalyze(const FilePath &clangIncludeDir, const QString &clangVersion) { - QTC_ASSERT(m_projectInfo.isValid(), return AnalyzeUnits()); + QTC_ASSERT(m_projectInfo, return AnalyzeUnits()); AnalyzeUnits units; for (const FileInfo &fileInfo : m_fileInfos) @@ -217,10 +217,14 @@ void ClangToolRunWorker::start() const QString &toolName = tool()->name(); Project *project = runControl()->project(); m_projectInfo = CppTools::CppModelManager::instance()->projectInfo(project); + if (!m_projectInfo) { + reportFailure(tr("No code model data available for project.")); + return; + } m_projectFiles = Utils::toSet(project->files(Project::AllFiles)); // Project changed in the mean time? - if (m_projectInfo.configurationOrFilesChanged(m_projectInfoBeforeBuild)) { + if (m_projectInfo->configurationOrFilesChanged(*m_projectInfoBeforeBuild)) { // If it's more than a release/debug build configuration change, e.g. // a version control checkout, files might be not valid C++ anymore // or even gone, so better stop here. @@ -239,7 +243,7 @@ void ClangToolRunWorker::start() return; } - const Utils::FilePath projectFile = m_projectInfo.project()->projectFilePath(); + const Utils::FilePath projectFile = m_projectInfo->projectFilePath(); appendMessage(tr("Running %1 on %2 with configuration \"%3\".") .arg(toolName) .arg(projectFile.toUserOutput()) diff --git a/src/plugins/clangtools/clangtoolruncontrol.h b/src/plugins/clangtools/clangtoolruncontrol.h index ccf2f87468b..3b27d339d9d 100644 --- a/src/plugins/clangtools/clangtoolruncontrol.h +++ b/src/plugins/clangtools/clangtoolruncontrol.h @@ -114,8 +114,8 @@ private: Utils::Environment m_environment; Utils::TemporaryDirectory m_temporaryDir; - CppTools::ProjectInfo m_projectInfoBeforeBuild; - CppTools::ProjectInfo m_projectInfo; + CppTools::ProjectInfo::Ptr m_projectInfoBeforeBuild; + CppTools::ProjectInfo::Ptr m_projectInfo; QString m_targetTriple; Utils::Id m_toolChainType; diff --git a/src/plugins/clangtools/clangtoolsunittests.cpp b/src/plugins/clangtools/clangtoolsunittests.cpp index 9d416f07cc1..6f85190e4b9 100644 --- a/src/plugins/clangtools/clangtoolsunittests.cpp +++ b/src/plugins/clangtools/clangtoolsunittests.cpp @@ -115,9 +115,7 @@ void ClangToolsUnitTests::testProject() // Open project Tests::ProjectOpenerAndCloser projectManager; - const ProjectInfo projectInfo = projectManager.open(projectFilePath, true, m_kit); - const bool isProjectOpen = projectInfo.isValid(); - QVERIFY(isProjectOpen); + QVERIFY(projectManager.open(projectFilePath, true, m_kit)); // Run tool ClangTool *tool = ClangTool::instance(); diff --git a/src/plugins/clangtools/documentclangtoolrunner.cpp b/src/plugins/clangtools/documentclangtoolrunner.cpp index 89d76e0f559..2fc0ae258c6 100644 --- a/src/plugins/clangtools/documentclangtoolrunner.cpp +++ b/src/plugins/clangtools/documentclangtoolrunner.cpp @@ -137,12 +137,13 @@ static VirtualFileSystemOverlay &vfso() static FileInfo getFileInfo(const Utils::FilePath &file, ProjectExplorer::Project *project) { - CppTools::ProjectInfo projectInfo = CppTools::CppModelManager::instance()->projectInfo(project); - if (!projectInfo.isValid()) + const CppTools::ProjectInfo::Ptr projectInfo + = CppTools::CppModelManager::instance()->projectInfo(project); + if (!projectInfo) return {}; FileInfo candidate; - for (const CppTools::ProjectPart::Ptr &projectPart : projectInfo.projectParts()) { + for (const CppTools::ProjectPart::Ptr &projectPart : projectInfo->projectParts()) { QTC_ASSERT(projectPart, continue); for (const CppTools::ProjectFile &projectFile : qAsConst(projectPart->files)) { diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdatabasetests.cpp b/src/plugins/compilationdatabaseprojectmanager/compilationdatabasetests.cpp index 243fab9cf90..609db41026c 100644 --- a/src/plugins/compilationdatabaseprojectmanager/compilationdatabasetests.cpp +++ b/src/plugins/compilationdatabaseprojectmanager/compilationdatabasetests.cpp @@ -77,11 +77,10 @@ void CompilationDatabaseTests::testProject() QFETCH(QString, projectFilePath); CppTools::Tests::ProjectOpenerAndCloser projectManager; - const CppTools::ProjectInfo projectInfo = projectManager.open(projectFilePath, true); - QVERIFY(projectInfo.isValid()); + const CppTools::ProjectInfo::Ptr projectInfo = projectManager.open(projectFilePath, true); + QVERIFY(projectInfo); - projectInfo.projectParts(); - QVector<CppTools::ProjectPart::Ptr> projectParts = projectInfo.projectParts(); + QVector<CppTools::ProjectPart::Ptr> projectParts = projectInfo->projectParts(); QVERIFY(!projectParts.isEmpty()); CppTools::ProjectPart &projectPart = *projectParts.first(); diff --git a/src/plugins/cppcheck/cppchecktool.cpp b/src/plugins/cppcheck/cppchecktool.cpp index 883a727bbf4..312a0f420ef 100644 --- a/src/plugins/cppcheck/cppchecktool.cpp +++ b/src/plugins/cppcheck/cppchecktool.cpp @@ -203,8 +203,11 @@ void CppcheckTool::check(const Utils::FilePaths &files) if (filtered.isEmpty()) return; - const CppTools::ProjectInfo info = CppTools::CppModelManager::instance()->projectInfo(m_project); - const QVector<CppTools::ProjectPart::Ptr> parts = info.projectParts(); + const CppTools::ProjectInfo::Ptr info + = CppTools::CppModelManager::instance()->projectInfo(m_project); + if (!info) + return; + const QVector<CppTools::ProjectPart::Ptr> parts = info->projectParts(); if (parts.size() == 1) { QTC_ASSERT(parts.first(), return); addToQueue(filtered, *parts.first()); diff --git a/src/plugins/cppcheck/cppchecktrigger.cpp b/src/plugins/cppcheck/cppchecktrigger.cpp index 5007ad6161d..93a36596a64 100644 --- a/src/plugins/cppcheck/cppchecktrigger.cpp +++ b/src/plugins/cppcheck/cppchecktrigger.cpp @@ -76,8 +76,9 @@ void CppcheckTrigger::checkEditors(const QList<Core::IEditor *> &editors) return; using CppModelManager = CppTools::CppModelManager; - const CppTools::ProjectInfo info = CppModelManager::instance()->projectInfo(m_currentProject); - if (!info.isValid()) + const CppTools::ProjectInfo::Ptr info + = CppModelManager::instance()->projectInfo(m_currentProject); + if (!info) return; const QList<Core::IEditor *> editorList = !editors.isEmpty() @@ -99,7 +100,7 @@ void CppcheckTrigger::checkEditors(const QList<Core::IEditor *> &editors) continue; const QString &pathString = path.toString(); - if (!info.sourceFiles().contains(pathString)) + if (!info->sourceFiles().contains(pathString)) continue; connect(document, &Core::IDocument::aboutToReload, diff --git a/src/plugins/cppeditor/cppcodemodelinspectordialog.cpp b/src/plugins/cppeditor/cppcodemodelinspectordialog.cpp index 98a7a3a1805..3d1126014db 100644 --- a/src/plugins/cppeditor/cppcodemodelinspectordialog.cpp +++ b/src/plugins/cppeditor/cppcodemodelinspectordialog.cpp @@ -34,6 +34,7 @@ #include <cpptools/cppcodemodelinspectordumper.h> #include <cpptools/cppmodelmanager.h> #include <cpptools/cpptoolsbridge.h> +#include <cpptools/cpptoolsreuse.h> #include <cpptools/cppworkingcopy.h> #include <projectexplorer/projectmacro.h> #include <projectexplorer/project.h> @@ -1111,7 +1112,7 @@ class ProjectPartsModel : public QAbstractListModel public: ProjectPartsModel(QObject *parent); - void configure(const QList<ProjectInfo> &projectInfos, + void configure(const QList<ProjectInfo::Ptr> &projectInfos, const ProjectPart::Ptr ¤tEditorsProjectPart); QModelIndex indexForCurrentEditorsProjectPart() const; @@ -1134,13 +1135,13 @@ ProjectPartsModel::ProjectPartsModel(QObject *parent) { } -void ProjectPartsModel::configure(const QList<ProjectInfo> &projectInfos, +void ProjectPartsModel::configure(const QList<ProjectInfo::Ptr> &projectInfos, const ProjectPart::Ptr ¤tEditorsProjectPart) { emit layoutAboutToBeChanged(); m_projectPartsList.clear(); - foreach (const ProjectInfo &info, projectInfos) { - foreach (const ProjectPart::Ptr &projectPart, info.projectParts()) { + foreach (const ProjectInfo::Ptr &info, projectInfos) { + foreach (const ProjectPart::Ptr &projectPart, info->projectParts()) { if (!m_projectPartsList.contains(projectPart)) { m_projectPartsList << projectPart; if (projectPart == currentEditorsProjectPart) @@ -1592,7 +1593,7 @@ void CppCodeModelInspectorDialog::refresh() ? cppEditorDocument->processor()->parser()->projectPartInfo().projectPart : ProjectPart::Ptr(); - const QList<ProjectInfo> projectInfos = cmmi->projectInfos(); + const QList<ProjectInfo::Ptr> projectInfos = cmmi->projectInfos(); dumper.dumpProjectInfos(projectInfos); m_projectPartsModel->configure(projectInfos, editorsProjectPart); m_projectPartsView->resizeColumns(ProjectPartsModel::ColumnCount); @@ -1784,9 +1785,10 @@ void CppCodeModelInspectorDialog::updateProjectPartData(const ProjectPart::Ptr & // General QString projectName = QLatin1String("<None>"); QString projectFilePath = QLatin1String("<None>"); - if (ProjectExplorer::Project *project = part->project) { - projectName = project->displayName(); - projectFilePath = project->projectFilePath().toUserOutput(); + if (part->hasProject()) { + projectFilePath = part->topLevelProject.toUserOutput(); + if (const ProjectExplorer::Project * const project = projectForProjectPart(*part)) + projectName = project->displayName(); } const QString callGroupId = part->callGroupId.isEmpty() ? QString::fromLatin1("<None>") : part->callGroupId; diff --git a/src/plugins/cppeditor/cppeditorwidget.cpp b/src/plugins/cppeditor/cppeditorwidget.cpp index d2abe8699f8..27e8b810dd5 100644 --- a/src/plugins/cppeditor/cppeditorwidget.cpp +++ b/src/plugins/cppeditor/cppeditorwidget.cpp @@ -610,7 +610,7 @@ ProjectPart *findProjectPartForCurrentProject(const QList<ProjectPart::Ptr> &pro const auto found = std::find_if(projectParts.cbegin(), projectParts.cend(), [&](const CppTools::ProjectPart::Ptr &projectPart) { - return projectPart->project == currentProject; + return projectPart->belongsToProject(currentProject); }); if (found != projectParts.cend()) diff --git a/src/plugins/cppeditor/fileandtokenactions_test.cpp b/src/plugins/cppeditor/fileandtokenactions_test.cpp index 1c058c0f821..06da9430776 100644 --- a/src/plugins/cppeditor/fileandtokenactions_test.cpp +++ b/src/plugins/cppeditor/fileandtokenactions_test.cpp @@ -152,15 +152,12 @@ TestActionsTestCase::TestActionsTestCase(const Actions &tokenActions, const Acti // Collect files to process QStringList filesToOpen; QList<QPointer<ProjectExplorer::Project> > projects; - const QList<ProjectInfo> projectInfos = m_modelManager->projectInfos(); - - foreach (const ProjectInfo &info, projectInfos) { - QPointer<ProjectExplorer::Project> project = info.project(); - if (!projects.contains(project)) - projects << project; - qDebug() << "Project" << info.project()->displayName() << "- files to process:" - << info.sourceFiles().size(); - foreach (const QString &sourceFile, info.sourceFiles()) + const QList<ProjectInfo::Ptr> projectInfos = m_modelManager->projectInfos(); + + foreach (const ProjectInfo::Ptr &info, projectInfos) { + qDebug() << "Project" << info->projectFilePath().toUserOutput() << "- files to process:" + << info->sourceFiles().size(); + foreach (const QString &sourceFile, info->sourceFiles()) filesToOpen << sourceFile; } diff --git a/src/plugins/cpptools/builtineditordocumentparser.cpp b/src/plugins/cpptools/builtineditordocumentparser.cpp index 390dd0420da..1d2a1874328 100644 --- a/src/plugins/cpptools/builtineditordocumentparser.cpp +++ b/src/plugins/cpptools/builtineditordocumentparser.cpp @@ -100,7 +100,7 @@ void BuiltinEditorDocumentParser::updateImpl(const QFutureInterface<void> &futur configFile += overwrittenToolchainDefines(*part.data()); configFile += ProjectExplorer::Macro::toByteArray(part->projectMacros); if (!part->projectConfigFile.isEmpty()) - configFile += ProjectPart::readProjectConfigFile(part); + configFile += ProjectPart::readProjectConfigFile(part->projectConfigFile); headerPaths = part->headerPaths; projectConfigFile = part->projectConfigFile; includedFiles = part->includedFiles; diff --git a/src/plugins/cpptools/compileroptionsbuilder.cpp b/src/plugins/cpptools/compileroptionsbuilder.cpp index 09291830b33..0536ba2ff30 100644 --- a/src/plugins/cpptools/compileroptionsbuilder.cpp +++ b/src/plugins/cpptools/compileroptionsbuilder.cpp @@ -666,8 +666,8 @@ void CompilerOptionsBuilder::addIncludeDirOptionForPath(const ProjectExplorer::H systemPath = true; } else { // ProjectExplorer::HeaderPathType::User - if (m_useSystemHeader == UseSystemHeader::Yes - && !path.path.startsWith(m_projectPart.project->rootProjectDirectory().toString())) { + if (m_useSystemHeader == UseSystemHeader::Yes && m_projectPart.hasProject() + && !Utils::FilePath::fromString(path.path).isChildOf(m_projectPart.topLevelProject)) { systemPath = true; } } diff --git a/src/plugins/cpptools/compileroptionsbuilder_test.cpp b/src/plugins/cpptools/compileroptionsbuilder_test.cpp index ac500ecc406..256cabe58fb 100644 --- a/src/plugins/cpptools/compileroptionsbuilder_test.cpp +++ b/src/plugins/cpptools/compileroptionsbuilder_test.cpp @@ -26,6 +26,7 @@ #include "cpptoolsplugin.h" #include "compileroptionsbuilder.h" +#include "projectinfo.h" #include "projectpart.h" #include <projectexplorer/headerpath.h> @@ -46,29 +47,31 @@ namespace { class CompilerOptionsBuilderTest { public: - CompilerOptionsBuilderTest() + ProjectPart finalize() { QFile pchFile(pchFileNativePath()); pchFile.open(QIODevice::WriteOnly); - projectPart.project = project.get(); - projectPart.toolchainType = Constants::CLANG_TOOLCHAIN_TYPEID; - projectPart.languageVersion = Utils::LanguageVersion::CXX17; - projectPart.toolChainWordWidth = ProjectPart::WordWidth64Bit; - projectPart.toolChainTargetTriple = "x86_64-apple-darwin10"; - projectPart.precompiledHeaders = QStringList{pchFileNativePath()}; - projectPart.toolChainMacros = {Macro{"foo", "bar"}, - Macro{"__cplusplus", "2"}, - Macro{"__STDC_VERSION__", "2"}, - Macro{"_MSVC_LANG", "2"}, - Macro{"_MSC_BUILD", "2"}, - Macro{"_MSC_FULL_VER", "1900"}, - Macro{"_MSC_VER", "19"}}; - projectPart.projectMacros = {Macro{"projectFoo", "projectBar"}}; - projectPart.qtVersion = Utils::QtVersion::Qt5; - - projectPart.headerPaths = {HeaderPath{"/tmp/builtin_path", HeaderPathType::BuiltIn}, - HeaderPath{"/tmp/system_path", HeaderPathType::System}, - HeaderPath{"/tmp/path", HeaderPathType::User}}; + RawProjectPart rpp; + rpp.setPreCompiledHeaders({pchFileNativePath()}); + rpp.setMacros({Macro{"projectFoo", "projectBar"}}); + rpp.setQtVersion(Utils::QtVersion::Qt5); + rpp.setHeaderPaths(headerPaths); + rpp.setConfigFileName(projectConfigFile); + ToolChainInfo tcInfo; + tcInfo.type = toolchainType; + tcInfo.wordWidth = 64; + tcInfo.targetTriple = targetTriple; + tcInfo.isMsvc2015ToolChain = isMsvc2015; + tcInfo.extraCodeModelFlags = extraFlags; + tcInfo.macroInspectionRunner = [this](const QStringList &) { + return ToolChain::MacroInspectionReport{toolchainMacros, languageVersion}; + }; + RawProjectPartFlags rppFlags; + rppFlags.commandLineFlags = flags; + projectPart = ProjectPart::create({}, rpp, {}, {}, Utils::Language::Cxx, {}, rppFlags, + tcInfo); + compilerOptionsBuilder.emplace(CompilerOptionsBuilder(*projectPart)); + return *projectPart; } static HeaderPath builtIn(const QString &path) @@ -87,25 +90,43 @@ public: + "/compileroptionsbuilder.pch"); } - std::unique_ptr<Project> project{std::make_unique<Project>(QString(), Utils::FilePath())}; - ProjectPart projectPart; - CompilerOptionsBuilder compilerOptionsBuilder{projectPart}; + QStringList flags; + Utils::Id toolchainType = Constants::CLANG_TOOLCHAIN_TYPEID; + QString targetTriple = "x86_64-apple-darwin10"; + HeaderPaths headerPaths = {HeaderPath{"/tmp/builtin_path", HeaderPathType::BuiltIn}, + HeaderPath{"/tmp/system_path", HeaderPathType::System}, + HeaderPath{"/tmp/path", HeaderPathType::User}}; + Utils::LanguageVersion languageVersion = Utils::LanguageVersion::CXX17; + Utils::LanguageExtensions languageExtensions; + Macros toolchainMacros{ + Macro{"foo", "bar"}, Macro{"__cplusplus", "2"}, Macro{"__STDC_VERSION__", "2"}, + Macro{"_MSVC_LANG", "2"}, Macro{"_MSC_BUILD", "2"}, Macro{"_MSC_FULL_VER", "1900"}, + Macro{"_MSC_VER", "19"}}; + QString projectConfigFile; + QStringList extraFlags; + bool isMsvc2015 = false; + + Utils::optional<CompilerOptionsBuilder> compilerOptionsBuilder; + +private: + ProjectPart::Ptr projectPart; }; } void CppToolsPlugin::test_optionsBuilder_addProjectMacros() { CompilerOptionsBuilderTest t; - t.compilerOptionsBuilder.addProjectMacros(); + t.finalize(); + t.compilerOptionsBuilder->addProjectMacros(); - QCOMPARE(t.compilerOptionsBuilder.options(), QStringList("-DprojectFoo=projectBar")); + QCOMPARE(t.compilerOptionsBuilder->options(), QStringList("-DprojectFoo=projectBar")); } void CppToolsPlugin::test_optionsBuilder_unknownFlagsAreForwarded() { CompilerOptionsBuilderTest t; - ProjectPart part = t.projectPart; - part.compilerFlags = QStringList{"-fancyFlag"}; + t.flags = QStringList{"-fancyFlag"}; + ProjectPart part = t.finalize(); CompilerOptionsBuilder compilerOptionsBuilder{part, UseSystemHeader::No, UseTweakedHeaderPaths::No, UseLanguageDefines::Yes}; compilerOptionsBuilder.build(ProjectFile::CXXSource, UsePrecompiledHeaders::No); @@ -116,8 +137,8 @@ void CppToolsPlugin::test_optionsBuilder_unknownFlagsAreForwarded() void CppToolsPlugin::test_optionsBuilder_warningsFlagsAreNotFilteredIfRequested() { CompilerOptionsBuilderTest t; - ProjectPart part = t.projectPart; - part.compilerFlags = QStringList{"-Whello"}; + t.flags = QStringList{"-Whello"}; + ProjectPart part = t.finalize(); CompilerOptionsBuilder compilerOptionsBuilder{part, UseSystemHeader::No, UseTweakedHeaderPaths::No, UseLanguageDefines::No, UseBuildSystemWarnings::Yes}; @@ -129,8 +150,8 @@ void CppToolsPlugin::test_optionsBuilder_warningsFlagsAreNotFilteredIfRequested( void CppToolsPlugin::test_optionsBuilder_diagnosticOptionsAreRemoved() { CompilerOptionsBuilderTest t; - ProjectPart part = t.projectPart; - part.compilerFlags = QStringList{"-Wbla", "-pedantic"}; + t.flags = QStringList{"-Wbla", "-pedantic"}; + ProjectPart part = t.finalize(); CompilerOptionsBuilder compilerOptionsBuilder{part, UseSystemHeader::No, UseTweakedHeaderPaths::No, UseLanguageDefines::Yes}; compilerOptionsBuilder.build(ProjectFile::CXXSource, UsePrecompiledHeaders::No); @@ -142,12 +163,11 @@ void CppToolsPlugin::test_optionsBuilder_diagnosticOptionsAreRemoved() void CppToolsPlugin::test_optionsBuilder_cLanguageVersionIsRewritten() { CompilerOptionsBuilderTest t; - ProjectPart part = t.projectPart; - part.compilerFlags = QStringList{"-std=c18"}; - // We need to set the language version here to overcome a QTC_ASSERT checking // consistency between ProjectFile::Kind and ProjectPart::LanguageVersion - part.languageVersion = Utils::LanguageVersion::C18; + t.flags = QStringList{"-std=c18"}; + t.languageVersion = Utils::LanguageVersion::C18; + ProjectPart part = t.finalize(); CompilerOptionsBuilder compilerOptionsBuilder{part, UseSystemHeader::No, UseTweakedHeaderPaths::No, UseLanguageDefines::Yes}; @@ -160,7 +180,7 @@ void CppToolsPlugin::test_optionsBuilder_cLanguageVersionIsRewritten() void CppToolsPlugin::test_optionsBuilder_languageVersionIsExplicitlySetIfNotProvided() { CompilerOptionsBuilderTest t; - CompilerOptionsBuilder compilerOptionsBuilder{t.projectPart, UseSystemHeader::No, + CompilerOptionsBuilder compilerOptionsBuilder{t.finalize(), UseSystemHeader::No, UseTweakedHeaderPaths::No, UseLanguageDefines::Yes}; compilerOptionsBuilder.build(ProjectFile::CXXSource, UsePrecompiledHeaders::No); @@ -170,8 +190,8 @@ void CppToolsPlugin::test_optionsBuilder_languageVersionIsExplicitlySetIfNotProv void CppToolsPlugin::test_optionsBuilder_LanguageVersionIsExplicitlySetIfNotProvidedMsvc() { CompilerOptionsBuilderTest t; - t.projectPart.toolchainType = Constants::MSVC_TOOLCHAIN_TYPEID; - CompilerOptionsBuilder compilerOptionsBuilder{t.projectPart, UseSystemHeader::No, + t.toolchainType = Constants::MSVC_TOOLCHAIN_TYPEID; + CompilerOptionsBuilder compilerOptionsBuilder{t.finalize(), UseSystemHeader::No, UseTweakedHeaderPaths::No, UseLanguageDefines::Yes}; compilerOptionsBuilder.build(ProjectFile::CXXSource, UsePrecompiledHeaders::No); @@ -181,15 +201,16 @@ void CppToolsPlugin::test_optionsBuilder_LanguageVersionIsExplicitlySetIfNotProv void CppToolsPlugin::test_optionsBuilder_addWordWidth() { CompilerOptionsBuilderTest t; - t.compilerOptionsBuilder.addWordWidth(); + t.finalize(); + t.compilerOptionsBuilder->addWordWidth(); - QCOMPARE(t.compilerOptionsBuilder.options(), QStringList("-m64")); + QCOMPARE(t.compilerOptionsBuilder->options(), QStringList("-m64")); } void CppToolsPlugin::test_optionsBuilder_headerPathOptionsOrder() { CompilerOptionsBuilderTest t; - CompilerOptionsBuilder compilerOptionsBuilder{t.projectPart, UseSystemHeader::No, + CompilerOptionsBuilder compilerOptionsBuilder{t.finalize(), UseSystemHeader::No, UseTweakedHeaderPaths::Yes, UseLanguageDefines::No, UseBuildSystemWarnings::No, "dummy_version", ""}; compilerOptionsBuilder.addHeaderPathOptions(); @@ -203,8 +224,8 @@ void CppToolsPlugin::test_optionsBuilder_headerPathOptionsOrder() void CppToolsPlugin::test_optionsBuilder_HeaderPathOptionsOrderMsvc() { CompilerOptionsBuilderTest t; - t.projectPart.toolchainType = Constants::MSVC_TOOLCHAIN_TYPEID; - CompilerOptionsBuilder compilerOptionsBuilder{t.projectPart, UseSystemHeader::No, + t.toolchainType = Constants::MSVC_TOOLCHAIN_TYPEID; + CompilerOptionsBuilder compilerOptionsBuilder{t.finalize(), UseSystemHeader::No, UseTweakedHeaderPaths::Yes, UseLanguageDefines::No, UseBuildSystemWarnings::No, "dummy_version", ""}; compilerOptionsBuilder.evaluateCompilerFlags(); @@ -220,7 +241,7 @@ void CppToolsPlugin::test_optionsBuilder_HeaderPathOptionsOrderMsvc() void CppToolsPlugin::test_optionsBuilder_useSystemHeader() { CompilerOptionsBuilderTest t; - CompilerOptionsBuilder compilerOptionsBuilder{t.projectPart, UseSystemHeader::Yes, + CompilerOptionsBuilder compilerOptionsBuilder{t.finalize(), UseSystemHeader::Yes, UseTweakedHeaderPaths::Yes, UseLanguageDefines::No, UseBuildSystemWarnings::No, "dummy_version", ""}; compilerOptionsBuilder.addHeaderPathOptions(); @@ -234,26 +255,25 @@ void CppToolsPlugin::test_optionsBuilder_useSystemHeader() void CppToolsPlugin::test_optionsBuilder_noClangHeadersPath() { CompilerOptionsBuilderTest t; - t.compilerOptionsBuilder.addHeaderPathOptions(); + t.finalize(); + t.compilerOptionsBuilder->addHeaderPathOptions(); - QCOMPARE(t.compilerOptionsBuilder.options(), + QCOMPARE(t.compilerOptionsBuilder->options(), (QStringList{"-I", t.toNative("/tmp/path"), "-I", t.toNative("/tmp/system_path")})); } void CppToolsPlugin::test_optionsBuilder_clangHeadersAndCppIncludePathsOrderMacOs() { CompilerOptionsBuilderTest t; - const auto defaultPaths = t.projectPart.headerPaths; - t.projectPart.headerPaths = { + const HeaderPaths additionalHeaderPaths = { t.builtIn("/usr/include/c++/4.2.1"), t.builtIn("/usr/include/c++/4.2.1/backward"), t.builtIn("/usr/local/include"), t.builtIn("/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/6.0/include"), t.builtIn("/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include"), - t.builtIn("/usr/include") - }; - t.projectPart.headerPaths.append(defaultPaths); - CompilerOptionsBuilder compilerOptionsBuilder(t.projectPart, UseSystemHeader::No, + t.builtIn("/usr/include")}; + t.headerPaths = additionalHeaderPaths + t.headerPaths; + CompilerOptionsBuilder compilerOptionsBuilder(t.finalize(), UseSystemHeader::No, UseTweakedHeaderPaths::Yes, UseLanguageDefines::No, UseBuildSystemWarnings::No, "dummy_version", ""); compilerOptionsBuilder.addHeaderPathOptions(); @@ -273,17 +293,16 @@ void CppToolsPlugin::test_optionsBuilder_clangHeadersAndCppIncludePathsOrderMacO void CppToolsPlugin::test_optionsBuilder_clangHeadersAndCppIncludePathsOrderLinux() { CompilerOptionsBuilderTest t; - t.projectPart.headerPaths = { + t.targetTriple = "x86_64-linux-gnu"; + t.headerPaths = { t.builtIn("/usr/include/c++/4.8"), t.builtIn("/usr/include/c++/4.8/backward"), t.builtIn("/usr/include/x86_64-linux-gnu/c++/4.8"), t.builtIn("/usr/local/include"), t.builtIn("/usr/lib/gcc/x86_64-linux-gnu/4.8/include"), t.builtIn("/usr/include/x86_64-linux-gnu"), - t.builtIn("/usr/include"), - }; - t.projectPart.toolChainTargetTriple = "x86_64-linux-gnu"; - CompilerOptionsBuilder compilerOptionsBuilder(t.projectPart, UseSystemHeader::No, + t.builtIn("/usr/include")}; + CompilerOptionsBuilder compilerOptionsBuilder(t.finalize(), UseSystemHeader::No, UseTweakedHeaderPaths::Yes, UseLanguageDefines::No, UseBuildSystemWarnings::No, "dummy_version", ""); compilerOptionsBuilder.addHeaderPathOptions(); @@ -303,14 +322,13 @@ void CppToolsPlugin::test_optionsBuilder_clangHeadersAndCppIncludePathsOrderLinu void CppToolsPlugin::test_optionsBuilder_clangHeadersAndCppIncludePathsOrderNoVersion() { CompilerOptionsBuilderTest t; - t.projectPart.headerPaths = { + t.targetTriple = "x86_64-w64-windows-gnu"; + t.headerPaths = { t.builtIn("C:/mingw530/i686-w64-mingw32/include"), t.builtIn("C:/mingw530/i686-w64-mingw32/include/c++"), t.builtIn("C:/mingw530/i686-w64-mingw32/include/c++/i686-w64-mingw32"), - t.builtIn("C:/mingw530/i686-w64-mingw32/include/c++/backward"), - }; - t.projectPart.toolChainTargetTriple = "x86_64-w64-windows-gnu"; - CompilerOptionsBuilder compilerOptionsBuilder(t.projectPart, UseSystemHeader::No, + t.builtIn("C:/mingw530/i686-w64-mingw32/include/c++/backward")}; + CompilerOptionsBuilder compilerOptionsBuilder(t.finalize(), UseSystemHeader::No, UseTweakedHeaderPaths::Yes, UseLanguageDefines::No, UseBuildSystemWarnings::No, "dummy_version", ""); compilerOptionsBuilder.addHeaderPathOptions(); @@ -327,15 +345,14 @@ void CppToolsPlugin::test_optionsBuilder_clangHeadersAndCppIncludePathsOrderNoVe void CppToolsPlugin::test_optionsBuilder_clangHeadersAndCppIncludePathsOrderAndroidClang() { CompilerOptionsBuilderTest t; - t.projectPart.headerPaths = { + t.targetTriple = "i686-linux-android"; + t.headerPaths = { t.builtIn("C:/Android/sdk/ndk-bundle/sysroot/usr/include/i686-linux-android"), t.builtIn("C:/Android/sdk/ndk-bundle/sources/cxx-stl/llvm-libc++/include"), t.builtIn("C:/Android/sdk/ndk-bundle/sources/android/support/include"), t.builtIn("C:/Android/sdk/ndk-bundle/sources/cxx-stl/llvm-libc++abi/include"), - t.builtIn("C:/Android/sdk/ndk-bundle/sysroot/usr/include"), - }; - t.projectPart.toolChainTargetTriple = "i686-linux-android"; - CompilerOptionsBuilder compilerOptionsBuilder(t.projectPart, UseSystemHeader::No, + t.builtIn("C:/Android/sdk/ndk-bundle/sysroot/usr/include")}; + CompilerOptionsBuilder compilerOptionsBuilder(t.finalize(), UseSystemHeader::No, UseTweakedHeaderPaths::Yes, UseLanguageDefines::No, UseBuildSystemWarnings::No, "dummy_version", ""); compilerOptionsBuilder.addHeaderPathOptions(); @@ -353,24 +370,26 @@ void CppToolsPlugin::test_optionsBuilder_clangHeadersAndCppIncludePathsOrderAndr void CppToolsPlugin::test_optionsBuilder_noPrecompiledHeader() { CompilerOptionsBuilderTest t; - t.compilerOptionsBuilder.addPrecompiledHeaderOptions(UsePrecompiledHeaders::No); + t.finalize(); + t.compilerOptionsBuilder->addPrecompiledHeaderOptions(UsePrecompiledHeaders::No); - QVERIFY(t.compilerOptionsBuilder.options().empty()); + QVERIFY(t.compilerOptionsBuilder->options().empty()); } void CppToolsPlugin::test_optionsBuilder_usePrecompiledHeader() { CompilerOptionsBuilderTest t; - t.compilerOptionsBuilder.addPrecompiledHeaderOptions(UsePrecompiledHeaders::Yes); + t.finalize(); + t.compilerOptionsBuilder->addPrecompiledHeaderOptions(UsePrecompiledHeaders::Yes); - QCOMPARE(t.compilerOptionsBuilder.options(), (QStringList{"-include", t.pchFileNativePath()})); + QCOMPARE(t.compilerOptionsBuilder->options(), (QStringList{"-include", t.pchFileNativePath()})); } void CppToolsPlugin::test_optionsBuilder_usePrecompiledHeaderMsvc() { CompilerOptionsBuilderTest t; - t.projectPart.toolchainType = Constants::MSVC_TOOLCHAIN_TYPEID; - CompilerOptionsBuilder compilerOptionsBuilder{t.projectPart}; + t.toolchainType = Constants::MSVC_TOOLCHAIN_TYPEID; + CompilerOptionsBuilder compilerOptionsBuilder{t.finalize()}; compilerOptionsBuilder.evaluateCompilerFlags(); compilerOptionsBuilder.addPrecompiledHeaderOptions(UsePrecompiledHeaders::Yes); @@ -380,40 +399,44 @@ void CppToolsPlugin::test_optionsBuilder_usePrecompiledHeaderMsvc() void CppToolsPlugin::test_optionsBuilder_addMacros() { CompilerOptionsBuilderTest t; - t.compilerOptionsBuilder.addMacros(Macros{Macro{"key", "value"}}); + t.finalize(); + t.compilerOptionsBuilder->addMacros(Macros{Macro{"key", "value"}}); - QCOMPARE(t.compilerOptionsBuilder.options(), QStringList("-Dkey=value")); + QCOMPARE(t.compilerOptionsBuilder->options(), QStringList("-Dkey=value")); } void CppToolsPlugin::test_optionsBuilder_addTargetTriple() { CompilerOptionsBuilderTest t; - t.compilerOptionsBuilder.addTargetTriple(); + t.finalize(); + t.compilerOptionsBuilder->addTargetTriple(); - QCOMPARE(t.compilerOptionsBuilder.options(), QStringList("--target=x86_64-apple-darwin10")); + QCOMPARE(t.compilerOptionsBuilder->options(), QStringList("--target=x86_64-apple-darwin10")); } void CppToolsPlugin::test_optionsBuilder_enableCExceptions() { CompilerOptionsBuilderTest t; - t.projectPart.languageVersion = Utils::LanguageVersion::C99; - t.compilerOptionsBuilder.enableExceptions(); + t.languageVersion = Utils::LanguageVersion::C99; + t.finalize(); + t.compilerOptionsBuilder->enableExceptions(); - QCOMPARE(t.compilerOptionsBuilder.options(), QStringList("-fexceptions")); + QCOMPARE(t.compilerOptionsBuilder->options(), QStringList("-fexceptions")); } void CppToolsPlugin::test_optionsBuilder_enableCxxExceptions() { CompilerOptionsBuilderTest t; - t.compilerOptionsBuilder.enableExceptions(); + t.finalize(); + t.compilerOptionsBuilder->enableExceptions(); - QCOMPARE(t.compilerOptionsBuilder.options(), (QStringList{"-fcxx-exceptions", "-fexceptions"})); + QCOMPARE(t.compilerOptionsBuilder->options(), (QStringList{"-fcxx-exceptions", "-fexceptions"})); } void CppToolsPlugin::test_optionsBuilder_insertWrappedQtHeaders() { CompilerOptionsBuilderTest t; - CompilerOptionsBuilder compilerOptionsBuilder{t.projectPart, UseSystemHeader::Yes, + CompilerOptionsBuilder compilerOptionsBuilder{t.finalize(), UseSystemHeader::Yes, UseTweakedHeaderPaths::Yes, UseLanguageDefines::No, UseBuildSystemWarnings::No, "dummy_version", ""}; compilerOptionsBuilder.insertWrappedQtHeaders(); @@ -425,13 +448,8 @@ void CppToolsPlugin::test_optionsBuilder_insertWrappedQtHeaders() void CppToolsPlugin::test_optionsBuilder_insertWrappedMingwHeadersWithNonMingwToolchain() { CompilerOptionsBuilderTest t; - CompilerOptionsBuilder builder{t.projectPart, - UseSystemHeader::Yes, - UseTweakedHeaderPaths::Yes, - UseLanguageDefines::No, - UseBuildSystemWarnings::No, - "dummy_version", - ""}; + CompilerOptionsBuilder builder{t.finalize(), UseSystemHeader::Yes, UseTweakedHeaderPaths::Yes, + UseLanguageDefines::No, UseBuildSystemWarnings::No, "dummy_version", ""}; builder.insertWrappedMingwHeaders(); QVERIFY(!Utils::contains(builder.options(), @@ -441,9 +459,9 @@ void CppToolsPlugin::test_optionsBuilder_insertWrappedMingwHeadersWithNonMingwTo void CppToolsPlugin::test_optionsBuilder_insertWrappedMingwHeadersWithMingwToolchain() { CompilerOptionsBuilderTest t; - CompilerOptionsBuilder builder{t.projectPart, UseSystemHeader::Yes, UseTweakedHeaderPaths::Yes, + t.toolchainType = Constants::MINGW_TOOLCHAIN_TYPEID; + CompilerOptionsBuilder builder{t.finalize(), UseSystemHeader::Yes, UseTweakedHeaderPaths::Yes, UseLanguageDefines::No, UseBuildSystemWarnings::No, "dummy_version", ""}; - t.projectPart.toolchainType = Constants::MINGW_TOOLCHAIN_TYPEID; builder.insertWrappedMingwHeaders(); QVERIFY(Utils::contains(builder.options(), @@ -453,16 +471,17 @@ void CppToolsPlugin::test_optionsBuilder_insertWrappedMingwHeadersWithMingwToolc void CppToolsPlugin::test_optionsBuilder_setLanguageVersion() { CompilerOptionsBuilderTest t; - t.compilerOptionsBuilder.updateFileLanguage(ProjectFile::CXXSource); + t.finalize(); + t.compilerOptionsBuilder->updateFileLanguage(ProjectFile::CXXSource); - QCOMPARE(t.compilerOptionsBuilder.options(), (QStringList{"-x", "c++"})); + QCOMPARE(t.compilerOptionsBuilder->options(), (QStringList{"-x", "c++"})); } void CppToolsPlugin::test_optionsBuilder_setLanguageVersionMsvc() { CompilerOptionsBuilderTest t; - t.projectPart.toolchainType = Constants::MSVC_TOOLCHAIN_TYPEID; - CompilerOptionsBuilder compilerOptionsBuilder{t.projectPart}; + t.toolchainType = Constants::MSVC_TOOLCHAIN_TYPEID; + CompilerOptionsBuilder compilerOptionsBuilder{t.finalize()}; compilerOptionsBuilder.evaluateCompilerFlags(); compilerOptionsBuilder.updateFileLanguage(ProjectFile::CXXSource); @@ -472,26 +491,29 @@ void CppToolsPlugin::test_optionsBuilder_setLanguageVersionMsvc() void CppToolsPlugin::test_optionsBuilder_handleLanguageExtension() { CompilerOptionsBuilderTest t; - t.projectPart.languageExtensions = Utils::LanguageExtension::ObjectiveC; - t.compilerOptionsBuilder.updateFileLanguage(ProjectFile::CXXSource); + t.languageVersion = Utils::LanguageVersion::CXX17; + t.languageExtensions = Utils::LanguageExtension::ObjectiveC; + t.finalize(); + t.compilerOptionsBuilder->updateFileLanguage(ProjectFile::CXXSource); - QCOMPARE(t.compilerOptionsBuilder.options(), (QStringList{"-x", "objective-c++"})); + QCOMPARE(t.compilerOptionsBuilder->options(), (QStringList{"-x", "objective-c++"})); } void CppToolsPlugin::test_optionsBuilder_updateLanguageVersion() { CompilerOptionsBuilderTest t; - t.compilerOptionsBuilder.updateFileLanguage(ProjectFile::CXXSource); - t.compilerOptionsBuilder.updateFileLanguage(ProjectFile::CXXHeader); + t.finalize(); + t.compilerOptionsBuilder->updateFileLanguage(ProjectFile::CXXSource); + t.compilerOptionsBuilder->updateFileLanguage(ProjectFile::CXXHeader); - QCOMPARE(t.compilerOptionsBuilder.options(), (QStringList{"-x", "c++-header"})); + QCOMPARE(t.compilerOptionsBuilder->options(), (QStringList{"-x", "c++-header"})); } void CppToolsPlugin::test_optionsBuilder_updateLanguageVersionMsvc() { CompilerOptionsBuilderTest t; - t.projectPart.toolchainType = Constants::MSVC_TOOLCHAIN_TYPEID; - CompilerOptionsBuilder compilerOptionsBuilder{t.projectPart}; + t.toolchainType = Constants::MSVC_TOOLCHAIN_TYPEID; + CompilerOptionsBuilder compilerOptionsBuilder{t.finalize()}; compilerOptionsBuilder.evaluateCompilerFlags(); compilerOptionsBuilder.updateFileLanguage(ProjectFile::CXXSource); compilerOptionsBuilder.updateFileLanguage(ProjectFile::CSource); @@ -502,48 +524,52 @@ void CppToolsPlugin::test_optionsBuilder_updateLanguageVersionMsvc() void CppToolsPlugin::test_optionsBuilder_addMsvcCompatibilityVersion() { CompilerOptionsBuilderTest t; - t.projectPart.toolchainType = Constants::MSVC_TOOLCHAIN_TYPEID; - t.projectPart.toolChainMacros.append(Macro{"_MSC_FULL_VER", "190000000"}); - t.compilerOptionsBuilder.addMsvcCompatibilityVersion(); + t.toolchainType = Constants::MSVC_TOOLCHAIN_TYPEID; + t.toolchainMacros.append(Macro{"_MSC_FULL_VER", "190000000"}); + t.finalize(); + t.compilerOptionsBuilder->addMsvcCompatibilityVersion(); - QCOMPARE(t.compilerOptionsBuilder.options(), QStringList("-fms-compatibility-version=19.00")); + QCOMPARE(t.compilerOptionsBuilder->options(), QStringList("-fms-compatibility-version=19.00")); } void CppToolsPlugin::test_optionsBuilder_undefineCppLanguageFeatureMacrosForMsvc2015() { CompilerOptionsBuilderTest t; - t.projectPart.toolchainType = Constants::MSVC_TOOLCHAIN_TYPEID; - t.projectPart.isMsvc2015Toolchain = true; - t.compilerOptionsBuilder.undefineCppLanguageFeatureMacrosForMsvc2015(); + t.toolchainType = Constants::MSVC_TOOLCHAIN_TYPEID; + t.isMsvc2015 = true; + t.finalize(); + t.compilerOptionsBuilder->undefineCppLanguageFeatureMacrosForMsvc2015(); - QVERIFY(t.compilerOptionsBuilder.options().contains("-U__cpp_aggregate_bases")); + QVERIFY(t.compilerOptionsBuilder->options().contains("-U__cpp_aggregate_bases")); } void CppToolsPlugin::test_optionsBuilder_addDefineFunctionMacrosMsvc() { CompilerOptionsBuilderTest t; - t.projectPart.toolchainType = Constants::MSVC_TOOLCHAIN_TYPEID; - t.compilerOptionsBuilder.addDefineFunctionMacrosMsvc(); + t.toolchainType = Constants::MSVC_TOOLCHAIN_TYPEID; + t.finalize(); + t.compilerOptionsBuilder->addDefineFunctionMacrosMsvc(); - QVERIFY(t.compilerOptionsBuilder.options().contains( + QVERIFY(t.compilerOptionsBuilder->options().contains( "-D__FUNCTION__=\"someLegalAndLongishFunctionNameThatWorksAroundQTCREATORBUG-24580\"")); } void CppToolsPlugin::test_optionsBuilder_addProjectConfigFileInclude() { CompilerOptionsBuilderTest t; - t.projectPart.projectConfigFile = "dummy_file.h"; - t.compilerOptionsBuilder.addProjectConfigFileInclude(); + t.projectConfigFile = "dummy_file.h"; + t.finalize(); + t.compilerOptionsBuilder->addProjectConfigFileInclude(); - QCOMPARE(t.compilerOptionsBuilder.options(), (QStringList{"-include", "dummy_file.h"})); + QCOMPARE(t.compilerOptionsBuilder->options(), (QStringList{"-include", "dummy_file.h"})); } void CppToolsPlugin::test_optionsBuilder_addProjectConfigFileIncludeMsvc() { CompilerOptionsBuilderTest t; - t.projectPart.projectConfigFile = "dummy_file.h"; - t.projectPart.toolchainType = Constants::MSVC_TOOLCHAIN_TYPEID; - CompilerOptionsBuilder compilerOptionsBuilder{t.projectPart}; + t.projectConfigFile = "dummy_file.h"; + t.toolchainType = Constants::MSVC_TOOLCHAIN_TYPEID; + CompilerOptionsBuilder compilerOptionsBuilder{t.finalize()}; compilerOptionsBuilder.evaluateCompilerFlags(); compilerOptionsBuilder.addProjectConfigFileInclude(); @@ -553,28 +579,29 @@ void CppToolsPlugin::test_optionsBuilder_addProjectConfigFileIncludeMsvc() void CppToolsPlugin::test_optionsBuilder_noUndefineClangVersionMacrosForNewMsvc() { CompilerOptionsBuilderTest t; - t.projectPart.toolchainType = Constants::MSVC_TOOLCHAIN_TYPEID; - t.compilerOptionsBuilder.undefineClangVersionMacrosForMsvc(); + t.toolchainType = Constants::MSVC_TOOLCHAIN_TYPEID; + t.finalize(); + t.compilerOptionsBuilder->undefineClangVersionMacrosForMsvc(); - QVERIFY(!t.compilerOptionsBuilder.options().contains("-U__clang__")); + QVERIFY(!t.compilerOptionsBuilder->options().contains("-U__clang__")); } void CppToolsPlugin::test_optionsBuilder_undefineClangVersionMacrosForOldMsvc() { CompilerOptionsBuilderTest t; - t.projectPart.toolchainType = Constants::MSVC_TOOLCHAIN_TYPEID; - t.projectPart.toolChainMacros = {Macro{"_MSC_FULL_VER", "1300"}, - Macro{"_MSC_VER", "13"}}; - t.compilerOptionsBuilder.undefineClangVersionMacrosForMsvc(); + t.toolchainType = Constants::MSVC_TOOLCHAIN_TYPEID; + t.toolchainMacros = {Macro{"_MSC_FULL_VER", "1300"}, Macro{"_MSC_VER", "13"}}; + t.finalize(); + t.compilerOptionsBuilder->undefineClangVersionMacrosForMsvc(); - QVERIFY(t.compilerOptionsBuilder.options().contains("-U__clang__")); + QVERIFY(t.compilerOptionsBuilder->options().contains("-U__clang__")); } void CppToolsPlugin::test_optionsBuilder_buildAllOptions() { CompilerOptionsBuilderTest t; - t.projectPart.extraCodeModelFlags = QStringList{"-arch", "x86_64"}; - CompilerOptionsBuilder compilerOptionsBuilder(t.projectPart, UseSystemHeader::No, + t.extraFlags = QStringList{"-arch", "x86_64"}; + CompilerOptionsBuilder compilerOptionsBuilder(t.finalize(), UseSystemHeader::No, UseTweakedHeaderPaths::Yes, UseLanguageDefines::No, UseBuildSystemWarnings::No, "dummy_version", ""); compilerOptionsBuilder.build(ProjectFile::CXXSource, UsePrecompiledHeaders::No); @@ -597,8 +624,8 @@ void CppToolsPlugin::test_optionsBuilder_buildAllOptions() void CppToolsPlugin::test_optionsBuilder_buildAllOptionsMsvc() { CompilerOptionsBuilderTest t; - t.projectPart.toolchainType = Constants::MSVC_TOOLCHAIN_TYPEID; - CompilerOptionsBuilder compilerOptionsBuilder(t.projectPart, UseSystemHeader::No, + t.toolchainType = Constants::MSVC_TOOLCHAIN_TYPEID; + CompilerOptionsBuilder compilerOptionsBuilder(t.finalize(), UseSystemHeader::No, UseTweakedHeaderPaths::Yes, UseLanguageDefines::No, UseBuildSystemWarnings::No, "dummy_version", ""); compilerOptionsBuilder.build(ProjectFile::CXXSource, UsePrecompiledHeaders::No); @@ -625,9 +652,9 @@ void CppToolsPlugin::test_optionsBuilder_buildAllOptionsMsvc() void CppToolsPlugin::test_optionsBuilder_buildAllOptionsMsvcWithExceptions() { CompilerOptionsBuilderTest t; - t.projectPart.toolchainType = Constants::MSVC_TOOLCHAIN_TYPEID; - t.projectPart.toolChainMacros.append(Macro{"_CPPUNWIND", "1"}); - CompilerOptionsBuilder compilerOptionsBuilder(t.projectPart, UseSystemHeader::No, + t.toolchainType = Constants::MSVC_TOOLCHAIN_TYPEID; + t.toolchainMacros.append(Macro{"_CPPUNWIND", "1"}); + CompilerOptionsBuilder compilerOptionsBuilder(t.finalize(), UseSystemHeader::No, UseTweakedHeaderPaths::Yes, UseLanguageDefines::No, UseBuildSystemWarnings::No, "dummy_version", ""); compilerOptionsBuilder.build(ProjectFile::CXXSource, UsePrecompiledHeaders::No); diff --git a/src/plugins/cpptools/cppcodemodelinspectordumper.cpp b/src/plugins/cpptools/cppcodemodelinspectordumper.cpp index e7944e0b9ac..efaf909c55f 100644 --- a/src/plugins/cpptools/cppcodemodelinspectordumper.cpp +++ b/src/plugins/cpptools/cppcodemodelinspectordumper.cpp @@ -26,6 +26,7 @@ #include "cppcodemodelinspectordumper.h" #include "cppmodelmanager.h" +#include "cpptoolsreuse.h" #include "cppworkingcopy.h" #include <app/app_version.h> @@ -501,7 +502,7 @@ static void printIncludeType(QTextStream &out, ProjectExplorer::HeaderPathType t } } -void Dumper::dumpProjectInfos( const QList<ProjectInfo> &projectInfos) +void Dumper::dumpProjectInfos(const QList<ProjectInfo::Ptr> &projectInfos) { const QByteArray i1 = indent(1); const QByteArray i2 = indent(2); @@ -509,18 +510,18 @@ void Dumper::dumpProjectInfos( const QList<ProjectInfo> &projectInfos) const QByteArray i4 = indent(4); m_out << "Projects loaded: " << projectInfos.size() << "{{{1\n"; - foreach (const ProjectInfo &info, projectInfos) { - const QPointer<ProjectExplorer::Project> project = info.project(); - m_out << i1 << "Project " << project->displayName() - << " (" << project->projectFilePath().toUserOutput() << "){{{2\n"; + foreach (const ProjectInfo::Ptr &info, projectInfos) { + m_out << i1 << "Project " << info->projectName() + << " (" << info->projectFilePath().toUserOutput() << "){{{2\n"; - const QVector<ProjectPart::Ptr> projectParts = info.projectParts(); + const QVector<ProjectPart::Ptr> projectParts = info->projectParts(); foreach (const ProjectPart::Ptr &part, projectParts) { QString projectName = QLatin1String("<None>"); - QString projectFilePath = QLatin1String("<None>"); - if (ProjectExplorer::Project *project = part->project) { - projectName = project->displayName(); - projectFilePath = project->projectFilePath().toUserOutput(); + QString projectFilePath = "<None>"; + if (part->hasProject()) { + projectFilePath = part->topLevelProject.toUserOutput(); + if (const ProjectExplorer::Project * const project = projectForProjectPart(*part)) + projectName = project->displayName(); } if (!part->projectConfigFile.isEmpty()) m_out << i3 << "Project Config File: " << part->projectConfigFile << "\n"; diff --git a/src/plugins/cpptools/cppcodemodelinspectordumper.h b/src/plugins/cpptools/cppcodemodelinspectordumper.h index c7769315c17..ef48abbfd55 100644 --- a/src/plugins/cpptools/cppcodemodelinspectordumper.h +++ b/src/plugins/cpptools/cppcodemodelinspectordumper.h @@ -70,7 +70,7 @@ public: const QString &logFileId = QString()); ~Dumper(); - void dumpProjectInfos(const QList<CppTools::ProjectInfo> &projectInfos); + void dumpProjectInfos(const QList<CppTools::ProjectInfo::Ptr> &projectInfos); void dumpSnapshot(const CPlusPlus::Snapshot &snapshot, const QString &title, bool isGlobalSnapshot = false); diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index 8d58f429b98..920e2353b01 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -153,7 +153,7 @@ public: // Project integration mutable QMutex m_projectMutex; - QMap<ProjectExplorer::Project *, ProjectInfo> m_projectToProjectsInfo; + QMap<ProjectExplorer::Project *, ProjectInfo::Ptr> m_projectToProjectsInfo; QHash<ProjectExplorer::Project *, bool> m_projectToIndexerCanceled; QMap<Utils::FilePath, QList<ProjectPart::Ptr> > m_fileToProjectParts; QMap<QString, ProjectPart::Ptr> m_projectPartIdToProjectProjectPart; @@ -748,8 +748,8 @@ void CppModelManager::ensureUpdated() QStringList CppModelManager::internalProjectFiles() const { QStringList files; - for (const ProjectInfo &pinfo : qAsConst(d->m_projectToProjectsInfo)) { - foreach (const ProjectPart::Ptr &part, pinfo.projectParts()) { + for (const ProjectInfo::Ptr &pinfo : qAsConst(d->m_projectToProjectsInfo)) { + foreach (const ProjectPart::Ptr &part, pinfo->projectParts()) { foreach (const ProjectFile &file, part->files) files += file.path; } @@ -761,8 +761,8 @@ QStringList CppModelManager::internalProjectFiles() const ProjectExplorer::HeaderPaths CppModelManager::internalHeaderPaths() const { ProjectExplorer::HeaderPaths headerPaths; - for (const ProjectInfo &pinfo : qAsConst(d->m_projectToProjectsInfo)) { - foreach (const ProjectPart::Ptr &part, pinfo.projectParts()) { + for (const ProjectInfo::Ptr &pinfo : qAsConst(d->m_projectToProjectsInfo)) { + foreach (const ProjectPart::Ptr &part, pinfo->projectParts()) { foreach (const ProjectExplorer::HeaderPath &path, part->headerPaths) { ProjectExplorer::HeaderPath hp(QDir::cleanPath(path.path), path.type); if (!headerPaths.contains(hp)) @@ -789,8 +789,8 @@ ProjectExplorer::Macros CppModelManager::internalDefinedMacros() const { ProjectExplorer::Macros macros; QSet<ProjectExplorer::Macro> alreadyIn; - for (const ProjectInfo &pinfo : qAsConst(d->m_projectToProjectsInfo)) { - for (const ProjectPart::Ptr &part : pinfo.projectParts()) { + for (const ProjectInfo::Ptr &pinfo : qAsConst(d->m_projectToProjectsInfo)) { + for (const ProjectPart::Ptr &part : pinfo->projectParts()) { addUnique(part->toolChainMacros, macros, alreadyIn); addUnique(part->projectMacros, macros, alreadyIn); } @@ -972,24 +972,21 @@ QFuture<void> CppModelManager::updateSourceFiles(const QSet<QString> &sourceFile return d->m_internalIndexingSupport->refreshSourceFiles(filteredFiles, mode); } -QList<ProjectInfo> CppModelManager::projectInfos() const +QList<ProjectInfo::Ptr> CppModelManager::projectInfos() const { QMutexLocker locker(&d->m_projectMutex); return d->m_projectToProjectsInfo.values(); } -ProjectInfo CppModelManager::projectInfo(ProjectExplorer::Project *project) const +ProjectInfo::Ptr CppModelManager::projectInfo(ProjectExplorer::Project *project) const { QMutexLocker locker(&d->m_projectMutex); - return d->m_projectToProjectsInfo.value(project, ProjectInfo()); + return d->m_projectToProjectsInfo.value(project); } /// \brief Remove all files and their includes (recursively) of given ProjectInfo from the snapshot. void CppModelManager::removeProjectInfoFilesAndIncludesFromSnapshot(const ProjectInfo &projectInfo) { - if (!projectInfo.isValid()) - return; - QMutexLocker snapshotLocker(&d->m_snapshotMutex); foreach (const ProjectPart::Ptr &projectPart, projectInfo.projectParts()) { foreach (const ProjectFile &cxxFile, projectPart->files) { @@ -1089,8 +1086,8 @@ void CppModelManager::recalculateProjectPartMappings() { d->m_projectPartIdToProjectProjectPart.clear(); d->m_fileToProjectParts.clear(); - foreach (const ProjectInfo &projectInfo, d->m_projectToProjectsInfo) { - foreach (const ProjectPart::Ptr &projectPart, projectInfo.projectParts()) { + foreach (const ProjectInfo::Ptr &projectInfo, d->m_projectToProjectsInfo) { + foreach (const ProjectPart::Ptr &projectPart, projectInfo->projectParts()) { d->m_projectPartIdToProjectProjectPart[projectPart->id()] = projectPart; foreach (const ProjectFile &cxxFile, projectPart->files) d->m_fileToProjectParts[Utils::FilePath::fromString(cxxFile.path)].append( @@ -1152,37 +1149,37 @@ void CppModelManager::updateCppEditorDocuments(bool projectsUpdated) const } } -QFuture<void> CppModelManager::updateProjectInfo(const ProjectInfo &newProjectInfo, +QFuture<void> CppModelManager::updateProjectInfo(const ProjectInfo::Ptr &newProjectInfo, const QSet<QString> &additionalFiles) { - if (!newProjectInfo.isValid()) - return QFuture<void>(); - - ProjectInfo theNewProjectInfo = newProjectInfo; - theNewProjectInfo.finish(); + if (!newProjectInfo) + return {}; QSet<QString> filesToReindex; QStringList removedProjectParts; bool filesRemoved = false; - ProjectExplorer::Project *project = theNewProjectInfo.project().data(); + + ProjectExplorer::Project * const project = projectForProjectInfo(*newProjectInfo); + if (!project) + return {}; { // Only hold the mutex for a limited scope, so the dumping afterwards does not deadlock. QMutexLocker projectLocker(&d->m_projectMutex); - const QSet<QString> newSourceFiles = theNewProjectInfo.sourceFiles(); + const QSet<QString> newSourceFiles = newProjectInfo->sourceFiles(); // Check if we can avoid a full reindexing - ProjectInfo oldProjectInfo = d->m_projectToProjectsInfo.value(project); + const ProjectInfo::Ptr oldProjectInfo = d->m_projectToProjectsInfo.value(project); const bool previousIndexerCanceled = d->m_projectToIndexerCanceled.value(project, false); - if (!previousIndexerCanceled && oldProjectInfo.isValid()) { - ProjectInfoComparer comparer(oldProjectInfo, theNewProjectInfo); + if (!previousIndexerCanceled && oldProjectInfo) { + ProjectInfoComparer comparer(*oldProjectInfo, *newProjectInfo); if (comparer.configurationOrFilesChanged()) { d->m_dirty = true; // If the project configuration changed, do a full reindexing if (comparer.configurationChanged()) { - removeProjectInfoFilesAndIncludesFromSnapshot(oldProjectInfo); + removeProjectInfoFilesAndIncludesFromSnapshot(*oldProjectInfo); filesToReindex.unite(newSourceFiles); // The "configuration file" includes all defines and therefore should be updated @@ -1218,7 +1215,7 @@ QFuture<void> CppModelManager::updateProjectInfo(const ProjectInfo &newProjectIn } // Update Project/ProjectInfo and File/ProjectPart table - d->m_projectToProjectsInfo.insert(project, theNewProjectInfo); + d->m_projectToProjectsInfo.insert(project, newProjectInfo); recalculateProjectPartMappings(); } // Mutex scope @@ -1236,7 +1233,7 @@ QFuture<void> CppModelManager::updateProjectInfo(const ProjectInfo &newProjectIn emit projectPartsRemoved(removedProjectParts); // Announce added project parts - emit projectPartsUpdated(theNewProjectInfo.project().data()); + emit projectPartsUpdated(project); // Ideally, we would update all the editor documents that depend on the 'filesToReindex'. // However, on e.g. a session restore first the editor documents are created and then the @@ -1531,18 +1528,16 @@ void CppModelManager::onCoreAboutToClose() void CppModelManager::setupFallbackProjectPart() { - ProjectPart::Ptr part(new ProjectPart); - - part->projectMacros = definedMacros(); - part->headerPaths = headerPaths(); + ToolChainInfo tcInfo; + RawProjectPart rpp; + rpp.setMacros(definedMacros()); + rpp.setHeaderPaths(headerPaths()); + rpp.setQtVersion(Utils::QtVersion::Qt5); // Do not activate ObjectiveCExtensions since this will lead to the // "objective-c++" language option for a project-less *.cpp file. - part->languageExtensions = Utils::LanguageExtension::All; - part->languageExtensions &= ~Utils::LanguageExtensions( - Utils::LanguageExtension::ObjectiveC); - - part->qtVersion = Utils::QtVersion::Qt5; + Utils::LanguageExtensions langExtensions = Utils::LanguageExtension::All; + langExtensions &= ~Utils::LanguageExtensions(Utils::LanguageExtension::ObjectiveC); // TODO: Use different fallback toolchain for different kinds of files? const Kit * const defaultKit = KitManager::isLoaded() ? KitManager::defaultKit() : nullptr; @@ -1553,15 +1548,17 @@ void CppModelManager::setupFallbackProjectPart() if (sysroot.isEmpty()) sysroot = Utils::FilePath::fromString(defaultTc->sysRoot()); Utils::Environment env = defaultKit->buildEnvironment(); - ToolChainInfo tcInfo(defaultTc, sysroot.toString(), env); - part->setupToolchainProperties(tcInfo, {}); - if (part->language == Language::C) - part->languageVersion = Utils::LanguageVersion::LatestC; - else - part->languageVersion = Utils::LanguageVersion::LatestCxx; + tcInfo = ToolChainInfo(defaultTc, sysroot.toString(), env); + const auto macroInspectionWrapper = [runner = tcInfo.macroInspectionRunner]( + const QStringList &flags) { + ToolChain::MacroInspectionReport report = runner(flags); + report.languageVersion = Utils::LanguageVersion::LatestCxx; + return report; + }; + tcInfo.macroInspectionRunner = macroInspectionWrapper; } - part->updateLanguageFeatures(); + const auto part = ProjectPart::create({}, rpp, {}, {}, {}, langExtensions, {}, tcInfo); QMutexLocker locker(&d->m_fallbackProjectPartMutex); d->m_fallbackProjectPart = part; } diff --git a/src/plugins/cpptools/cppmodelmanager.h b/src/plugins/cpptools/cppmodelmanager.h index bc7f345ea1f..f2106fed663 100644 --- a/src/plugins/cpptools/cppmodelmanager.h +++ b/src/plugins/cpptools/cppmodelmanager.h @@ -114,9 +114,9 @@ public: QByteArray codeModelConfiguration() const; CppLocatorData *locatorData() const; - QList<ProjectInfo> projectInfos() const; - ProjectInfo projectInfo(ProjectExplorer::Project *project) const; - QFuture<void> updateProjectInfo(const ProjectInfo &newProjectInfo, + QList<ProjectInfo::Ptr> projectInfos() const; + ProjectInfo::Ptr projectInfo(ProjectExplorer::Project *project) const; + QFuture<void> updateProjectInfo(const ProjectInfo::Ptr &newProjectInfo, const QSet<QString> &additionalFiles = {}); /// \return The project part with the given project file diff --git a/src/plugins/cpptools/cppmodelmanager_test.cpp b/src/plugins/cpptools/cppmodelmanager_test.cpp index 8e2700c2a23..66fbbcc57d3 100644 --- a/src/plugins/cpptools/cppmodelmanager_test.cpp +++ b/src/plugins/cpptools/cppmodelmanager_test.cpp @@ -104,20 +104,20 @@ public: foreach (const QString &file, files) projectFiles << projectDir.file(file); - Project *project = modelManagerTestHelper->createProject(name); - projectInfo = ProjectInfo(project); - - ProjectPart::Ptr part(new ProjectPart); - part->qtVersion = Utils::QtVersion::Qt5; - foreach (const QString &file, projectFiles) { - ProjectFile projectFile(file, ProjectFile::classify(file)); - part->files.append(projectFile); - } - projectInfo.appendProjectPart(part); + RawProjectPart rpp; + rpp.setQtVersion(Utils::QtVersion::Qt5); + const ProjectFiles rppFiles = Utils::transform<ProjectFiles>(projectFiles, + [](const QString &file) { return ProjectFile(file, ProjectFile::classify(file)); }); + const auto project = modelManagerTestHelper->createProject( + name, Utils::FilePath::fromString(dir).pathAppended(name + ".pro")); + + const auto part = ProjectPart::create(project->projectFilePath(), rpp, {}, rppFiles); + projectInfo = ProjectInfo::create(ProjectUpdateInfo(project, KitInfo(nullptr), {}, {}), + {part}); } ModelManagerTestHelper *modelManagerTestHelper; - ProjectInfo projectInfo; + ProjectInfo::Ptr projectInfo; QStringList projectFiles; }; @@ -180,15 +180,16 @@ void CppToolsPlugin::test_modelmanager_paths_are_clean() const MyTestDataDir testDataDir(_("testdata")); - Project *project = helper.createProject(_("test_modelmanager_paths_are_clean")); - ProjectInfo pi = ProjectInfo(project); - - ProjectPart::Ptr part(new ProjectPart); - part->qtVersion = Utils::QtVersion::Qt5; - part->projectMacros = {ProjectExplorer::Macro("OH_BEHAVE", "-1")}; - part->headerPaths = {{testDataDir.includeDir(false), HeaderPathType::User}, - {testDataDir.frameworksDir(false), HeaderPathType::Framework}}; - pi.appendProjectPart(part); + const auto project = helper.createProject(_("test_modelmanager_paths_are_clean"), + Utils::FilePath::fromString("blubb.pro")); + RawProjectPart rpp; + rpp.setQtVersion(Utils::QtVersion::Qt5); + rpp.setMacros({ProjectExplorer::Macro("OH_BEHAVE", "-1")}); + rpp.setHeaderPaths({{testDataDir.includeDir(false), HeaderPathType::User}, + {testDataDir.frameworksDir(false), HeaderPathType::Framework}}); + const auto part = ProjectPart::create(project->projectFilePath(), rpp); + const auto pi = ProjectInfo::create(ProjectUpdateInfo(project, KitInfo(nullptr), {}, {}), + {part}); mm->updateProjectInfo(pi); @@ -209,18 +210,19 @@ void CppToolsPlugin::test_modelmanager_framework_headers() const MyTestDataDir testDataDir(_("testdata")); - Project *project = helper.createProject(_("test_modelmanager_framework_headers")); - ProjectInfo pi = ProjectInfo(project); - - ProjectPart::Ptr part(new ProjectPart); - part->qtVersion = Utils::QtVersion::Qt5; - part->projectMacros = {{"OH_BEHAVE", "-1"}}; - part->headerPaths = {{testDataDir.includeDir(false), HeaderPathType::User}, - {testDataDir.frameworksDir(false), HeaderPathType::Framework}}; + const auto project = helper.createProject(_("test_modelmanager_framework_headers"), + Utils::FilePath::fromString("blubb.pro")); + RawProjectPart rpp; + rpp.setQtVersion(Utils::QtVersion::Qt5); + rpp.setMacros({{"OH_BEHAVE", "-1"}}); + rpp.setHeaderPaths({{testDataDir.includeDir(false), HeaderPathType::User}, + {testDataDir.frameworksDir(false), HeaderPathType::Framework}}); const QString &source = testDataDir.fileFromSourcesDir( _("test_modelmanager_framework_headers.cpp")); - part->files << ProjectFile(source, ProjectFile::CXXSource); - pi.appendProjectPart(part); + const auto part = ProjectPart::create(project->projectFilePath(), rpp, {}, + {ProjectFile(source, ProjectFile::CXXSource)}); + const auto pi = ProjectInfo::create(ProjectUpdateInfo(project, KitInfo(nullptr), {}, {}), + {part}); mm->updateProjectInfo(pi).waitForFinished(); QCoreApplication::processEvents(); @@ -255,16 +257,16 @@ void CppToolsPlugin::test_modelmanager_refresh_also_includes_of_project_files() const QString testCpp(testDataDir.fileFromSourcesDir(_("test_modelmanager_refresh.cpp"))); const QString testHeader(testDataDir.fileFromSourcesDir( _("test_modelmanager_refresh.h"))); - Project *project = helper.createProject( - _("test_modelmanager_refresh_also_includes_of_project_files")); - ProjectInfo pi = ProjectInfo(project); - - ProjectPart::Ptr part(new ProjectPart); - part->qtVersion = Utils::QtVersion::Qt5; - part->projectMacros = {{"OH_BEHAVE", "-1"}}; - part->headerPaths = {{testDataDir.includeDir(false), HeaderPathType::User}}; - part->files.append(ProjectFile(testCpp, ProjectFile::CXXSource)); - pi.appendProjectPart(part); + const auto project + = helper.createProject(_("test_modelmanager_refresh_also_includes_of_project_files"), + Utils::FilePath::fromString("blubb.pro")); + RawProjectPart rpp; + rpp.setQtVersion(Utils::QtVersion::Qt5); + rpp.setMacros({{"OH_BEHAVE", "-1"}}); + rpp.setHeaderPaths({{testDataDir.includeDir(false), HeaderPathType::User}}); + auto part = ProjectPart::create(project->projectFilePath(), rpp, {}, + {ProjectFile(testCpp, ProjectFile::CXXSource)}); + auto pi = ProjectInfo::create(ProjectUpdateInfo(project, KitInfo(nullptr), {}, {}), {part}); QSet<QString> refreshedFiles = helper.updateProjectInfo(pi); QCOMPARE(refreshedFiles.size(), 1); @@ -279,9 +281,10 @@ void CppToolsPlugin::test_modelmanager_refresh_also_includes_of_project_files() QVERIFY(macrosInHeaderBefore.first().name() == "test_modelmanager_refresh_h"); // Introduce a define that will enable another define once the document is reparsed. - part->projectMacros = {{"TEST_DEFINE", "1"}}; - pi = ProjectInfo(project); - pi.appendProjectPart(part); + rpp.setMacros({{"TEST_DEFINE", "1"}}); + part = ProjectPart::create(project->projectFilePath(), rpp, {}, + {ProjectFile(testCpp, ProjectFile::CXXSource)}); + pi = ProjectInfo::create(ProjectUpdateInfo(project, KitInfo(nullptr), {}, {}), {part}); refreshedFiles = helper.updateProjectInfo(pi); @@ -312,15 +315,17 @@ void CppToolsPlugin::test_modelmanager_refresh_several_times() const QString testHeader2(testDataDir.file(_("header.h"))); const QString testCpp(testDataDir.file(_("source.cpp"))); - Project *project = helper.createProject(_("test_modelmanager_refresh_several_times")); - ProjectInfo pi = ProjectInfo(project); - - ProjectPart::Ptr part(new ProjectPart); - part->qtVersion = Utils::QtVersion::Qt5; - part->files.append(ProjectFile(testHeader1, ProjectFile::CXXHeader)); - part->files.append(ProjectFile(testHeader2, ProjectFile::CXXHeader)); - part->files.append(ProjectFile(testCpp, ProjectFile::CXXSource)); - pi.appendProjectPart(part); + const auto project = helper.createProject(_("test_modelmanager_refresh_several_times"), + Utils::FilePath::fromString("blubb.pro")); + RawProjectPart rpp; + rpp.setQtVersion(Utils::QtVersion::Qt5); + const ProjectFiles files = { + ProjectFile(testHeader1, ProjectFile::CXXHeader), + ProjectFile(testHeader2, ProjectFile::CXXHeader), + ProjectFile(testCpp, ProjectFile::CXXSource) + }; + const auto part = ProjectPart::create(project->projectFilePath(), rpp, {}, files); + auto pi = ProjectInfo::create(ProjectUpdateInfo(project, KitInfo(nullptr), {}, {}), {part}); mm->updateProjectInfo(pi); CPlusPlus::Snapshot snapshot; @@ -329,16 +334,11 @@ void CppToolsPlugin::test_modelmanager_refresh_several_times() ProjectExplorer::Macros macros = {{"FIRST_DEFINE"}}; for (int i = 0; i < 2; ++i) { - pi = ProjectInfo(project); - ProjectPart::Ptr part(new ProjectPart); // Simulate project configuration change by having different defines each time. macros += {"ANOTHER_DEFINE"}; - part->projectMacros = macros; - part->qtVersion = Utils::QtVersion::Qt5; - part->files.append(ProjectFile(testHeader1, ProjectFile::CXXHeader)); - part->files.append(ProjectFile(testHeader2, ProjectFile::CXXHeader)); - part->files.append(ProjectFile(testCpp, ProjectFile::CXXSource)); - pi.appendProjectPart(part); + rpp.setMacros(macros); + const auto part = ProjectPart::create(project->projectFilePath(), rpp, {}, files); + pi = ProjectInfo::create({project, KitInfo(nullptr), {}, {}}, {part}); refreshedFiles = helper.updateProjectInfo(pi); QCOMPARE(refreshedFiles.size(), 3); @@ -374,13 +374,13 @@ void CppToolsPlugin::test_modelmanager_refresh_test_for_changes() const MyTestDataDir testDataDir(_("testdata_refresh")); const QString testCpp(testDataDir.file(_("source.cpp"))); - Project *project = helper.createProject(_("test_modelmanager_refresh_2")); - ProjectInfo pi = ProjectInfo(project); - - ProjectPart::Ptr part(new ProjectPart); - part->qtVersion = Utils::QtVersion::Qt5; - part->files.append(ProjectFile(testCpp, ProjectFile::CXXSource)); - pi.appendProjectPart(part); + const auto project = helper.createProject(_("test_modelmanager_refresh_2"), + Utils::FilePath::fromString("blubb.pro")); + RawProjectPart rpp; + rpp.setQtVersion(Utils::QtVersion::Qt5); + const auto part = ProjectPart::create(project->projectFilePath(), rpp, {}, + {ProjectFile(testCpp, ProjectFile::CXXSource)}); + const auto pi = ProjectInfo::create({project, KitInfo(nullptr), {}, {}}, {part}); // Reindexing triggers a reparsing thread helper.resetRefreshedSourceFiles(); @@ -409,14 +409,13 @@ void CppToolsPlugin::test_modelmanager_refresh_added_and_purge_removed() const QString testHeader2(testDataDir.file(_("defines.h"))); const QString testCpp(testDataDir.file(_("source.cpp"))); - Project *project = helper.createProject(_("test_modelmanager_refresh_3")); - ProjectInfo pi = ProjectInfo(project); - - ProjectPart::Ptr part(new ProjectPart); - part->qtVersion = Utils::QtVersion::Qt5; - part->files.append(ProjectFile(testCpp, ProjectFile::CXXSource)); - part->files.append(ProjectFile(testHeader1, ProjectFile::CXXHeader)); - pi.appendProjectPart(part); + const auto project = helper.createProject(_("test_modelmanager_refresh_3"), + Utils::FilePath::fromString("blubb.pro")); + RawProjectPart rpp; + rpp.setQtVersion(Utils::QtVersion::Qt5); + const auto part = ProjectPart::create(project->projectFilePath(), rpp, {}, + {{testCpp, ProjectFile::CXXSource}, {testHeader1, ProjectFile::CXXHeader}}); + auto pi = ProjectInfo::create({project, KitInfo(nullptr), {}, {}}, {part}); CPlusPlus::Snapshot snapshot; QSet<QString> refreshedFiles; @@ -432,12 +431,9 @@ void CppToolsPlugin::test_modelmanager_refresh_added_and_purge_removed() QVERIFY(snapshot.contains(testCpp)); // Now add testHeader2 and remove testHeader1 - pi = ProjectInfo(project); - ProjectPart::Ptr newPart(new ProjectPart); - newPart->qtVersion = Utils::QtVersion::Qt5; - newPart->files.append(ProjectFile(testCpp, ProjectFile::CXXSource)); - newPart->files.append(ProjectFile(testHeader2, ProjectFile::CXXHeader)); - pi.appendProjectPart(newPart); + const auto newPart = ProjectPart::create(project->projectFilePath(), rpp, {}, + {{testCpp, ProjectFile::CXXSource}, {testHeader2, ProjectFile::CXXHeader}}); + pi = ProjectInfo::create({project, KitInfo(nullptr), {}, {}}, {newPart}); refreshedFiles = helper.updateProjectInfo(pi); @@ -469,15 +465,15 @@ void CppToolsPlugin::test_modelmanager_refresh_timeStampModified_if_sourcefiles_ ModelManagerTestHelper helper; CppModelManager *mm = CppModelManager::instance(); - Project *project = helper.createProject(_("test_modelmanager_refresh_timeStampModified")); - ProjectInfo pi = ProjectInfo(project); - - ProjectPart::Ptr part(new ProjectPart); - part->qtVersion = Utils::QtVersion::Qt5; - foreach (const QString &file, initialProjectFiles) - part->files.append(ProjectFile(file, ProjectFile::CXXSource)); - pi = ProjectInfo(project); - pi.appendProjectPart(part); + const auto project = helper.createProject(_("test_modelmanager_refresh_timeStampModified"), + Utils::FilePath::fromString("blubb.pro")); + RawProjectPart rpp; + rpp.setQtVersion(Utils::QtVersion::Qt5); + auto files = Utils::transform<ProjectFiles>(initialProjectFiles, [](const QString &f) { + return ProjectFile(f, ProjectFile::CXXSource); + }); + auto part = ProjectPart::create(project->projectFilePath(), rpp, {}, files); + auto pi = ProjectInfo::create({project, KitInfo(nullptr), {}, {}}, {part}); Document::Ptr document; CPlusPlus::Snapshot snapshot; @@ -506,11 +502,11 @@ void CppToolsPlugin::test_modelmanager_refresh_timeStampModified_if_sourcefiles_ QVERIFY(fileChangerAndRestorer.writeContents(newFileContentes)); // Add or remove source file. The configuration stays the same. - part->files.clear(); - foreach (const QString &file, finalProjectFiles) - part->files.append(ProjectFile(file, ProjectFile::CXXSource)); - pi = ProjectInfo(project); - pi.appendProjectPart(part); + files = Utils::transform<ProjectFiles>(finalProjectFiles, [](const QString &f) { + return ProjectFile(f, ProjectFile::CXXSource); + }); + part = ProjectPart::create(project->projectFilePath(), rpp, {}, files); + pi = ProjectInfo::create({project, KitInfo(nullptr), {}, {}}, {part}); refreshedFiles = helper.updateProjectInfo(pi); @@ -603,8 +599,7 @@ void CppToolsPlugin::test_modelmanager_extraeditorsupport_uiFiles() const QString projectFile = temporaryDir.absolutePath("testdata_guiproject1.pro"); ProjectOpenerAndCloser projects; - ProjectInfo projectInfo = projects.open(projectFile, /*configureAsExampleProject=*/ true); - QVERIFY(projectInfo.isValid()); + QVERIFY(projects.open(projectFile, /*configureAsExampleProject=*/ true)); // Check working copy. // An AbstractEditorSupport object should have been added for the ui_* file. @@ -745,28 +740,26 @@ void CppToolsPlugin::test_modelmanager_defines_per_project() CppModelManager *mm = CppModelManager::instance(); - Project *project = helper.createProject(_("test_modelmanager_defines_per_project")); - - ProjectPart::Ptr part1(new ProjectPart); - part1->projectFile = QLatin1String("project1.projectfile"); - part1->files.append(ProjectFile(main1File, ProjectFile::CXXSource)); - part1->files.append(ProjectFile(header, ProjectFile::CXXHeader)); - part1->qtVersion = Utils::QtVersion::None; - part1->projectMacros = {{"SUB1"}}; - part1->headerPaths = {{testDataDirectory.includeDir(false), HeaderPathType::User}}; - - ProjectPart::Ptr part2(new ProjectPart); - part2->projectFile = QLatin1String("project1.projectfile"); - part2->files.append(ProjectFile(main2File, ProjectFile::CXXSource)); - part2->files.append(ProjectFile(header, ProjectFile::CXXHeader)); - part2->qtVersion = Utils::QtVersion::None; - part2->projectMacros = {{"SUB2"}}; - part2->headerPaths = {{testDataDirectory.includeDir(false), HeaderPathType::User}}; - - ProjectInfo pi = ProjectInfo(project); - pi.appendProjectPart(part1); - pi.appendProjectPart(part2); - + const auto project = helper.createProject(_("test_modelmanager_defines_per_project"), + Utils::FilePath::fromString("blubb.pro")); + + RawProjectPart rpp1; + rpp1.setProjectFileLocation("project1.projectfile"); + rpp1.setQtVersion(Utils::QtVersion::None); + rpp1.setMacros({{"SUB1"}}); + rpp1.setHeaderPaths({{testDataDirectory.includeDir(false), HeaderPathType::User}}); + const auto part1 = ProjectPart::create(project->projectFilePath(), rpp1, {}, + {{main1File, ProjectFile::CXXSource}, {header, ProjectFile::CXXHeader}}); + + RawProjectPart rpp2; + rpp2.setProjectFileLocation("project1.projectfile"); + rpp2.setQtVersion(Utils::QtVersion::None); + rpp2.setMacros({{"SUB2"}}); + rpp2.setHeaderPaths({{testDataDirectory.includeDir(false), HeaderPathType::User}}); + const auto part2 = ProjectPart::create(project->projectFilePath(), rpp2, {}, + {{main2File, ProjectFile::CXXSource}, {header, ProjectFile::CXXHeader}}); + + const auto pi = ProjectInfo::create({project, KitInfo(nullptr), {}, {}}, {part1, part2}); helper.updateProjectInfo(pi); QCOMPARE(mm->snapshot().size(), 4); @@ -809,29 +802,26 @@ void CppToolsPlugin::test_modelmanager_precompiled_headers() CppModelManager *mm = CppModelManager::instance(); - Project *project = helper.createProject(_("test_modelmanager_defines_per_project_pch")); - - ProjectPart::Ptr part1(new ProjectPart); - part1->projectFile = QLatin1String("project1.projectfile"); - part1->files.append(ProjectFile(main1File, ProjectFile::CXXSource)); - part1->files.append(ProjectFile(header, ProjectFile::CXXHeader)); - part1->qtVersion = Utils::QtVersion::None; - part1->precompiledHeaders.append(pch1File); - part1->headerPaths = {{testDataDirectory.includeDir(false), HeaderPathType::User}}; - part1->updateLanguageFeatures(); - - ProjectPart::Ptr part2(new ProjectPart); - part2->projectFile = QLatin1String("project2.projectfile"); - part2->files.append(ProjectFile(main2File, ProjectFile::CXXSource)); - part2->files.append(ProjectFile(header, ProjectFile::CXXHeader)); - part2->qtVersion = Utils::QtVersion::None; - part2->precompiledHeaders.append(pch2File); - part2->headerPaths = {{testDataDirectory.includeDir(false), HeaderPathType::User}}; - part2->updateLanguageFeatures(); - - ProjectInfo pi = ProjectInfo(project); - pi.appendProjectPart(part1); - pi.appendProjectPart(part2); + const auto project = helper.createProject(_("test_modelmanager_defines_per_project_pch"), + Utils::FilePath::fromString("blubb.pro")); + + RawProjectPart rpp1; + rpp1.setProjectFileLocation("project1.projectfile"); + rpp1.setQtVersion(Utils::QtVersion::None); + rpp1.setPreCompiledHeaders({pch1File}); + rpp1.setHeaderPaths({{testDataDirectory.includeDir(false), HeaderPathType::User}}); + const auto part1 = ProjectPart::create(project->projectFilePath(), rpp1, {}, + {{main1File, ProjectFile::CXXSource}, {header, ProjectFile::CXXHeader}}); + + RawProjectPart rpp2; + rpp2.setProjectFileLocation("project2.projectfile"); + rpp2.setQtVersion(Utils::QtVersion::None); + rpp2.setPreCompiledHeaders({pch2File}); + rpp2.setHeaderPaths({{testDataDirectory.includeDir(false), HeaderPathType::User}}); + const auto part2 = ProjectPart::create(project->projectFilePath(), rpp2, {}, + {{main2File, ProjectFile::CXXSource}, {header, ProjectFile::CXXHeader}}); + + const auto pi = ProjectInfo::create({project, KitInfo(nullptr), {}, {}}, {part1, part2}); helper.updateProjectInfo(pi); QCOMPARE(mm->snapshot().size(), 4); @@ -891,24 +881,22 @@ void CppToolsPlugin::test_modelmanager_defines_per_editor() CppModelManager *mm = CppModelManager::instance(); - Project *project = helper.createProject(_("test_modelmanager_defines_per_editor")); - - ProjectPart::Ptr part1(new ProjectPart); - part1->files.append(ProjectFile(main1File, ProjectFile::CXXSource)); - part1->files.append(ProjectFile(header, ProjectFile::CXXHeader)); - part1->qtVersion = Utils::QtVersion::None; - part1->headerPaths = {{testDataDirectory.includeDir(false), HeaderPathType::User}}; + const auto project = helper.createProject(_("test_modelmanager_defines_per_editor"), + Utils::FilePath::fromString("blubb.pro")); - ProjectPart::Ptr part2(new ProjectPart); - part2->files.append(ProjectFile(main2File, ProjectFile::CXXSource)); - part2->files.append(ProjectFile(header, ProjectFile::CXXHeader)); - part2->qtVersion = Utils::QtVersion::None; - part2->headerPaths = {{testDataDirectory.includeDir(false), HeaderPathType::User}}; + RawProjectPart rpp1; + rpp1.setQtVersion(Utils::QtVersion::None); + rpp1.setHeaderPaths({{testDataDirectory.includeDir(false), HeaderPathType::User}}); + const auto part1 = ProjectPart::create(project->projectFilePath(), rpp1, {}, + {{main1File, ProjectFile::CXXSource}, {header, ProjectFile::CXXHeader}}); - ProjectInfo pi = ProjectInfo(project); - pi.appendProjectPart(part1); - pi.appendProjectPart(part2); + RawProjectPart rpp2; + rpp2.setQtVersion(Utils::QtVersion::None); + rpp2.setHeaderPaths({{testDataDirectory.includeDir(false), HeaderPathType::User}}); + const auto part2 = ProjectPart::create(project->projectFilePath(), rpp2, {}, + {{main2File, ProjectFile::CXXSource}, {header, ProjectFile::CXXHeader}}); + const auto pi = ProjectInfo::create({project, KitInfo(nullptr), {}, {}}, {part1, part2}); helper.updateProjectInfo(pi); QCOMPARE(mm->snapshot().size(), 4); @@ -960,7 +948,7 @@ void CppToolsPlugin::test_modelmanager_updateEditorsAfterProjectUpdate() QCOMPARE(Core::DocumentModel::openedDocuments().size(), 1); QVERIFY(TestCase::waitForProcessedEditorDocument(fileA)); ProjectPart::Ptr documentAProjectPart = projectPartOfEditorDocument(fileA); - QVERIFY(!documentAProjectPart->project); + QVERIFY(!documentAProjectPart->hasProject()); // Open file B in editor Core::IEditor *editorB = Core::EditorManager::openEditor(fileB); @@ -969,34 +957,32 @@ void CppToolsPlugin::test_modelmanager_updateEditorsAfterProjectUpdate() QCOMPARE(Core::DocumentModel::openedDocuments().size(), 2); QVERIFY(TestCase::waitForProcessedEditorDocument(fileB)); ProjectPart::Ptr documentBProjectPart = projectPartOfEditorDocument(fileB); - QVERIFY(!documentBProjectPart->project); + QVERIFY(!documentBProjectPart->hasProject()); // Switch back to document A Core::EditorManager::activateEditor(editorA); // Open/update related project - Project *project = helper.createProject(_("test_modelmanager_updateEditorsAfterProjectUpdate")); - - ProjectPart::Ptr part(new ProjectPart); - part->project = project; - part->files.append(ProjectFile(fileA, ProjectFile::CXXSource)); - part->files.append(ProjectFile(fileB, ProjectFile::CXXSource)); - part->qtVersion = Utils::QtVersion::None; - - ProjectInfo pi = ProjectInfo(project); - pi.appendProjectPart(part); + const auto project + = helper.createProject(_("test_modelmanager_updateEditorsAfterProjectUpdate"), + Utils::FilePath::fromString("blubb.pro")); + RawProjectPart rpp; + rpp.setQtVersion(Utils::QtVersion::None); + const auto part = ProjectPart::create(project->projectFilePath(), rpp, {}, + {{fileA, ProjectFile::CXXSource}, {fileB, ProjectFile::CXXSource}}); + const auto pi = ProjectInfo::create({project, KitInfo(nullptr), {}, {}}, {part}); helper.updateProjectInfo(pi); // ... and check for updated editor document A QVERIFY(TestCase::waitForProcessedEditorDocument(fileA)); documentAProjectPart = projectPartOfEditorDocument(fileA); - QCOMPARE(documentAProjectPart->project, project); + QCOMPARE(documentAProjectPart->topLevelProject, pi->projectFilePath()); // Switch back to document B and check if that's updated, too Core::EditorManager::activateEditor(editorB); QVERIFY(TestCase::waitForProcessedEditorDocument(fileB)); documentBProjectPart = projectPartOfEditorDocument(fileB); - QCOMPARE(documentBProjectPart->project, project); + QCOMPARE(documentBProjectPart->topLevelProject, pi->projectFilePath()); } void CppToolsPlugin::test_modelmanager_renameIncludes() diff --git a/src/plugins/cpptools/cppprojectinfogenerator.cpp b/src/plugins/cpptools/cppprojectinfogenerator.cpp index cf3152163f7..f81524f1028 100644 --- a/src/plugins/cpptools/cppprojectinfogenerator.cpp +++ b/src/plugins/cpptools/cppprojectinfogenerator.cpp @@ -42,24 +42,23 @@ using namespace ProjectExplorer; namespace CppTools { namespace Internal { -ProjectInfoGenerator::ProjectInfoGenerator(const QFutureInterface<ProjectInfo> &futureInterface, +ProjectInfoGenerator::ProjectInfoGenerator(const QFutureInterface<ProjectInfo::Ptr> &futureInterface, const ProjectUpdateInfo &projectUpdateInfo) : m_futureInterface(futureInterface) , m_projectUpdateInfo(projectUpdateInfo) { } -ProjectInfo ProjectInfoGenerator::generate() +ProjectInfo::Ptr ProjectInfoGenerator::generate() { - ProjectInfo projectInfo(m_projectUpdateInfo.project); - + QVector<ProjectPart::Ptr> projectParts; for (const RawProjectPart &rpp : m_projectUpdateInfo.rawProjectParts) { if (m_futureInterface.isCanceled()) - return ProjectInfo(); - - for (const ProjectPart::Ptr &part : createProjectParts(rpp)) - projectInfo.appendProjectPart(part); + return {}; + for (const ProjectPart::Ptr &part : createProjectParts(rpp, m_projectUpdateInfo.projectFilePath)) + projectParts << part; } + const auto projectInfo = ProjectInfo::create(m_projectUpdateInfo, projectParts); static const auto showWarning = [](const QString &message) { QTimer::singleShot(0, TaskHub::instance(), [message] { @@ -79,40 +78,8 @@ ProjectInfo ProjectInfoGenerator::generate() return projectInfo; } -static ProjectPart::Ptr projectPartFromRawProjectPart( - const RawProjectPart &rawProjectPart, Project *project) -{ - ProjectPart::Ptr part(new ProjectPart); - part->project = project; - part->projectFile = rawProjectPart.projectFile; - part->projectConfigFile = rawProjectPart.projectConfigFile; - part->projectFileLine = rawProjectPart.projectFileLine; - part->projectFileColumn = rawProjectPart.projectFileColumn; - part->callGroupId = rawProjectPart.callGroupId; - part->buildSystemTarget = rawProjectPart.buildSystemTarget; - part->buildTargetType = rawProjectPart.buildTargetType; - part->qtVersion = rawProjectPart.qtVersion; - part->projectMacros = rawProjectPart.projectMacros; - if (!part->projectConfigFile.isEmpty()) - part->projectMacros += Macro::toMacros(ProjectPart::readProjectConfigFile(part)); - - // Prevent duplicate include paths. - std::set<QString> seenPaths; - for (const HeaderPath &p : qAsConst(rawProjectPart.headerPaths)) { - const QString cleanPath = QDir::cleanPath(p.path); - if (seenPaths.insert(cleanPath).second) - part->headerPaths << HeaderPath(cleanPath, p.type); - } - - part->precompiledHeaders = rawProjectPart.precompiledHeaders; - part->includedFiles = rawProjectPart.includedFiles; - part->selectedForBuilding = rawProjectPart.selectedForBuilding; - - return part; -} - const QVector<ProjectPart::Ptr> ProjectInfoGenerator::createProjectParts( - const RawProjectPart &rawProjectPart) + const RawProjectPart &rawProjectPart, const Utils::FilePath &projectFilePath) { using Utils::LanguageExtension; @@ -124,21 +91,18 @@ const QVector<ProjectPart::Ptr> ProjectInfoGenerator::createProjectParts( if (!cat.hasParts()) return result; - const ProjectPart::Ptr part = projectPartFromRawProjectPart(rawProjectPart, - m_projectUpdateInfo.project); - - if (m_projectUpdateInfo.cxxToolChain) { + if (m_projectUpdateInfo.cxxToolChainInfo.isValid()) { if (cat.hasCxxSources()) { - result << createProjectPart(rawProjectPart, - part, + result << createProjectPart(projectFilePath, + rawProjectPart, cat.cxxSources(), cat.partName("C++"), Language::Cxx, LanguageExtension::None); } if (cat.hasObjcxxSources()) { - result << createProjectPart(rawProjectPart, - part, + result << createProjectPart(projectFilePath, + rawProjectPart, cat.objcxxSources(), cat.partName("Obj-C++"), Language::Cxx, @@ -148,10 +112,10 @@ const QVector<ProjectPart::Ptr> ProjectInfoGenerator::createProjectParts( m_cxxToolchainMissing = true; } - if (m_projectUpdateInfo.cToolChain) { + if (m_projectUpdateInfo.cToolChainInfo.isValid()) { if (cat.hasCSources()) { - result << createProjectPart(rawProjectPart, - part, + result << createProjectPart(projectFilePath, + rawProjectPart, cat.cSources(), cat.partName("C"), Language::C, @@ -159,8 +123,8 @@ const QVector<ProjectPart::Ptr> ProjectInfoGenerator::createProjectParts( } if (cat.hasObjcSources()) { - result << createProjectPart(rawProjectPart, - part, + result << createProjectPart(projectFilePath, + rawProjectPart, cat.objcSources(), cat.partName("Obj-C"), Language::C, @@ -174,12 +138,12 @@ const QVector<ProjectPart::Ptr> ProjectInfoGenerator::createProjectParts( } ProjectPart::Ptr ProjectInfoGenerator::createProjectPart( - const RawProjectPart &rawProjectPart, - const ProjectPart::Ptr &templateProjectPart, - const ProjectFiles &projectFiles, - const QString &partName, - Language language, - Utils::LanguageExtensions languageExtensions) + const Utils::FilePath &projectFilePath, + const RawProjectPart &rawProjectPart, + const ProjectFiles &projectFiles, + const QString &partName, + Language language, + Utils::LanguageExtensions languageExtensions) { RawProjectPartFlags flags; ToolChainInfo tcInfo; @@ -193,16 +157,8 @@ ProjectPart::Ptr ProjectInfoGenerator::createProjectPart( tcInfo = m_projectUpdateInfo.cxxToolChainInfo; } - ProjectPart::Ptr part(templateProjectPart->copy()); - part->displayName = partName; - part->files = projectFiles; - part->warningFlags = flags.warningFlags; - part->language = language; - part->languageExtensions = flags.languageExtensions | languageExtensions; - part->setupToolchainProperties(tcInfo, flags.commandLineFlags); - part->updateLanguageFeatures(); - - return part; + return ProjectPart::create(projectFilePath, rawProjectPart, partName, projectFiles, + language, languageExtensions, flags, tcInfo); } } // namespace Internal diff --git a/src/plugins/cpptools/cppprojectinfogenerator.h b/src/plugins/cpptools/cppprojectinfogenerator.h index 7e97f1c5ca2..64fc60c2384 100644 --- a/src/plugins/cpptools/cppprojectinfogenerator.h +++ b/src/plugins/cpptools/cppprojectinfogenerator.h @@ -36,23 +36,22 @@ namespace Internal { class ProjectInfoGenerator { public: - ProjectInfoGenerator(const QFutureInterface<ProjectInfo> &futureInterface, + ProjectInfoGenerator(const QFutureInterface<ProjectInfo::Ptr> &futureInterface, const ProjectExplorer::ProjectUpdateInfo &projectUpdateInfo); - ProjectInfo generate(); + ProjectInfo::Ptr generate(); private: - const QVector<ProjectPart::Ptr> createProjectParts( - const ProjectExplorer::RawProjectPart &rawProjectPart); - ProjectPart::Ptr createProjectPart(const ProjectExplorer::RawProjectPart &rawProjectPart, - const ProjectPart::Ptr &templateProjectPart, + const QVector<ProjectPart::Ptr> createProjectParts(const ProjectExplorer::RawProjectPart &rawProjectPart, const Utils::FilePath &projectFilePath); + ProjectPart::Ptr createProjectPart(const Utils::FilePath &projectFilePath, + const ProjectExplorer::RawProjectPart &rawProjectPart, const ProjectFiles &projectFiles, const QString &partName, Language language, Utils::LanguageExtensions languageExtensions); private: - const QFutureInterface<ProjectInfo> m_futureInterface; + const QFutureInterface<ProjectInfo::Ptr> m_futureInterface; const ProjectExplorer::ProjectUpdateInfo &m_projectUpdateInfo; bool m_cToolchainMissing = false; bool m_cxxToolchainMissing = false; diff --git a/src/plugins/cpptools/cppprojectpartchooser.cpp b/src/plugins/cpptools/cppprojectpartchooser.cpp index 548ccbe6f25..03a540ea32f 100644 --- a/src/plugins/cpptools/cppprojectpartchooser.cpp +++ b/src/plugins/cpptools/cppprojectpartchooser.cpp @@ -102,7 +102,7 @@ private: if (!m_preferredProjectPartId.isEmpty() && projectPart.id() == m_preferredProjectPartId) thePriority += 1000; - if (projectPart.project == m_activeProject) + if (projectPart.belongsToProject(m_activeProject)) thePriority += 100; if (projectPart.selectedForBuilding) diff --git a/src/plugins/cpptools/cppprojectupdater.cpp b/src/plugins/cpptools/cppprojectupdater.cpp index f34628af51a..9b483359510 100644 --- a/src/plugins/cpptools/cppprojectupdater.cpp +++ b/src/plugins/cpptools/cppprojectupdater.cpp @@ -74,13 +74,10 @@ void CppProjectUpdater::update(const ProjectUpdateInfo &projectUpdateInfo, }); m_projectUpdateInfo = projectUpdateInfo; - // Ensure that we do not operate on a deleted toolchain. using namespace ProjectExplorer; - connect(ToolChainManager::instance(), &ToolChainManager::toolChainRemoved, - this, &CppProjectUpdater::onToolChainRemoved); // Run the project info generator in a worker thread and continue if that one is finished. - auto generateFuture = Utils::runAsync([=](QFutureInterface<ProjectInfo> &futureInterface) { + auto generateFuture = Utils::runAsync([=](QFutureInterface<ProjectInfo::Ptr> &futureInterface) { ProjectUpdateInfo fullProjectUpdateInfo = projectUpdateInfo; if (fullProjectUpdateInfo.rppGenerator) fullProjectUpdateInfo.rawProjectParts = fullProjectUpdateInfo.rppGenerator(); @@ -134,20 +131,8 @@ void CppProjectUpdater::cancel() m_futureSynchronizer.cancelAllFutures(); } -void CppProjectUpdater::onToolChainRemoved(ToolChain *t) -{ - QTC_ASSERT(t, return); - if (t == m_projectUpdateInfo.cToolChain || t == m_projectUpdateInfo.cxxToolChain) - cancel(); -} - void CppProjectUpdater::onProjectInfoGenerated() { - // From now on we do not access the toolchain anymore, so disconnect. - using namespace ProjectExplorer; - disconnect(ToolChainManager::instance(), &ToolChainManager::toolChainRemoved, - this, &CppProjectUpdater::onToolChainRemoved); - if (m_generateFutureWatcher.isCanceled() || m_generateFutureWatcher.future().resultCount() < 1) return; diff --git a/src/plugins/cpptools/cppprojectupdater.h b/src/plugins/cpptools/cppprojectupdater.h index c356ab63d19..a76122d4b4d 100644 --- a/src/plugins/cpptools/cppprojectupdater.h +++ b/src/plugins/cpptools/cppprojectupdater.h @@ -63,7 +63,6 @@ public: void cancel() override; private: - void onToolChainRemoved(ProjectExplorer::ToolChain *); void onProjectInfoGenerated(); void checkForExtraCompilersFinished(); @@ -71,7 +70,7 @@ private: ProjectExplorer::ProjectUpdateInfo m_projectUpdateInfo; QList<QPointer<ProjectExplorer::ExtraCompiler>> m_extraCompilers; - QFutureWatcher<ProjectInfo> m_generateFutureWatcher; + QFutureWatcher<ProjectInfo::Ptr> m_generateFutureWatcher; bool m_isProjectInfoGenerated = false; QSet<QFutureWatcher<void> *> m_extraCompilersFutureWatchers; std::unique_ptr<QFutureInterface<void>> m_projectUpdateFutureInterface; diff --git a/src/plugins/cpptools/cpptoolsplugin.cpp b/src/plugins/cpptools/cpptoolsplugin.cpp index 1e77501c0f4..a334846213d 100644 --- a/src/plugins/cpptools/cpptoolsplugin.cpp +++ b/src/plugins/cpptools/cpptoolsplugin.cpp @@ -469,9 +469,9 @@ QString correspondingHeaderOrSource(const QString &fileName, bool *wasHeader, Ca // Find files in other projects } else { CppModelManager *modelManager = CppModelManager::instance(); - QList<ProjectInfo> projectInfos = modelManager->projectInfos(); - foreach (const ProjectInfo &projectInfo, projectInfos) { - const ProjectExplorer::Project *project = projectInfo.project().data(); + QList<ProjectInfo::Ptr> projectInfos = modelManager->projectInfos(); + foreach (const ProjectInfo::Ptr &projectInfo, projectInfos) { + const ProjectExplorer::Project *project = projectForProjectInfo(*projectInfo); if (project == currentProject) continue; // We have already checked the current project. diff --git a/src/plugins/cpptools/cpptoolsreuse.cpp b/src/plugins/cpptools/cpptoolsreuse.cpp index 5294f1314b5..de7dbcaeeef 100644 --- a/src/plugins/cpptools/cpptoolsreuse.cpp +++ b/src/plugins/cpptools/cpptoolsreuse.cpp @@ -29,11 +29,13 @@ #include "cpprefactoringchanges.h" #include "cpptoolsconstants.h" #include "cpptoolsplugin.h" +#include "projectinfo.h" #include <coreplugin/documentmanager.h> #include <coreplugin/editormanager/editormanager.h> #include <coreplugin/idocument.h> #include <coreplugin/messagemanager.h> +#include <projectexplorer/session.h> #include <cplusplus/Overview.h> #include <cplusplus/LookupContext.h> @@ -572,4 +574,14 @@ NamespaceAST *NSCheckerVisitor::currentNamespace() return m_enteredNamespaces.empty() ? nullptr : m_enteredNamespaces.back(); } +ProjectExplorer::Project *projectForProjectPart(const ProjectPart &part) +{ + return ProjectExplorer::SessionManager::projectWithProjectFilePath(part.topLevelProject); +} + +ProjectExplorer::Project *projectForProjectInfo(const ProjectInfo &info) +{ + return ProjectExplorer::SessionManager::projectWithProjectFilePath(info.projectFilePath()); +} + } // CppTools diff --git a/src/plugins/cpptools/cpptoolsreuse.h b/src/plugins/cpptools/cpptoolsreuse.h index 02633f91eaf..1946a931761 100644 --- a/src/plugins/cpptools/cpptoolsreuse.h +++ b/src/plugins/cpptools/cpptoolsreuse.h @@ -49,6 +49,7 @@ class LookupContext; namespace CppTools { class CppRefactoringFile; +class ProjectInfo; void CPPTOOLS_EXPORT moveCursorToEndOfIdentifier(QTextCursor *tc); void CPPTOOLS_EXPORT moveCursorToStartOfIdentifier(QTextCursor *tc); @@ -83,6 +84,9 @@ UsePrecompiledHeaders CPPTOOLS_EXPORT getPchUsage(); int indexerFileSizeLimitInMb(); bool fileSizeExceedsLimit(const QFileInfo &fileInfo, int sizeLimitInMb); +ProjectExplorer::Project CPPTOOLS_EXPORT *projectForProjectInfo(const CppTools::ProjectInfo &info); +ProjectExplorer::Project CPPTOOLS_EXPORT *projectForProjectPart(const CppTools::ProjectPart &part); + class ClangDiagnosticConfigsModel; ClangDiagnosticConfigsModel CPPTOOLS_EXPORT diagnosticConfigsModel(); ClangDiagnosticConfigsModel CPPTOOLS_EXPORT diff --git a/src/plugins/cpptools/cpptoolstestcase.cpp b/src/plugins/cpptools/cpptoolstestcase.cpp index 5efe6f8affa..9f024619581 100644 --- a/src/plugins/cpptools/cpptoolstestcase.cpp +++ b/src/plugins/cpptools/cpptoolstestcase.cpp @@ -237,7 +237,7 @@ bool TestCase::waitUntilProjectIsFullyOpened(Project *project, int timeOutInMs) [project]() { return SessionManager::startupBuildSystem() && !SessionManager::startupBuildSystem()->isParsing() - && CppModelManager::instance()->projectInfo(project).isValid(); + && CppModelManager::instance()->projectInfo(project); }, timeOutInMs); } @@ -278,14 +278,14 @@ ProjectOpenerAndCloser::~ProjectOpenerAndCloser() QCoreApplication::processEvents(); } -ProjectInfo ProjectOpenerAndCloser::open(const QString &projectFile, bool configureAsExampleProject, - Kit *kit) +ProjectInfo::Ptr ProjectOpenerAndCloser::open(const QString &projectFile, + bool configureAsExampleProject, Kit *kit) { ProjectExplorerPlugin::OpenProjectResult result = ProjectExplorerPlugin::openProject(FilePath::fromString(projectFile)); if (!result) { qWarning() << result.errorMessage() << result.alreadyOpen(); - return ProjectInfo(); + return {}; } Project *project = result.project(); @@ -297,7 +297,7 @@ ProjectInfo ProjectOpenerAndCloser::open(const QString &projectFile, bool config return CppModelManager::instance()->projectInfo(project); } - return ProjectInfo(); + return {}; } TemporaryDir::TemporaryDir() diff --git a/src/plugins/cpptools/cpptoolstestcase.h b/src/plugins/cpptools/cpptoolstestcase.h index d03a1b297c6..7919f3c921d 100644 --- a/src/plugins/cpptools/cpptoolstestcase.h +++ b/src/plugins/cpptools/cpptoolstestcase.h @@ -27,6 +27,8 @@ #include "cpptools_global.h" +#include "projectinfo.h" + #include <cplusplus/CppDocument.h> #include <utils/temporarydirectory.h> @@ -52,7 +54,6 @@ class IAssistProposal; namespace CppTools { class CppModelManager; -class ProjectInfo; namespace Tests { @@ -140,7 +141,7 @@ public: ProjectOpenerAndCloser(); ~ProjectOpenerAndCloser(); // Closes opened projects - ProjectInfo open(const QString &projectFile, bool configureAsExampleProject = false, + CppTools::ProjectInfo::Ptr open(const QString &projectFile, bool configureAsExampleProject = false, ProjectExplorer::Kit *kit = nullptr); private: diff --git a/src/plugins/cpptools/modelmanagertesthelper.cpp b/src/plugins/cpptools/modelmanagertesthelper.cpp index 08d01c02e06..b80ce255647 100644 --- a/src/plugins/cpptools/modelmanagertesthelper.cpp +++ b/src/plugins/cpptools/modelmanagertesthelper.cpp @@ -29,6 +29,8 @@ #include "cppworkingcopy.h" #include "projectinfo.h" +#include <projectexplorer/session.h> + #include <QtTest> #include <cassert> @@ -36,8 +38,8 @@ using namespace CppTools::Internal; using namespace CppTools::Tests; -TestProject::TestProject(const QString &name, QObject *parent) : - ProjectExplorer::Project("x-binary/foo", Utils::FilePath()), +TestProject::TestProject(const QString &name, QObject *parent, const Utils::FilePath &filePath) : + ProjectExplorer::Project("x-binary/foo", filePath), m_name(name) { setParent(parent); @@ -75,22 +77,28 @@ ModelManagerTestHelper::~ModelManagerTestHelper() void ModelManagerTestHelper::cleanup() { CppModelManager *mm = CppModelManager::instance(); - QList<ProjectInfo> pies = mm->projectInfos(); - foreach (const ProjectInfo &pie, pies) - emit aboutToRemoveProject(pie.project().data()); + QList<ProjectInfo::Ptr> pies = mm->projectInfos(); + for (Project * const p : qAsConst(m_projects)) { + ProjectExplorer::SessionManager::removeProject(p); + emit aboutToRemoveProject(p); + } if (!pies.isEmpty()) waitForFinishedGc(); } -ModelManagerTestHelper::Project *ModelManagerTestHelper::createProject(const QString &name) +ModelManagerTestHelper::Project *ModelManagerTestHelper::createProject( + const QString &name, const Utils::FilePath &filePath) { - auto tp = new TestProject(name, this); + auto tp = new TestProject(name, this, filePath); + m_projects.push_back(tp); + ProjectExplorer::SessionManager::addProject(tp); emit projectAdded(tp); return tp; } -QSet<QString> ModelManagerTestHelper::updateProjectInfo(const CppTools::ProjectInfo &projectInfo) +QSet<QString> ModelManagerTestHelper::updateProjectInfo( + const CppTools::ProjectInfo::Ptr &projectInfo) { resetRefreshedSourceFiles(); CppModelManager::instance()->updateProjectInfo(projectInfo).waitForFinished(); diff --git a/src/plugins/cpptools/modelmanagertesthelper.h b/src/plugins/cpptools/modelmanagertesthelper.h index 9fe887006de..e5ee32cca89 100644 --- a/src/plugins/cpptools/modelmanagertesthelper.h +++ b/src/plugins/cpptools/modelmanagertesthelper.h @@ -40,7 +40,7 @@ class CPPTOOLS_EXPORT TestProject: public ProjectExplorer::Project Q_OBJECT public: - TestProject(const QString &name, QObject *parent); + TestProject(const QString &name, QObject *parent, const Utils::FilePath &filePath = {}); bool needsConfiguration() const final { return false; } @@ -61,9 +61,9 @@ public: void cleanup(); - Project *createProject(const QString &name); + Project *createProject(const QString &name, const Utils::FilePath &filePath = {}); - QSet<QString> updateProjectInfo(const ProjectInfo &projectInfo); + QSet<QString> updateProjectInfo(const ProjectInfo::Ptr &projectInfo); void resetRefreshedSourceFiles(); QSet<QString> waitForRefreshedSourceFiles(); @@ -82,6 +82,7 @@ private: bool m_refreshHappened; bool m_testOnlyForCleanedProjects; QSet<QString> m_lastRefreshedSourceFiles; + QList<Project *> m_projects; }; } // namespace Tests diff --git a/src/plugins/cpptools/projectinfo.cpp b/src/plugins/cpptools/projectinfo.cpp index a7047dc9721..2125862be43 100644 --- a/src/plugins/cpptools/projectinfo.cpp +++ b/src/plugins/cpptools/projectinfo.cpp @@ -33,19 +33,10 @@ namespace CppTools { -ProjectInfo::ProjectInfo(QPointer<ProjectExplorer::Project> project) - : m_project(project) +ProjectInfo::Ptr ProjectInfo::create(const ProjectExplorer::ProjectUpdateInfo &updateInfo, + const QVector<ProjectPart::Ptr> &projectParts) { -} - -bool ProjectInfo::isValid() const -{ - return !m_project.isNull(); -} - -QPointer<ProjectExplorer::Project> ProjectInfo::project() const -{ - return m_project; + return Ptr(new ProjectInfo(updateInfo, projectParts)); } const QVector<ProjectPart::Ptr> ProjectInfo::projectParts() const @@ -60,7 +51,9 @@ const QSet<QString> ProjectInfo::sourceFiles() const bool ProjectInfo::operator ==(const ProjectInfo &other) const { - return m_project == other.m_project + return m_projectName == other.m_projectName + && m_projectFilePath == other.m_projectFilePath + && m_buildRoot == other.m_buildRoot && m_projectParts == other.m_projectParts && m_headerPaths == other.m_headerPaths && m_sourceFiles == other.m_sourceFiles @@ -87,35 +80,46 @@ bool ProjectInfo::configurationOrFilesChanged(const ProjectInfo &other) const return configurationChanged(other) || m_sourceFiles != other.m_sourceFiles; } -void ProjectInfo::appendProjectPart(const ProjectPart::Ptr &projectPart) +static QSet<QString> getSourceFiles(const QVector<ProjectPart::Ptr> &projectParts) { - if (projectPart) - m_projectParts.append(projectPart); + QSet<QString> sourceFiles; + for (const ProjectPart::Ptr &part : projectParts) { + for (const ProjectFile &file : qAsConst(part->files)) + sourceFiles.insert(file.path); + } + return sourceFiles; } -void ProjectInfo::finish() +static ProjectExplorer::Macros getDefines(const QVector<ProjectPart::Ptr> &projectParts) { - QSet<ProjectExplorer::HeaderPath> uniqueHeaderPaths; + ProjectExplorer::Macros defines; + for (const ProjectPart::Ptr &part : projectParts) { + defines.append(part->toolChainMacros); + defines.append(part->projectMacros); + } + return defines; +} - foreach (const ProjectPart::Ptr &part, m_projectParts) { - // Update header paths - foreach (const ProjectExplorer::HeaderPath &headerPath, part->headerPaths) { - const int count = uniqueHeaderPaths.count(); +static ProjectExplorer::HeaderPaths getHeaderPaths(const QVector<ProjectPart::Ptr> &projectParts) +{ + QSet<ProjectExplorer::HeaderPath> uniqueHeaderPaths; + for (const ProjectPart::Ptr &part : projectParts) { + for (const ProjectExplorer::HeaderPath &headerPath : qAsConst(part->headerPaths)) uniqueHeaderPaths.insert(headerPath); - if (count < uniqueHeaderPaths.count()) - m_headerPaths += headerPath; - } - - // Update source files - foreach (const ProjectFile &file, part->files) - m_sourceFiles.insert(file.path); - - // Update defines - m_defines.append(part->toolChainMacros); - m_defines.append(part->projectMacros); - if (!part->projectConfigFile.isEmpty()) - m_defines += ProjectExplorer::Macro::toMacros(ProjectPart::readProjectConfigFile(part)); } + return ProjectExplorer::HeaderPaths(uniqueHeaderPaths.cbegin(), uniqueHeaderPaths.cend()); +} + +ProjectInfo::ProjectInfo(const ProjectExplorer::ProjectUpdateInfo &updateInfo, + const QVector<ProjectPart::Ptr> &projectParts) + : m_projectParts(projectParts), + m_projectName(updateInfo.projectName), + m_projectFilePath(updateInfo.projectFilePath), + m_buildRoot(updateInfo.buildRoot), + m_headerPaths(getHeaderPaths(projectParts)), + m_sourceFiles(getSourceFiles(projectParts)), + m_defines(getDefines(projectParts)) +{ } } // namespace CppTools diff --git a/src/plugins/cpptools/projectinfo.h b/src/plugins/cpptools/projectinfo.h index 347e72f477e..bf73bd71bb1 100644 --- a/src/plugins/cpptools/projectinfo.h +++ b/src/plugins/cpptools/projectinfo.h @@ -32,25 +32,29 @@ #include <projectexplorer/project.h> #include <projectexplorer/rawprojectpart.h> #include <projectexplorer/toolchain.h> +#include <utils/fileutils.h> #include <QHash> -#include <QPointer> #include <QSet> #include <QVector> +#include <memory> + namespace CppTools { class CPPTOOLS_EXPORT ProjectInfo { public: - ProjectInfo() = default; - explicit ProjectInfo(QPointer<ProjectExplorer::Project> project); - - bool isValid() const; + using Ptr = std::shared_ptr<ProjectInfo>; + static Ptr create(const ProjectExplorer::ProjectUpdateInfo &updateInfo, + const QVector<ProjectPart::Ptr> &projectParts); - QPointer<ProjectExplorer::Project> project() const; const QVector<ProjectPart::Ptr> projectParts() const; const QSet<QString> sourceFiles() const; + QString projectName() const { return m_projectName; } + Utils::FilePath projectFilePath() const { return m_projectFilePath; } + Utils::FilePath projectRoot() const { return m_projectFilePath.parentDir(); } + Utils::FilePath buildRoot() const { return m_buildRoot; } // Comparisons bool operator ==(const ProjectInfo &other) const; @@ -59,18 +63,17 @@ public: bool configurationChanged(const ProjectInfo &other) const; bool configurationOrFilesChanged(const ProjectInfo &other) const; - // Construction - void appendProjectPart(const ProjectPart::Ptr &projectPart); - void finish(); - private: - QPointer<ProjectExplorer::Project> m_project; - QVector<ProjectPart::Ptr> m_projectParts; + ProjectInfo(const ProjectExplorer::ProjectUpdateInfo &updateInfo, + const QVector<ProjectPart::Ptr> &projectParts); - // The members below are (re)calculated from the project parts with finish() - ProjectExplorer::HeaderPaths m_headerPaths; - QSet<QString> m_sourceFiles; - ProjectExplorer::Macros m_defines; + const QVector<ProjectPart::Ptr> m_projectParts; + const QString m_projectName; + const Utils::FilePath m_projectFilePath; + const Utils::FilePath m_buildRoot; + const ProjectExplorer::HeaderPaths m_headerPaths; + const QSet<QString> m_sourceFiles; + const ProjectExplorer::Macros m_defines; }; } // namespace CppTools diff --git a/src/plugins/cpptools/projectinfo_test.cpp b/src/plugins/cpptools/projectinfo_test.cpp index e371e388a61..69ba398a0ac 100644 --- a/src/plugins/cpptools/projectinfo_test.cpp +++ b/src/plugins/cpptools/projectinfo_test.cpp @@ -60,19 +60,22 @@ public: const ProjectPartInfo choose() { return chooser.choose(filePath, currentProjectPartInfo, preferredProjectPartId, - activeProject, languagePreference, projectsChanged); + projectMap.value(activeProject).get(), + languagePreference, projectsChanged); } static QList<ProjectPart::Ptr> createProjectPartsWithDifferentProjects() { QList<ProjectPart::Ptr> projectParts; - const ProjectPart::Ptr p1{new ProjectPart}; - p1->project = reinterpret_cast<Project *>(1 << 0); - projectParts.append(p1); - const ProjectPart::Ptr p2{new ProjectPart}; - p2->project = reinterpret_cast<Project *>(1 << 1); - projectParts.append(p2); + const auto p1 = std::make_shared<Project>( + QString(), Utils::FilePath::fromString("p1.pro")); + projectMap.insert(p1->projectFilePath(), p1); + projectParts.append(ProjectPart::create(p1->projectFilePath())); + const auto p2 = std::make_shared<Project>( + QString(), Utils::FilePath::fromString("p2.pro")); + projectMap.insert(p2->projectFilePath(), p2); + projectParts.append(ProjectPart::create(p2->projectFilePath())); return projectParts; } @@ -80,27 +83,34 @@ public: static QList<ProjectPart::Ptr> createCAndCxxProjectParts() { QList<ProjectPart::Ptr> projectParts; + ToolChainInfo tcInfo; // Create project part for C - const ProjectPart::Ptr cprojectpart{new ProjectPart}; - cprojectpart->languageVersion = Utils::LanguageVersion::C11; + tcInfo.macroInspectionRunner = [](const QStringList &) { + return ToolChain::MacroInspectionReport{{}, Utils::LanguageVersion::C11}; + }; + const ProjectPart::Ptr cprojectpart = ProjectPart::create({}, {}, {}, {}, {}, {}, {}, + tcInfo); projectParts.append(cprojectpart); // Create project part for CXX - const ProjectPart::Ptr cxxprojectpart{new ProjectPart}; - cxxprojectpart->languageVersion = Utils::LanguageVersion::CXX98; + tcInfo.macroInspectionRunner = [](const QStringList &) { + return ToolChain::MacroInspectionReport{{}, Utils::LanguageVersion::CXX98}; + }; + const ProjectPart::Ptr cxxprojectpart = ProjectPart::create({}, {}, {}, {}, {}, {}, {}, + tcInfo); projectParts.append(cxxprojectpart); return projectParts; } QString filePath; - ProjectPart::Ptr currentProjectPart{new ProjectPart}; + ProjectPart::Ptr currentProjectPart = ProjectPart::create({}); ProjectPartInfo currentProjectPartInfo{currentProjectPart, {currentProjectPart}, ProjectPartInfo::NoHint}; QString preferredProjectPartId; - const Project *activeProject = nullptr; + Utils::FilePath activeProject; Language languagePreference = Language::Cxx; bool projectsChanged = false; ProjectPartChooser chooser; @@ -108,15 +118,21 @@ public: QList<ProjectPart::Ptr> projectPartsForFile; QList<ProjectPart::Ptr> projectPartsFromDependenciesForFile; ProjectPart::Ptr fallbackProjectPart; + + static QHash<Utils::FilePath, std::shared_ptr<Project>> projectMap; }; + +QHash<Utils::FilePath, std::shared_ptr<Project>> +ProjectPartChooserTest::projectMap; } void CppToolsPlugin::test_projectPartChooser_chooseManuallySet() { - ProjectPart::Ptr p1(new ProjectPart); - ProjectPart::Ptr p2(new ProjectPart); + ProjectPart::Ptr p1 = ProjectPart::create({}); + RawProjectPart rpp2; + rpp2.setProjectFileLocation("someId"); + ProjectPart::Ptr p2 = ProjectPart::create({}, rpp2); ProjectPartChooserTest t; - p2->projectFile = "someId"; t.preferredProjectPartId = p2->projectFile; t.projectPartsForFile += {p1, p2}; @@ -125,10 +141,11 @@ void CppToolsPlugin::test_projectPartChooser_chooseManuallySet() void CppToolsPlugin::test_projectPartChooser_indicateManuallySet() { - ProjectPart::Ptr p1(new ProjectPart); - ProjectPart::Ptr p2(new ProjectPart); + ProjectPart::Ptr p1 = ProjectPart::create({}); + RawProjectPart rpp2; + rpp2.setProjectFileLocation("someId"); + ProjectPart::Ptr p2 = ProjectPart::create({}, rpp2); ProjectPartChooserTest t; - p2->projectFile = "someId"; t.preferredProjectPartId = p2->projectFile; t.projectPartsForFile += {p1, p2}; @@ -137,10 +154,11 @@ void CppToolsPlugin::test_projectPartChooser_indicateManuallySet() void CppToolsPlugin::test_projectPartChooser_indicateManuallySetForFallbackToProjectPartFromDependencies() { - ProjectPart::Ptr p1(new ProjectPart); - ProjectPart::Ptr p2(new ProjectPart); + ProjectPart::Ptr p1 = ProjectPart::create({}); + RawProjectPart rpp2; + rpp2.setProjectFileLocation("someId"); + ProjectPart::Ptr p2 = ProjectPart::create({}, rpp2); ProjectPartChooserTest t; - p2->projectFile = "someId"; t.preferredProjectPartId = p2->projectFile; t.projectPartsFromDependenciesForFile += {p1, p2}; @@ -158,17 +176,19 @@ void CppToolsPlugin::test_projectPartChooser_forMultipleChooseFromActiveProject( const QList<ProjectPart::Ptr> projectParts = t.createProjectPartsWithDifferentProjects(); const ProjectPart::Ptr secondProjectPart = projectParts.at(1); t.projectPartsForFile += projectParts; - t.activeProject = secondProjectPart->project; + t.activeProject = secondProjectPart->topLevelProject; QCOMPARE(t.choose().projectPart, secondProjectPart); } void CppToolsPlugin::test_projectPartChooser_forMultiplePreferSelectedForBuilding() { - const ProjectPart::Ptr firstProjectPart{new ProjectPart}; - const ProjectPart::Ptr secondProjectPart{new ProjectPart}; - firstProjectPart->selectedForBuilding = false; - secondProjectPart->selectedForBuilding = true; + RawProjectPart rpp1; + rpp1.setSelectedForBuilding(false); + RawProjectPart rpp2; + rpp1.setSelectedForBuilding(true); + const ProjectPart::Ptr firstProjectPart = ProjectPart::create({}, rpp1); + const ProjectPart::Ptr secondProjectPart = ProjectPart::create({}, rpp2); ProjectPartChooserTest t; t.projectPartsForFile += firstProjectPart; t.projectPartsForFile += secondProjectPart; @@ -182,7 +202,7 @@ void CppToolsPlugin::test_projectPartChooser_forMultipleFromDependenciesChooseFr const QList<ProjectPart::Ptr> projectParts = t.createProjectPartsWithDifferentProjects(); const ProjectPart::Ptr secondProjectPart = projectParts.at(1); t.projectPartsFromDependenciesForFile += projectParts; - t.activeProject = secondProjectPart->project; + t.activeProject = secondProjectPart->topLevelProject; QCOMPARE(t.choose().projectPart, secondProjectPart); } @@ -195,7 +215,7 @@ void CppToolsPlugin::test_projectPartChooser_forMultipleCheckIfActiveProjectChan const ProjectPart::Ptr secondProjectPart = projectParts.at(1); t.projectPartsForFile += projectParts; t.currentProjectPartInfo.projectPart = firstProjectPart; - t.activeProject = secondProjectPart->project; + t.activeProject = secondProjectPart->topLevelProject; QCOMPARE(t.choose().projectPart, secondProjectPart); } @@ -222,27 +242,27 @@ void CppToolsPlugin::test_projectPartChooser_forMultipleAndAmbigiousHeaderPrefer void CppToolsPlugin::test_projectPartChooser_indicateMultiple() { - const ProjectPart::Ptr p1{new ProjectPart}; - const ProjectPart::Ptr p2{new ProjectPart}; + const ProjectPart::Ptr p1 = ProjectPart::create({}); + const ProjectPart::Ptr p2 = ProjectPart::create({}); ProjectPartChooserTest t; - t.projectPartsForFile += { p1, p2 }; + t.projectPartsForFile += {p1, p2}; QVERIFY(t.choose().hints & ProjectPartInfo::IsAmbiguousMatch); } void CppToolsPlugin::test_projectPartChooser_indicateMultipleForFallbackToProjectPartFromDependencies() { - const ProjectPart::Ptr p1{new ProjectPart}; - const ProjectPart::Ptr p2{new ProjectPart}; + const ProjectPart::Ptr p1 = ProjectPart::create({}); + const ProjectPart::Ptr p2 = ProjectPart::create({}); ProjectPartChooserTest t; - t.projectPartsFromDependenciesForFile += { p1, p2 }; + t.projectPartsFromDependenciesForFile += {p1, p2}; QVERIFY(t.choose().hints & ProjectPartInfo::IsAmbiguousMatch); } void CppToolsPlugin::test_projectPartChooser_forMultipleChooseNewIfPreviousIsGone() { - const ProjectPart::Ptr newProjectPart{new ProjectPart}; + const ProjectPart::Ptr newProjectPart = ProjectPart::create({}); ProjectPartChooserTest t; t.projectPartsForFile += newProjectPart; @@ -251,7 +271,7 @@ void CppToolsPlugin::test_projectPartChooser_forMultipleChooseNewIfPreviousIsGon void CppToolsPlugin::test_projectPartChooser_fallbackToProjectPartFromDependencies() { - const ProjectPart::Ptr fromDependencies{new ProjectPart}; + const ProjectPart::Ptr fromDependencies = ProjectPart::create({}); ProjectPartChooserTest t; t.projectPartsFromDependenciesForFile += fromDependencies; @@ -261,7 +281,7 @@ void CppToolsPlugin::test_projectPartChooser_fallbackToProjectPartFromDependenci void CppToolsPlugin::test_projectPartChooser_fallbackToProjectPartFromModelManager() { ProjectPartChooserTest t; - t.fallbackProjectPart.reset(new ProjectPart); + t.fallbackProjectPart = ProjectPart::create({}); QCOMPARE(t.choose().projectPart, t.fallbackProjectPart); } @@ -270,10 +290,10 @@ void CppToolsPlugin::test_projectPartChooser_continueUsingFallbackFromModelManag { // ...without re-calculating the dependency table. ProjectPartChooserTest t; - t.fallbackProjectPart.reset(new ProjectPart); + t.fallbackProjectPart = ProjectPart::create({}); t.currentProjectPartInfo.projectPart = t.fallbackProjectPart; t.currentProjectPartInfo.hints |= ProjectPartInfo::IsFallbackMatch; - t.projectPartsFromDependenciesForFile += ProjectPart::Ptr(new ProjectPart); + t.projectPartsFromDependenciesForFile += ProjectPart::create({}); QCOMPARE(t.choose().projectPart, t.fallbackProjectPart); } @@ -281,10 +301,10 @@ void CppToolsPlugin::test_projectPartChooser_continueUsingFallbackFromModelManag void CppToolsPlugin::test_projectPartChooser_stopUsingFallbackFromModelManagerIfProjectChanges1() { ProjectPartChooserTest t; - t.fallbackProjectPart.reset(new ProjectPart); + t.fallbackProjectPart = ProjectPart::create({}); t.currentProjectPartInfo.projectPart = t.fallbackProjectPart; t.currentProjectPartInfo.hints |= ProjectPartInfo::IsFallbackMatch; - const ProjectPart::Ptr addedProject(new ProjectPart); + const ProjectPart::Ptr addedProject = ProjectPart::create({}); t.projectPartsForFile += addedProject; QCOMPARE(t.choose().projectPart, addedProject); @@ -293,10 +313,10 @@ void CppToolsPlugin::test_projectPartChooser_stopUsingFallbackFromModelManagerIf void CppToolsPlugin::test_projectPartChooser_stopUsingFallbackFromModelManagerIfProjectChanges2() { ProjectPartChooserTest t; - t.fallbackProjectPart.reset(new ProjectPart); + t.fallbackProjectPart = ProjectPart::create({}); t.currentProjectPartInfo.projectPart = t.fallbackProjectPart; t.currentProjectPartInfo.hints |= ProjectPartInfo::IsFallbackMatch; - const ProjectPart::Ptr addedProject(new ProjectPart); + const ProjectPart::Ptr addedProject = ProjectPart::create({}); t.projectPartsFromDependenciesForFile += addedProject; t.projectsChanged = true; @@ -306,7 +326,7 @@ void CppToolsPlugin::test_projectPartChooser_stopUsingFallbackFromModelManagerIf void CppToolsPlugin::test_projectPartChooser_indicateFallbacktoProjectPartFromModelManager() { ProjectPartChooserTest t; - t.fallbackProjectPart.reset(new ProjectPart); + t.fallbackProjectPart = ProjectPart::create({}); QVERIFY(t.choose().hints & ProjectPartInfo::IsFallbackMatch); } @@ -314,7 +334,7 @@ void CppToolsPlugin::test_projectPartChooser_indicateFallbacktoProjectPartFromMo void CppToolsPlugin::test_projectPartChooser_indicateFromDependencies() { ProjectPartChooserTest t; - t.projectPartsFromDependenciesForFile += ProjectPart::Ptr(new ProjectPart); + t.projectPartsFromDependenciesForFile += ProjectPart::create({}); QVERIFY(t.choose().hints & ProjectPartInfo::IsFromDependenciesMatch); } @@ -322,7 +342,7 @@ void CppToolsPlugin::test_projectPartChooser_indicateFromDependencies() void CppToolsPlugin::test_projectPartChooser_doNotIndicateFromDependencies() { ProjectPartChooserTest t; - t.projectPartsForFile += ProjectPart::Ptr(new ProjectPart); + t.projectPartsForFile += ProjectPart::create({}); QVERIFY(!(t.choose().hints & ProjectPartInfo::IsFromDependenciesMatch)); } @@ -351,14 +371,18 @@ private: class ProjectInfoGeneratorTest { public: - ProjectInfo generate() + ProjectInfoGeneratorTest() { - QFutureInterface<ProjectInfo> fi; TestToolchain aToolChain; + projectUpdateInfo.cxxToolChainInfo = {&aToolChain, {}, {}}; + projectUpdateInfo.cToolChainInfo = {&aToolChain, {}, {}}; + } + + ProjectInfo::Ptr generate() + { + QFutureInterface<ProjectInfo::Ptr> fi; projectUpdateInfo.rawProjectParts += rawProjectPart; - projectUpdateInfo.cxxToolChain = &aToolChain; - projectUpdateInfo.cToolChain = &aToolChain; ProjectInfoGenerator generator(fi, projectUpdateInfo); return generator.generate(); @@ -372,37 +396,37 @@ public: void CppToolsPlugin::test_projectInfoGenerator_createNoProjectPartsForEmptyFileList() { ProjectInfoGeneratorTest t; - const ProjectInfo projectInfo = t.generate(); + const ProjectInfo::Ptr projectInfo = t.generate(); - QVERIFY(projectInfo.projectParts().isEmpty()); + QVERIFY(projectInfo->projectParts().isEmpty()); } void CppToolsPlugin::test_projectInfoGenerator_createSingleProjectPart() { ProjectInfoGeneratorTest t; t.rawProjectPart.files = QStringList{ "foo.cpp", "foo.h"}; - const ProjectInfo projectInfo = t.generate(); + const ProjectInfo::Ptr projectInfo = t.generate(); - QCOMPARE(projectInfo.projectParts().size(), 1); + QCOMPARE(projectInfo->projectParts().size(), 1); } void CppToolsPlugin::test_projectInfoGenerator_createMultipleProjectParts() { ProjectInfoGeneratorTest t; t.rawProjectPart.files = QStringList{ "foo.cpp", "foo.h", "bar.c", "bar.h" }; - const ProjectInfo projectInfo = t.generate(); + const ProjectInfo::Ptr projectInfo = t.generate(); - QCOMPARE(projectInfo.projectParts().size(), 2); + QCOMPARE(projectInfo->projectParts().size(), 2); } void CppToolsPlugin::test_projectInfoGenerator_projectPartIndicatesObjectiveCExtensionsByDefault() { ProjectInfoGeneratorTest t; t.rawProjectPart.files = QStringList{ "foo.mm" }; - const ProjectInfo projectInfo = t.generate(); - QCOMPARE(projectInfo.projectParts().size(), 1); + const ProjectInfo::Ptr projectInfo = t.generate(); + QCOMPARE(projectInfo->projectParts().size(), 1); - const ProjectPart &projectPart = *projectInfo.projectParts().at(0); + const ProjectPart &projectPart = *projectInfo->projectParts().at(0); QVERIFY(projectPart.languageExtensions & Utils::LanguageExtension::ObjectiveC); } @@ -410,10 +434,10 @@ void CppToolsPlugin::test_projectInfoGenerator_projectPartHasLatestLanguageVersi { ProjectInfoGeneratorTest t; t.rawProjectPart.files = QStringList{ "foo.cpp" }; - const ProjectInfo projectInfo = t.generate(); - QCOMPARE(projectInfo.projectParts().size(), 1); + const ProjectInfo::Ptr projectInfo = t.generate(); + QCOMPARE(projectInfo->projectParts().size(), 1); - const ProjectPart &projectPart = *projectInfo.projectParts().at(0); + const ProjectPart &projectPart = *projectInfo->projectParts().at(0); QCOMPARE(projectPart.languageVersion, Utils::LanguageVersion::LatestCxx); } @@ -424,11 +448,11 @@ void CppToolsPlugin::test_projectInfoGenerator_useMacroInspectionReportForLangua return TestToolchain::MacroInspectionReport{Macros(), Utils::LanguageVersion::CXX17}; }; t.rawProjectPart.files = QStringList{ "foo.cpp" }; - const ProjectInfo projectInfo = t.generate(); + const ProjectInfo::Ptr projectInfo = t.generate(); - QCOMPARE(projectInfo.projectParts().size(), 1); + QCOMPARE(projectInfo->projectParts().size(), 1); - const ProjectPart &projectPart = *projectInfo.projectParts().at(0); + const ProjectPart &projectPart = *projectInfo->projectParts().at(0); QCOMPARE(projectPart.languageVersion, Utils::LanguageVersion::CXX17); } @@ -437,11 +461,11 @@ void CppToolsPlugin::test_projectInfoGenerator_useCompilerFlagsForLanguageExtens ProjectInfoGeneratorTest t; t.rawProjectPart.files = QStringList{ "foo.cpp" }; t.rawProjectPart.flagsForCxx.languageExtensions = Utils::LanguageExtension::Microsoft; - const ProjectInfo projectInfo = t.generate(); + const ProjectInfo::Ptr projectInfo = t.generate(); - QCOMPARE(projectInfo.projectParts().size(), 1); + QCOMPARE(projectInfo->projectParts().size(), 1); - const ProjectPart &projectPart = *projectInfo.projectParts().at(0); + const ProjectPart &projectPart = *projectInfo->projectParts().at(0); QVERIFY(projectPart.languageExtensions & Utils::LanguageExtension::Microsoft); } @@ -449,22 +473,22 @@ void CppToolsPlugin::test_projectInfoGenerator_projectFileKindsMatchProjectPartV { ProjectInfoGeneratorTest t; t.rawProjectPart.files = QStringList{ "foo.h" }; - const ProjectInfo projectInfo = t.generate(); + const ProjectInfo::Ptr projectInfo = t.generate(); - QCOMPARE(projectInfo.projectParts().size(), 4); - QVERIFY(Utils::contains(projectInfo.projectParts(), [](const ProjectPart::Ptr &p) { + QCOMPARE(projectInfo->projectParts().size(), 4); + QVERIFY(Utils::contains(projectInfo->projectParts(), [](const ProjectPart::Ptr &p) { return p->languageVersion == Utils::LanguageVersion::LatestC && p->files.first().kind == ProjectFile::CHeader; })); - QVERIFY(Utils::contains(projectInfo.projectParts(), [](const ProjectPart::Ptr &p) { + QVERIFY(Utils::contains(projectInfo->projectParts(), [](const ProjectPart::Ptr &p) { return p->languageVersion == Utils::LanguageVersion::LatestC && p->files.first().kind == ProjectFile::ObjCHeader; })); - QVERIFY(Utils::contains(projectInfo.projectParts(), [](const ProjectPart::Ptr &p) { + QVERIFY(Utils::contains(projectInfo->projectParts(), [](const ProjectPart::Ptr &p) { return p->languageVersion == Utils::LanguageVersion::LatestCxx && p->files.first().kind == ProjectFile::CXXHeader; })); - QVERIFY(Utils::contains(projectInfo.projectParts(), [](const ProjectPart::Ptr &p) { + QVERIFY(Utils::contains(projectInfo->projectParts(), [](const ProjectPart::Ptr &p) { return p->languageVersion == Utils::LanguageVersion::LatestCxx && p->files.first().kind == ProjectFile::ObjCXXHeader; })); @@ -474,20 +498,18 @@ namespace { class HeaderPathFilterTest { public: - HeaderPathFilterTest() : project({}, Utils::FilePath::fromString("test")) + ProjectPart finalize() { - const auto headerPaths = HeaderPaths{ - HeaderPath{"", HeaderPathType::BuiltIn}, - HeaderPath{"/builtin_path", HeaderPathType::BuiltIn}, - HeaderPath{"/system_path", HeaderPathType::System}, - HeaderPath{"/framework_path", HeaderPathType::Framework}, - HeaderPath{"/outside_project_user_path", HeaderPathType::User}, - HeaderPath{"/build/user_path", HeaderPathType::User}, - HeaderPath{"/buildb/user_path", HeaderPathType::User}, - HeaderPath{"/projectb/user_path", HeaderPathType::User}, - HeaderPath{"/project/user_path", HeaderPathType::User}}; - projectPart.headerPaths = headerPaths; - projectPart.project = &project; + RawProjectPart rpp; + rpp.setHeaderPaths(headerPaths); + ToolChainInfo tcInfo; + tcInfo.type = toolchainType; + tcInfo.targetTriple = targetTriple; + tcInfo.installDir = toolchainInstallDir; + projectPart = ProjectPart::create({}, rpp, {}, {}, {}, {}, {}, tcInfo); + filter.emplace(HeaderPathFilter(*projectPart, UseTweakedHeaderPaths::No, {}, {}, + "/project", "/build")); + return *projectPart; } static HeaderPath builtIn(const QString &path) @@ -507,26 +529,43 @@ public: return HeaderPath{path, HeaderPathType::User}; } - Project project; - ProjectPart projectPart; - HeaderPathFilter filter{projectPart, UseTweakedHeaderPaths::No, {}, {}, "/project", "/build"}; + QString targetTriple; + Utils::Id toolchainType; + Utils::FilePath toolchainInstallDir; + HeaderPaths headerPaths = { + HeaderPath{"", HeaderPathType::BuiltIn}, + HeaderPath{"/builtin_path", HeaderPathType::BuiltIn}, + HeaderPath{"/system_path", HeaderPathType::System}, + HeaderPath{"/framework_path", HeaderPathType::Framework}, + HeaderPath{"/outside_project_user_path", HeaderPathType::User}, + HeaderPath{"/build/user_path", HeaderPathType::User}, + HeaderPath{"/buildb/user_path", HeaderPathType::User}, + HeaderPath{"/projectb/user_path", HeaderPathType::User}, + HeaderPath{"/project/user_path", HeaderPathType::User}}; + + Utils::optional<HeaderPathFilter> filter; + +private: + ProjectPart::Ptr projectPart; }; } void CppToolsPlugin::test_headerPathFilter_builtin() { HeaderPathFilterTest t; - t.filter.process(); + t.finalize(); + t.filter->process(); - QCOMPARE(t.filter.builtInHeaderPaths, (HeaderPaths{t.builtIn("/builtin_path")})); + QCOMPARE(t.filter->builtInHeaderPaths, (HeaderPaths{t.builtIn("/builtin_path")})); } void CppToolsPlugin::test_headerPathFilter_system() { HeaderPathFilterTest t; - t.filter.process(); + t.finalize(); + t.filter->process(); - QCOMPARE(t.filter.systemHeaderPaths, (HeaderPaths{ + QCOMPARE(t.filter->systemHeaderPaths, (HeaderPaths{ t.system("/project/.pre_includes"), t.system("/system_path"), t.framework("/framework_path"), t.user("/outside_project_user_path"), t.user("/buildb/user_path"), t.user("/projectb/user_path")})); @@ -535,16 +574,16 @@ void CppToolsPlugin::test_headerPathFilter_system() void CppToolsPlugin::test_headerPathFilter_user() { HeaderPathFilterTest t; - t.filter.process(); + t.filter->process(); - QCOMPARE(t.filter.userHeaderPaths, (HeaderPaths{t.user("/build/user_path"), - t.user("/project/user_path")})); + QCOMPARE(t.filter->userHeaderPaths, (HeaderPaths{t.user("/build/user_path"), + t.user("/project/user_path")})); } void CppToolsPlugin::test_headerPathFilter_noProjectPathSet() { HeaderPathFilterTest t; - HeaderPathFilter filter{t.projectPart, UseTweakedHeaderPaths::No}; + HeaderPathFilter filter{t.finalize(), UseTweakedHeaderPaths::No}; filter.process(); QCOMPARE(filter.userHeaderPaths, (HeaderPaths{ @@ -556,20 +595,21 @@ void CppToolsPlugin::test_headerPathFilter_noProjectPathSet() void CppToolsPlugin::test_headerPathFilter_dontAddInvalidPath() { HeaderPathFilterTest t; - t.filter.process(); - QCOMPARE(t.filter.builtInHeaderPaths, (HeaderPaths{t.builtIn("/builtin_path")})); - QCOMPARE(t.filter.systemHeaderPaths, HeaderPaths({ + t.finalize(); + t.filter->process(); + QCOMPARE(t.filter->builtInHeaderPaths, (HeaderPaths{t.builtIn("/builtin_path")})); + QCOMPARE(t.filter->systemHeaderPaths, HeaderPaths({ t.system("/project/.pre_includes"), t.system("/system_path"), t.framework("/framework_path"), t.user("/outside_project_user_path"), t.user("/buildb/user_path"), t.user("/projectb/user_path")})); - QCOMPARE(t.filter.userHeaderPaths, HeaderPaths({t.user("/build/user_path"), - t.user("/project/user_path")})); + QCOMPARE(t.filter->userHeaderPaths, HeaderPaths({t.user("/build/user_path"), + t.user("/project/user_path")})); } void CppToolsPlugin::test_headerPathFilter_clangHeadersPath() { HeaderPathFilterTest t; - HeaderPathFilter filter(t.projectPart, UseTweakedHeaderPaths::Yes, "6.0", "clang_dir"); + HeaderPathFilter filter(t.finalize(), UseTweakedHeaderPaths::Yes, "6.0", "clang_dir"); filter.process(); QCOMPARE(filter.builtInHeaderPaths, (HeaderPaths{t.builtIn("clang_dir"), @@ -579,7 +619,7 @@ void CppToolsPlugin::test_headerPathFilter_clangHeadersPath() void CppToolsPlugin::test_headerPathFilter_clangHeadersPathWitoutClangVersion() { HeaderPathFilterTest t; - HeaderPathFilter filter(t.projectPart, UseTweakedHeaderPaths::Yes); + HeaderPathFilter filter(t.finalize(), UseTweakedHeaderPaths::Yes); filter.process(); QCOMPARE(filter.builtInHeaderPaths, (HeaderPaths{t.builtIn("/builtin_path")})); @@ -588,6 +628,7 @@ void CppToolsPlugin::test_headerPathFilter_clangHeadersPathWitoutClangVersion() void CppToolsPlugin::test_headerPathFilter_clangHeadersAndCppIncludesPathsOrderMacOs() { HeaderPathFilterTest t; + t.targetTriple = "x86_64-apple-darwin10"; const auto builtIns = { t.builtIn("/usr/include/c++/4.2.1"), t.builtIn("/usr/include/c++/4.2.1/backward"), t.builtIn("/usr/local/include"), @@ -595,10 +636,9 @@ void CppToolsPlugin::test_headerPathFilter_clangHeadersAndCppIncludesPathsOrderM t.builtIn("/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include"), t.builtIn("/usr/include") }; - t.projectPart.toolChainTargetTriple = "x86_64-apple-darwin10"; std::copy(builtIns.begin(), builtIns.end(), - std::inserter(t.projectPart.headerPaths, t.projectPart.headerPaths.begin())); - HeaderPathFilter filter(t.projectPart, UseTweakedHeaderPaths::Yes, "6.0", "clang_dir"); + std::inserter(t.headerPaths, t.headerPaths.begin())); + HeaderPathFilter filter(t.finalize(), UseTweakedHeaderPaths::Yes, "6.0", "clang_dir"); filter.process(); QCOMPARE(filter.builtInHeaderPaths, (HeaderPaths{ @@ -612,15 +652,15 @@ void CppToolsPlugin::test_headerPathFilter_clangHeadersAndCppIncludesPathsOrderM void CppToolsPlugin::test_headerPathFilter_clangHeadersAndCppIncludesPathsOrderLinux() { HeaderPathFilterTest t; + t.targetTriple = "x86_64-linux-gnu"; const auto builtIns = { t.builtIn("/usr/include/c++/4.8"), t.builtIn("/usr/include/c++/4.8/backward"), t.builtIn("/usr/include/x86_64-linux-gnu/c++/4.8"), t.builtIn("/usr/local/include"), t.builtIn("/usr/lib/gcc/x86_64-linux-gnu/4.8/include"), t.builtIn("/usr/include/x86_64-linux-gnu"), t.builtIn("/usr/include")}; std::copy(builtIns.begin(), builtIns.end(), - std::inserter(t.projectPart.headerPaths, t.projectPart.headerPaths.begin())); - t.projectPart.toolChainTargetTriple = "x86_64-linux-gnu"; - HeaderPathFilter filter(t.projectPart, UseTweakedHeaderPaths::Yes, "6.0", "clang_dir"); + std::inserter(t.headerPaths, t.headerPaths.begin())); + HeaderPathFilter filter(t.finalize(), UseTweakedHeaderPaths::Yes, "6.0", "clang_dir"); filter.process(); QCOMPARE(filter.builtInHeaderPaths, (HeaderPaths{ @@ -636,13 +676,13 @@ void CppToolsPlugin::test_headerPathFilter_clangHeadersAndCppIncludesPathsOrderL void CppToolsPlugin::test_headerPathFilter_removeGccInternalPaths() { HeaderPathFilterTest t; - t.projectPart.toolChainInstallDir = Utils::FilePath::fromUtf8("/usr/lib/gcc/x86_64-linux-gnu/7"); - t.projectPart.toolchainType = Constants::GCC_TOOLCHAIN_TYPEID; - t.projectPart.headerPaths = { + t.toolchainInstallDir = Utils::FilePath::fromUtf8("/usr/lib/gcc/x86_64-linux-gnu/7"); + t.toolchainType = Constants::GCC_TOOLCHAIN_TYPEID; + t.headerPaths = { t.builtIn("/usr/lib/gcc/x86_64-linux-gnu/7/include"), t.builtIn("/usr/lib/gcc/x86_64-linux-gnu/7/include-fixed"), }; - HeaderPathFilter filter(t.projectPart, UseTweakedHeaderPaths::Yes, "6.0", "clang_dir"); + HeaderPathFilter filter(t.finalize(), UseTweakedHeaderPaths::Yes, "6.0", "clang_dir"); filter.process(); QCOMPARE(filter.builtInHeaderPaths, (HeaderPaths{t.builtIn("clang_dir")})); @@ -654,18 +694,17 @@ void CppToolsPlugin::test_headerPathFilter_removeGccInternalPaths() void CppToolsPlugin::test_headerPathFilter_removeGccInternalPathsExceptForStandardPaths() { HeaderPathFilterTest t; - t.projectPart.toolChainInstallDir = Utils::FilePath::fromUtf8( - "c:/mingw/lib/gcc/x86_64-w64-mingw32/7.3.0"); - t.projectPart.toolchainType = Constants::MINGW_TOOLCHAIN_TYPEID; - t.projectPart.headerPaths = { + t.toolchainInstallDir = Utils::FilePath::fromUtf8("c:/mingw/lib/gcc/x86_64-w64-mingw32/7.3.0"); + t.toolchainType = Constants::MINGW_TOOLCHAIN_TYPEID; + t.headerPaths = { t.builtIn("c:/mingw/lib/gcc/x86_64-w64-mingw32/7.3.0/include/c++"), t.builtIn("c:/mingw/lib/gcc/x86_64-w64-mingw32/7.3.0/include/c++/x86_64-w64-mingw32"), t.builtIn("c:/mingw/lib/gcc/x86_64-w64-mingw32/7.3.0/include/c++/backward"), }; - HeaderPaths expected = t.projectPart.headerPaths; + HeaderPaths expected = t.headerPaths; expected.append(t.builtIn("clang_dir")); - HeaderPathFilter filter(t.projectPart, UseTweakedHeaderPaths::Yes, "6.0", "clang_dir"); + HeaderPathFilter filter(t.finalize(), UseTweakedHeaderPaths::Yes, "6.0", "clang_dir"); filter.process(); QCOMPARE(filter.builtInHeaderPaths, expected); @@ -674,14 +713,14 @@ void CppToolsPlugin::test_headerPathFilter_removeGccInternalPathsExceptForStanda void CppToolsPlugin::test_headerPathFilter_clangHeadersAndCppIncludesPathsOrderNoVersion() { HeaderPathFilterTest t; - t.projectPart.headerPaths = { + t.headerPaths = { t.builtIn("C:/mingw/i686-w64-mingw32/include"), t.builtIn("C:/mingw/i686-w64-mingw32/include/c++"), t.builtIn("C:/mingw/i686-w64-mingw32/include/c++/i686-w64-mingw32"), t.builtIn("C:/mingw/i686-w64-mingw32/include/c++/backward"), }; - t.projectPart.toolChainTargetTriple = "x86_64-w64-windows-gnu"; - HeaderPathFilter filter(t.projectPart, UseTweakedHeaderPaths::Yes, "6.0", "clang_dir"); + t.targetTriple = "x86_64-w64-windows-gnu"; + HeaderPathFilter filter(t.finalize(), UseTweakedHeaderPaths::Yes, "6.0", "clang_dir"); filter.process(); QCOMPARE(filter.builtInHeaderPaths, (HeaderPaths{ @@ -695,15 +734,15 @@ void CppToolsPlugin::test_headerPathFilter_clangHeadersAndCppIncludesPathsOrderN void CppToolsPlugin::test_headerPathFilter_clangHeadersAndCppIncludesPathsOrderAndroidClang() { HeaderPathFilterTest t; - t.projectPart.headerPaths = { + t.headerPaths = { t.builtIn("C:/Android/sdk/ndk-bundle/sysroot/usr/include/i686-linux-android"), t.builtIn("C:/Android/sdk/ndk-bundle/sources/cxx-stl/llvm-libc++/include"), t.builtIn("C:/Android/sdk/ndk-bundle/sources/android/support/include"), t.builtIn("C:/Android/sdk/ndk-bundle/sources/cxx-stl/llvm-libc++abi/include"), t.builtIn("C:/Android/sdk/ndk-bundle/sysroot/usr/include") }; - t.projectPart.toolChainTargetTriple = "i686-linux-android"; - HeaderPathFilter filter(t.projectPart, UseTweakedHeaderPaths::Yes, "6.0", "clang_dir"); + t.targetTriple = "i686-linux-android"; + HeaderPathFilter filter(t.finalize(), UseTweakedHeaderPaths::Yes, "6.0", "clang_dir"); filter.process(); QCOMPARE(filter.builtInHeaderPaths, (HeaderPaths{ diff --git a/src/plugins/cpptools/projectpart.cpp b/src/plugins/cpptools/projectpart.cpp index d3d4668a814..8286412da5b 100644 --- a/src/plugins/cpptools/projectpart.cpp +++ b/src/plugins/cpptools/projectpart.cpp @@ -25,6 +25,8 @@ #include "projectpart.h" +#include <projectexplorer/project.h> + #include <utils/algorithm.h> #include <QFile> @@ -35,66 +37,6 @@ using namespace ProjectExplorer; namespace CppTools { -void ProjectPart::updateLanguageFeatures() -{ - const bool hasCxx = languageVersion >= Utils::LanguageVersion::CXX98; - const bool hasQt = hasCxx && qtVersion != Utils::QtVersion::None; - languageFeatures.cxx11Enabled = languageVersion >= Utils::LanguageVersion::CXX11; - languageFeatures.cxx14Enabled = languageVersion >= Utils::LanguageVersion::CXX14; - languageFeatures.cxxEnabled = hasCxx; - languageFeatures.c99Enabled = languageVersion >= Utils::LanguageVersion::C99; - languageFeatures.objCEnabled = languageExtensions.testFlag(Utils::LanguageExtension::ObjectiveC); - languageFeatures.qtEnabled = hasQt; - languageFeatures.qtMocRunEnabled = hasQt; - if (!hasQt) { - languageFeatures.qtKeywordsEnabled = false; - } else { - languageFeatures.qtKeywordsEnabled = !Utils::contains( - projectMacros, - [] (const ProjectExplorer::Macro ¯o) { return macro.key == "QT_NO_KEYWORDS"; }); - } -} - -void ProjectPart::setupToolchainProperties(const ToolChainInfo &tcInfo, const QStringList &flags) -{ - toolchainType = tcInfo.type; - isMsvc2015Toolchain = tcInfo.isMsvc2015ToolChain; - toolChainWordWidth = tcInfo.wordWidth == 64 ? ProjectPart::WordWidth64Bit - : ProjectPart::WordWidth32Bit; - toolChainInstallDir = tcInfo.installDir; - toolChainTargetTriple = tcInfo.targetTriple; - extraCodeModelFlags = tcInfo.extraCodeModelFlags; - compilerFlags = flags; - - // Toolchain macros and language version - if (tcInfo.macroInspectionRunner) { - const auto macroInspectionReport = tcInfo.macroInspectionRunner(compilerFlags); - toolChainMacros = macroInspectionReport.macros; - languageVersion = macroInspectionReport.languageVersion; - // No compiler set in kit. - } else if (language == Utils::Language::C) { - languageVersion = Utils::LanguageVersion::LatestC; - } else { - languageVersion = Utils::LanguageVersion::LatestCxx; - } - - // Header paths - if (tcInfo.headerPathsRunner) { - const HeaderPaths builtInHeaderPaths - = tcInfo.headerPathsRunner(compilerFlags, tcInfo.sysRootPath, tcInfo.targetTriple); - for (const HeaderPath &header : builtInHeaderPaths) { - const HeaderPath headerPath{header.path, header.type}; - if (!headerPaths.contains(headerPath)) - headerPaths.push_back(headerPath); - } - } -} - -ProjectPart::Ptr ProjectPart::copy() const -{ - return Ptr(new ProjectPart(*this)); -} - QString ProjectPart::id() const { QString projectPartId = projectFileLocation(); @@ -113,11 +55,16 @@ QString ProjectPart::projectFileLocation() const return location; } -QByteArray ProjectPart::readProjectConfigFile(const Ptr &projectPart) +bool ProjectPart::belongsToProject(const ProjectExplorer::Project *project) const +{ + return project && topLevelProject == project->projectFilePath(); +} + +QByteArray ProjectPart::readProjectConfigFile(const QString &projectConfigFile) { QByteArray result; - QFile f(projectPart->projectConfigFile); + QFile f(projectConfigFile); if (f.open(QIODevice::ReadOnly)) { QTextStream is(&f); result = is.readAll().toUtf8(); @@ -127,4 +74,116 @@ QByteArray ProjectPart::readProjectConfigFile(const Ptr &projectPart) return result; } +// TODO: Why do we keep the file *and* the resulting macros? Why do we read the file +// in several places? +static Macros getProjectMacros(const RawProjectPart &rpp) +{ + Macros macros = rpp.projectMacros; + if (!rpp.projectConfigFile.isEmpty()) + macros += Macro::toMacros(ProjectPart::readProjectConfigFile(rpp.projectConfigFile)); + return macros; +} + +static HeaderPaths getHeaderPaths(const RawProjectPart &rpp, + const RawProjectPartFlags &flags, + const ProjectExplorer::ToolChainInfo &tcInfo) +{ + HeaderPaths headerPaths; + + // Prevent duplicate include paths. + // TODO: Do this once when finalizing the raw project part? + std::set<QString> seenPaths; + for (const HeaderPath &p : qAsConst(rpp.headerPaths)) { + const QString cleanPath = QDir::cleanPath(p.path); + if (seenPaths.insert(cleanPath).second) + headerPaths << HeaderPath(cleanPath, p.type); + } + + if (tcInfo.headerPathsRunner) { + const HeaderPaths builtInHeaderPaths = tcInfo.headerPathsRunner( + flags.commandLineFlags, tcInfo.sysRootPath, tcInfo.targetTriple); + for (const HeaderPath &header : builtInHeaderPaths) { + if (seenPaths.insert(header.path).second) + headerPaths.push_back(HeaderPath{header.path, header.type}); + } + } + return headerPaths; +} + +static ToolChain::MacroInspectionReport getToolchainMacros( + const RawProjectPartFlags &flags, const ToolChainInfo &tcInfo, Utils::Language language) +{ + ToolChain::MacroInspectionReport report; + if (tcInfo.macroInspectionRunner) { + report = tcInfo.macroInspectionRunner(flags.commandLineFlags); + } else if (language == Utils::Language::C) { // No compiler set in kit. + report.languageVersion = Utils::LanguageVersion::LatestC; + } else { + report.languageVersion = Utils::LanguageVersion::LatestCxx; + } + return report; +} + +ProjectPart::ProjectPart(const Utils::FilePath &topLevelProject, + const RawProjectPart &rpp, + const QString &displayName, + const ProjectFiles &files, + Utils::Language language, + Utils::LanguageExtensions languageExtensions, + const RawProjectPartFlags &flags, + const ToolChainInfo &tcInfo) + : topLevelProject(topLevelProject), + displayName(displayName), + projectFile(rpp.projectFile), + projectConfigFile(rpp.projectConfigFile), + projectFileLine(rpp.projectFileLine), + projectFileColumn(rpp.projectFileColumn), + callGroupId(rpp.callGroupId), + language(language), + languageExtensions(languageExtensions | flags.languageExtensions), + qtVersion(rpp.qtVersion), + files(files), + includedFiles(rpp.includedFiles), + precompiledHeaders(rpp.precompiledHeaders), + headerPaths(getHeaderPaths(rpp, flags, tcInfo)), + projectMacros(getProjectMacros(rpp)), + buildSystemTarget(rpp.buildSystemTarget), + buildTargetType(rpp.buildTargetType), + selectedForBuilding(rpp.selectedForBuilding), + toolchainType(tcInfo.type), + isMsvc2015Toolchain(tcInfo.isMsvc2015ToolChain), + toolChainTargetTriple(tcInfo.targetTriple), + toolChainWordWidth(tcInfo.wordWidth == 64 ? ProjectPart::WordWidth64Bit + : ProjectPart::WordWidth32Bit), + toolChainInstallDir(tcInfo.installDir), + compilerFilePath(tcInfo.compilerFilePath), + warningFlags(flags.warningFlags), + extraCodeModelFlags(tcInfo.extraCodeModelFlags), + compilerFlags(flags.commandLineFlags), + m_macroReport(getToolchainMacros(flags, tcInfo, language)), + languageFeatures(deriveLanguageFeatures()) +{ +} + +CPlusPlus::LanguageFeatures ProjectPart::deriveLanguageFeatures() const +{ + const bool hasCxx = languageVersion >= Utils::LanguageVersion::CXX98; + const bool hasQt = hasCxx && qtVersion != Utils::QtVersion::None; + CPlusPlus::LanguageFeatures features; + features.cxx11Enabled = languageVersion >= Utils::LanguageVersion::CXX11; + features.cxx14Enabled = languageVersion >= Utils::LanguageVersion::CXX14; + features.cxxEnabled = hasCxx; + features.c99Enabled = languageVersion >= Utils::LanguageVersion::C99; + features.objCEnabled = languageExtensions.testFlag(Utils::LanguageExtension::ObjectiveC); + features.qtEnabled = hasQt; + features.qtMocRunEnabled = hasQt; + if (!hasQt) { + features.qtKeywordsEnabled = false; + } else { + features.qtKeywordsEnabled = !Utils::contains(projectMacros, + [] (const ProjectExplorer::Macro ¯o) { return macro.key == "QT_NO_KEYWORDS"; }); + } + return features; +} + } // namespace CppTools diff --git a/src/plugins/cpptools/projectpart.h b/src/plugins/cpptools/projectpart.h index 010a21a3120..b7a86f15cbb 100644 --- a/src/plugins/cpptools/projectpart.h +++ b/src/plugins/cpptools/projectpart.h @@ -43,9 +43,7 @@ #include <QString> #include <QSharedPointer> -namespace ProjectExplorer { -class Project; -} +namespace ProjectExplorer { class Project; } namespace CppTools { @@ -60,60 +58,88 @@ public: using Ptr = QSharedPointer<ProjectPart>; public: + static Ptr create(const Utils::FilePath &topLevelProject, + const ProjectExplorer::RawProjectPart &rpp = {}, + const QString &displayName = {}, + const ProjectFiles &files = {}, + Utils::Language language = Utils::Language::Cxx, + Utils::LanguageExtensions languageExtensions = {}, + const ProjectExplorer::RawProjectPartFlags &flags = {}, + const ProjectExplorer::ToolChainInfo &tcInfo = {}) + { + return Ptr(new ProjectPart(topLevelProject, rpp, displayName, files, language, + languageExtensions, flags, tcInfo)); + } + QString id() const; QString projectFileLocation() const; + bool hasProject() const { return !topLevelProject.isEmpty(); } + bool belongsToProject(const ProjectExplorer::Project *project) const; - Ptr copy() const; - void updateLanguageFeatures(); - void setupToolchainProperties(const ProjectExplorer::ToolChainInfo &tcInfo, - const QStringList &flags); - - static QByteArray readProjectConfigFile(const Ptr &projectPart); + static QByteArray readProjectConfigFile(const QString &projectConfigFile); public: - ProjectExplorer::Project *project = nullptr; + const Utils::FilePath topLevelProject; + const QString displayName; + const QString projectFile; + const QString projectConfigFile; // Generic Project Manager only - QString displayName; - - QString projectFile; - int projectFileLine = -1; - int projectFileColumn = -1; - QString callGroupId; + const int projectFileLine = -1; + const int projectFileColumn = -1; + const QString callGroupId; // Versions, features and extensions - ::Utils::Language language = ::Utils::Language::Cxx; - ::Utils::LanguageVersion languageVersion = ::Utils::LanguageVersion::LatestCxx; - ::Utils::LanguageExtensions languageExtensions = ::Utils::LanguageExtension::None; - CPlusPlus::LanguageFeatures languageFeatures; - ::Utils::QtVersion qtVersion = ::Utils::QtVersion::Unknown; + const Utils::Language language = Utils::Language::Cxx; + const Utils::LanguageVersion &languageVersion = m_macroReport.languageVersion; + const Utils::LanguageExtensions languageExtensions = Utils::LanguageExtension::None; + const Utils::QtVersion qtVersion = Utils::QtVersion::Unknown; // Files - ProjectFiles files; - QStringList includedFiles; - QStringList precompiledHeaders; - ProjectExplorer::HeaderPaths headerPaths; - QString projectConfigFile; // Generic Project Manager only + const ProjectFiles files; + const QStringList includedFiles; + const QStringList precompiledHeaders; + const ProjectExplorer::HeaderPaths headerPaths; // Macros - ProjectExplorer::Macros projectMacros; - ProjectExplorer::Macros toolChainMacros; + const ProjectExplorer::Macros projectMacros; + const ProjectExplorer::Macros &toolChainMacros = m_macroReport.macros; // Build system - QString buildSystemTarget; - ProjectExplorer::BuildTargetType buildTargetType = ProjectExplorer::BuildTargetType::Unknown; - bool selectedForBuilding = true; + const QString buildSystemTarget; + const ProjectExplorer::BuildTargetType buildTargetType + = ProjectExplorer::BuildTargetType::Unknown; + const bool selectedForBuilding = true; // ToolChain - Utils::Id toolchainType; - bool isMsvc2015Toolchain = false; - QString toolChainTargetTriple; - ToolChainWordWidth toolChainWordWidth = WordWidth32Bit; - ::Utils::FilePath toolChainInstallDir; - ::Utils::WarningFlags warningFlags = ::Utils::WarningFlags::Default; + const Utils::Id toolchainType; + const bool isMsvc2015Toolchain = false; + const QString toolChainTargetTriple; + const ToolChainWordWidth toolChainWordWidth = WordWidth32Bit; + const Utils::FilePath toolChainInstallDir; + const Utils::FilePath compilerFilePath; + const Utils::WarningFlags warningFlags = Utils::WarningFlags::Default; // Misc - QStringList extraCodeModelFlags; - QStringList compilerFlags; + const QStringList extraCodeModelFlags; + const QStringList compilerFlags; + +private: + ProjectPart(const Utils::FilePath &topLevelProject, + const ProjectExplorer::RawProjectPart &rpp, + const QString &displayName, + const ProjectFiles &files, + Utils::Language language, + Utils::LanguageExtensions languageExtensions, + const ProjectExplorer::RawProjectPartFlags &flags, + const ProjectExplorer::ToolChainInfo &tcInfo); + + CPlusPlus::LanguageFeatures deriveLanguageFeatures() const; + + const ProjectExplorer::ToolChain::MacroInspectionReport m_macroReport; + +public: + // Must come last due to initialization order. + const CPlusPlus::LanguageFeatures languageFeatures; }; } // namespace CppTools diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index a4318596647..7e0906a5378 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -2333,8 +2333,7 @@ void DebuggerUnitTests::testStateMachine() QString proFile = m_tmpDir->absolutePath("simple/simple.pro"); CppTools::Tests::ProjectOpenerAndCloser projectManager; - const CppTools::ProjectInfo projectInfo = projectManager.open(proFile, true); - QVERIFY(projectInfo.isValid()); + QVERIFY(projectManager.open(proFile, true)); QEventLoop loop; connect(BuildManager::instance(), &BuildManager::buildQueueFinished, diff --git a/src/plugins/projectexplorer/rawprojectpart.cpp b/src/plugins/projectexplorer/rawprojectpart.cpp index 45041a91b29..74e9c1b8e12 100644 --- a/src/plugins/projectexplorer/rawprojectpart.cpp +++ b/src/plugins/projectexplorer/rawprojectpart.cpp @@ -26,6 +26,7 @@ #include "rawprojectpart.h" #include "abi.h" +#include "buildconfiguration.h" #include "kitinformation.h" #include "project.h" #include "projectexplorerconstants.h" @@ -187,6 +188,7 @@ ToolChainInfo::ToolChainInfo(const ToolChain *toolChain, targetTriple = toolChain->originalTargetTriple(); extraCodeModelFlags = toolChain->extraCodeModelFlags(); installDir = toolChain->installDir(); + compilerFilePath = toolChain->compilerCommand(); // ...and save the potentially expensive operations for later so that // they can be run from a worker thread. @@ -201,18 +203,17 @@ ProjectUpdateInfo::ProjectUpdateInfo(Project *project, const Utils::Environment &env, const RawProjectParts &rawProjectParts, const RppGenerator &rppGenerator) - : project(project) - , rawProjectParts(rawProjectParts) + : rawProjectParts(rawProjectParts) , rppGenerator(rppGenerator) - , cToolChain(kitInfo.cToolChain) - , cxxToolChain(kitInfo.cxxToolChain) - , cToolChainInfo(ToolChainInfo(cToolChain, kitInfo.sysRootPath, env)) - , cxxToolChainInfo(ToolChainInfo(cxxToolChain, kitInfo.sysRootPath, env)) -{} - -bool ProjectUpdateInfo::isValid() const -{ - return project && !rawProjectParts.isEmpty(); + , cToolChainInfo(ToolChainInfo(kitInfo.cToolChain, kitInfo.sysRootPath, env)) + , cxxToolChainInfo(ToolChainInfo(kitInfo.cxxToolChain, kitInfo.sysRootPath, env)) +{ + if (project) { + projectName = project->displayName(); + projectFilePath = project->projectFilePath(); + if (project->activeTarget() && project->activeTarget()->activeBuildConfiguration()) + buildRoot = project->activeTarget()->activeBuildConfiguration()->buildDirectory(); + } } } // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/rawprojectpart.h b/src/plugins/projectexplorer/rawprojectpart.h index 49452e418c3..e430dfa365d 100644 --- a/src/plugins/projectexplorer/rawprojectpart.h +++ b/src/plugins/projectexplorer/rawprojectpart.h @@ -156,6 +156,7 @@ public: bool isMsvc2015ToolChain = false; unsigned wordWidth = 0; QString targetTriple; + Utils::FilePath compilerFilePath; Utils::FilePath installDir; QStringList extraCodeModelFlags; @@ -175,16 +176,14 @@ public: const Utils::Environment &env, const RawProjectParts &rawProjectParts, const RppGenerator &rppGenerator = {}); - bool isValid() const; public: - QPointer<Project> project; + QString projectName; + Utils::FilePath projectFilePath; + Utils::FilePath buildRoot; RawProjectParts rawProjectParts; RppGenerator rppGenerator; - const ToolChain *cToolChain = nullptr; - const ToolChain *cxxToolChain = nullptr; - ToolChainInfo cToolChainInfo; ToolChainInfo cxxToolChainInfo; }; diff --git a/src/plugins/projectexplorer/session.cpp b/src/plugins/projectexplorer/session.cpp index 7f3fd32723c..1c7f33d6e5a 100644 --- a/src/plugins/projectexplorer/session.cpp +++ b/src/plugins/projectexplorer/session.cpp @@ -703,6 +703,12 @@ Project *SessionManager::projectForFile(const Utils::FilePath &fileName) [&fileName](const Project *p) { return p->isKnownFile(fileName); }); } +Project *SessionManager::projectWithProjectFilePath(const Utils::FilePath &filePath) +{ + return Utils::findOrDefault(SessionManager::projects(), + [&filePath](const Project *p) { return p->projectFilePath() == filePath; }); +} + void SessionManager::configureEditor(IEditor *editor, const QString &fileName) { if (auto textEditor = qobject_cast<TextEditor::BaseTextEditor*>(editor)) { diff --git a/src/plugins/projectexplorer/session.h b/src/plugins/projectexplorer/session.h index b05f090005d..61b88ee412e 100644 --- a/src/plugins/projectexplorer/session.h +++ b/src/plugins/projectexplorer/session.h @@ -118,6 +118,7 @@ public: static QList<Project *> projectOrder(const Project *project = nullptr); static Project *projectForFile(const Utils::FilePath &fileName); + static Project *projectWithProjectFilePath(const Utils::FilePath &filePath); static QStringList projectsForSessionName(const QString &session); diff --git a/src/plugins/todo/cpptodoitemsscanner.cpp b/src/plugins/todo/cpptodoitemsscanner.cpp index 8fa99722743..2bcdb35499b 100644 --- a/src/plugins/todo/cpptodoitemsscanner.cpp +++ b/src/plugins/todo/cpptodoitemsscanner.cpp @@ -58,9 +58,8 @@ void CppTodoItemsScanner::scannerParamsChanged() CppTools::CppModelManager *modelManager = CppTools::CppModelManager::instance(); QSet<QString> filesToBeUpdated; - foreach (const CppTools::ProjectInfo &info, modelManager->projectInfos()) - filesToBeUpdated.unite(Utils::transform<QSet>(info.project().data()->files(ProjectExplorer::Project::SourceFiles), - &Utils::FilePath::toString)); + foreach (const CppTools::ProjectInfo::Ptr &info, modelManager->projectInfos()) + filesToBeUpdated.unite(info->sourceFiles()); modelManager->updateSourceFiles(filesToBeUpdated); } |