aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/cpptools
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/cpptools')
-rw-r--r--src/plugins/cpptools/CMakeLists.txt22
-rw-r--r--src/plugins/cpptools/abstractoverviewmodel.h3
-rw-r--r--src/plugins/cpptools/builtineditordocumentparser.cpp2
-rw-r--r--src/plugins/cpptools/compileroptionsbuilder.cpp76
-rw-r--r--src/plugins/cpptools/compileroptionsbuilder.h6
-rw-r--r--src/plugins/cpptools/compileroptionsbuilder_test.cpp684
-rw-r--r--src/plugins/cpptools/compileroptionsbuilder_test.h80
-rw-r--r--src/plugins/cpptools/cppcodegen_test.cpp29
-rw-r--r--src/plugins/cpptools/cppcodegen_test.h53
-rw-r--r--src/plugins/cpptools/cppcodemodelinspectordumper.cpp21
-rw-r--r--src/plugins/cpptools/cppcodemodelinspectordumper.h2
-rw-r--r--src/plugins/cpptools/cppcodemodelsettings.cpp30
-rw-r--r--src/plugins/cpptools/cppcodemodelsettings.h5
-rw-r--r--src/plugins/cpptools/cppcodemodelsettingspage.cpp23
-rw-r--r--src/plugins/cpptools/cppcompletion_test.cpp30
-rw-r--r--src/plugins/cpptools/cppcompletion_test.h58
-rw-r--r--src/plugins/cpptools/cppfilesettingspage.cpp24
-rw-r--r--src/plugins/cpptools/cppfindreferences.cpp3
-rw-r--r--src/plugins/cpptools/cppheadersource_test.cpp18
-rw-r--r--src/plugins/cpptools/cppheadersource_test.h44
-rw-r--r--src/plugins/cpptools/cpplocalsymbols_test.cpp6
-rw-r--r--src/plugins/cpptools/cpplocalsymbols_test.h41
-rw-r--r--src/plugins/cpptools/cpplocatorfilter_test.cpp12
-rw-r--r--src/plugins/cpptools/cpplocatorfilter_test.h44
-rw-r--r--src/plugins/cpptools/cppmodelmanager.cpp187
-rw-r--r--src/plugins/cpptools/cppmodelmanager.h9
-rw-r--r--src/plugins/cpptools/cppmodelmanager_test.cpp367
-rw-r--r--src/plugins/cpptools/cppmodelmanager_test.h58
-rw-r--r--src/plugins/cpptools/cpppointerdeclarationformatter_test.cpp23
-rw-r--r--src/plugins/cpptools/cpppointerdeclarationformatter_test.h49
-rw-r--r--src/plugins/cpptools/cppprojectinfogenerator.cpp96
-rw-r--r--src/plugins/cpptools/cppprojectinfogenerator.h13
-rw-r--r--src/plugins/cpptools/cppprojectpartchooser.cpp2
-rw-r--r--src/plugins/cpptools/cppprojectupdater.cpp17
-rw-r--r--src/plugins/cpptools/cppprojectupdater.h3
-rw-r--r--src/plugins/cpptools/cpprefactoringchanges.cpp3
-rw-r--r--src/plugins/cpptools/cppsemanticinfoupdater.cpp3
-rw-r--r--src/plugins/cpptools/cppsourceprocessor_test.cpp12
-rw-r--r--src/plugins/cpptools/cppsourceprocessor_test.h44
-rw-r--r--src/plugins/cpptools/cpptools.pro16
-rw-r--r--src/plugins/cpptools/cpptools.qbs14
-rw-r--r--src/plugins/cpptools/cpptoolsjsextension.cpp3
-rw-r--r--src/plugins/cpptools/cpptoolsplugin.cpp103
-rw-r--r--src/plugins/cpptools/cpptoolsplugin.h112
-rw-r--r--src/plugins/cpptools/cpptoolsreuse.cpp12
-rw-r--r--src/plugins/cpptools/cpptoolsreuse.h4
-rw-r--r--src/plugins/cpptools/cpptoolstestcase.cpp64
-rw-r--r--src/plugins/cpptools/cpptoolstestcase.h5
-rw-r--r--src/plugins/cpptools/cpptoolsunittestfiles.pri20
-rw-r--r--src/plugins/cpptools/functionutils.cpp5
-rw-r--r--src/plugins/cpptools/functionutils.h14
-rw-r--r--src/plugins/cpptools/headerpathfilter.cpp13
-rw-r--r--src/plugins/cpptools/headerpathfilter.h7
-rw-r--r--src/plugins/cpptools/includeutils.cpp33
-rw-r--r--src/plugins/cpptools/includeutils.h16
-rw-r--r--src/plugins/cpptools/modelmanagertesthelper.cpp24
-rw-r--r--src/plugins/cpptools/modelmanagertesthelper.h7
-rw-r--r--src/plugins/cpptools/projectinfo.cpp74
-rw-r--r--src/plugins/cpptools/projectinfo.h35
-rw-r--r--src/plugins/cpptools/projectinfo_test.cpp865
-rw-r--r--src/plugins/cpptools/projectinfo_test.h109
-rw-r--r--src/plugins/cpptools/projectpart.cpp183
-rw-r--r--src/plugins/cpptools/projectpart.h106
-rw-r--r--src/plugins/cpptools/senddocumenttracker.cpp175
-rw-r--r--src/plugins/cpptools/senddocumenttracker.h31
-rw-r--r--src/plugins/cpptools/symbolsearcher_test.cpp29
-rw-r--r--src/plugins/cpptools/symbolsearcher_test.h41
-rw-r--r--src/plugins/cpptools/typehierarchybuilder_test.cpp6
-rw-r--r--src/plugins/cpptools/typehierarchybuilder_test.h41
69 files changed, 3409 insertions, 960 deletions
diff --git a/src/plugins/cpptools/CMakeLists.txt b/src/plugins/cpptools/CMakeLists.txt
index fe481af941..6e08f283f8 100644
--- a/src/plugins/cpptools/CMakeLists.txt
+++ b/src/plugins/cpptools/CMakeLists.txt
@@ -110,17 +110,19 @@ add_qtc_plugin(CppTools
extend_qtc_plugin(CppTools
CONDITION WITH_TESTS
SOURCES
- cppcodegen_test.cpp
- cppcompletion_test.cpp
- cppheadersource_test.cpp
- cpplocalsymbols_test.cpp
- cpplocatorfilter_test.cpp
- cppmodelmanager_test.cpp
- cpppointerdeclarationformatter_test.cpp
+ compileroptionsbuilder_test.cpp compileroptionsbuilder_test.h
+ cppcodegen_test.cpp cppcodegen_test.h
+ cppcompletion_test.cpp cppcompletion_test.h
+ cppheadersource_test.cpp cppheadersource_test.h
+ cpplocalsymbols_test.cpp cpplocalsymbols_test.h
+ cpplocatorfilter_test.cpp cpplocatorfilter_test.h
+ cppmodelmanager_test.cpp cppmodelmanager_test.h
+ cpppointerdeclarationformatter_test.cpp cpppointerdeclarationformatter_test.h
cppsourceprocessertesthelper.cpp cppsourceprocessertesthelper.h
- cppsourceprocessor_test.cpp
+ cppsourceprocessor_test.cpp cppsourceprocessor_test.h
cpptoolstestcase.cpp cpptoolstestcase.h
modelmanagertesthelper.cpp modelmanagertesthelper.h
- symbolsearcher_test.cpp
- typehierarchybuilder_test.cpp
+ projectinfo_test.cpp projectinfo_test.h
+ symbolsearcher_test.cpp symbolsearcher_test.h
+ typehierarchybuilder_test.cpp typehierarchybuilder_test.h
)
diff --git a/src/plugins/cpptools/abstractoverviewmodel.h b/src/plugins/cpptools/abstractoverviewmodel.h
index 1035494a37..89280cf09c 100644
--- a/src/plugins/cpptools/abstractoverviewmodel.h
+++ b/src/plugins/cpptools/abstractoverviewmodel.h
@@ -84,7 +84,8 @@ public:
const QVariant lineNumber = data(index, LineNumberRole);
if (!lineNumber.canConvert<unsigned>())
continue;
- mimeData->addFile(fileName.toString(), static_cast<int>(lineNumber.value<unsigned>()));
+ mimeData->addFile(Utils::FilePath::fromVariant(fileName),
+ static_cast<int>(lineNumber.value<unsigned>()));
}
return mimeData;
}
diff --git a/src/plugins/cpptools/builtineditordocumentparser.cpp b/src/plugins/cpptools/builtineditordocumentparser.cpp
index 390dd0420d..1d2a187432 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 7ee9b6bdf8..0c8c5d9305 100644
--- a/src/plugins/cpptools/compileroptionsbuilder.cpp
+++ b/src/plugins/cpptools/compileroptionsbuilder.cpp
@@ -45,36 +45,39 @@
#include <QRegularExpression>
#include <QtGlobal>
+using namespace ProjectExplorer;
+using namespace Utils;
+
namespace CppTools {
-static const char defineOption[] = "-D";
-static const char undefineOption[] = "-U";
+const char defineOption[] = "-D";
+const char undefineOption[] = "-U";
-static const char includeUserPathOption[] = "-I";
-static const char includeUserPathOptionWindows[] = "/I";
-static const char includeSystemPathOption[] = "-isystem";
+const char includeUserPathOption[] = "-I";
+const char includeUserPathOptionWindows[] = "/I";
+const char includeSystemPathOption[] = "-isystem";
-static const char includeFileOptionGcc[] = "-include";
-static const char includeFileOptionCl[] = "/FI";
+const char includeFileOptionGcc[] = "-include";
+const char includeFileOptionCl[] = "/FI";
-static QByteArray macroOption(const ProjectExplorer::Macro &macro)
+static QByteArray macroOption(const Macro &macro)
{
switch (macro.type) {
- case ProjectExplorer::MacroType::Define:
+ case MacroType::Define:
return defineOption;
- case ProjectExplorer::MacroType::Undefine:
+ case MacroType::Undefine:
return undefineOption;
default:
return QByteArray();
}
}
-static QByteArray toDefineOption(const ProjectExplorer::Macro &macro)
+static QByteArray toDefineOption(const Macro &macro)
{
return macro.toKeyValue(macroOption(macro));
}
-static QString defineDirectiveToDefineOption(const ProjectExplorer::Macro &macro)
+static QString defineDirectiveToDefineOption(const Macro &macro)
{
const QByteArray option = toDefineOption(macro);
return QString::fromUtf8(option);
@@ -104,7 +107,7 @@ CompilerOptionsBuilder::CompilerOptionsBuilder(const ProjectPart &projectPart,
UseLanguageDefines useLanguageDefines,
UseBuildSystemWarnings useBuildSystemWarnings,
const QString &clangVersion,
- const QString &clangIncludeDirectory)
+ const FilePath &clangIncludeDirectory)
: m_projectPart(projectPart)
, m_useSystemHeader(useSystemHeader)
, m_useTweakedHeaderPaths(useTweakedHeaderPaths)
@@ -122,13 +125,11 @@ QStringList CompilerOptionsBuilder::build(ProjectFile::Kind fileKind,
evaluateCompilerFlags();
if (fileKind == ProjectFile::CHeader || fileKind == ProjectFile::CSource) {
- QTC_ASSERT(m_projectPart.languageVersion <= Utils::LanguageVersion::LatestC,
- return QStringList(););
+ QTC_ASSERT(m_projectPart.languageVersion <= LanguageVersion::LatestC, return {});
}
if (fileKind == ProjectFile::CXXHeader || fileKind == ProjectFile::CXXSource) {
- QTC_ASSERT(m_projectPart.languageVersion > Utils::LanguageVersion::LatestC,
- return QStringList(););
+ QTC_ASSERT(m_projectPart.languageVersion > LanguageVersion::LatestC, return {});
}
addCompilerFlags();
@@ -276,7 +277,7 @@ void CompilerOptionsBuilder::addMsvcExceptions()
{
if (!m_clStyle)
return;
- if (Utils::anyOf(m_projectPart.toolChainMacros, [](const ProjectExplorer::Macro &macro) {
+ if (Utils::anyOf(m_projectPart.toolChainMacros, [](const Macro &macro) {
return macro.key == "_CPPUNWIND";
})) {
enableExceptions();
@@ -289,7 +290,7 @@ void CompilerOptionsBuilder::enableExceptions()
// This is most likely due to incomplete exception support of clang.
// However, as we need exception support only in the frontend,
// enabling them explicitly should be fine.
- if (m_projectPart.languageVersion > ::Utils::LanguageVersion::LatestC)
+ if (m_projectPart.languageVersion > LanguageVersion::LatestC)
add("-fcxx-exceptions");
add("-fexceptions");
}
@@ -345,9 +346,6 @@ void CompilerOptionsBuilder::addHeaderPathOptions()
filter.process();
- using ProjectExplorer::HeaderPath;
- using ProjectExplorer::HeaderPathType;
-
for (const HeaderPath &headerPath : qAsConst(filter.userHeaderPaths))
addIncludeDirOptionForPath(headerPath);
for (const HeaderPath &headerPath : qAsConst(filter.systemHeaderPaths))
@@ -408,11 +406,11 @@ void CompilerOptionsBuilder::addProjectMacros()
addMacros(m_projectPart.projectMacros);
}
-void CompilerOptionsBuilder::addMacros(const ProjectExplorer::Macros &macros)
+void CompilerOptionsBuilder::addMacros(const Macros &macros)
{
QStringList options;
- for (const ProjectExplorer::Macro &macro : macros) {
+ for (const Macro &macro : macros) {
if (excludeDefineDirective(macro))
continue;
@@ -445,8 +443,7 @@ void CompilerOptionsBuilder::updateFileLanguage(ProjectFile::Kind fileKind)
return;
}
- const bool objcExt = m_projectPart.languageExtensions
- & Utils::LanguageExtension::ObjectiveC;
+ const bool objcExt = m_projectPart.languageExtensions & LanguageExtension::ObjectiveC;
const QStringList options = createLanguageOptionGcc(fileKind, objcExt);
if (options.isEmpty())
return;
@@ -461,9 +458,6 @@ void CompilerOptionsBuilder::updateFileLanguage(ProjectFile::Kind fileKind)
void CompilerOptionsBuilder::addLanguageVersionAndExtensions()
{
- using Utils::LanguageExtension;
- using Utils::LanguageVersion;
-
if (m_compilerFlags.isLanguageVersionSpecified)
return;
@@ -494,7 +488,7 @@ void CompilerOptionsBuilder::addLanguageVersionAndExtensions()
// Continue in case no cl-style option could be chosen.
}
- const Utils::LanguageExtensions languageExtensions = m_projectPart.languageExtensions;
+ const LanguageExtensions languageExtensions = m_projectPart.languageExtensions;
const bool gnuExtensions = languageExtensions & LanguageExtension::Gnu;
switch (m_projectPart.languageVersion) {
@@ -546,9 +540,9 @@ static QByteArray toMsCompatibilityVersionFormat(const QByteArray &mscFullVer)
+ mscFullVer.mid(2, 2);
}
-static QByteArray msCompatibilityVersionFromDefines(const ProjectExplorer::Macros &macros)
+static QByteArray msCompatibilityVersionFromDefines(const Macros &macros)
{
- for (const ProjectExplorer::Macro &macro : macros) {
+ for (const Macro &macro : macros) {
if (macro.key == "_MSC_FULL_VER")
return toMsCompatibilityVersionFormat(macro.value);
}
@@ -656,24 +650,24 @@ void CompilerOptionsBuilder::addDefineFunctionMacrosMsvc()
}
}
-void CompilerOptionsBuilder::addIncludeDirOptionForPath(const ProjectExplorer::HeaderPath &path)
+void CompilerOptionsBuilder::addIncludeDirOptionForPath(const HeaderPath &path)
{
- if (path.type == ProjectExplorer::HeaderPathType::Framework) {
+ if (path.type == HeaderPathType::Framework) {
QTC_ASSERT(!isClStyle(), return;);
add({"-F", QDir::toNativeSeparators(path.path)});
return;
}
bool systemPath = false;
- if (path.type == ProjectExplorer::HeaderPathType::BuiltIn) {
+ if (path.type == HeaderPathType::BuiltIn) {
systemPath = true;
- } else if (path.type == ProjectExplorer::HeaderPathType::System) {
+ } else if (path.type == HeaderPathType::System) {
if (m_useSystemHeader == UseSystemHeader::Yes)
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;
}
}
@@ -686,7 +680,7 @@ void CompilerOptionsBuilder::addIncludeDirOptionForPath(const ProjectExplorer::H
add({includeUserPathOption, QDir::toNativeSeparators(path.path)});
}
-bool CompilerOptionsBuilder::excludeDefineDirective(const ProjectExplorer::Macro &macro) const
+bool CompilerOptionsBuilder::excludeDefineDirective(const Macro &macro) const
{
// Avoid setting __cplusplus & co as this might conflict with other command line flags.
// Clang should set __cplusplus based on -std= and -fms-compatibility-version version.
@@ -730,7 +724,7 @@ bool CompilerOptionsBuilder::excludeDefineDirective(const ProjectExplorer::Macro
QStringList CompilerOptionsBuilder::wrappedQtHeadersIncludePath() const
{
- if (m_projectPart.qtVersion == Utils::QtVersion::None)
+ if (m_projectPart.qtVersion == QtVersion::None)
return {};
return {"wrappedQtHeaders", "wrappedQtHeaders/QtCore"};
}
@@ -786,7 +780,7 @@ void CompilerOptionsBuilder::evaluateCompilerFlags()
qgetenv("QTC_CLANG_CMD_OPTIONS_BLACKLIST"))
.split(';', Qt::SkipEmptyParts);
- const Utils::Id &toolChain = m_projectPart.toolchainType;
+ const Id toolChain = m_projectPart.toolchainType;
bool containsDriverMode = false;
bool skipNext = false;
const QStringList allFlags = m_projectPart.compilerFlags + m_projectPart.extraCodeModelFlags;
diff --git a/src/plugins/cpptools/compileroptionsbuilder.h b/src/plugins/cpptools/compileroptionsbuilder.h
index c4d8589f17..69e2470096 100644
--- a/src/plugins/cpptools/compileroptionsbuilder.h
+++ b/src/plugins/cpptools/compileroptionsbuilder.h
@@ -50,8 +50,8 @@ public:
UseTweakedHeaderPaths useTweakedHeaderPaths = UseTweakedHeaderPaths::No,
UseLanguageDefines useLanguageDefines = UseLanguageDefines::No,
UseBuildSystemWarnings useBuildSystemWarnings = UseBuildSystemWarnings::No,
- const QString &clangVersion = QString(),
- const QString &clangIncludeDirectory = QString());
+ const QString &clangVersion = {},
+ const Utils::FilePath &clangIncludeDirectory = {});
QStringList build(ProjectFile::Kind fileKind, UsePrecompiledHeaders usePrecompiledHeaders);
QStringList options() const { return m_options; }
@@ -113,7 +113,7 @@ private:
const UseBuildSystemWarnings m_useBuildSystemWarnings;
const QString m_clangVersion;
- const QString m_clangIncludeDirectory;
+ const Utils::FilePath m_clangIncludeDirectory;
struct {
QStringList flags;
diff --git a/src/plugins/cpptools/compileroptionsbuilder_test.cpp b/src/plugins/cpptools/compileroptionsbuilder_test.cpp
new file mode 100644
index 0000000000..4847237c23
--- /dev/null
+++ b/src/plugins/cpptools/compileroptionsbuilder_test.cpp
@@ -0,0 +1,684 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "compileroptionsbuilder_test.h"
+
+#include "compileroptionsbuilder.h"
+#include "projectinfo.h"
+#include "projectpart.h"
+
+#include <projectexplorer/headerpath.h>
+#include <projectexplorer/project.h>
+#include <projectexplorer/projectexplorerconstants.h>
+#include <utils/algorithm.h>
+#include <utils/temporarydirectory.h>
+
+#include <QtTest>
+
+#include <memory>
+
+using namespace ProjectExplorer;
+
+namespace CppTools {
+namespace Internal {
+
+namespace {
+class TestHelper
+{
+public:
+ const ProjectPart &finalize()
+ {
+ QFile pchFile(pchFileNativePath());
+ pchFile.open(QIODevice::WriteOnly);
+ 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, languageExtensions,
+ rppFlags, tcInfo);
+ compilerOptionsBuilder.emplace(CompilerOptionsBuilder(*projectPart));
+ return *projectPart;
+ }
+
+ static HeaderPath builtIn(const QString &path)
+ {
+ return HeaderPath{path, HeaderPathType::BuiltIn};
+ }
+
+ QString toNative(const QString &toNative) const
+ {
+ return QDir::toNativeSeparators(toNative);
+ }
+
+ QString pchFileNativePath() const
+ {
+ return toNative(Utils::TemporaryDirectory::masterDirectoryPath()
+ + "/compileroptionsbuilder.pch");
+ }
+
+ 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 CompilerOptionsBuilderTest::testAddProjectMacros()
+{
+ TestHelper t;
+ t.finalize();
+ t.compilerOptionsBuilder->addProjectMacros();
+
+ QCOMPARE(t.compilerOptionsBuilder->options(), QStringList("-DprojectFoo=projectBar"));
+}
+
+void CompilerOptionsBuilderTest::testUnknownFlagsAreForwarded()
+{
+ TestHelper t;
+ t.flags = QStringList{"-fancyFlag"};
+ ProjectPart part = t.finalize();
+ CompilerOptionsBuilder compilerOptionsBuilder{part, UseSystemHeader::No,
+ UseTweakedHeaderPaths::No, UseLanguageDefines::Yes};
+ compilerOptionsBuilder.build(ProjectFile::CXXSource, UsePrecompiledHeaders::No);
+
+ QVERIFY(compilerOptionsBuilder.options().contains(part.compilerFlags.first()));
+}
+
+void CompilerOptionsBuilderTest::testWarningsFlagsAreNotFilteredIfRequested()
+{
+ TestHelper t;
+ t.flags = QStringList{"-Whello"};
+ ProjectPart part = t.finalize();
+ CompilerOptionsBuilder compilerOptionsBuilder{part, UseSystemHeader::No,
+ UseTweakedHeaderPaths::No, UseLanguageDefines::No,
+ UseBuildSystemWarnings::Yes};
+ compilerOptionsBuilder.build(ProjectFile::CXXSource, UsePrecompiledHeaders::No);
+
+ QVERIFY(compilerOptionsBuilder.options().contains(part.compilerFlags.first()));
+}
+
+void CompilerOptionsBuilderTest::testDiagnosticOptionsAreRemoved()
+{
+ TestHelper t;
+ t.flags = QStringList{"-Wbla", "-pedantic"};
+ ProjectPart part = t.finalize();
+ CompilerOptionsBuilder compilerOptionsBuilder{part, UseSystemHeader::No,
+ UseTweakedHeaderPaths::No, UseLanguageDefines::Yes};
+ compilerOptionsBuilder.build(ProjectFile::CXXSource, UsePrecompiledHeaders::No);
+
+ QVERIFY(!compilerOptionsBuilder.options().contains(part.compilerFlags.at(0)));
+ QVERIFY(!compilerOptionsBuilder.options().contains(part.compilerFlags.at(1)));
+}
+
+void CompilerOptionsBuilderTest::testCLanguageVersionIsRewritten()
+{
+ TestHelper t;
+ // We need to set the language version here to overcome a QTC_ASSERT checking
+ // consistency between ProjectFile::Kind and ProjectPart::LanguageVersion
+ t.flags = QStringList{"-std=c18"};
+ t.languageVersion = Utils::LanguageVersion::C18;
+ ProjectPart part = t.finalize();
+
+ CompilerOptionsBuilder compilerOptionsBuilder{part, UseSystemHeader::No,
+ UseTweakedHeaderPaths::No, UseLanguageDefines::Yes};
+ compilerOptionsBuilder.build(ProjectFile::CSource, UsePrecompiledHeaders::No);
+
+ QVERIFY(!compilerOptionsBuilder.options().contains(part.compilerFlags.first()));
+ QVERIFY(compilerOptionsBuilder.options().contains("-std=c17"));
+}
+
+void CompilerOptionsBuilderTest::testLanguageVersionIsExplicitlySetIfNotProvided()
+{
+ TestHelper t;
+ CompilerOptionsBuilder compilerOptionsBuilder{t.finalize(), UseSystemHeader::No,
+ UseTweakedHeaderPaths::No, UseLanguageDefines::Yes};
+ compilerOptionsBuilder.build(ProjectFile::CXXSource, UsePrecompiledHeaders::No);
+
+ QVERIFY(compilerOptionsBuilder.options().contains("-std=c++17"));
+}
+
+void CompilerOptionsBuilderTest::testLanguageVersionIsExplicitlySetIfNotProvidedMsvc()
+{
+ TestHelper t;
+ t.toolchainType = Constants::MSVC_TOOLCHAIN_TYPEID;
+ CompilerOptionsBuilder compilerOptionsBuilder{t.finalize(), UseSystemHeader::No,
+ UseTweakedHeaderPaths::No, UseLanguageDefines::Yes};
+ compilerOptionsBuilder.build(ProjectFile::CXXSource, UsePrecompiledHeaders::No);
+
+ QVERIFY(compilerOptionsBuilder.options().contains("/std:c++17"));
+}
+
+void CompilerOptionsBuilderTest::testAddWordWidth()
+{
+ TestHelper t;
+ t.finalize();
+ t.compilerOptionsBuilder->addWordWidth();
+
+ QCOMPARE(t.compilerOptionsBuilder->options(), QStringList("-m64"));
+}
+
+void CompilerOptionsBuilderTest::testHeaderPathOptionsOrder()
+{
+ TestHelper t;
+ CompilerOptionsBuilder compilerOptionsBuilder{t.finalize(), UseSystemHeader::No,
+ UseTweakedHeaderPaths::Yes, UseLanguageDefines::No, UseBuildSystemWarnings::No,
+ "dummy_version", ""};
+ compilerOptionsBuilder.addHeaderPathOptions();
+
+ QCOMPARE(compilerOptionsBuilder.options(),
+ (QStringList{"-nostdinc", "-nostdinc++", "-I", t.toNative("/tmp/path"),
+ "-I", t.toNative("/tmp/system_path"), "-isystem", "", "-isystem",
+ t.toNative("/tmp/builtin_path")}));
+}
+
+void CompilerOptionsBuilderTest::testHeaderPathOptionsOrderMsvc()
+{
+ TestHelper t;
+ t.toolchainType = Constants::MSVC_TOOLCHAIN_TYPEID;
+ CompilerOptionsBuilder compilerOptionsBuilder{t.finalize(), UseSystemHeader::No,
+ UseTweakedHeaderPaths::Yes, UseLanguageDefines::No, UseBuildSystemWarnings::No,
+ "dummy_version", ""};
+ compilerOptionsBuilder.evaluateCompilerFlags();
+ compilerOptionsBuilder.addHeaderPathOptions();
+
+ QCOMPARE(compilerOptionsBuilder.options(),
+ (QStringList{"-nostdinc", "-nostdinc++", "-I", t.toNative("/tmp/path"),
+ "-I", t.toNative("/tmp/system_path"), "/clang:-isystem",
+ "/clang:", "/clang:-isystem",
+ "/clang:" + t.toNative("/tmp/builtin_path")}));
+}
+
+void CompilerOptionsBuilderTest::testUseSystemHeader()
+{
+ TestHelper t;
+ CompilerOptionsBuilder compilerOptionsBuilder{t.finalize(), UseSystemHeader::Yes,
+ UseTweakedHeaderPaths::Yes, UseLanguageDefines::No, UseBuildSystemWarnings::No,
+ "dummy_version", ""};
+ compilerOptionsBuilder.addHeaderPathOptions();
+
+ QCOMPARE(compilerOptionsBuilder.options(),
+ (QStringList{"-nostdinc", "-nostdinc++", "-I", t.toNative("/tmp/path"),
+ "-isystem", t.toNative("/tmp/system_path"),
+ "-isystem", "", "-isystem", t.toNative("/tmp/builtin_path")}));
+}
+
+void CompilerOptionsBuilderTest::testNoClangHeadersPath()
+{
+ TestHelper t;
+ t.finalize();
+ t.compilerOptionsBuilder->addHeaderPathOptions();
+
+ QCOMPARE(t.compilerOptionsBuilder->options(),
+ (QStringList{"-I", t.toNative("/tmp/path"), "-I", t.toNative("/tmp/system_path")}));
+}
+
+void CompilerOptionsBuilderTest::testClangHeadersAndCppIncludePathsOrderMacOs()
+{
+ TestHelper t;
+ 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.headerPaths = additionalHeaderPaths + t.headerPaths;
+ CompilerOptionsBuilder compilerOptionsBuilder(t.finalize(), UseSystemHeader::No,
+ UseTweakedHeaderPaths::Yes, UseLanguageDefines::No, UseBuildSystemWarnings::No,
+ "dummy_version", "");
+ compilerOptionsBuilder.addHeaderPathOptions();
+
+ QCOMPARE(compilerOptionsBuilder.options(),
+ (QStringList{"-nostdinc", "-nostdinc++", "-I", t.toNative("/tmp/path"),
+ "-I", t.toNative("/tmp/system_path"),
+ "-isystem", t.toNative("/usr/include/c++/4.2.1"),
+ "-isystem", t.toNative("/usr/include/c++/4.2.1/backward"),
+ "-isystem", t.toNative("/usr/local/include"),
+ "-isystem", "",
+ "-isystem", t.toNative("/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include"),
+ "-isystem", t.toNative("/usr/include"),
+ "-isystem", t.toNative("/tmp/builtin_path")}));
+}
+
+void CompilerOptionsBuilderTest::testClangHeadersAndCppIncludePathsOrderLinux()
+{
+ TestHelper t;
+ 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")};
+ CompilerOptionsBuilder compilerOptionsBuilder(t.finalize(), UseSystemHeader::No,
+ UseTweakedHeaderPaths::Yes, UseLanguageDefines::No, UseBuildSystemWarnings::No,
+ "dummy_version", "");
+ compilerOptionsBuilder.addHeaderPathOptions();
+
+ QCOMPARE(compilerOptionsBuilder.options(),
+ (QStringList{"-nostdinc", "-nostdinc++",
+ "-isystem", t.toNative("/usr/include/c++/4.8"),
+ "-isystem", t.toNative("/usr/include/c++/4.8/backward"),
+ "-isystem", t.toNative("/usr/include/x86_64-linux-gnu/c++/4.8"),
+ "-isystem", t.toNative("/usr/local/include"),
+ "-isystem", "",
+ "-isystem", t.toNative("/usr/lib/gcc/x86_64-linux-gnu/4.8/include"),
+ "-isystem", t.toNative("/usr/include/x86_64-linux-gnu"),
+ "-isystem", t.toNative("/usr/include")}));
+}
+
+void CompilerOptionsBuilderTest::testClangHeadersAndCppIncludePathsOrderNoVersion()
+{
+ TestHelper t;
+ 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")};
+ CompilerOptionsBuilder compilerOptionsBuilder(t.finalize(), UseSystemHeader::No,
+ UseTweakedHeaderPaths::Yes, UseLanguageDefines::No, UseBuildSystemWarnings::No,
+ "dummy_version", "");
+ compilerOptionsBuilder.addHeaderPathOptions();
+
+ QCOMPARE(compilerOptionsBuilder.options(),
+ (QStringList{"-nostdinc", "-nostdinc++",
+ "-isystem", t.toNative("C:/mingw530/i686-w64-mingw32/include/c++"),
+ "-isystem", t.toNative("C:/mingw530/i686-w64-mingw32/include/c++/i686-w64-mingw32"),
+ "-isystem", t.toNative("C:/mingw530/i686-w64-mingw32/include/c++/backward"),
+ "-isystem", "",
+ "-isystem", t.toNative("C:/mingw530/i686-w64-mingw32/include")}));
+}
+
+void CompilerOptionsBuilderTest::testClangHeadersAndCppIncludePathsOrderAndroidClang()
+{
+ TestHelper t;
+ 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")};
+ CompilerOptionsBuilder compilerOptionsBuilder(t.finalize(), UseSystemHeader::No,
+ UseTweakedHeaderPaths::Yes, UseLanguageDefines::No, UseBuildSystemWarnings::No,
+ "dummy_version", "");
+ compilerOptionsBuilder.addHeaderPathOptions();
+
+ QCOMPARE(compilerOptionsBuilder.options(),
+ (QStringList{"-nostdinc", "-nostdinc++",
+ "-isystem", t.toNative("C:/Android/sdk/ndk-bundle/sources/cxx-stl/llvm-libc++/include"),
+ "-isystem", t.toNative("C:/Android/sdk/ndk-bundle/sources/cxx-stl/llvm-libc++abi/include"),
+ "-isystem", t.toNative(""),
+ "-isystem", t.toNative("C:/Android/sdk/ndk-bundle/sysroot/usr/include/i686-linux-android"),
+ "-isystem", t.toNative("C:/Android/sdk/ndk-bundle/sources/android/support/include"),
+ "-isystem", t.toNative("C:/Android/sdk/ndk-bundle/sysroot/usr/include")}));
+}
+
+void CompilerOptionsBuilderTest::testNoPrecompiledHeader()
+{
+ TestHelper t;
+ t.finalize();
+ t.compilerOptionsBuilder->addPrecompiledHeaderOptions(UsePrecompiledHeaders::No);
+
+ QVERIFY(t.compilerOptionsBuilder->options().empty());
+}
+
+void CompilerOptionsBuilderTest::testUsePrecompiledHeader()
+{
+ TestHelper t;
+ t.finalize();
+ t.compilerOptionsBuilder->addPrecompiledHeaderOptions(UsePrecompiledHeaders::Yes);
+
+ QCOMPARE(t.compilerOptionsBuilder->options(), (QStringList{"-include", t.pchFileNativePath()}));
+}
+
+void CompilerOptionsBuilderTest::testUsePrecompiledHeaderMsvc()
+{
+ TestHelper t;
+ t.toolchainType = Constants::MSVC_TOOLCHAIN_TYPEID;
+ CompilerOptionsBuilder compilerOptionsBuilder{t.finalize()};
+ compilerOptionsBuilder.evaluateCompilerFlags();
+ compilerOptionsBuilder.addPrecompiledHeaderOptions(UsePrecompiledHeaders::Yes);
+
+ QCOMPARE(compilerOptionsBuilder.options(), (QStringList{"/FI", t.pchFileNativePath()}));
+}
+
+void CompilerOptionsBuilderTest::testAddMacros()
+{
+ TestHelper t;
+ t.finalize();
+ t.compilerOptionsBuilder->addMacros(Macros{Macro{"key", "value"}});
+
+ QCOMPARE(t.compilerOptionsBuilder->options(), QStringList("-Dkey=value"));
+}
+
+void CompilerOptionsBuilderTest::testAddTargetTriple()
+{
+ TestHelper t;
+ t.finalize();
+ t.compilerOptionsBuilder->addTargetTriple();
+
+ QCOMPARE(t.compilerOptionsBuilder->options(), QStringList("--target=x86_64-apple-darwin10"));
+}
+
+void CompilerOptionsBuilderTest::testEnableCExceptions()
+{
+ TestHelper t;
+ t.languageVersion = Utils::LanguageVersion::C99;
+ t.finalize();
+ t.compilerOptionsBuilder->enableExceptions();
+
+ QCOMPARE(t.compilerOptionsBuilder->options(), QStringList("-fexceptions"));
+}
+
+void CompilerOptionsBuilderTest::testEnableCxxExceptions()
+{
+ TestHelper t;
+ t.finalize();
+ t.compilerOptionsBuilder->enableExceptions();
+
+ QCOMPARE(t.compilerOptionsBuilder->options(), (QStringList{"-fcxx-exceptions", "-fexceptions"}));
+}
+
+void CompilerOptionsBuilderTest::testInsertWrappedQtHeaders()
+{
+ TestHelper t;
+ CompilerOptionsBuilder compilerOptionsBuilder{t.finalize(), UseSystemHeader::Yes,
+ UseTweakedHeaderPaths::Yes, UseLanguageDefines::No, UseBuildSystemWarnings::No,
+ "dummy_version", ""};
+ compilerOptionsBuilder.insertWrappedQtHeaders();
+
+ QVERIFY(Utils::contains(compilerOptionsBuilder.options(),
+ [](const QString &o) { return o.contains("wrappedQtHeaders"); }));
+}
+
+void CompilerOptionsBuilderTest::testInsertWrappedMingwHeadersWithNonMingwToolchain()
+{
+ TestHelper t;
+ CompilerOptionsBuilder builder{t.finalize(), UseSystemHeader::Yes, UseTweakedHeaderPaths::Yes,
+ UseLanguageDefines::No, UseBuildSystemWarnings::No, "dummy_version", ""};
+ builder.insertWrappedMingwHeaders();
+
+ QVERIFY(!Utils::contains(builder.options(),
+ [](const QString &o) { return o.contains("wrappedMingwHeaders"); }));
+}
+
+void CompilerOptionsBuilderTest::testInsertWrappedMingwHeadersWithMingwToolchain()
+{
+ TestHelper t;
+ t.toolchainType = Constants::MINGW_TOOLCHAIN_TYPEID;
+ CompilerOptionsBuilder builder{t.finalize(), UseSystemHeader::Yes, UseTweakedHeaderPaths::Yes,
+ UseLanguageDefines::No, UseBuildSystemWarnings::No, "dummy_version", ""};
+ builder.insertWrappedMingwHeaders();
+
+ QVERIFY(Utils::contains(builder.options(),
+ [](const QString &o) { return o.contains("wrappedMingwHeaders"); }));
+}
+
+void CompilerOptionsBuilderTest::testSetLanguageVersion()
+{
+ TestHelper t;
+ t.finalize();
+ t.compilerOptionsBuilder->updateFileLanguage(ProjectFile::CXXSource);
+
+ QCOMPARE(t.compilerOptionsBuilder->options(), (QStringList{"-x", "c++"}));
+}
+
+void CompilerOptionsBuilderTest::testSetLanguageVersionMsvc()
+{
+ TestHelper t;
+ t.toolchainType = Constants::MSVC_TOOLCHAIN_TYPEID;
+ CompilerOptionsBuilder compilerOptionsBuilder{t.finalize()};
+ compilerOptionsBuilder.evaluateCompilerFlags();
+ compilerOptionsBuilder.updateFileLanguage(ProjectFile::CXXSource);
+
+ QCOMPARE(compilerOptionsBuilder.options(), QStringList("/TP"));
+}
+
+void CompilerOptionsBuilderTest::testHandleLanguageExtension()
+{
+ TestHelper t;
+ 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++"}));
+}
+
+void CompilerOptionsBuilderTest::testUpdateLanguageVersion()
+{
+ TestHelper t;
+ t.finalize();
+ t.compilerOptionsBuilder->updateFileLanguage(ProjectFile::CXXSource);
+ t.compilerOptionsBuilder->updateFileLanguage(ProjectFile::CXXHeader);
+
+ QCOMPARE(t.compilerOptionsBuilder->options(), (QStringList{"-x", "c++-header"}));
+}
+
+void CompilerOptionsBuilderTest::testUpdateLanguageVersionMsvc()
+{
+ TestHelper t;
+ t.toolchainType = Constants::MSVC_TOOLCHAIN_TYPEID;
+ CompilerOptionsBuilder compilerOptionsBuilder{t.finalize()};
+ compilerOptionsBuilder.evaluateCompilerFlags();
+ compilerOptionsBuilder.updateFileLanguage(ProjectFile::CXXSource);
+ compilerOptionsBuilder.updateFileLanguage(ProjectFile::CSource);
+
+ QCOMPARE(compilerOptionsBuilder.options(), QStringList("/TC"));
+}
+
+void CompilerOptionsBuilderTest::testAddMsvcCompatibilityVersion()
+{
+ TestHelper t;
+ 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"));
+}
+
+void CompilerOptionsBuilderTest::testUndefineCppLanguageFeatureMacrosForMsvc2015()
+{
+ TestHelper t;
+ t.toolchainType = Constants::MSVC_TOOLCHAIN_TYPEID;
+ t.isMsvc2015 = true;
+ t.finalize();
+ t.compilerOptionsBuilder->undefineCppLanguageFeatureMacrosForMsvc2015();
+
+ QVERIFY(t.compilerOptionsBuilder->options().contains("-U__cpp_aggregate_bases"));
+}
+
+void CompilerOptionsBuilderTest::testAddDefineFunctionMacrosMsvc()
+{
+ TestHelper t;
+ t.toolchainType = Constants::MSVC_TOOLCHAIN_TYPEID;
+ t.finalize();
+ t.compilerOptionsBuilder->addDefineFunctionMacrosMsvc();
+
+ QVERIFY(t.compilerOptionsBuilder->options().contains(
+ "-D__FUNCTION__=\"someLegalAndLongishFunctionNameThatWorksAroundQTCREATORBUG-24580\""));
+}
+
+void CompilerOptionsBuilderTest::testAddProjectConfigFileInclude()
+{
+ TestHelper t;
+ t.projectConfigFile = "dummy_file.h";
+ t.finalize();
+ t.compilerOptionsBuilder->addProjectConfigFileInclude();
+
+ QCOMPARE(t.compilerOptionsBuilder->options(), (QStringList{"-include", "dummy_file.h"}));
+}
+
+void CompilerOptionsBuilderTest::testAddProjectConfigFileIncludeMsvc()
+{
+ TestHelper t;
+ t.projectConfigFile = "dummy_file.h";
+ t.toolchainType = Constants::MSVC_TOOLCHAIN_TYPEID;
+ CompilerOptionsBuilder compilerOptionsBuilder{t.finalize()};
+ compilerOptionsBuilder.evaluateCompilerFlags();
+ compilerOptionsBuilder.addProjectConfigFileInclude();
+
+ QCOMPARE(compilerOptionsBuilder.options(), (QStringList{"/FI", "dummy_file.h"}));
+}
+
+void CompilerOptionsBuilderTest::testNoUndefineClangVersionMacrosForNewMsvc()
+{
+ TestHelper t;
+ t.toolchainType = Constants::MSVC_TOOLCHAIN_TYPEID;
+ t.finalize();
+ t.compilerOptionsBuilder->undefineClangVersionMacrosForMsvc();
+
+ QVERIFY(!t.compilerOptionsBuilder->options().contains("-U__clang__"));
+}
+
+void CompilerOptionsBuilderTest::testUndefineClangVersionMacrosForOldMsvc()
+{
+ TestHelper t;
+ 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__"));
+}
+
+void CompilerOptionsBuilderTest::testBuildAllOptions()
+{
+ TestHelper t;
+ 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);
+
+ const QString wrappedQtHeadersPath = Utils::findOrDefault(compilerOptionsBuilder.options(),
+ [](const QString &o) { return o.contains("wrappedQtHeaders"); });
+ const QString wrappedQtCoreHeadersPath = Utils::findOrDefault(compilerOptionsBuilder.options(),
+ [&t](const QString &o) { return o.contains(t.toNative("wrappedQtHeaders/QtCore")); });
+ QCOMPARE(compilerOptionsBuilder.options(),
+ (QStringList{"-nostdinc", "-nostdinc++", "-arch", "x86_64", "-fsyntax-only", "-m64",
+ "--target=x86_64-apple-darwin10", "-x", "c++", "-std=c++17",
+ "-DprojectFoo=projectBar", "-I", wrappedQtHeadersPath,
+ "-I", wrappedQtCoreHeadersPath,
+ "-I", t.toNative("/tmp/path"),
+ "-I", t.toNative("/tmp/system_path"),
+ "-isystem", "",
+ "-isystem", t.toNative("/tmp/builtin_path")}));
+}
+
+void CompilerOptionsBuilderTest::testBuildAllOptionsMsvc()
+{
+ TestHelper t;
+ 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);
+
+ const QString wrappedQtHeadersPath = Utils::findOrDefault(compilerOptionsBuilder.options(),
+ [](const QString &o) { return o.contains("wrappedQtHeaders"); });
+ const QString wrappedQtCoreHeadersPath = Utils::findOrDefault(compilerOptionsBuilder.options(),
+ [&t](const QString &o) { return o.contains(t.toNative("wrappedQtHeaders/QtCore")); });
+ QCOMPARE(compilerOptionsBuilder.options(),
+ (QStringList{"-nostdinc", "-nostdinc++", "--driver-mode=cl", "/Zs", "-m64",
+ "--target=x86_64-apple-darwin10", "/TP", "/std:c++17",
+ "-fms-compatibility-version=19.00", "-DprojectFoo=projectBar",
+ "-D__FUNCSIG__=\"void __cdecl someLegalAndLongishFunctionNameThatWorksAroundQTCREATORBUG-24580(void)\"",
+ "-D__FUNCTION__=\"someLegalAndLongishFunctionNameThatWorksAroundQTCREATORBUG-24580\"",
+ "-D__FUNCDNAME__=\"?someLegalAndLongishFunctionNameThatWorksAroundQTCREATORBUG-24580@@YAXXZ\"",
+ "-I", wrappedQtHeadersPath,
+ "-I", wrappedQtCoreHeadersPath,
+ "-I", t.toNative("/tmp/path"),
+ "-I", t.toNative("/tmp/system_path"),
+ "/clang:-isystem", "/clang:",
+ "/clang:-isystem", "/clang:" + t.toNative("/tmp/builtin_path")}));
+}
+
+void CompilerOptionsBuilderTest::testBuildAllOptionsMsvcWithExceptions()
+{
+ TestHelper t;
+ 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);
+
+ const QString wrappedQtHeadersPath = Utils::findOrDefault(compilerOptionsBuilder.options(),
+ [](const QString &o) { return o.contains("wrappedQtHeaders"); });
+ const QString wrappedQtCoreHeadersPath = Utils::findOrDefault(compilerOptionsBuilder.options(),
+ [&t](const QString &o) { return o.contains(t.toNative("wrappedQtHeaders/QtCore")); });
+ QCOMPARE(compilerOptionsBuilder.options(),
+ (QStringList{"-nostdinc", "-nostdinc++", "--driver-mode=cl", "/Zs", "-m64",
+ "--target=x86_64-apple-darwin10", "/TP", "/std:c++17", "-fcxx-exceptions",
+ "-fexceptions", "-fms-compatibility-version=19.00",
+ "-DprojectFoo=projectBar",
+ "-D__FUNCSIG__=\"void __cdecl someLegalAndLongishFunctionNameThatWorksAroundQTCREATORBUG-24580(void)\"",
+ "-D__FUNCTION__=\"someLegalAndLongishFunctionNameThatWorksAroundQTCREATORBUG-24580\"",
+ "-D__FUNCDNAME__=\"?someLegalAndLongishFunctionNameThatWorksAroundQTCREATORBUG-24580@@YAXXZ\"",
+ "-I", wrappedQtHeadersPath,
+ "-I", wrappedQtCoreHeadersPath,
+ "-I", t.toNative("/tmp/path"),
+ "-I", t.toNative("/tmp/system_path"),
+ "/clang:-isystem", "/clang:",
+ "/clang:-isystem", "/clang:" + t.toNative("/tmp/builtin_path")}));
+}
+
+} // namespace Internal
+} // namespace CppTools
diff --git a/src/plugins/cpptools/compileroptionsbuilder_test.h b/src/plugins/cpptools/compileroptionsbuilder_test.h
new file mode 100644
index 0000000000..83de91a461
--- /dev/null
+++ b/src/plugins/cpptools/compileroptionsbuilder_test.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QObject>
+
+namespace CppTools::Internal {
+
+class CompilerOptionsBuilderTest : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void testAddProjectMacros();
+ void testUnknownFlagsAreForwarded();
+ void testWarningsFlagsAreNotFilteredIfRequested();
+ void testDiagnosticOptionsAreRemoved();
+ void testCLanguageVersionIsRewritten();
+ void testLanguageVersionIsExplicitlySetIfNotProvided();
+ void testLanguageVersionIsExplicitlySetIfNotProvidedMsvc();
+ void testAddWordWidth();
+ void testHeaderPathOptionsOrder();
+ void testHeaderPathOptionsOrderMsvc();
+ void testUseSystemHeader();
+ void testNoClangHeadersPath();
+ void testClangHeadersAndCppIncludePathsOrderMacOs();
+ void testClangHeadersAndCppIncludePathsOrderLinux();
+ void testClangHeadersAndCppIncludePathsOrderNoVersion();
+ void testClangHeadersAndCppIncludePathsOrderAndroidClang();
+ void testNoPrecompiledHeader();
+ void testUsePrecompiledHeader();
+ void testUsePrecompiledHeaderMsvc();
+ void testAddMacros();
+ void testAddTargetTriple();
+ void testEnableCExceptions();
+ void testEnableCxxExceptions();
+ void testInsertWrappedQtHeaders();
+ void testInsertWrappedMingwHeadersWithNonMingwToolchain();
+ void testInsertWrappedMingwHeadersWithMingwToolchain();
+ void testSetLanguageVersion();
+ void testSetLanguageVersionMsvc();
+ void testHandleLanguageExtension();
+ void testUpdateLanguageVersion();
+ void testUpdateLanguageVersionMsvc();
+ void testAddMsvcCompatibilityVersion();
+ void testUndefineCppLanguageFeatureMacrosForMsvc2015();
+ void testAddDefineFunctionMacrosMsvc();
+ void testAddProjectConfigFileInclude();
+ void testAddProjectConfigFileIncludeMsvc();
+ void testNoUndefineClangVersionMacrosForNewMsvc();
+ void testUndefineClangVersionMacrosForOldMsvc();
+ void testBuildAllOptions();
+ void testBuildAllOptionsMsvc();
+ void testBuildAllOptionsMsvcWithExceptions();
+};
+
+} // namespace CppTools::Internal
diff --git a/src/plugins/cpptools/cppcodegen_test.cpp b/src/plugins/cpptools/cppcodegen_test.cpp
index 088e55c9de..6c4ac101eb 100644
--- a/src/plugins/cpptools/cppcodegen_test.cpp
+++ b/src/plugins/cpptools/cppcodegen_test.cpp
@@ -23,7 +23,8 @@
**
****************************************************************************/
-#include "cpptoolsplugin.h"
+#include "cppcodegen_test.h"
+
#include "cpptoolstestcase.h"
#include "insertionpointlocator.h"
@@ -73,7 +74,7 @@ Document::Ptr createDocumentAndFile(Tests::TemporaryDir *temporaryDir,
/*!
Should insert at line 3, column 1, with "public:\n" as prefix and without suffix.
*/
-void CppToolsPlugin::test_codegen_public_in_empty_class()
+void CodegenTest::testPublicInEmptyClass()
{
const QByteArray src = "\n"
"class Foo\n" // line 1
@@ -106,7 +107,7 @@ void CppToolsPlugin::test_codegen_public_in_empty_class()
/*!
Should insert at line 3, column 1, without prefix and without suffix.
*/
-void CppToolsPlugin::test_codegen_public_in_nonempty_class()
+void CodegenTest::testPublicInNonemptyClass()
{
const QByteArray src = "\n"
"class Foo\n" // line 1
@@ -140,7 +141,7 @@ void CppToolsPlugin::test_codegen_public_in_nonempty_class()
/*!
Should insert at line 3, column 1, with "public:\n" as prefix and "\n suffix.
*/
-void CppToolsPlugin::test_codegen_public_before_protected()
+void CodegenTest::testPublicBeforeProtected()
{
const QByteArray src = "\n"
"class Foo\n" // line 1
@@ -175,7 +176,7 @@ void CppToolsPlugin::test_codegen_public_before_protected()
Should insert at line 4, column 1, with "private:\n" as prefix and without
suffix.
*/
-void CppToolsPlugin::test_codegen_private_after_protected()
+void CodegenTest::testPrivateAfterProtected()
{
const QByteArray src = "\n"
"class Foo\n" // line 1
@@ -210,7 +211,7 @@ void CppToolsPlugin::test_codegen_private_after_protected()
Should insert at line 4, column 1, with "protected:\n" as prefix and without
suffix.
*/
-void CppToolsPlugin::test_codegen_protected_in_nonempty_class()
+void CodegenTest::testProtectedInNonemptyClass()
{
const QByteArray src = "\n"
"class Foo\n" // line 1
@@ -244,7 +245,7 @@ void CppToolsPlugin::test_codegen_protected_in_nonempty_class()
/*!
Should insert at line 4, column 1, with "protected\n" as prefix and "\n" suffix.
*/
-void CppToolsPlugin::test_codegen_protected_between_public_and_private()
+void CodegenTest::testProtectedBetweenPublicAndPrivate()
{
const QByteArray src = "\n"
"class Foo\n" // line 1
@@ -283,7 +284,7 @@ void CppToolsPlugin::test_codegen_protected_between_public_and_private()
This is the typical Qt Designer case, with test-input like what the integration
generates.
*/
-void CppToolsPlugin::test_codegen_qtdesigner_integration()
+void CodegenTest::testQtdesignerIntegration()
{
const QByteArray src = "/**** Some long (C)opyright notice ****/\n"
"#ifndef MAINWINDOW_H\n"
@@ -332,7 +333,7 @@ void CppToolsPlugin::test_codegen_qtdesigner_integration()
QCOMPARE(loc.column(), 1);
}
-void CppToolsPlugin::test_codegen_definition_empty_class()
+void CodegenTest::testDefinitionEmptyClass()
{
Tests::TemporaryDir temporaryDir;
QVERIFY(temporaryDir.isValid());
@@ -378,7 +379,7 @@ void CppToolsPlugin::test_codegen_definition_empty_class()
QCOMPARE(loc.column(), 1);
}
-void CppToolsPlugin::test_codegen_definition_first_member()
+void CodegenTest::testDefinitionFirstMember()
{
Tests::TemporaryDir temporaryDir;
QVERIFY(temporaryDir.isValid());
@@ -436,7 +437,7 @@ void CppToolsPlugin::test_codegen_definition_first_member()
QCOMPARE(loc.prefix(), QString());
}
-void CppToolsPlugin::test_codegen_definition_last_member()
+void CodegenTest::testDefinitionLastMember()
{
Tests::TemporaryDir temporaryDir;
QVERIFY(temporaryDir.isValid());
@@ -495,7 +496,7 @@ void CppToolsPlugin::test_codegen_definition_last_member()
QCOMPARE(loc.suffix(), QString());
}
-void CppToolsPlugin::test_codegen_definition_middle_member()
+void CodegenTest::testDefinitionMiddleMember()
{
Tests::TemporaryDir temporaryDir;
QVERIFY(temporaryDir.isValid());
@@ -561,7 +562,7 @@ void CppToolsPlugin::test_codegen_definition_middle_member()
QCOMPARE(loc.suffix(), QString());
}
-void CppToolsPlugin::test_codegen_definition_middle_member_surrounded_by_undefined()
+void CodegenTest::testDefinitionMiddleMemberSurroundedByUndefined()
{
Tests::TemporaryDir temporaryDir;
QVERIFY(temporaryDir.isValid());
@@ -621,7 +622,7 @@ void CppToolsPlugin::test_codegen_definition_middle_member_surrounded_by_undefin
QCOMPARE(loc.suffix(), QLatin1String("\n\n"));
}
-void CppToolsPlugin::test_codegen_definition_member_specific_file()
+void CodegenTest::testDefinitionMemberSpecificFile()
{
Tests::TemporaryDir temporaryDir;
QVERIFY(temporaryDir.isValid());
diff --git a/src/plugins/cpptools/cppcodegen_test.h b/src/plugins/cpptools/cppcodegen_test.h
new file mode 100644
index 0000000000..f3dfd1426b
--- /dev/null
+++ b/src/plugins/cpptools/cppcodegen_test.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QObject>
+
+namespace CppTools::Internal {
+
+class CodegenTest : public QObject
+{
+ Q_OBJECT
+public:
+
+private slots:
+ void testPublicInEmptyClass();
+ void testPublicInNonemptyClass();
+ void testPublicBeforeProtected();
+ void testPrivateAfterProtected();
+ void testProtectedInNonemptyClass();
+ void testProtectedBetweenPublicAndPrivate();
+ void testQtdesignerIntegration();
+ void testDefinitionEmptyClass();
+ void testDefinitionFirstMember();
+ void testDefinitionLastMember();
+ void testDefinitionMiddleMember();
+ void testDefinitionMiddleMemberSurroundedByUndefined();
+ void testDefinitionMemberSpecificFile();
+};
+
+} // namespace CppTools::Internal
diff --git a/src/plugins/cpptools/cppcodemodelinspectordumper.cpp b/src/plugins/cpptools/cppcodemodelinspectordumper.cpp
index 12ed4b3f16..44c968e10b 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>
@@ -502,7 +503,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);
@@ -510,18 +511,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 c7769315c1..ef48abbfd5 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/cppcodemodelsettings.cpp b/src/plugins/cpptools/cppcodemodelsettings.cpp
index c7cfc2d0cb..9a07c85ef2 100644
--- a/src/plugins/cpptools/cppcodemodelsettings.cpp
+++ b/src/plugins/cpptools/cppcodemodelsettings.cpp
@@ -69,6 +69,7 @@ static QString useClangdKey() { return QLatin1String("UseClangd"); }
static QString clangdPathKey() { return QLatin1String("ClangdPath"); }
static QString clangdIndexingKey() { return QLatin1String("ClangdIndexing"); }
static QString clangdThreadLimitKey() { return QLatin1String("ClangdThreadLimit"); }
+static QString clangdDocumentThresholdKey() { return QLatin1String("ClangdDocumentThreshold"); }
static QString clangdUseGlobalSettingsKey() { return QLatin1String("useGlobalSettings"); }
static FilePath g_defaultClangdFilePath;
@@ -76,14 +77,14 @@ static FilePath fallbackClangdFilePath()
{
if (g_defaultClangdFilePath.exists())
return g_defaultClangdFilePath;
- return FilePath::fromString("clangd");
+ return "clangd";
}
-static Utils::Id clangDiagnosticConfigIdFromSettings(QSettings *s)
+static Id clangDiagnosticConfigIdFromSettings(QSettings *s)
{
- QTC_ASSERT(s->group() == QLatin1String(Constants::CPPTOOLS_SETTINGSGROUP), return Utils::Id());
+ QTC_ASSERT(s->group() == QLatin1String(Constants::CPPTOOLS_SETTINGSGROUP), return Id());
- return Utils::Id::fromSetting(
+ return Id::fromSetting(
s->value(clangDiagnosticConfigKey(), initialClangDiagnosticConfigId().toSetting()));
}
@@ -132,7 +133,7 @@ static ClangDiagnosticConfigs removedBuiltinConfigs()
return configs;
}
-static ClangDiagnosticConfig convertToCustomConfig(const Utils::Id &id)
+static ClangDiagnosticConfig convertToCustomConfig(const Id &id)
{
const ClangDiagnosticConfig config
= Utils::findOrDefault(removedBuiltinConfigs(), [id](const ClangDiagnosticConfig &config) {
@@ -150,7 +151,7 @@ void CppCodeModelSettings::fromSettings(QSettings *s)
// Qt Creator 4.11 removes some built-in configs.
bool write = false;
- const Utils::Id id = m_clangDiagnosticConfigId;
+ const Id id = m_clangDiagnosticConfigId;
if (id == "Builtin.Pedantic" || id == "Builtin.EverythingWithExceptions") {
// If one of them was used, continue to use it, but convert it to a custom config.
const ClangDiagnosticConfig customConfig = convertToCustomConfig(id);
@@ -191,7 +192,7 @@ void CppCodeModelSettings::toSettings(QSettings *s)
{
s->beginGroup(QLatin1String(Constants::CPPTOOLS_SETTINGSGROUP));
const ClangDiagnosticConfigs previousConfigs = diagnosticConfigsFromSettings(s);
- const Utils::Id previousConfigId = clangDiagnosticConfigIdFromSettings(s);
+ const Id previousConfigId = clangDiagnosticConfigIdFromSettings(s);
diagnosticConfigsToSettings(s, m_clangCustomDiagnosticConfigs);
@@ -205,7 +206,7 @@ void CppCodeModelSettings::toSettings(QSettings *s)
s->endGroup();
- QVector<Utils::Id> invalidated
+ QVector<Id> invalidated
= ClangDiagnosticConfigsModel::changedOrRemovedConfigs(previousConfigs,
m_clangCustomDiagnosticConfigs);
@@ -217,19 +218,19 @@ void CppCodeModelSettings::toSettings(QSettings *s)
emit changed();
}
-Utils::Id CppCodeModelSettings::clangDiagnosticConfigId() const
+Id CppCodeModelSettings::clangDiagnosticConfigId() const
{
if (!diagnosticConfigsModel().hasConfigWithId(m_clangDiagnosticConfigId))
return defaultClangDiagnosticConfigId();
return m_clangDiagnosticConfigId;
}
-void CppCodeModelSettings::setClangDiagnosticConfigId(const Utils::Id &configId)
+void CppCodeModelSettings::setClangDiagnosticConfigId(const Id &configId)
{
m_clangDiagnosticConfigId = configId;
}
-Utils::Id CppCodeModelSettings::defaultClangDiagnosticConfigId()
+Id CppCodeModelSettings::defaultClangDiagnosticConfigId()
{
return initialClangDiagnosticConfigId();
}
@@ -309,7 +310,7 @@ ClangdSettings &ClangdSettings::instance()
return settings;
}
-void ClangdSettings::setDefaultClangdPath(const Utils::FilePath &filePath)
+void ClangdSettings::setDefaultClangdPath(const FilePath &filePath)
{
g_defaultClangdFilePath = filePath;
}
@@ -342,7 +343,8 @@ void ClangdSettings::saveSettings()
#ifdef WITH_TESTS
void ClangdSettings::setUseClangd(bool use) { instance().m_data.useClangd = use; }
-void ClangdSettings::setClangdFilePath(const Utils::FilePath &filePath)
+
+void ClangdSettings::setClangdFilePath(const FilePath &filePath)
{
instance().m_data.executableFilePath = filePath;
}
@@ -402,6 +404,7 @@ QVariantMap ClangdSettings::Data::toMap() const
map.insert(clangdPathKey(), executableFilePath.toString());
map.insert(clangdIndexingKey(), enableIndexing);
map.insert(clangdThreadLimitKey(), workerThreadLimit);
+ map.insert(clangdDocumentThresholdKey(), documentUpdateThreshold);
return map;
}
@@ -411,4 +414,5 @@ void ClangdSettings::Data::fromMap(const QVariantMap &map)
executableFilePath = FilePath::fromString(map.value(clangdPathKey()).toString());
enableIndexing = map.value(clangdIndexingKey(), true).toBool();
workerThreadLimit = map.value(clangdThreadLimitKey(), 0).toInt();
+ documentUpdateThreshold = map.value(clangdDocumentThresholdKey(), 500).toInt();
}
diff --git a/src/plugins/cpptools/cppcodemodelsettings.h b/src/plugins/cpptools/cppcodemodelsettings.h
index d4da25f3b0..c229638d95 100644
--- a/src/plugins/cpptools/cppcodemodelsettings.h
+++ b/src/plugins/cpptools/cppcodemodelsettings.h
@@ -112,6 +112,7 @@ public:
int workerThreadLimit = 0;
bool useClangd = false;
bool enableIndexing = true;
+ int documentUpdateThreshold = 500;
};
ClangdSettings(const Data &data) : m_data(data) {}
@@ -123,6 +124,7 @@ public:
Utils::FilePath clangdFilePath() const;
bool indexingEnabled() const { return m_data.enableIndexing; }
int workerThreadLimit() const { return m_data.workerThreadLimit; }
+ int documentUpdateThreshold() const { return m_data.documentUpdateThreshold; }
void setData(const Data &data);
Data data() const { return m_data; }
@@ -149,7 +151,8 @@ inline bool operator==(const ClangdSettings::Data &s1, const ClangdSettings::Dat
return s1.useClangd == s2.useClangd
&& s1.executableFilePath == s2.executableFilePath
&& s1.workerThreadLimit == s2.workerThreadLimit
- && s1.enableIndexing == s2.enableIndexing;
+ && s1.enableIndexing == s2.enableIndexing
+ && s1.documentUpdateThreshold == s2.documentUpdateThreshold;
}
inline bool operator!=(const ClangdSettings::Data &s1, const ClangdSettings::Data &s2)
{
diff --git a/src/plugins/cpptools/cppcodemodelsettingspage.cpp b/src/plugins/cpptools/cppcodemodelsettingspage.cpp
index dc04dc3cb8..123497d4af 100644
--- a/src/plugins/cpptools/cppcodemodelsettingspage.cpp
+++ b/src/plugins/cpptools/cppcodemodelsettingspage.cpp
@@ -95,9 +95,8 @@ void CppCodeModelSettingsWidget::setupClangCodeModelWidgets()
m_ui->clangDiagnosticConfigsSelectionWidget
->refresh(diagnosticConfigsModel(),
m_settings->clangDiagnosticConfigId(),
- [](const CppTools::ClangDiagnosticConfigs &configs,
- const Utils::Id &configToSelect) {
- return new CppTools::ClangDiagnosticConfigsWidget(configs, configToSelect);
+ [](const ClangDiagnosticConfigs &configs, const Utils::Id &configToSelect) {
+ return new ClangDiagnosticConfigsWidget(configs, configToSelect);
});
const bool isClangActive = CppModelManager::instance()->isClangCodeModelActive();
@@ -197,6 +196,7 @@ public:
QCheckBox useClangdCheckBox;
QCheckBox indexingCheckBox;
QSpinBox threadLimitSpinBox;
+ QSpinBox documentUpdateThreshold;
Utils::PathChooser clangdChooser;
};
@@ -216,6 +216,15 @@ ClangdSettingsWidget::ClangdSettingsWidget(const ClangdSettings::Data &settingsD
"the project is first opened."));
d->threadLimitSpinBox.setValue(settings.workerThreadLimit());
d->threadLimitSpinBox.setSpecialValueText("Automatic");
+ d->documentUpdateThreshold.setMinimum(50);
+ d->documentUpdateThreshold.setMaximum(10000);
+ d->documentUpdateThreshold.setValue(settings.documentUpdateThreshold());
+ d->documentUpdateThreshold.setSingleStep(100);
+ d->documentUpdateThreshold.setSuffix(" ms");
+ d->documentUpdateThreshold.setToolTip(
+ tr("Defines the amount of time Qt Creator waits before sending document changes to the "
+ "server.\n"
+ "If the document changes again while waiting, this timeout resets.\n"));
const auto layout = new QVBoxLayout(this);
layout->addWidget(&d->useClangdCheckBox);
@@ -227,8 +236,13 @@ ClangdSettingsWidget::ClangdSettingsWidget(const ClangdSettings::Data &settingsD
const auto threadLimitLayout = new QHBoxLayout;
threadLimitLayout->addWidget(&d->threadLimitSpinBox);
threadLimitLayout->addStretch(1);
- const auto threadLimitLabel = new QLabel(tr("Set worker thread count:"));
+ const auto threadLimitLabel = new QLabel(tr("Worker thread count:"));
formLayout->addRow(threadLimitLabel, threadLimitLayout);
+ const auto documentUpdateThresholdLayout = new QHBoxLayout;
+ documentUpdateThresholdLayout->addWidget(&d->documentUpdateThreshold);
+ documentUpdateThresholdLayout->addStretch(1);
+ const auto documentUpdateThresholdLabel = new QLabel(tr("Document update threshold:"));
+ formLayout->addRow(documentUpdateThresholdLabel, documentUpdateThresholdLayout);
layout->addLayout(formLayout);
layout->addStretch(1);
@@ -265,6 +279,7 @@ ClangdSettings::Data ClangdSettingsWidget::settingsData() const
data.executableFilePath = d->clangdChooser.filePath();
data.enableIndexing = d->indexingCheckBox.isChecked();
data.workerThreadLimit = d->threadLimitSpinBox.value();
+ data.documentUpdateThreshold = d->documentUpdateThreshold.value();
return data;
}
diff --git a/src/plugins/cpptools/cppcompletion_test.cpp b/src/plugins/cpptools/cppcompletion_test.cpp
index 73a4035d53..1af079083b 100644
--- a/src/plugins/cpptools/cppcompletion_test.cpp
+++ b/src/plugins/cpptools/cppcompletion_test.cpp
@@ -23,10 +23,11 @@
**
****************************************************************************/
+#include "cppcompletion_test.h"
+
#include "cppcompletionassist.h"
#include "cppdoxygen.h"
#include "cppmodelmanager.h"
-#include "cpptoolsplugin.h"
#include "cpptoolstestcase.h"
#include <texteditor/codeassist/iassistproposal.h>
@@ -34,6 +35,7 @@
#include <texteditor/textdocument.h>
#include <coreplugin/editormanager/editormanager.h>
+#include <utils/algorithm.h>
#include <utils/changeset.h>
#include <utils/textutils.h>
#include <utils/fileutils.h>
@@ -185,7 +187,7 @@ bool isDoxygenTagCompletion(const QStringList &list)
} // anonymous namespace
-void CppToolsPlugin::test_completion_basic_1()
+void CompletionTest::testCompletionBasic1()
{
const QByteArray source =
"class Foo\n"
@@ -217,7 +219,7 @@ void CppToolsPlugin::test_completion_basic_1()
QVERIFY(!memberCompletions.contains(QLatin1String("f")));
}
-void CppToolsPlugin::test_completion_prefix_first_QTCREATORBUG_8737()
+void CompletionTest::testCompletionPrefixFirstQTCREATORBUG_8737()
{
const QByteArray source =
"void f()\n"
@@ -237,7 +239,7 @@ void CppToolsPlugin::test_completion_prefix_first_QTCREATORBUG_8737()
QVERIFY(completions.contains(QLatin1String("a_b_c")));
}
-void CppToolsPlugin::test_completion_prefix_first_QTCREATORBUG_9236()
+void CompletionTest::testCompletionPrefixFirstQTCREATORBUG_9236()
{
const QByteArray source =
"class r_etclass\n"
@@ -266,7 +268,7 @@ void CppToolsPlugin::test_completion_prefix_first_QTCREATORBUG_9236()
QVERIFY(completions.contains(QLatin1String("r_et")));
}
-void CppToolsPlugin::test_completion_template_function()
+void CompletionTest::testCompletionTemplateFunction()
{
QFETCH(QByteArray, code);
QFETCH(QStringList, expectedCompletions);
@@ -282,7 +284,7 @@ void CppToolsPlugin::test_completion_template_function()
}
}
-void CppToolsPlugin::test_completion_template_function_data()
+void CompletionTest::testCompletionTemplateFunction_data()
{
QTest::addColumn<QByteArray>("code");
QTest::addColumn<QStringList>("expectedCompletions");
@@ -322,7 +324,7 @@ void CppToolsPlugin::test_completion_template_function_data()
<< code << completions;
}
-void CppToolsPlugin::test_completion()
+void CompletionTest::testCompletion()
{
QFETCH(QByteArray, code);
QFETCH(QByteArray, prefix);
@@ -348,7 +350,7 @@ void CppToolsPlugin::test_completion()
QCOMPARE(actualCompletions, expectedCompletions);
}
-void CppToolsPlugin::test_global_completion_data()
+void CompletionTest::testGlobalCompletion_data()
{
QTest::addColumn<QByteArray>("code");
QTest::addColumn<QByteArray>("prefix");
@@ -378,7 +380,7 @@ void CppToolsPlugin::test_global_completion_data()
}
}
-void CppToolsPlugin::test_global_completion()
+void CompletionTest::testGlobalCompletion()
{
QFETCH(QByteArray, code);
QFETCH(QByteArray, prefix);
@@ -391,7 +393,7 @@ void CppToolsPlugin::test_global_completion()
QVERIFY(Utils::toSet(completions).contains(Utils::toSet(requiredCompletionItems)));
}
-void CppToolsPlugin::test_doxygen_tag_completion_data()
+void CompletionTest::testDoxygenTagCompletion_data()
{
QTest::addColumn<QByteArray>("code");
@@ -407,7 +409,7 @@ void CppToolsPlugin::test_doxygen_tag_completion_data()
" */\n");
}
-void CppToolsPlugin::test_doxygen_tag_completion()
+void CompletionTest::testDoxygenTagCompletion()
{
QFETCH(QByteArray, code);
@@ -435,7 +437,7 @@ static void enumTestCase(const QByteArray &tag, const QByteArray &source,
<< QStringList({"val1", "val2", "val3"});
}
-void CppToolsPlugin::test_completion_data()
+void CompletionTest::testCompletion_data()
{
QTest::addColumn<QByteArray>("code");
QTest::addColumn<QByteArray>("prefix");
@@ -2747,7 +2749,7 @@ void CppToolsPlugin::test_completion_data()
) << _("s.begin()->") << QStringList({"Foo", "bar"});
}
-void CppToolsPlugin::test_completion_member_access_operator()
+void CompletionTest::testCompletionMemberAccessOperator()
{
QFETCH(QByteArray, code);
QFETCH(QByteArray, prefix);
@@ -2768,7 +2770,7 @@ void CppToolsPlugin::test_completion_member_access_operator()
QCOMPARE(replaceAccessOperator, expectedReplaceAccessOperator);
}
-void CppToolsPlugin::test_completion_member_access_operator_data()
+void CompletionTest::testCompletionMemberAccessOperator_data()
{
QTest::addColumn<QByteArray>("code");
QTest::addColumn<QByteArray>("prefix");
diff --git a/src/plugins/cpptools/cppcompletion_test.h b/src/plugins/cpptools/cppcompletion_test.h
new file mode 100644
index 0000000000..c27b45223c
--- /dev/null
+++ b/src/plugins/cpptools/cppcompletion_test.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QObject>
+
+namespace CppTools::Internal {
+
+class CompletionTest : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void testCompletionBasic1();
+
+ void testCompletionTemplateFunction_data();
+ void testCompletionTemplateFunction();
+
+ void testCompletion_data();
+ void testCompletion();
+
+ void testGlobalCompletion_data();
+ void testGlobalCompletion();
+
+ void testDoxygenTagCompletion_data();
+ void testDoxygenTagCompletion();
+
+ void testCompletionMemberAccessOperator_data();
+ void testCompletionMemberAccessOperator();
+
+ void testCompletionPrefixFirstQTCREATORBUG_8737();
+ void testCompletionPrefixFirstQTCREATORBUG_9236();
+};
+
+} // namespace CppTools::Internal
diff --git a/src/plugins/cpptools/cppfilesettingspage.cpp b/src/plugins/cpptools/cppfilesettingspage.cpp
index f63eb41b24..d289e6334e 100644
--- a/src/plugins/cpptools/cppfilesettingspage.cpp
+++ b/src/plugins/cpptools/cppfilesettingspage.cpp
@@ -51,6 +51,8 @@
#include <QTextCodec>
#include <QTextStream>
+using namespace Utils;
+
namespace CppTools {
namespace Internal {
@@ -271,8 +273,8 @@ public:
private:
void slotEdit();
- QString licenseTemplatePath() const;
- void setLicenseTemplatePath(const QString &);
+ FilePath licenseTemplatePath() const;
+ void setLicenseTemplatePath(const FilePath &);
Ui::CppFileSettingsPage m_ui;
CppFileSettings *m_settings = nullptr;
@@ -301,14 +303,14 @@ CppFileSettingsWidget::CppFileSettingsWidget(CppFileSettings *settings)
setSettings(*m_settings);
}
-QString CppFileSettingsWidget::licenseTemplatePath() const
+FilePath CppFileSettingsWidget::licenseTemplatePath() const
{
- return m_ui.licenseTemplatePathChooser->filePath().toString();
+ return m_ui.licenseTemplatePathChooser->filePath();
}
-void CppFileSettingsWidget::setLicenseTemplatePath(const QString &lp)
+void CppFileSettingsWidget::setLicenseTemplatePath(const FilePath &lp)
{
- m_ui.licenseTemplatePathChooser->setPath(lp);
+ m_ui.licenseTemplatePathChooser->setFilePath(lp);
}
static QStringList trimmedPaths(const QString &paths)
@@ -330,7 +332,7 @@ void CppFileSettingsWidget::apply()
rc.sourceSuffix = m_ui.sourceSuffixComboBox->currentText();
rc.headerSearchPaths = trimmedPaths(m_ui.headerSearchPathsEdit->text());
rc.sourceSearchPaths = trimmedPaths(m_ui.sourceSearchPathsEdit->text());
- rc.licenseTemplatePath = licenseTemplatePath();
+ rc.licenseTemplatePath = licenseTemplatePath().toString();
if (rc == *m_settings)
return;
@@ -358,18 +360,18 @@ void CppFileSettingsWidget::setSettings(const CppFileSettings &s)
setComboText(m_ui.sourceSuffixComboBox, s.sourceSuffix);
m_ui.headerSearchPathsEdit->setText(s.headerSearchPaths.join(comma));
m_ui.sourceSearchPathsEdit->setText(s.sourceSearchPaths.join(comma));
- setLicenseTemplatePath(s.licenseTemplatePath);
+ setLicenseTemplatePath(FilePath::fromString(s.licenseTemplatePath));
}
void CppFileSettingsWidget::slotEdit()
{
- QString path = licenseTemplatePath();
+ FilePath path = licenseTemplatePath();
if (path.isEmpty()) {
// Pick a file name and write new template, edit with C++
- path = QFileDialog::getSaveFileName(this, tr("Choose Location for New License Template File"));
+ path = FileUtils::getSaveFilePath(this, tr("Choose Location for New License Template File"));
if (path.isEmpty())
return;
- Utils::FileSaver saver(Utils::FilePath::fromString(path), QIODevice::Text);
+ FileSaver saver(path, QIODevice::Text);
saver.write(tr(licenseTemplateTemplate).arg(Core::Constants::IDE_DISPLAY_NAME).toUtf8());
if (!saver.finalize(this))
return;
diff --git a/src/plugins/cpptools/cppfindreferences.cpp b/src/plugins/cpptools/cppfindreferences.cpp
index 9180e7d15a..9c96b5e44e 100644
--- a/src/plugins/cpptools/cppfindreferences.cpp
+++ b/src/plugins/cpptools/cppfindreferences.cpp
@@ -58,6 +58,7 @@
using namespace Core;
using namespace ProjectExplorer;
+using namespace Utils;
namespace CppTools {
@@ -618,7 +619,7 @@ CPlusPlus::Symbol *CppFindReferences::findSymbol(const CppFindReferencesParamete
QByteArray source = getSource(Utils::FilePath::fromString(newSymbolDocument->fileName()),
m_modelManager->workingCopy());
CPlusPlus::Document::Ptr doc =
- snapshot.preprocessedDocument(source, newSymbolDocument->fileName());
+ snapshot.preprocessedDocument(source, FilePath::fromString(newSymbolDocument->fileName()));
doc->check();
// find matching symbol in new document and return the new parameters
diff --git a/src/plugins/cpptools/cppheadersource_test.cpp b/src/plugins/cpptools/cppheadersource_test.cpp
index be0bdd03c2..1900040419 100644
--- a/src/plugins/cpptools/cppheadersource_test.cpp
+++ b/src/plugins/cpptools/cppheadersource_test.cpp
@@ -23,6 +23,8 @@
**
****************************************************************************/
+#include "cppheadersource_test.h"
+
#include "cpptoolsplugin.h"
#include "cpptoolsreuse.h"
#include "cpptoolstestcase.h"
@@ -52,7 +54,7 @@ static QString baseTestDir()
namespace CppTools {
namespace Internal {
-void CppToolsPlugin::test_headersource()
+void HeaderSourceTest::test()
{
QFETCH(QString, sourceFileName);
QFETCH(QString, headerFileName);
@@ -67,15 +69,15 @@ void CppToolsPlugin::test_headersource()
createTempFile(headerPath);
bool wasHeader;
- clearHeaderSourceCache();
+ CppToolsPlugin::clearHeaderSourceCache();
QCOMPARE(correspondingHeaderOrSource(sourcePath, &wasHeader), headerPath);
QVERIFY(!wasHeader);
- clearHeaderSourceCache();
+ CppToolsPlugin::clearHeaderSourceCache();
QCOMPARE(correspondingHeaderOrSource(headerPath, &wasHeader), sourcePath);
QVERIFY(wasHeader);
}
-void CppToolsPlugin::test_headersource_data()
+void HeaderSourceTest::test_data()
{
QTest::addColumn<QString>("sourceFileName");
QTest::addColumn<QString>("headerFileName");
@@ -86,10 +88,10 @@ void CppToolsPlugin::test_headersource_data()
QTest::newRow("sourceAndHeaderPrefixWithBothsub") << _("src/testc_foo.cpp") << _("include/testh_foo.h");
}
-void CppToolsPlugin::initTestCase()
+void HeaderSourceTest::initTestCase()
{
QDir(baseTestDir()).mkpath(_("."));
- CppFileSettings *fs = fileSettings();
+ CppFileSettings *fs = CppToolsPlugin::fileSettings();
fs->headerSearchPaths.append(QLatin1String("include"));
fs->headerSearchPaths.append(QLatin1String("../include"));
fs->sourceSearchPaths.append(QLatin1String("src"));
@@ -98,10 +100,10 @@ void CppToolsPlugin::initTestCase()
fs->sourcePrefixes.append(QLatin1String("testc_"));
}
-void CppToolsPlugin::cleanupTestCase()
+void HeaderSourceTest::cleanupTestCase()
{
Utils::FilePath::fromString(baseTestDir()).removeRecursively();
- CppFileSettings *fs = fileSettings();
+ CppFileSettings *fs = CppToolsPlugin::fileSettings();
fs->headerSearchPaths.removeLast();
fs->headerSearchPaths.removeLast();
fs->sourceSearchPaths.removeLast();
diff --git a/src/plugins/cpptools/cppheadersource_test.h b/src/plugins/cpptools/cppheadersource_test.h
new file mode 100644
index 0000000000..d3066e3415
--- /dev/null
+++ b/src/plugins/cpptools/cppheadersource_test.h
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QObject>
+
+namespace CppTools::Internal {
+
+class HeaderSourceTest : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+
+ void test_data();
+ void test();
+};
+
+} // namespace CppTools::Internal
diff --git a/src/plugins/cpptools/cpplocalsymbols_test.cpp b/src/plugins/cpptools/cpplocalsymbols_test.cpp
index 7a21b1bc4d..978d06d3b9 100644
--- a/src/plugins/cpptools/cpplocalsymbols_test.cpp
+++ b/src/plugins/cpptools/cpplocalsymbols_test.cpp
@@ -23,7 +23,7 @@
**
****************************************************************************/
-#include "cpptoolsplugin.h"
+#include "cpplocalsymbols_test.h"
#include "cpplocalsymbols.h"
#include "cppsemanticinfo.h"
@@ -131,7 +131,7 @@ QT_END_NAMESPACE
namespace CppTools {
namespace Internal {
-void CppToolsPlugin::test_cpplocalsymbols_data()
+void LocalSymbolsTest::test_data()
{
QTest::addColumn<QByteArray>("source");
QTest::addColumn<QList<Result>>("expectedUses");
@@ -165,7 +165,7 @@ void CppToolsPlugin::test_cpplocalsymbols_data()
<< Result(_("func"), 3, 5, 4));
}
-void CppToolsPlugin::test_cpplocalsymbols()
+void LocalSymbolsTest::test()
{
QFETCH(QByteArray, source);
QFETCH(QList<Result>, expectedUses);
diff --git a/src/plugins/cpptools/cpplocalsymbols_test.h b/src/plugins/cpptools/cpplocalsymbols_test.h
new file mode 100644
index 0000000000..aa487b029a
--- /dev/null
+++ b/src/plugins/cpptools/cpplocalsymbols_test.h
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QObject>
+
+namespace CppTools::Internal {
+
+class LocalSymbolsTest : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void test_data();
+ void test();
+};
+
+} // namespace CppTools::Internal
diff --git a/src/plugins/cpptools/cpplocatorfilter_test.cpp b/src/plugins/cpptools/cpplocatorfilter_test.cpp
index 71bdf5ba40..9aff8dd649 100644
--- a/src/plugins/cpptools/cpplocatorfilter_test.cpp
+++ b/src/plugins/cpptools/cpplocatorfilter_test.cpp
@@ -23,7 +23,7 @@
**
****************************************************************************/
-#include "cpptoolsplugin.h"
+#include "cpplocatorfilter_test.h"
#include "cppclassesfilter.h"
#include "cppcurrentdocumentfilter.h"
@@ -137,7 +137,7 @@ private:
} // anonymous namespace
-void CppToolsPlugin::test_cpplocatorfilters_CppLocatorFilter()
+void LocatorFilterTest::testLocatorFilter()
{
QFETCH(QString, testFile);
QFETCH(ILocatorFilter *, filter);
@@ -149,7 +149,7 @@ void CppToolsPlugin::test_cpplocatorfilters_CppLocatorFilter()
CppLocatorFilterTestCase(filter, testFile, searchText, expectedResults);
}
-void CppToolsPlugin::test_cpplocatorfilters_CppLocatorFilter_data()
+void LocatorFilterTest::testLocatorFilter_data()
{
QTest::addColumn<QString>("testFile");
QTest::addColumn<ILocatorFilter *>("filter");
@@ -321,7 +321,7 @@ void CppToolsPlugin::test_cpplocatorfilters_CppLocatorFilter_data()
};
}
-void CppToolsPlugin::test_cpplocatorfilters_CppCurrentDocumentFilter()
+void LocatorFilterTest::testCurrentDocumentFilter()
{
MyTestDataDir testDirectory("testdata_basic");
const QString testFile = testDirectory.file("file1.cpp");
@@ -375,7 +375,7 @@ void CppToolsPlugin::test_cpplocatorfilters_CppCurrentDocumentFilter()
CppCurrentDocumentFilterTestCase(testFile, expectedResults);
}
-void CppToolsPlugin::test_cpplocatorfilters_CppCurrentDocumentHighlighting()
+void LocatorFilterTest::testCurrentDocumentHighlighting()
{
MyTestDataDir testDirectory("testdata_basic");
const QString testFile = testDirectory.file("file1.cpp");
@@ -399,7 +399,7 @@ void CppToolsPlugin::test_cpplocatorfilters_CppCurrentDocumentHighlighting()
CppCurrentDocumentFilterTestCase(testFile, expectedResults, searchText);
}
-void CppToolsPlugin::test_cpplocatorfilters_CppFunctionsFilterHighlighting()
+void LocatorFilterTest::testFunctionsFilterHighlighting()
{
MyTestDataDir testDirectory("testdata_basic");
const QString testFile = testDirectory.file("file1.cpp");
diff --git a/src/plugins/cpptools/cpplocatorfilter_test.h b/src/plugins/cpptools/cpplocatorfilter_test.h
new file mode 100644
index 0000000000..ddda9a394b
--- /dev/null
+++ b/src/plugins/cpptools/cpplocatorfilter_test.h
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QObject>
+
+namespace CppTools::Internal {
+
+class LocatorFilterTest : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void testLocatorFilter();
+ void testLocatorFilter_data();
+ void testCurrentDocumentFilter();
+ void testCurrentDocumentHighlighting();
+ void testFunctionsFilterHighlighting();
+};
+
+} // namespace CppTools::Internal
diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp
index 8d58f429b9..74ac1557fc 100644
--- a/src/plugins/cpptools/cppmodelmanager.cpp
+++ b/src/plugins/cpptools/cppmodelmanager.cpp
@@ -144,17 +144,27 @@ namespace Internal {
static CppModelManager *m_instance;
+class ProjectData
+{
+public:
+ ProjectInfo::Ptr projectInfo;
+ QFutureWatcher<void> *indexer = nullptr;
+ bool fullyIndexed = false;
+};
+
class CppModelManagerPrivate
{
public:
+ void setupWatcher(const QFuture<void> &future, ProjectExplorer::Project *project,
+ ProjectData *projectData, CppModelManager *q);
+
// Snapshot
mutable QMutex m_snapshotMutex;
Snapshot m_snapshot;
// Project integration
mutable QMutex m_projectMutex;
- QMap<ProjectExplorer::Project *, ProjectInfo> m_projectToProjectsInfo;
- QHash<ProjectExplorer::Project *, bool> m_projectToIndexerCanceled;
+ QHash<ProjectExplorer::Project *, ProjectData> m_projectData;
QMap<Utils::FilePath, QList<ProjectPart::Ptr> > m_fileToProjectParts;
QMap<QString, ProjectPart::Ptr> m_projectPartIdToProjectProjectPart;
// The members below are cached/(re)calculated from the projects and/or their project parts
@@ -173,7 +183,6 @@ public:
ModelManagerSupport::Ptr m_activeModelManagerSupport;
// Indexing
- CppIndexingSupport *m_indexingSupporter;
CppIndexingSupport *m_internalIndexingSupport;
bool m_indexerEnabled;
@@ -364,7 +373,8 @@ bool CppModelManager::positionRequiresSignal(const QString &filePath, const QByt
fixedContent.insert(position, 'x');
const Snapshot snapshot = this->snapshot();
- const Document::Ptr document = snapshot.preprocessedDocument(fixedContent, filePath);
+ const Document::Ptr document = snapshot.preprocessedDocument(fixedContent,
+ Utils::FilePath::fromString(filePath));
document->check();
QTextDocument textDocument(QString::fromUtf8(fixedContent));
QTextCursor cursor(&textDocument);
@@ -643,7 +653,6 @@ CppModelManager::CppModelManager()
setObjectName("CppModelManager");
ExtensionSystem::PluginManager::addObject(this);
- d->m_indexingSupporter = nullptr;
d->m_enableGC = true;
// Visual C++ has 1MiB, macOSX has 512KiB
@@ -748,9 +757,9 @@ void CppModelManager::ensureUpdated()
QStringList CppModelManager::internalProjectFiles() const
{
QStringList files;
- for (const ProjectInfo &pinfo : qAsConst(d->m_projectToProjectsInfo)) {
- foreach (const ProjectPart::Ptr &part, pinfo.projectParts()) {
- foreach (const ProjectFile &file, part->files)
+ for (const ProjectData &projectData : qAsConst(d->m_projectData)) {
+ for (const ProjectPart::Ptr &part : projectData.projectInfo->projectParts()) {
+ for (const ProjectFile &file : part->files)
files += file.path;
}
}
@@ -761,9 +770,9 @@ 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()) {
- foreach (const ProjectExplorer::HeaderPath &path, part->headerPaths) {
+ for (const ProjectData &projectData: qAsConst(d->m_projectData)) {
+ for (const ProjectPart::Ptr &part : projectData.projectInfo->projectParts()) {
+ for (const ProjectExplorer::HeaderPath &path : part->headerPaths) {
ProjectExplorer::HeaderPath hp(QDir::cleanPath(path.path), path.type);
if (!headerPaths.contains(hp))
headerPaths.push_back(std::move(hp));
@@ -789,8 +798,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 ProjectData &projectData : qAsConst(d->m_projectData)) {
+ for (const ProjectPart::Ptr &part : projectData.projectInfo->projectParts()) {
addUnique(part->toolChainMacros, macros, alreadyIn);
addUnique(part->projectMacros, macros, alreadyIn);
}
@@ -967,29 +976,25 @@ QFuture<void> CppModelManager::updateSourceFiles(const QSet<QString> &sourceFile
const QSet<QString> filteredFiles = tooBigFilesRemoved(sourceFiles, indexerFileSizeLimitInMb());
- if (d->m_indexingSupporter)
- d->m_indexingSupporter->refreshSourceFiles(filteredFiles, mode);
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();
+ return Utils::transform<QList<ProjectInfo::Ptr>>(d->m_projectData,
+ [](const ProjectData &d) { return d.projectInfo; });
}
-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_projectData.value(project).projectInfo;
}
/// \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,38 +1094,35 @@ 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()) {
+ for (const ProjectData &projectData : qAsConst(d->m_projectData)) {
+ for (const ProjectPart::Ptr &projectPart : projectData.projectInfo->projectParts()) {
d->m_projectPartIdToProjectProjectPart[projectPart->id()] = projectPart;
- foreach (const ProjectFile &cxxFile, projectPart->files)
+ for (const ProjectFile &cxxFile : projectPart->files)
d->m_fileToProjectParts[Utils::FilePath::fromString(cxxFile.path)].append(
projectPart);
-
}
}
d->m_symbolFinder.clearCache();
}
-void CppModelManager::watchForCanceledProjectIndexer(const QFuture<void> &future,
- ProjectExplorer::Project *project)
+void CppModelManagerPrivate::setupWatcher(const QFuture<void> &future,
+ ProjectExplorer::Project *project,
+ ProjectData *projectData, CppModelManager *q)
{
- if (future.isCanceled() || future.isFinished())
- return;
-
- auto watcher = new QFutureWatcher<void>(this);
- connect(watcher, &QFutureWatcher<void>::canceled, this, [this, project, watcher]() {
- if (d->m_projectToIndexerCanceled.contains(project)) // Project not yet removed
- d->m_projectToIndexerCanceled.insert(project, true);
- watcher->disconnect(this);
- watcher->deleteLater();
- });
- connect(watcher, &QFutureWatcher<void>::finished, this, [this, project, watcher]() {
- d->m_projectToIndexerCanceled.remove(project);
- watcher->disconnect(this);
+ projectData->indexer = new QFutureWatcher<void>(q);
+ const auto handleFinished = [this, project, watcher = projectData->indexer, q] {
+ if (const auto it = m_projectData.find(project);
+ it != m_projectData.end() && it->indexer == watcher) {
+ it->indexer = nullptr;
+ it->fullyIndexed = !watcher->isCanceled();
+ }
+ watcher->disconnect(q);
watcher->deleteLater();
- });
- watcher->setFuture(future);
+ };
+ q->connect(projectData->indexer, &QFutureWatcher<void>::canceled, q, handleFinished);
+ q->connect(projectData->indexer, &QFutureWatcher<void>::finished, q, handleFinished);
+ projectData->indexer->setFuture(future);
}
void CppModelManager::updateCppEditorDocuments(bool projectsUpdated) const
@@ -1152,37 +1154,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 {};
+
+ ProjectData *projectData = nullptr;
{ // 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 bool previousIndexerCanceled = d->m_projectToIndexerCanceled.value(project, false);
- if (!previousIndexerCanceled && oldProjectInfo.isValid()) {
- ProjectInfoComparer comparer(oldProjectInfo, theNewProjectInfo);
+ const auto it = d->m_projectData.find(project);
+ if (it != d->m_projectData.end() && it->projectInfo && it->fullyIndexed) {
+ ProjectInfoComparer comparer(*it->projectInfo, *newProjectInfo);
if (comparer.configurationOrFilesChanged()) {
d->m_dirty = true;
// If the project configuration changed, do a full reindexing
if (comparer.configurationChanged()) {
- removeProjectInfoFilesAndIncludesFromSnapshot(oldProjectInfo);
+ removeProjectInfoFilesAndIncludesFromSnapshot(*it->projectInfo);
filesToReindex.unite(newSourceFiles);
// The "configuration file" includes all defines and therefore should be updated
@@ -1218,9 +1220,16 @@ QFuture<void> CppModelManager::updateProjectInfo(const ProjectInfo &newProjectIn
}
// Update Project/ProjectInfo and File/ProjectPart table
- d->m_projectToProjectsInfo.insert(project, theNewProjectInfo);
+ if (it != d->m_projectData.end()) {
+ if (it->indexer)
+ it->indexer->cancel();
+ it->projectInfo = newProjectInfo;
+ it->fullyIndexed = false;
+ }
+ projectData = it == d->m_projectData.end()
+ ? &(d->m_projectData[project] = ProjectData{newProjectInfo, nullptr, false})
+ : &(*it);
recalculateProjectPartMappings();
-
} // Mutex scope
// If requested, dump everything we got
@@ -1236,7 +1245,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
@@ -1248,10 +1257,12 @@ QFuture<void> CppModelManager::updateProjectInfo(const ProjectInfo &newProjectIn
// Trigger reindexing
const QFuture<void> indexingFuture = updateSourceFiles(filesToReindex,
ForcedProgressNotification);
- if (!filesToReindex.isEmpty()) {
- d->m_projectToIndexerCanceled.insert(project, false);
- }
- watchForCanceledProjectIndexer(indexingFuture, project);
+
+ // It's safe to do this here, as only the UI thread writes to the map and no other thread
+ // uses the indexer value.
+ // FIXME: Use a read/write lock instead of a mutex.
+ d->setupWatcher(indexingFuture, project, projectData, this);
+
return indexingFuture;
}
@@ -1342,14 +1353,12 @@ void CppModelManager::onAboutToRemoveProject(ProjectExplorer::Project *project)
{
QStringList idsOfRemovedProjectParts;
- d->m_projectToIndexerCanceled.remove(project);
-
{
QMutexLocker locker(&d->m_projectMutex);
d->m_dirty = true;
const QStringList projectPartsIdsBefore = d->m_projectPartIdToProjectProjectPart.keys();
- d->m_projectToProjectsInfo.remove(project);
+ d->m_projectData.remove(project);
recalculateProjectPartMappings();
const QStringList projectPartsIdsAfter = d->m_projectPartIdToProjectProjectPart.keys();
@@ -1369,7 +1378,7 @@ void CppModelManager::onActiveProjectChanged(ProjectExplorer::Project *project)
{
QMutexLocker locker(&d->m_projectMutex);
- if (!d->m_projectToProjectsInfo.contains(project))
+ if (!d->m_projectData.contains(project))
return; // Not yet known to us.
}
@@ -1531,18 +1540,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 +1560,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;
}
@@ -1654,19 +1663,9 @@ BaseEditorDocumentProcessor *CppModelManager::createEditorDocumentProcessor(
return d->m_activeModelManagerSupport->createEditorDocumentProcessor(baseTextDocument);
}
-void CppModelManager::setIndexingSupport(CppIndexingSupport *indexingSupport)
-{
- if (indexingSupport) {
- if (dynamic_cast<BuiltinIndexingSupport *>(indexingSupport))
- d->m_indexingSupporter = nullptr;
- else
- d->m_indexingSupporter = indexingSupport;
- }
-}
-
CppIndexingSupport *CppModelManager::indexingSupport()
{
- return d->m_indexingSupporter ? d->m_indexingSupporter : d->m_internalIndexingSupport;
+ return d->m_internalIndexingSupport;
}
QStringList CppModelManager::projectFiles()
diff --git a/src/plugins/cpptools/cppmodelmanager.h b/src/plugins/cpptools/cppmodelmanager.h
index bc7f345ea1..0af91d702b 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
@@ -192,7 +192,6 @@ public:
FollowSymbolInterface &followSymbolInterface() const;
std::unique_ptr<AbstractOverviewModel> createOverviewModel() const;
- void setIndexingSupport(CppIndexingSupport *indexingSupport);
CppIndexingSupport *indexingSupport();
QStringList projectFiles();
@@ -287,8 +286,6 @@ private:
void initializeBuiltinModelManagerSupport();
void delayedGC();
void recalculateProjectPartMappings();
- void watchForCanceledProjectIndexer(const QFuture<void> &future,
- ProjectExplorer::Project *project);
void replaceSnapshot(const CPlusPlus::Snapshot &newSnapshot);
void removeFilesFromSnapshot(const QSet<QString> &removedFiles);
diff --git a/src/plugins/cpptools/cppmodelmanager_test.cpp b/src/plugins/cpptools/cppmodelmanager_test.cpp
index 8e2700c2a2..1f3fdfe932 100644
--- a/src/plugins/cpptools/cppmodelmanager_test.cpp
+++ b/src/plugins/cpptools/cppmodelmanager_test.cpp
@@ -23,10 +23,11 @@
**
****************************************************************************/
+#include "cppmodelmanager_test.h"
+
#include "baseeditordocumentprocessor.h"
#include "builtineditordocumentparser.h"
#include "cppsourceprocessor.h"
-#include "cpptoolsplugin.h"
#include "cpptoolstestcase.h"
#include "editordocumenthandle.h"
#include "modelmanagertesthelper.h"
@@ -104,20 +105,20 @@ public:
foreach (const QString &file, files)
projectFiles << projectDir.file(file);
- Project *project = modelManagerTestHelper->createProject(name);
- projectInfo = ProjectInfo(project);
+ 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"));
- 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);
+ 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;
};
@@ -173,22 +174,23 @@ ProjectPart::Ptr projectPartOfEditorDocument(const QString &filePath)
} // anonymous namespace
/// Check: The preprocessor cleans include and framework paths.
-void CppToolsPlugin::test_modelmanager_paths_are_clean()
+void ModelManagerTest::testPathsAreClean()
{
ModelManagerTestHelper helper;
CppModelManager *mm = CppModelManager::instance();
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);
@@ -199,7 +201,7 @@ void CppToolsPlugin::test_modelmanager_paths_are_clean()
}
/// Check: Frameworks headers are resolved.
-void CppToolsPlugin::test_modelmanager_framework_headers()
+void ModelManagerTest::testFrameworkHeaders()
{
if (Utils::HostOsInfo::isWindowsHost())
QSKIP("Can't resolve framework soft links on Windows.");
@@ -209,18 +211,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();
@@ -245,7 +248,7 @@ void CppToolsPlugin::test_modelmanager_framework_headers()
/// QTCREATORBUG-9056
/// Check: If the project configuration changes, all project files and their
/// includes have to be reparsed.
-void CppToolsPlugin::test_modelmanager_refresh_also_includes_of_project_files()
+void ModelManagerTest::testRefreshAlsoIncludesOfProjectFiles()
{
ModelManagerTestHelper helper;
CppModelManager *mm = CppModelManager::instance();
@@ -255,16 +258,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 +282,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);
@@ -301,7 +305,7 @@ void CppToolsPlugin::test_modelmanager_refresh_also_includes_of_project_files()
/// QTCREATORBUG-9205
/// Check: When reparsing the same files again, no errors occur
/// (The CppSourceProcessor's already seen files are properly cleared!).
-void CppToolsPlugin::test_modelmanager_refresh_several_times()
+void ModelManagerTest::testRefreshSeveralTimes()
{
ModelManagerTestHelper helper;
CppModelManager *mm = CppModelManager::instance();
@@ -312,15 +316,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 +335,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);
@@ -366,7 +367,7 @@ void CppToolsPlugin::test_modelmanager_refresh_several_times()
/// QTCREATORBUG-9581
/// Check: If nothing has changes, nothing should be reindexed.
-void CppToolsPlugin::test_modelmanager_refresh_test_for_changes()
+void ModelManagerTest::testRefreshTestForChanges()
{
ModelManagerTestHelper helper;
CppModelManager *mm = CppModelManager::instance();
@@ -374,13 +375,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();
@@ -398,7 +399,7 @@ void CppToolsPlugin::test_modelmanager_refresh_test_for_changes()
/// Check: (1) Added project files are recognized and parsed.
/// Check: (2) Removed project files are recognized and purged from the snapshot.
-void CppToolsPlugin::test_modelmanager_refresh_added_and_purge_removed()
+void ModelManagerTest::testRefreshAddedAndPurgeRemoved()
{
ModelManagerTestHelper helper;
CppModelManager *mm = CppModelManager::instance();
@@ -409,14 +410,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 +432,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);
@@ -454,7 +451,7 @@ void CppToolsPlugin::test_modelmanager_refresh_added_and_purge_removed()
/// Check: Timestamp modified files are reparsed if project files are added or removed
/// while the project configuration stays the same
-void CppToolsPlugin::test_modelmanager_refresh_timeStampModified_if_sourcefiles_change()
+void ModelManagerTest::testRefreshTimeStampModifiedIfSourcefilesChange()
{
QFETCH(QString, fileToChange);
QFETCH(QStringList, initialProjectFiles);
@@ -469,15 +466,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 +503,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);
@@ -528,7 +525,7 @@ void CppToolsPlugin::test_modelmanager_refresh_timeStampModified_if_sourcefiles_
QCOMPARE(document->globalSymbolAt(1)->name()->identifier()->chars(), "addedOtherGlobal");
}
-void CppToolsPlugin::test_modelmanager_refresh_timeStampModified_if_sourcefiles_change_data()
+void ModelManagerTest::testRefreshTimeStampModifiedIfSourcefilesChange_data()
{
QTest::addColumn<QString>("fileToChange");
QTest::addColumn<QStringList>("initialProjectFiles");
@@ -550,7 +547,7 @@ void CppToolsPlugin::test_modelmanager_refresh_timeStampModified_if_sourcefiles_
/// Check: If a second project is opened, the code model is still aware of
/// files of the first project.
-void CppToolsPlugin::test_modelmanager_snapshot_after_two_projects()
+void ModelManagerTest::testSnapshotAfterTwoProjects()
{
QSet<QString> refreshedFiles;
ModelManagerTestHelper helper;
@@ -594,7 +591,7 @@ void CppToolsPlugin::test_modelmanager_snapshot_after_two_projects()
/// though it might not be actually generated in the build dir.
///
-void CppToolsPlugin::test_modelmanager_extraeditorsupport_uiFiles()
+void ModelManagerTest::testExtraeditorsupportUiFiles()
{
VerifyCleanCppModelManager verify;
@@ -603,8 +600,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.
@@ -640,7 +636,7 @@ void CppToolsPlugin::test_modelmanager_extraeditorsupport_uiFiles()
/// QTCREATORBUG-9828: Locator shows symbols of closed files
/// Check: The garbage collector should be run if the last CppEditor is closed.
-void CppToolsPlugin::test_modelmanager_gc_if_last_cppeditor_closed()
+void ModelManagerTest::testGcIfLastCppeditorClosed()
{
ModelManagerTestHelper helper;
@@ -671,7 +667,7 @@ void CppToolsPlugin::test_modelmanager_gc_if_last_cppeditor_closed()
}
/// Check: Files that are open in the editor are not garbage collected.
-void CppToolsPlugin::test_modelmanager_dont_gc_opened_files()
+void ModelManagerTest::testDontGcOpenedFiles()
{
ModelManagerTestHelper helper;
@@ -734,7 +730,7 @@ QString nameOfFirstDeclaration(const Document::Ptr &doc)
}
}
-void CppToolsPlugin::test_modelmanager_defines_per_project()
+void ModelManagerTest::testDefinesPerProject()
{
ModelManagerTestHelper helper;
@@ -745,28 +741,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);
@@ -796,7 +790,7 @@ void CppToolsPlugin::test_modelmanager_defines_per_project()
}
}
-void CppToolsPlugin::test_modelmanager_precompiled_headers()
+void ModelManagerTest::testPrecompiledHeaders()
{
ModelManagerTestHelper helper;
@@ -809,29 +803,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);
@@ -880,7 +871,7 @@ void CppToolsPlugin::test_modelmanager_precompiled_headers()
}
}
-void CppToolsPlugin::test_modelmanager_defines_per_editor()
+void ModelManagerTest::testDefinesPerEditor()
{
ModelManagerTestHelper helper;
@@ -891,24 +882,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);
@@ -945,7 +934,7 @@ void CppToolsPlugin::test_modelmanager_defines_per_editor()
}
}
-void CppToolsPlugin::test_modelmanager_updateEditorsAfterProjectUpdate()
+void ModelManagerTest::testUpdateEditorsAfterProjectUpdate()
{
ModelManagerTestHelper helper;
@@ -960,7 +949,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,37 +958,35 @@ 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()
+void ModelManagerTest::testRenameIncludes()
{
struct ModelManagerGCHelper {
~ModelManagerGCHelper() { CppModelManager::instance()->GC(); }
@@ -1047,7 +1034,7 @@ void CppToolsPlugin::test_modelmanager_renameIncludes()
QCOMPARE(snapshot.allIncludesForDocument(sourceFile), QSet<QString>() << newHeader);
}
-void CppToolsPlugin::test_modelmanager_renameIncludesInEditor()
+void ModelManagerTest::testRenameIncludesInEditor()
{
struct ModelManagerGCHelper {
~ModelManagerGCHelper() { CppModelManager::instance()->GC(); }
@@ -1171,7 +1158,7 @@ void CppToolsPlugin::test_modelmanager_renameIncludesInEditor()
QCOMPARE(snapshot.allIncludesForDocument(sourceFile), QSet<QString>() << renamedHeaderWithPragmaOnce);
}
-void CppToolsPlugin::test_modelmanager_documentsAndRevisions()
+void ModelManagerTest::testDocumentsAndRevisions()
{
TestCase helper;
diff --git a/src/plugins/cpptools/cppmodelmanager_test.h b/src/plugins/cpptools/cppmodelmanager_test.h
new file mode 100644
index 0000000000..292b93e680
--- /dev/null
+++ b/src/plugins/cpptools/cppmodelmanager_test.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QObject>
+
+namespace CppTools::Internal {
+
+class ModelManagerTest : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void testPathsAreClean();
+ void testFrameworkHeaders();
+ void testRefreshAlsoIncludesOfProjectFiles();
+ void testRefreshSeveralTimes();
+ void testRefreshTestForChanges();
+ void testRefreshAddedAndPurgeRemoved();
+ void testRefreshTimeStampModifiedIfSourcefilesChange();
+ void testRefreshTimeStampModifiedIfSourcefilesChange_data();
+ void testSnapshotAfterTwoProjects();
+ void testExtraeditorsupportUiFiles();
+ void testGcIfLastCppeditorClosed();
+ void testDontGcOpenedFiles();
+ void testDefinesPerProject();
+ void testDefinesPerEditor();
+ void testUpdateEditorsAfterProjectUpdate();
+ void testPrecompiledHeaders();
+ void testRenameIncludes();
+ void testRenameIncludesInEditor();
+ void testDocumentsAndRevisions();
+};
+
+} // namespace CppTools::Internal
diff --git a/src/plugins/cpptools/cpppointerdeclarationformatter_test.cpp b/src/plugins/cpptools/cpppointerdeclarationformatter_test.cpp
index 6e8bf332e6..19a16d5e05 100644
--- a/src/plugins/cpptools/cpppointerdeclarationformatter_test.cpp
+++ b/src/plugins/cpptools/cpppointerdeclarationformatter_test.cpp
@@ -23,8 +23,9 @@
**
****************************************************************************/
+#include "cpppointerdeclarationformatter_test.h"
+
#include "cpppointerdeclarationformatter.h"
-#include "cpptoolsplugin.h"
#include "cpptoolstestcase.h"
#include <coreplugin/coreconstants.h>
@@ -141,7 +142,7 @@ public:
} // anonymous namespace
-void CppToolsPlugin::test_format_pointerdeclaration_in_simpledeclarations()
+void PointerDeclarationFormatterTest::testInSimpledeclarations()
{
QFETCH(QString, source);
QFETCH(QString, reformattedSource);
@@ -152,7 +153,7 @@ void CppToolsPlugin::test_format_pointerdeclaration_in_simpledeclarations()
PointerDeclarationFormatter::RespectCursor);
}
-void CppToolsPlugin::test_format_pointerdeclaration_in_simpledeclarations_data()
+void PointerDeclarationFormatterTest::testInSimpledeclarations_data()
{
QTest::addColumn<QString>("source");
QTest::addColumn<QString>("reformattedSource");
@@ -365,7 +366,7 @@ void CppToolsPlugin::test_format_pointerdeclaration_in_simpledeclarations_data()
<< "C & C::operator = (const C &) {}";
}
-void CppToolsPlugin::test_format_pointerdeclaration_in_controlflowstatements()
+void PointerDeclarationFormatterTest::testInControlflowstatements()
{
QFETCH(QString, source);
QFETCH(QString, reformattedSource);
@@ -376,7 +377,7 @@ void CppToolsPlugin::test_format_pointerdeclaration_in_controlflowstatements()
PointerDeclarationFormatter::RespectCursor);
}
-void CppToolsPlugin::test_format_pointerdeclaration_in_controlflowstatements_data()
+void PointerDeclarationFormatterTest::testInControlflowstatements_data()
{
QTest::addColumn<QString>("source");
QTest::addColumn<QString>("reformattedSource");
@@ -440,7 +441,7 @@ void CppToolsPlugin::test_format_pointerdeclaration_in_controlflowstatements_dat
QTest::newRow("precondition-fail-no-pointer") << source << stripCursor(source);
}
-void CppToolsPlugin::test_format_pointerdeclaration_multiple_declarators()
+void PointerDeclarationFormatterTest::testMultipleDeclarators()
{
QFETCH(QString, source);
QFETCH(QString, reformattedSource);
@@ -451,7 +452,7 @@ void CppToolsPlugin::test_format_pointerdeclaration_multiple_declarators()
PointerDeclarationFormatter::RespectCursor);
}
-void CppToolsPlugin::test_format_pointerdeclaration_multiple_declarators_data()
+void PointerDeclarationFormatterTest::testMultipleDeclarators_data()
{
QTest::addColumn<QString>("source");
QTest::addColumn<QString>("reformattedSource");
@@ -495,7 +496,7 @@ void CppToolsPlugin::test_format_pointerdeclaration_multiple_declarators_data()
<< "char *s, * (*foo)(char * s) = 0;";
}
-void CppToolsPlugin::test_format_pointerdeclaration_multiple_matches()
+void PointerDeclarationFormatterTest::testMultipleMatches()
{
QFETCH(QString, source);
QFETCH(QString, reformattedSource);
@@ -506,7 +507,7 @@ void CppToolsPlugin::test_format_pointerdeclaration_multiple_matches()
PointerDeclarationFormatter::IgnoreCursor);
}
-void CppToolsPlugin::test_format_pointerdeclaration_multiple_matches_data()
+void PointerDeclarationFormatterTest::testMultipleMatches_data()
{
QTest::addColumn<QString>("source");
QTest::addColumn<QString>("reformattedSource");
@@ -578,7 +579,7 @@ void CppToolsPlugin::test_format_pointerdeclaration_multiple_matches_data()
"}\n";
}
-void CppToolsPlugin::test_format_pointerdeclaration_macros()
+void PointerDeclarationFormatterTest::testMacros()
{
QFETCH(QString, source);
QFETCH(QString, reformattedSource);
@@ -589,7 +590,7 @@ void CppToolsPlugin::test_format_pointerdeclaration_macros()
PointerDeclarationFormatter::RespectCursor);
}
-void CppToolsPlugin::test_format_pointerdeclaration_macros_data()
+void PointerDeclarationFormatterTest::testMacros_data()
{
QTest::addColumn<QString>("source");
QTest::addColumn<QString>("reformattedSource");
diff --git a/src/plugins/cpptools/cpppointerdeclarationformatter_test.h b/src/plugins/cpptools/cpppointerdeclarationformatter_test.h
new file mode 100644
index 0000000000..8ebf00c514
--- /dev/null
+++ b/src/plugins/cpptools/cpppointerdeclarationformatter_test.h
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QObject>
+
+namespace CppTools::Internal {
+
+class PointerDeclarationFormatterTest : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void testInSimpledeclarations();
+ void testInSimpledeclarations_data();
+ void testInControlflowstatements();
+ void testInControlflowstatements_data();
+ void testMultipleDeclarators();
+ void testMultipleDeclarators_data();
+ void testMultipleMatches();
+ void testMultipleMatches_data();
+ void testMacros();
+ void testMacros_data();
+};
+
+} // namespace CppTools::Internal
diff --git a/src/plugins/cpptools/cppprojectinfogenerator.cpp b/src/plugins/cpptools/cppprojectinfogenerator.cpp
index cf3152163f..f81524f102 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 7e97f1c5ca..64fc60c238 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 548ccbe6f2..03a540ea32 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 f34628af51..9b48335951 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 c356ab63d1..a76122d4b4 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/cpprefactoringchanges.cpp b/src/plugins/cpptools/cpprefactoringchanges.cpp
index d452204756..c05b264730 100644
--- a/src/plugins/cpptools/cpprefactoringchanges.cpp
+++ b/src/plugins/cpptools/cpprefactoringchanges.cpp
@@ -163,10 +163,9 @@ Document::Ptr CppRefactoringFile::cppDocument() const
if (!m_cppDocument || !m_cppDocument->translationUnit() ||
!m_cppDocument->translationUnit()->ast()) {
const QByteArray source = document()->toPlainText().toUtf8();
- const QString name = filePath().toString();
const Snapshot &snapshot = data()->m_snapshot;
- m_cppDocument = snapshot.preprocessedDocument(source, name);
+ m_cppDocument = snapshot.preprocessedDocument(source, filePath());
m_cppDocument->check();
}
diff --git a/src/plugins/cpptools/cppsemanticinfoupdater.cpp b/src/plugins/cpptools/cppsemanticinfoupdater.cpp
index 0c94c7715c..64819115aa 100644
--- a/src/plugins/cpptools/cppsemanticinfoupdater.cpp
+++ b/src/plugins/cpptools/cppsemanticinfoupdater.cpp
@@ -118,7 +118,8 @@ SemanticInfo SemanticInfoUpdaterPrivate::update(const SemanticInfo::Source &sour
newSemanticInfo.revision = source.revision;
newSemanticInfo.snapshot = source.snapshot;
- Document::Ptr doc = newSemanticInfo.snapshot.preprocessedDocument(source.code, source.fileName);
+ Document::Ptr doc = newSemanticInfo.snapshot.preprocessedDocument(source.code,
+ Utils::FilePath::fromString(source.fileName));
if (processor)
doc->control()->setTopLevelDeclarationProcessor(processor);
doc->check();
diff --git a/src/plugins/cpptools/cppsourceprocessor_test.cpp b/src/plugins/cpptools/cppsourceprocessor_test.cpp
index 67a1b9f702..a30c3e4280 100644
--- a/src/plugins/cpptools/cppsourceprocessor_test.cpp
+++ b/src/plugins/cpptools/cppsourceprocessor_test.cpp
@@ -23,7 +23,7 @@
**
****************************************************************************/
-#include "cpptoolsplugin.h"
+#include "cppsourceprocessor_test.h"
#include "baseeditordocumentprocessor.h"
#include "cppmodelmanager.h"
@@ -90,7 +90,7 @@ private:
};
/// Check: Resolved and unresolved includes are properly tracked.
-void CppToolsPlugin::test_cppsourceprocessor_includes_resolvedUnresolved()
+void SourceProcessorTest::testIncludesResolvedUnresolved()
{
const QString testFilePath
= TestIncludePaths::testFilePath(QLatin1String("test_main_resolvedUnresolved.cpp"));
@@ -115,7 +115,7 @@ void CppToolsPlugin::test_cppsourceprocessor_includes_resolvedUnresolved()
}
/// Check: Avoid self-include entries due to cyclic includes.
-void CppToolsPlugin::test_cppsourceprocessor_includes_cyclic()
+void SourceProcessorTest::testIncludesCyclic()
{
const QString fileName1 = TestIncludePaths::testFilePath(QLatin1String("cyclic1.h"));
const QString fileName2 = TestIncludePaths::testFilePath(QLatin1String("cyclic2.h"));
@@ -154,7 +154,7 @@ void CppToolsPlugin::test_cppsourceprocessor_includes_cyclic()
}
/// Check: All include errors are reported as diagnostic messages.
-void CppToolsPlugin::test_cppsourceprocessor_includes_allDiagnostics()
+void SourceProcessorTest::testIncludesAllDiagnostics()
{
const QString testFilePath
= TestIncludePaths::testFilePath(QLatin1String("test_main_allDiagnostics.cpp"));
@@ -168,7 +168,7 @@ void CppToolsPlugin::test_cppsourceprocessor_includes_allDiagnostics()
QCOMPARE(document->diagnosticMessages().size(), 3);
}
-void CppToolsPlugin::test_cppsourceprocessor_macroUses()
+void SourceProcessorTest::testMacroUses()
{
const QString testFilePath
= TestIncludePaths::testFilePath(QLatin1String("test_main_macroUses.cpp"));
@@ -198,7 +198,7 @@ static bool isMacroDefinedInDocument(const QByteArray &macroName, const Document
static inline QString _(const QByteArray &ba) { return QString::fromLatin1(ba, ba.size()); }
-void CppToolsPlugin::test_cppsourceprocessor_includeNext()
+void SourceProcessorTest::testIncludeNext()
{
const Core::Tests::TestDataDir data(
_(SRCDIR "/../../../tests/auto/cplusplus/preprocessor/data/include_next-data/"));
diff --git a/src/plugins/cpptools/cppsourceprocessor_test.h b/src/plugins/cpptools/cppsourceprocessor_test.h
new file mode 100644
index 0000000000..c0175cf8b3
--- /dev/null
+++ b/src/plugins/cpptools/cppsourceprocessor_test.h
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QObject>
+
+namespace CppTools::Internal {
+
+class SourceProcessorTest : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void testIncludesResolvedUnresolved();
+ void testIncludesCyclic();
+ void testIncludesAllDiagnostics();
+ void testMacroUses();
+ void testIncludeNext();
+};
+
+} // namespace CppTools::Internal
diff --git a/src/plugins/cpptools/cpptools.pro b/src/plugins/cpptools/cpptools.pro
index 7052d01ab6..3cb0e6c9f9 100644
--- a/src/plugins/cpptools/cpptools.pro
+++ b/src/plugins/cpptools/cpptools.pro
@@ -199,9 +199,21 @@ FORMS += \
equals(TEST, 1) {
HEADERS += \
+ compileroptionsbuilder_test.h \
+ cppcodegen_test.h \
+ cppcompletion_test.h \
+ cppheadersource_test.h \
+ cpplocalsymbols_test.h \
+ cpplocatorfilter_test.h \
+ cppmodelmanager_test.h \
+ cpppointerdeclarationformatter_test.h \
+ cppsourceprocessor_test.h \
cppsourceprocessertesthelper.h \
cpptoolstestcase.h \
- modelmanagertesthelper.h
+ modelmanagertesthelper.h \
+ projectinfo_test.h \
+ symbolsearcher_test.h \
+ typehierarchybuilder_test.h
SOURCES += \
cppcodegen_test.cpp \
@@ -214,7 +226,9 @@ equals(TEST, 1) {
cppsourceprocessertesthelper.cpp \
cppsourceprocessor_test.cpp \
cpptoolstestcase.cpp \
+ compileroptionsbuilder_test.cpp \
modelmanagertesthelper.cpp \
+ projectinfo_test.cpp \
symbolsearcher_test.cpp \
typehierarchybuilder_test.cpp
diff --git a/src/plugins/cpptools/cpptools.qbs b/src/plugins/cpptools/cpptools.qbs
index 13382138bf..13c79ccff5 100644
--- a/src/plugins/cpptools/cpptools.qbs
+++ b/src/plugins/cpptools/cpptools.qbs
@@ -229,20 +229,34 @@ Project {
name: "Tests"
condition: qtc.testsEnabled
files: [
+ "compileroptionsbuilder_test.cpp",
+ "compileroptionsbuilder_test.h",
"cppcodegen_test.cpp",
+ "cppcodegen_test.h",
"cppcompletion_test.cpp",
+ "cppcompletion_test.h",
"cppheadersource_test.cpp",
+ "cppheadersource_test.h",
"cpplocalsymbols_test.cpp",
+ "cpplocalsymbols_test.h",
"cpplocatorfilter_test.cpp",
+ "cpplocatorfilter_test.h",
"cppmodelmanager_test.cpp",
+ "cppmodelmanager_test.h",
"cpppointerdeclarationformatter_test.cpp",
+ "cpppointerdeclarationformatter_test.h",
"cppsourceprocessertesthelper.cpp",
"cppsourceprocessertesthelper.h",
"cppsourceprocessor_test.cpp",
+ "cppsourceprocessor_test.h",
"modelmanagertesthelper.cpp",
"modelmanagertesthelper.h",
+ "projectinfo_test.cpp",
+ "projectinfo_test.h",
"symbolsearcher_test.cpp",
+ "symbolsearcher_test.h",
"typehierarchybuilder_test.cpp",
+ "typehierarchybuilder_test.h",
]
cpp.defines: outer.concat(['SRCDIR="' + FileInfo.path(filePath) + '"'])
diff --git a/src/plugins/cpptools/cpptoolsjsextension.cpp b/src/plugins/cpptools/cpptoolsjsextension.cpp
index 64df64c101..04104d1526 100644
--- a/src/plugins/cpptools/cpptoolsjsextension.cpp
+++ b/src/plugins/cpptools/cpptoolsjsextension.cpp
@@ -164,7 +164,8 @@ bool CppToolsJsExtension::hasQObjectParent(const QString &klassName) const
return false;
source = file.readAll();
}
- const auto doc = snapshot.preprocessedDocument(source, item->fileName());
+ const auto doc = snapshot.preprocessedDocument(source,
+ Utils::FilePath::fromString(item->fileName()));
if (!doc)
return false;
doc->check();
diff --git a/src/plugins/cpptools/cpptoolsplugin.cpp b/src/plugins/cpptools/cpptoolsplugin.cpp
index 1e77501c0f..7eb0c916ee 100644
--- a/src/plugins/cpptools/cpptoolsplugin.cpp
+++ b/src/plugins/cpptools/cpptoolsplugin.cpp
@@ -24,6 +24,7 @@
****************************************************************************/
#include "cpptoolsplugin.h"
+
#include "cppcodemodelsettingspage.h"
#include "cppcodestylesettingspage.h"
#include "cppfilesettingspage.h"
@@ -59,6 +60,24 @@
#include <utils/mimetypes/mimedatabase.h>
#include <utils/qtcassert.h>
+#ifdef WITH_TESTS
+#include "compileroptionsbuilder_test.h"
+#include "cppcodegen_test.h"
+#include "cppcompletion_test.h"
+#include "cppheadersource_test.h"
+#include "cpplocalsymbols_test.h"
+#include "cpplocatorfilter_test.h"
+#include "cppmodelmanager_test.h"
+#include "cpppointerdeclarationformatter_test.h"
+#include "cppsourceprocessor_test.h"
+#include "functionutils.h"
+#include "includeutils.h"
+#include "projectinfo_test.h"
+#include "senddocumenttracker.h"
+#include "symbolsearcher_test.h"
+#include "typehierarchybuilder_test.h"
+#endif
+
#include <QFileInfo>
#include <QDir>
#include <QDebug>
@@ -67,6 +86,7 @@
using namespace Core;
using namespace CPlusPlus;
+using namespace ProjectExplorer;
using namespace Utils;
namespace CppTools {
@@ -125,9 +145,9 @@ void CppToolsPlugin::clearHeaderSourceCache()
m_headerSourceMapping.clear();
}
-Utils::FilePath CppToolsPlugin::licenseTemplatePath()
+FilePath CppToolsPlugin::licenseTemplatePath()
{
- return Utils::FilePath::fromString(m_instance->d->m_fileSettings.licenseTemplatePath);
+ return FilePath::fromString(m_instance->d->m_fileSettings.licenseTemplatePath);
}
QString CppToolsPlugin::licenseTemplate()
@@ -191,14 +211,14 @@ bool CppToolsPlugin::initialize(const QStringList &arguments, QString *error)
QAction *openInNextSplitAction = new QAction(tr("Open Corresponding Header/Source in Next Split"), this);
command = ActionManager::registerAction(openInNextSplitAction, Constants::OPEN_HEADER_SOURCE_IN_NEXT_SPLIT, context, true);
- command->setDefaultKeySequence(QKeySequence(Utils::HostOsInfo::isMacHost()
+ command->setDefaultKeySequence(QKeySequence(HostOsInfo::isMacHost()
? tr("Meta+E, F4")
: tr("Ctrl+E, F4")));
mcpptools->addAction(command);
connect(openInNextSplitAction, &QAction::triggered,
this, &CppToolsPlugin::switchHeaderSourceInNextSplit);
- Utils::MacroExpander *expander = Utils::globalMacroExpander();
+ MacroExpander *expander = globalMacroExpander();
expander->registerVariable("Cpp:LicenseTemplate",
tr("The license template."),
[]() { return CppToolsPlugin::licenseTemplate(); });
@@ -211,13 +231,13 @@ bool CppToolsPlugin::initialize(const QStringList &arguments, QString *error)
tr("Insert \"#pragma once\" instead of \"#ifndef\" include guards into header file"),
[] { return usePragmaOnce() ? QString("true") : QString(); });
- const auto panelFactory = new ProjectExplorer::ProjectPanelFactory;
+ const auto panelFactory = new ProjectPanelFactory;
panelFactory->setPriority(100);
panelFactory->setDisplayName(tr("Clangd"));
- panelFactory->setCreateWidgetFunction([](ProjectExplorer::Project *project) {
+ panelFactory->setCreateWidgetFunction([](Project *project) {
return new ClangdProjectSettingsWidget(project);
});
- ProjectExplorer::ProjectPanelFactory::registerFactory(panelFactory);
+ ProjectPanelFactory::registerFactory(panelFactory);
return true;
}
@@ -233,6 +253,32 @@ void CppToolsPlugin::extensionsInitialized()
d->m_clangdSettingsPage = new ClangdSettingsPage;
}
+QVector<QObject *> CppToolsPlugin::createTestObjects() const
+{
+ return {
+#ifdef WITH_TESTS
+ new CodegenTest,
+ new CompilerOptionsBuilderTest,
+ new CompletionTest,
+ new FunctionUtilsTest,
+ new HeaderPathFilterTest,
+ new HeaderSourceTest,
+ new IncludeGroupsTest,
+ new LocalSymbolsTest,
+ new LocatorFilterTest,
+ new ModelManagerTest,
+ new PointerDeclarationFormatterTest,
+ new ProjectFileCategorizerTest,
+ new ProjectInfoGeneratorTest,
+ new ProjectPartChooserTest,
+ new DocumentTrackerTest,
+ new SourceProcessorTest,
+ new SymbolSearcherTest,
+ new TypeHierarchyBuilderTest,
+#endif
+ };
+}
+
CppCodeModelSettings *CppToolsPlugin::codeModelSettings()
{
return &d->m_codeModelSettings;
@@ -240,7 +286,7 @@ CppCodeModelSettings *CppToolsPlugin::codeModelSettings()
CppFileSettings *CppToolsPlugin::fileSettings()
{
- return &d->m_fileSettings;
+ return &instance()->d->m_fileSettings;
}
void CppToolsPlugin::switchHeaderSource()
@@ -256,8 +302,7 @@ void CppToolsPlugin::switchHeaderSourceInNextSplit()
EditorManager::openEditor(otherFile, Id(), EditorManager::OpenInOtherSplit);
}
-static QStringList findFilesInProject(const QString &name,
- const ProjectExplorer::Project *project)
+static QStringList findFilesInProject(const QString &name, const Project *project)
{
if (debug)
qDebug() << Q_FUNC_INFO << name << project;
@@ -268,11 +313,11 @@ static QStringList findFilesInProject(const QString &name,
QString pattern = QString(1, QLatin1Char('/'));
pattern += name;
const QStringList projectFiles
- = Utils::transform(project->files(ProjectExplorer::Project::AllFiles), &Utils::FilePath::toString);
+ = transform(project->files(Project::AllFiles), &FilePath::toString);
const QStringList::const_iterator pcend = projectFiles.constEnd();
QStringList candidateList;
for (QStringList::const_iterator it = projectFiles.constBegin(); it != pcend; ++it) {
- if (it->endsWith(pattern, Utils::HostOsInfo::fileNameCaseSensitivity()))
+ if (it->endsWith(pattern, HostOsInfo::fileNameCaseSensitivity()))
candidateList.append(*it);
}
return candidateList;
@@ -310,7 +355,7 @@ static QStringList baseNameWithAllSuffixes(const QString &baseName, const QStrin
{
QStringList result;
const QChar dot = QLatin1Char('.');
- foreach (const QString &suffix, suffixes) {
+ for (const QString &suffix : suffixes) {
QString fileName = baseName;
fileName += dot;
fileName += suffix;
@@ -325,16 +370,16 @@ static QStringList baseNamesWithAllPrefixes(const QStringList &baseNames, bool i
const QStringList &sourcePrefixes = m_instance->sourcePrefixes();
const QStringList &headerPrefixes = m_instance->headerPrefixes();
- foreach (const QString &name, baseNames) {
- foreach (const QString &prefix, isHeader ? headerPrefixes : sourcePrefixes) {
+ for (const QString &name : baseNames) {
+ for (const QString &prefix : isHeader ? headerPrefixes : sourcePrefixes) {
if (name.startsWith(prefix)) {
QString nameWithoutPrefix = name.mid(prefix.size());
result += nameWithoutPrefix;
- foreach (const QString &prefix, isHeader ? sourcePrefixes : headerPrefixes)
+ for (const QString &prefix : isHeader ? sourcePrefixes : headerPrefixes)
result += prefix + nameWithoutPrefix;
}
}
- foreach (const QString &prefix, isHeader ? sourcePrefixes : headerPrefixes)
+ for (const QString &prefix : isHeader ? sourcePrefixes : headerPrefixes)
result += prefix + name;
}
@@ -344,7 +389,7 @@ static QStringList baseNamesWithAllPrefixes(const QStringList &baseNames, bool i
static QStringList baseDirWithAllDirectories(const QDir &baseDir, const QStringList &directories)
{
QStringList result;
- foreach (const QString &dir, directories)
+ for (const QString &dir : directories)
result << QDir::cleanPath(baseDir.absoluteFilePath(dir));
return result;
}
@@ -353,7 +398,7 @@ static int commonFilePathLength(const QString &s1, const QString &s2)
{
int length = qMin(s1.length(), s2.length());
for (int i = 0; i < length; ++i)
- if (Utils::HostOsInfo::fileNameCaseSensitivity() == Qt::CaseSensitive) {
+ if (HostOsInfo::fileNameCaseSensitivity() == Qt::CaseSensitive) {
if (s1[i] != s2[i])
return i;
} else {
@@ -365,16 +410,16 @@ static int commonFilePathLength(const QString &s1, const QString &s2)
static QString correspondingHeaderOrSourceInProject(const QFileInfo &fileInfo,
const QStringList &candidateFileNames,
- const ProjectExplorer::Project *project,
+ const Project *project,
CacheUsage cacheUsage)
{
QString bestFileName;
int compareValue = 0;
const QString filePath = fileInfo.filePath();
- foreach (const QString &candidateFileName, candidateFileNames) {
+ for (const QString &candidateFileName : candidateFileNames) {
const QStringList projectFiles = findFilesInProject(candidateFileName, project);
// Find the file having the most common path with fileName
- foreach (const QString &projectFile, projectFiles) {
+ for (const QString &projectFile : projectFiles) {
int value = commonFilePathLength(filePath, projectFile);
if (value > compareValue) {
compareValue = value;
@@ -442,10 +487,10 @@ QString correspondingHeaderOrSource(const QString &fileName, bool *wasHeader, Ca
candidateFileNames += baseNamesWithAllPrefixes(candidateFileNames, isHeader);
// Try to find a file in the same or sibling directories first
- foreach (const QString &candidateDir, candidateDirs) {
- foreach (const QString &candidateFileName, candidateFileNames) {
+ for (const QString &candidateDir : qAsConst(candidateDirs)) {
+ for (const QString &candidateFileName : qAsConst(candidateFileNames)) {
const QString candidateFilePath = candidateDir + QLatin1Char('/') + candidateFileName;
- const QString normalized = Utils::FileUtils::normalizePathName(candidateFilePath);
+ const QString normalized = FileUtils::normalizedPathName(candidateFilePath);
const QFileInfo candidateFi(normalized);
if (candidateFi.isFile()) {
if (cacheUsage == CacheUsage::ReadWrite) {
@@ -459,7 +504,7 @@ QString correspondingHeaderOrSource(const QString &fileName, bool *wasHeader, Ca
}
// Find files in the current project
- ProjectExplorer::Project *currentProject = ProjectExplorer::ProjectTree::currentProject();
+ Project *currentProject = ProjectTree::currentProject();
if (currentProject) {
const QString path = correspondingHeaderOrSourceInProject(fi, candidateFileNames,
currentProject, cacheUsage);
@@ -469,9 +514,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();
+ const QList<ProjectInfo::Ptr> projectInfos = modelManager->projectInfos();
+ for (const ProjectInfo::Ptr &projectInfo : projectInfos) {
+ const Project *project = projectForProjectInfo(*projectInfo);
if (project == currentProject)
continue; // We have already checked the current project.
diff --git a/src/plugins/cpptools/cpptoolsplugin.h b/src/plugins/cpptools/cpptoolsplugin.h
index 24f981d15f..d5610265d0 100644
--- a/src/plugins/cpptools/cpptoolsplugin.h
+++ b/src/plugins/cpptools/cpptoolsplugin.h
@@ -58,120 +58,18 @@ public:
static QString licenseTemplate();
static bool usePragmaOnce();
- bool initialize(const QStringList &arguments, QString *errorMessage) final;
- void extensionsInitialized() final;
-
CppCodeModelSettings *codeModelSettings();
+ static CppFileSettings *fileSettings();
public slots:
void switchHeaderSource();
void switchHeaderSourceInNextSplit();
-#ifdef WITH_TESTS
-private slots:
- // Init/Cleanup methods implemented in cppheadersource_test.cpp
- void initTestCase();
- void cleanupTestCase();
-
- void test_codegen_public_in_empty_class();
- void test_codegen_public_in_nonempty_class();
- void test_codegen_public_before_protected();
- void test_codegen_private_after_protected();
- void test_codegen_protected_in_nonempty_class();
- void test_codegen_protected_between_public_and_private();
- void test_codegen_qtdesigner_integration();
- void test_codegen_definition_empty_class();
- void test_codegen_definition_first_member();
- void test_codegen_definition_last_member();
- void test_codegen_definition_middle_member();
- void test_codegen_definition_middle_member_surrounded_by_undefined();
- void test_codegen_definition_member_specific_file();
-
- void test_completion_basic_1();
-
- void test_completion_template_function_data();
- void test_completion_template_function();
-
- void test_completion_data();
- void test_completion();
-
- void test_global_completion_data();
- void test_global_completion();
-
- void test_doxygen_tag_completion_data();
- void test_doxygen_tag_completion();
-
- void test_completion_member_access_operator_data();
- void test_completion_member_access_operator();
-
- void test_completion_prefix_first_QTCREATORBUG_8737();
- void test_completion_prefix_first_QTCREATORBUG_9236();
-
- void test_format_pointerdeclaration_in_simpledeclarations();
- void test_format_pointerdeclaration_in_simpledeclarations_data();
- void test_format_pointerdeclaration_in_controlflowstatements();
- void test_format_pointerdeclaration_in_controlflowstatements_data();
- void test_format_pointerdeclaration_multiple_declarators();
- void test_format_pointerdeclaration_multiple_declarators_data();
- void test_format_pointerdeclaration_multiple_matches();
- void test_format_pointerdeclaration_multiple_matches_data();
- void test_format_pointerdeclaration_macros();
- void test_format_pointerdeclaration_macros_data();
-
- void test_cppsourceprocessor_includes_resolvedUnresolved();
- void test_cppsourceprocessor_includes_cyclic();
- void test_cppsourceprocessor_includes_allDiagnostics();
- void test_cppsourceprocessor_macroUses();
- void test_cppsourceprocessor_includeNext();
-
- void test_functionutils_virtualFunctions();
- void test_functionutils_virtualFunctions_data();
-
- void test_modelmanager_paths_are_clean();
- void test_modelmanager_framework_headers();
- void test_modelmanager_refresh_also_includes_of_project_files();
- void test_modelmanager_refresh_several_times();
- void test_modelmanager_refresh_test_for_changes();
- void test_modelmanager_refresh_added_and_purge_removed();
- void test_modelmanager_refresh_timeStampModified_if_sourcefiles_change();
- void test_modelmanager_refresh_timeStampModified_if_sourcefiles_change_data();
- void test_modelmanager_snapshot_after_two_projects();
- void test_modelmanager_extraeditorsupport_uiFiles();
- void test_modelmanager_gc_if_last_cppeditor_closed();
- void test_modelmanager_dont_gc_opened_files();
- void test_modelmanager_defines_per_project();
- void test_modelmanager_defines_per_editor();
- void test_modelmanager_updateEditorsAfterProjectUpdate();
- void test_modelmanager_precompiled_headers();
- void test_modelmanager_renameIncludes();
- void test_modelmanager_renameIncludesInEditor();
- void test_modelmanager_documentsAndRevisions();
-
- void test_cpplocatorfilters_CppLocatorFilter();
- void test_cpplocatorfilters_CppLocatorFilter_data();
- void test_cpplocatorfilters_CppCurrentDocumentFilter();
- void test_cpplocatorfilters_CppCurrentDocumentHighlighting();
- void test_cpplocatorfilters_CppFunctionsFilterHighlighting();
-
- void test_builtinsymbolsearcher();
- void test_builtinsymbolsearcher_data();
-
- void test_headersource_data();
- void test_headersource();
-
- void test_typehierarchy_data();
- void test_typehierarchy();
-
- void test_cpplocalsymbols_data();
- void test_cpplocalsymbols();
-
- void test_includeGroups_detectIncludeGroupsByNewLines();
- void test_includeGroups_detectIncludeGroupsByIncludeDir();
- void test_includeGroups_detectIncludeGroupsByIncludeType();
-#endif
-
private:
- CppFileSettings *fileSettings();
+ bool initialize(const QStringList &arguments, QString *errorMessage) final;
+ void extensionsInitialized() final;
+ QVector<QObject *> createTestObjects() const final;
+
class CppToolsPluginPrivate *d = nullptr;
};
diff --git a/src/plugins/cpptools/cpptoolsreuse.cpp b/src/plugins/cpptools/cpptoolsreuse.cpp
index 5294f1314b..de7dbcaeee 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 02633f91ea..1946a93176 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 e9a6e85d0d..fca2d11eed 100644
--- a/src/plugins/cpptools/cpptoolstestcase.cpp
+++ b/src/plugins/cpptools/cpptoolstestcase.cpp
@@ -50,30 +50,30 @@
#include <QtTest>
using namespace ProjectExplorer;
+using namespace Utils;
+
+namespace CppTools {
+namespace Tests {
static bool closeEditorsWithoutGarbageCollectorInvocation(const QList<Core::IEditor *> &editors)
{
- CppTools::CppModelManager::instance()->enableGarbageCollector(false);
+ CppModelManager::instance()->enableGarbageCollector(false);
const bool closeEditorsSucceeded = Core::EditorManager::closeEditors(editors, false);
- CppTools::CppModelManager::instance()->enableGarbageCollector(true);
+ CppModelManager::instance()->enableGarbageCollector(true);
return closeEditorsSucceeded;
}
static bool snapshotContains(const CPlusPlus::Snapshot &snapshot, const QSet<QString> &filePaths)
{
- foreach (const QString &filePath, filePaths) {
+ for (const QString &filePath : filePaths) {
if (!snapshot.contains(filePath)) {
- const QString warning = QLatin1String("Missing file in snapshot: ") + filePath;
- QWARN(qPrintable(warning));
+ qWarning() << "Missing file in snapshot:" << qPrintable(filePath);
return false;
}
}
return true;
}
-namespace CppTools {
-namespace Tests {
-
TestDocument::TestDocument(const QByteArray &fileName, const QByteArray &source, char cursorMarker)
: m_fileName(QString::fromUtf8(fileName))
, m_source(QString::fromUtf8(source))
@@ -174,11 +174,11 @@ bool TestCase::parseFiles(const QSet<QString> &filePaths)
QCoreApplication::processEvents();
const CPlusPlus::Snapshot snapshot = globalSnapshot();
if (snapshot.isEmpty()) {
- QWARN("After parsing: snapshot is empty.");
+ qWarning("After parsing: snapshot is empty.");
return false;
}
if (!snapshotContains(snapshot, filePaths)) {
- QWARN("After parsing: snapshot does not contain all expected files.");
+ qWarning("After parsing: snapshot does not contain all expected files.");
return false;
}
return true;
@@ -214,7 +214,7 @@ QList<CPlusPlus::Document::Ptr> TestCase::waitForFilesInGlobalSnapshot(const QSt
t.start();
QList<CPlusPlus::Document::Ptr> result;
- foreach (const QString &filePath, filePaths) {
+ for (const QString &filePath : filePaths) {
forever {
if (CPlusPlus::Document::Ptr document = globalSnapshot().document(filePath)) {
result.append(document);
@@ -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);
}
@@ -246,8 +246,7 @@ bool TestCase::writeFile(const QString &filePath, const QByteArray &contents)
{
Utils::FileSaver saver(Utils::FilePath::fromString(filePath));
if (!saver.write(contents) || !saver.finalize()) {
- const QString warning = QLatin1String("Failed to write file to disk: ") + filePath;
- QWARN(qPrintable(warning));
+ qWarning() << "Failed to write file to disk:" << qPrintable(filePath);
return false;
}
return true;
@@ -279,13 +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(projectFile);
+ 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()
@@ -322,21 +322,18 @@ static bool copyRecursively(const QString &sourceDirPath,
const QString &targetDirPath,
QString *error)
{
- auto copyHelper = [](QFileInfo sourceInfo, QFileInfo targetInfo, QString *error) -> bool {
- const QString sourcePath = sourceInfo.absoluteFilePath();
- const QString targetPath = targetInfo.absoluteFilePath();
- if (!QFile::copy(sourcePath, targetPath)) {
+ auto copyHelper = [](const FilePath &sourcePath, const FilePath &targetPath, QString *error) -> bool {
+ if (!sourcePath.copyFile(targetPath)) {
if (error) {
*error = QString::fromLatin1("copyRecursively() failed: \"%1\" to \"%2\".")
- .arg(sourcePath, targetPath);
+ .arg(sourcePath.toUserOutput(), targetPath.toUserOutput());
}
return false;
}
// Copied files from Qt resources are read-only. Make them writable
// so that their parent directory can be removed without warnings.
- QFile file(targetPath);
- return file.setPermissions(file.permissions() | QFile::WriteUser);
+ return targetPath.setPermissions(targetPath.permissions() | QFile::WriteUser);
};
return Utils::FileUtils::copyRecursively(Utils::FilePath::fromString(sourceDirPath),
@@ -361,7 +358,7 @@ TemporaryCopiedDir::TemporaryCopiedDir(const QString &sourceDirPath)
QString errorMessage;
if (!copyRecursively(sourceDirPath, path(), &errorMessage)) {
- QWARN(qPrintable(errorMessage));
+ qWarning() << qPrintable(errorMessage);
m_isValid = false;
}
}
@@ -375,11 +372,8 @@ FileWriterAndRemover::FileWriterAndRemover(const QString &filePath, const QByteA
: m_filePath(filePath)
{
if (QFileInfo::exists(filePath)) {
- const QString warning = QString::fromLatin1(
- "Will not overwrite existing file: \"%1\"."
- " If this file is left over due to a(n) abort/crash, please remove manually.")
- .arg(m_filePath);
- QWARN(qPrintable(warning));
+ qWarning().nospace() << "Will not overwrite existing file: " << m_filePath << "."
+ << " If this file is left over due to a(n) abort/crash, please remove manually.";
m_writtenSuccessfully = false;
} else {
m_writtenSuccessfully = TestCase::writeFile(filePath, contents);
@@ -388,10 +382,8 @@ FileWriterAndRemover::FileWriterAndRemover(const QString &filePath, const QByteA
FileWriterAndRemover::~FileWriterAndRemover()
{
- if (m_writtenSuccessfully && !QFile::remove(m_filePath)) {
- const QString warning = QLatin1String("Failed to remove file from disk: ") + m_filePath;
- QWARN(qPrintable(warning));
- }
+ if (m_writtenSuccessfully && !QFile::remove(m_filePath))
+ qWarning() << "Failed to remove file from disk:" << qPrintable(m_filePath);
}
VerifyCleanCppModelManager::VerifyCleanCppModelManager()
diff --git a/src/plugins/cpptools/cpptoolstestcase.h b/src/plugins/cpptools/cpptoolstestcase.h
index d03a1b297c..7919f3c921 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/cpptoolsunittestfiles.pri b/src/plugins/cpptools/cpptoolsunittestfiles.pri
index 5d09a1d130..85f6d91ab2 100644
--- a/src/plugins/cpptools/cpptoolsunittestfiles.pri
+++ b/src/plugins/cpptools/cpptoolsunittestfiles.pri
@@ -5,23 +5,7 @@ shared {
}
HEADERS += \
- $$PWD/cppprojectfile.h \
- $$PWD/senddocumenttracker.h \
- $$PWD/projectpart.h \
- $$PWD/compileroptionsbuilder.h \
- $$PWD/cppprojectfilecategorizer.h \
- $$PWD/projectinfo.h \
- $$PWD/cppprojectinfogenerator.cpp \
- $$PWD/cppprojectpartchooser.h \
- $$PWD/headerpathfilter.h
+ $$PWD/cppprojectfile.h
SOURCES += \
- $$PWD/cppprojectfile.cpp \
- $$PWD/senddocumenttracker.cpp \
- $$PWD/projectpart.cpp \
- $$PWD/compileroptionsbuilder.cpp \
- $$PWD/cppprojectfilecategorizer.cpp \
- $$PWD/projectinfo.cpp \
- $$PWD/cppprojectinfogenerator.cpp \
- $$PWD/cppprojectpartchooser.cpp \
- $$PWD/headerpathfilter.cpp
+ $$PWD/cppprojectfile.cpp
diff --git a/src/plugins/cpptools/functionutils.cpp b/src/plugins/cpptools/functionutils.cpp
index ff7c1ecb6d..981169ea97 100644
--- a/src/plugins/cpptools/functionutils.cpp
+++ b/src/plugins/cpptools/functionutils.cpp
@@ -215,7 +215,6 @@ QList<Function *> FunctionUtils::overrides(Function *function, Class *functionsC
}
#ifdef WITH_TESTS
-#include "cpptoolsplugin.h"
#include <QTest>
@@ -237,7 +236,7 @@ Q_DECLARE_METATYPE(CppTools::Internal::Virtuality)
namespace CppTools {
namespace Internal {
-void CppToolsPlugin::test_functionutils_virtualFunctions()
+void FunctionUtilsTest::testVirtualFunctions()
{
// Create and parse document
QFETCH(QByteArray, source);
@@ -292,7 +291,7 @@ void CppToolsPlugin::test_functionutils_virtualFunctions()
QVERIFY(firstVirtualList.isEmpty());
}
-void CppToolsPlugin::test_functionutils_virtualFunctions_data()
+void FunctionUtilsTest::testVirtualFunctions_data()
{
using _ = QByteArray;
QTest::addColumn<QByteArray>("source");
diff --git a/src/plugins/cpptools/functionutils.h b/src/plugins/cpptools/functionutils.h
index 56c13f0da6..90c2be2d3f 100644
--- a/src/plugins/cpptools/functionutils.h
+++ b/src/plugins/cpptools/functionutils.h
@@ -28,6 +28,7 @@
#include "cpptools_global.h"
#include <QList>
+#include <QObject>
namespace CPlusPlus {
class Class;
@@ -56,4 +57,17 @@ public:
const CPlusPlus::Snapshot &snapshot);
};
+#ifdef WITH_TESTS
+namespace Internal {
+class FunctionUtilsTest : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void testVirtualFunctions();
+ void testVirtualFunctions_data();
+};
+} // namespace Internal
+#endif // WITH_TESTS
+
} // namespace CppTools
diff --git a/src/plugins/cpptools/headerpathfilter.cpp b/src/plugins/cpptools/headerpathfilter.cpp
index 2e010ead5a..73913ed7b2 100644
--- a/src/plugins/cpptools/headerpathfilter.cpp
+++ b/src/plugins/cpptools/headerpathfilter.cpp
@@ -36,11 +36,10 @@
#include <utils/algorithm.h>
-namespace CppTools {
+using namespace ProjectExplorer;
+using namespace Utils;
-using ProjectExplorer::HeaderPath;
-using ProjectExplorer::HeaderPaths;
-using ProjectExplorer::HeaderPathType;
+namespace CppTools {
void HeaderPathFilter::process()
{
@@ -104,7 +103,7 @@ void HeaderPathFilter::filterHeaderPath(const ProjectExplorer::HeaderPath &heade
namespace {
-QString clangIncludeDirectory(const QString &clangVersion, const QString &clangFallbackIncludeDir)
+FilePath clangIncludeDirectory(const QString &clangVersion, const FilePath &clangFallbackIncludeDir)
{
#ifndef UNIT_TESTS
return Core::ICore::clangIncludeDirectory(clangVersion, clangFallbackIncludeDir);
@@ -158,9 +157,9 @@ void HeaderPathFilter::tweakHeaderPaths()
auto split = resourceIterator(builtInHeaderPaths);
if (!clangVersion.isEmpty()) {
- const QString clangIncludePath
+ const FilePath clangIncludePath
= clangIncludeDirectory(clangVersion, clangFallbackIncludeDirectory);
- builtInHeaderPaths.insert(split, HeaderPath{clangIncludePath, HeaderPathType::BuiltIn});
+ builtInHeaderPaths.insert(split, HeaderPath{clangIncludePath.toString(), HeaderPathType::BuiltIn});
}
}
diff --git a/src/plugins/cpptools/headerpathfilter.h b/src/plugins/cpptools/headerpathfilter.h
index 4482c230ae..49fefd721c 100644
--- a/src/plugins/cpptools/headerpathfilter.h
+++ b/src/plugins/cpptools/headerpathfilter.h
@@ -28,14 +28,17 @@
#include "compileroptionsbuilder.h"
#include "projectpart.h"
+#include <utils/filepath.h>
+
namespace CppTools {
+
class CPPTOOLS_EXPORT HeaderPathFilter
{
public:
HeaderPathFilter(const ProjectPart &projectPart,
UseTweakedHeaderPaths useTweakedHeaderPaths = UseTweakedHeaderPaths::Yes,
const QString &clangVersion = {},
- const QString &clangIncludeDirectory = {},
+ const Utils::FilePath &clangIncludeDirectory = {},
const QString &projectDirectory = {},
const QString &buildDirectory = {})
: projectPart{projectPart}
@@ -67,7 +70,7 @@ public:
ProjectExplorer::HeaderPaths userHeaderPaths;
const ProjectPart &projectPart;
const QString clangVersion;
- const QString clangFallbackIncludeDirectory;
+ const Utils::FilePath clangFallbackIncludeDirectory;
const QString projectDirectory;
const QString buildDirectory;
const UseTweakedHeaderPaths useTweakedHeaderPaths;
diff --git a/src/plugins/cpptools/includeutils.cpp b/src/plugins/cpptools/includeutils.cpp
index c42b104acf..114093ce0f 100644
--- a/src/plugins/cpptools/includeutils.cpp
+++ b/src/plugins/cpptools/includeutils.cpp
@@ -33,6 +33,15 @@
#include <utils/qtcassert.h>
#include <utils/stringutils.h>
+#ifdef WITH_TESTS
+#include "cppmodelmanager.h"
+#include "cppsourceprocessertesthelper.h"
+#include "cppsourceprocessor.h"
+#include "cpptoolsplugin.h"
+#include "cpptoolstestcase.h"
+#include <QtTest>
+#endif // WITH_TESTS
+
#include <QDir>
#include <QFileInfo>
#include <QStringList>
@@ -42,7 +51,6 @@
#include <algorithm>
using namespace CPlusPlus;
-using namespace CppTools;
using namespace CppTools::IncludeUtils;
using namespace Utils;
@@ -117,6 +125,8 @@ int lineAfterFirstComment(const QTextDocument *textDocument)
} // anonymous namespace
+namespace CppTools {
+
LineForNewIncludeDirective::LineForNewIncludeDirective(const QTextDocument *textDocument,
const Document::Ptr cppDocument,
MocIncludeMode mocIncludeMode,
@@ -516,17 +526,7 @@ bool IncludeGroup::hasCommonIncludeDir() const
}
#ifdef WITH_TESTS
-
-#include "cppmodelmanager.h"
-#include "cppsourceprocessertesthelper.h"
-#include "cppsourceprocessor.h"
-#include "cpptoolsplugin.h"
-#include "cpptoolstestcase.h"
-
-#include <QtTest>
-
using namespace Tests;
-using CppTools::Internal::CppToolsPlugin;
static QList<Include> includesForSource(const QString &filePath)
{
@@ -542,7 +542,8 @@ static QList<Include> includesForSource(const QString &filePath)
return document->resolvedIncludes();
}
-void CppToolsPlugin::test_includeGroups_detectIncludeGroupsByNewLines()
+namespace Internal {
+void IncludeGroupsTest::testDetectIncludeGroupsByNewLines()
{
const QString testFilePath = TestIncludePaths::testFilePath(
QLatin1String("test_main_detectIncludeGroupsByNewLines.cpp"));
@@ -584,7 +585,7 @@ void CppToolsPlugin::test_includeGroups_detectIncludeGroupsByNewLines()
QCOMPARE(IncludeGroup::filterMixedIncludeGroups(includeGroups).size(), 1);
}
-void CppToolsPlugin::test_includeGroups_detectIncludeGroupsByIncludeDir()
+void IncludeGroupsTest::testDetectIncludeGroupsByIncludeDir()
{
const QString testFilePath = TestIncludePaths::testFilePath(
QLatin1String("test_main_detectIncludeGroupsByIncludeDir.cpp"));
@@ -608,7 +609,7 @@ void CppToolsPlugin::test_includeGroups_detectIncludeGroupsByIncludeDir()
QCOMPARE(includeGroups.at(3).commonIncludeDir(), QLatin1String(""));
}
-void CppToolsPlugin::test_includeGroups_detectIncludeGroupsByIncludeType()
+void IncludeGroupsTest::testDetectIncludeGroupsByIncludeType()
{
const QString testFilePath = TestIncludePaths::testFilePath(
QLatin1String("test_main_detectIncludeGroupsByIncludeType.cpp"));
@@ -632,4 +633,8 @@ void CppToolsPlugin::test_includeGroups_detectIncludeGroupsByIncludeType()
QVERIFY(includeGroups.at(3).hasOnlyIncludesOfType(Client::IncludeGlobal));
}
+} // namespace Internal
+
#endif // WITH_TESTS
+
+} // namespace CppTools
diff --git a/src/plugins/cpptools/includeutils.h b/src/plugins/cpptools/includeutils.h
index 59ff8b81a7..508047c168 100644
--- a/src/plugins/cpptools/includeutils.h
+++ b/src/plugins/cpptools/includeutils.h
@@ -31,6 +31,7 @@
#include <cplusplus/PreprocessorClient.h>
#include <QList>
+#include <QObject>
#include <QString>
QT_FORWARD_DECLARE_CLASS(QTextDocument)
@@ -105,4 +106,19 @@ private:
};
} // namespace IncludeUtils
+
+#ifdef WITH_TESTS
+namespace Internal {
+class IncludeGroupsTest : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void testDetectIncludeGroupsByNewLines();
+ void testDetectIncludeGroupsByIncludeDir();
+ void testDetectIncludeGroupsByIncludeType();
+};
+} // namespace Internal
+#endif // WITH_TESTS
+
} // namespace CppTools
diff --git a/src/plugins/cpptools/modelmanagertesthelper.cpp b/src/plugins/cpptools/modelmanagertesthelper.cpp
index 08d01c02e0..b80ce25564 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 9fe887006d..e5ee32cca8 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 a7047dc972..2125862be4 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 347e72f477..bf73bd71bb 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
new file mode 100644
index 0000000000..fb24554684
--- /dev/null
+++ b/src/plugins/cpptools/projectinfo_test.cpp
@@ -0,0 +1,865 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "projectinfo_test.h"
+
+#include "cppprojectfilecategorizer.h"
+#include "cppprojectinfogenerator.h"
+#include "cppprojectpartchooser.h"
+#include "headerpathfilter.h"
+#include "projectinfo.h"
+
+#include <projectexplorer/projectexplorerconstants.h>
+#include <projectexplorer/toolchainconfigwidget.h>
+#include <utils/algorithm.h>
+
+#include <QtTest>
+
+using namespace ProjectExplorer;
+
+namespace CppTools {
+namespace Internal {
+
+namespace {
+class ProjectPartChooserTestHelper
+{
+public:
+ ProjectPartChooserTestHelper()
+ {
+ chooser.setFallbackProjectPart([&]() {
+ return fallbackProjectPart;
+ });
+ chooser.setProjectPartsForFile([&](const QString &) {
+ return projectPartsForFile;
+ });
+ chooser.setProjectPartsFromDependenciesForFile([&](const QString &) {
+ return projectPartsFromDependenciesForFile;
+ });
+ }
+
+ const ProjectPartInfo choose()
+ {
+ return chooser.choose(filePath, currentProjectPartInfo, preferredProjectPartId,
+ projectMap.value(activeProject).get(),
+ languagePreference, projectsChanged);
+ }
+
+ static QList<ProjectPart::Ptr> createProjectPartsWithDifferentProjects()
+ {
+ QList<ProjectPart::Ptr> projectParts;
+
+ 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;
+ }
+
+ static QList<ProjectPart::Ptr> createCAndCxxProjectParts()
+ {
+ QList<ProjectPart::Ptr> projectParts;
+ ToolChainInfo tcInfo;
+
+ // Create project part for C
+ 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
+ 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 = ProjectPart::create({});
+ ProjectPartInfo currentProjectPartInfo{currentProjectPart,
+ {currentProjectPart},
+ ProjectPartInfo::NoHint};
+ QString preferredProjectPartId;
+ Utils::FilePath activeProject;
+ Language languagePreference = Language::Cxx;
+ bool projectsChanged = false;
+ ProjectPartChooser chooser;
+
+ 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>>
+ProjectPartChooserTestHelper::projectMap;
+}
+
+void ProjectPartChooserTest::testChooseManuallySet()
+{
+ ProjectPart::Ptr p1 = ProjectPart::create({});
+ RawProjectPart rpp2;
+ rpp2.setProjectFileLocation("someId");
+ ProjectPart::Ptr p2 = ProjectPart::create({}, rpp2);
+ ProjectPartChooserTestHelper t;
+ t.preferredProjectPartId = p2->projectFile;
+ t.projectPartsForFile += {p1, p2};
+
+ QCOMPARE(t.choose().projectPart, p2);
+}
+
+void ProjectPartChooserTest::testIndicateManuallySet()
+{
+ ProjectPart::Ptr p1 = ProjectPart::create({});
+ RawProjectPart rpp2;
+ rpp2.setProjectFileLocation("someId");
+ ProjectPart::Ptr p2 = ProjectPart::create({}, rpp2);
+ ProjectPartChooserTestHelper t;
+ t.preferredProjectPartId = p2->projectFile;
+ t.projectPartsForFile += {p1, p2};
+
+ QVERIFY(t.choose().hints & ProjectPartInfo::IsPreferredMatch);
+}
+
+void ProjectPartChooserTest::testIndicateManuallySetForFallbackToProjectPartFromDependencies()
+{
+ ProjectPart::Ptr p1 = ProjectPart::create({});
+ RawProjectPart rpp2;
+ rpp2.setProjectFileLocation("someId");
+ ProjectPart::Ptr p2 = ProjectPart::create({}, rpp2);
+ ProjectPartChooserTestHelper t;
+ t.preferredProjectPartId = p2->projectFile;
+ t.projectPartsFromDependenciesForFile += {p1, p2};
+
+ QVERIFY(t.choose().hints & ProjectPartInfo::IsPreferredMatch);
+}
+
+void ProjectPartChooserTest::testDoNotIndicateNotManuallySet()
+{
+ QVERIFY(!(ProjectPartChooserTestHelper().choose().hints & ProjectPartInfo::IsPreferredMatch));
+}
+
+void ProjectPartChooserTest::testForMultipleChooseFromActiveProject()
+{
+ ProjectPartChooserTestHelper t;
+ const QList<ProjectPart::Ptr> projectParts = t.createProjectPartsWithDifferentProjects();
+ const ProjectPart::Ptr secondProjectPart = projectParts.at(1);
+ t.projectPartsForFile += projectParts;
+ t.activeProject = secondProjectPart->topLevelProject;
+
+ QCOMPARE(t.choose().projectPart, secondProjectPart);
+}
+
+void ProjectPartChooserTest::testForMultiplePreferSelectedForBuilding()
+{
+ RawProjectPart rpp1;
+ rpp1.setSelectedForBuilding(false);
+ RawProjectPart rpp2;
+ rpp2.setSelectedForBuilding(true);
+ const ProjectPart::Ptr firstProjectPart = ProjectPart::create({}, rpp1);
+ const ProjectPart::Ptr secondProjectPart = ProjectPart::create({}, rpp2);
+ ProjectPartChooserTestHelper t;
+ t.projectPartsForFile += firstProjectPart;
+ t.projectPartsForFile += secondProjectPart;
+
+ QCOMPARE(t.choose().projectPart, secondProjectPart);
+}
+
+void ProjectPartChooserTest::testForMultipleFromDependenciesChooseFromActiveProject()
+{
+ ProjectPartChooserTestHelper t;
+ const QList<ProjectPart::Ptr> projectParts = t.createProjectPartsWithDifferentProjects();
+ const ProjectPart::Ptr secondProjectPart = projectParts.at(1);
+ t.projectPartsFromDependenciesForFile += projectParts;
+ t.activeProject = secondProjectPart->topLevelProject;
+
+ QCOMPARE(t.choose().projectPart, secondProjectPart);
+}
+
+void ProjectPartChooserTest::testForMultipleCheckIfActiveProjectChanged()
+{
+ ProjectPartChooserTestHelper t;
+ const QList<ProjectPart::Ptr> projectParts = t.createProjectPartsWithDifferentProjects();
+ const ProjectPart::Ptr firstProjectPart = projectParts.at(0);
+ const ProjectPart::Ptr secondProjectPart = projectParts.at(1);
+ t.projectPartsForFile += projectParts;
+ t.currentProjectPartInfo.projectPart = firstProjectPart;
+ t.activeProject = secondProjectPart->topLevelProject;
+
+ QCOMPARE(t.choose().projectPart, secondProjectPart);
+}
+
+void ProjectPartChooserTest::testForMultipleAndAmbigiousHeaderPreferCProjectPart()
+{
+ ProjectPartChooserTestHelper t;
+ t.languagePreference = Language::C;
+ t.projectPartsForFile = t.createCAndCxxProjectParts();
+ const ProjectPart::Ptr cProjectPart = t.projectPartsForFile.at(0);
+
+ QCOMPARE(t.choose().projectPart, cProjectPart);
+}
+
+void ProjectPartChooserTest::testForMultipleAndAmbigiousHeaderPreferCxxProjectPart()
+{
+ ProjectPartChooserTestHelper t;
+ t.languagePreference = Language::Cxx;
+ t.projectPartsForFile = t.createCAndCxxProjectParts();
+ const ProjectPart::Ptr cxxProjectPart = t.projectPartsForFile.at(1);
+
+ QCOMPARE(t.choose().projectPart, cxxProjectPart);
+}
+
+void ProjectPartChooserTest::testIndicateMultiple()
+{
+ const ProjectPart::Ptr p1 = ProjectPart::create({});
+ const ProjectPart::Ptr p2 = ProjectPart::create({});
+ ProjectPartChooserTestHelper t;
+ t.projectPartsForFile += {p1, p2};
+
+ QVERIFY(t.choose().hints & ProjectPartInfo::IsAmbiguousMatch);
+}
+
+void ProjectPartChooserTest::testIndicateMultipleForFallbackToProjectPartFromDependencies()
+{
+ const ProjectPart::Ptr p1 = ProjectPart::create({});
+ const ProjectPart::Ptr p2 = ProjectPart::create({});
+ ProjectPartChooserTestHelper t;
+ t.projectPartsFromDependenciesForFile += {p1, p2};
+
+ QVERIFY(t.choose().hints & ProjectPartInfo::IsAmbiguousMatch);
+}
+
+void ProjectPartChooserTest::testForMultipleChooseNewIfPreviousIsGone()
+{
+ const ProjectPart::Ptr newProjectPart = ProjectPart::create({});
+ ProjectPartChooserTestHelper t;
+ t.projectPartsForFile += newProjectPart;
+
+ QCOMPARE(t.choose().projectPart, newProjectPart);
+}
+
+void ProjectPartChooserTest::testFallbackToProjectPartFromDependencies()
+{
+ const ProjectPart::Ptr fromDependencies = ProjectPart::create({});
+ ProjectPartChooserTestHelper t;
+ t.projectPartsFromDependenciesForFile += fromDependencies;
+
+ QCOMPARE(t.choose().projectPart, fromDependencies);
+}
+
+void ProjectPartChooserTest::testFallbackToProjectPartFromModelManager()
+{
+ ProjectPartChooserTestHelper t;
+ t.fallbackProjectPart = ProjectPart::create({});
+
+ QCOMPARE(t.choose().projectPart, t.fallbackProjectPart);
+}
+
+void ProjectPartChooserTest::testContinueUsingFallbackFromModelManagerIfProjectDoesNotChange()
+{
+ // ...without re-calculating the dependency table.
+ ProjectPartChooserTestHelper t;
+ t.fallbackProjectPart = ProjectPart::create({});
+ t.currentProjectPartInfo.projectPart = t.fallbackProjectPart;
+ t.currentProjectPartInfo.hints |= ProjectPartInfo::IsFallbackMatch;
+ t.projectPartsFromDependenciesForFile += ProjectPart::create({});
+
+ QCOMPARE(t.choose().projectPart, t.fallbackProjectPart);
+}
+
+void ProjectPartChooserTest::testStopUsingFallbackFromModelManagerIfProjectChanges1()
+{
+ ProjectPartChooserTestHelper t;
+ t.fallbackProjectPart = ProjectPart::create({});
+ t.currentProjectPartInfo.projectPart = t.fallbackProjectPart;
+ t.currentProjectPartInfo.hints |= ProjectPartInfo::IsFallbackMatch;
+ const ProjectPart::Ptr addedProject = ProjectPart::create({});
+ t.projectPartsForFile += addedProject;
+
+ QCOMPARE(t.choose().projectPart, addedProject);
+}
+
+void ProjectPartChooserTest::testStopUsingFallbackFromModelManagerIfProjectChanges2()
+{
+ ProjectPartChooserTestHelper t;
+ t.fallbackProjectPart = ProjectPart::create({});
+ t.currentProjectPartInfo.projectPart = t.fallbackProjectPart;
+ t.currentProjectPartInfo.hints |= ProjectPartInfo::IsFallbackMatch;
+ const ProjectPart::Ptr addedProject = ProjectPart::create({});
+ t.projectPartsFromDependenciesForFile += addedProject;
+ t.projectsChanged = true;
+
+ QCOMPARE(t.choose().projectPart, addedProject);
+}
+
+void ProjectPartChooserTest::testIndicateFallbacktoProjectPartFromModelManager()
+{
+ ProjectPartChooserTestHelper t;
+ t.fallbackProjectPart = ProjectPart::create({});
+
+ QVERIFY(t.choose().hints & ProjectPartInfo::IsFallbackMatch);
+}
+
+void ProjectPartChooserTest::testIndicateFromDependencies()
+{
+ ProjectPartChooserTestHelper t;
+ t.projectPartsFromDependenciesForFile += ProjectPart::create({});
+
+ QVERIFY(t.choose().hints & ProjectPartInfo::IsFromDependenciesMatch);
+}
+
+void ProjectPartChooserTest::testDoNotIndicateFromDependencies()
+{
+ ProjectPartChooserTestHelper t;
+ t.projectPartsForFile += ProjectPart::create({});
+
+ QVERIFY(!(t.choose().hints & ProjectPartInfo::IsFromDependenciesMatch));
+}
+
+namespace {
+class TestToolchain : public ToolChain
+{
+public:
+ TestToolchain() : ToolChain("dummy") {}
+
+private:
+ MacroInspectionRunner createMacroInspectionRunner() const override { return {}; }
+ Utils::LanguageExtensions languageExtensions(const QStringList &) const override { return {}; }
+ Utils::WarningFlags warningFlags(const QStringList &) const override { return {}; }
+ BuiltInHeaderPathsRunner createBuiltInHeaderPathsRunner(
+ const Utils::Environment &) const override { return {}; }
+ void addToEnvironment(Utils::Environment &) const override {}
+ Utils::FilePath makeCommand(const Utils::Environment &) const override { return {}; }
+ QList<Utils::OutputLineParser *> createOutputParsers() const override { return {}; }
+ std::unique_ptr<ToolChainConfigWidget> createConfigurationWidget() override
+ {
+ return {};
+ };
+};
+
+class ProjectInfoGeneratorTestHelper
+{
+public:
+ ProjectInfoGeneratorTestHelper()
+ {
+ TestToolchain aToolChain;
+ projectUpdateInfo.cxxToolChainInfo = {&aToolChain, {}, {}};
+ projectUpdateInfo.cToolChainInfo = {&aToolChain, {}, {}};
+ }
+
+ ProjectInfo::Ptr generate()
+ {
+ QFutureInterface<ProjectInfo::Ptr> fi;
+
+ projectUpdateInfo.rawProjectParts += rawProjectPart;
+ ProjectInfoGenerator generator(fi, projectUpdateInfo);
+
+ return generator.generate();
+ }
+
+ ProjectUpdateInfo projectUpdateInfo;
+ RawProjectPart rawProjectPart;
+};
+}
+
+void ProjectInfoGeneratorTest::testCreateNoProjectPartsForEmptyFileList()
+{
+ ProjectInfoGeneratorTestHelper t;
+ const ProjectInfo::Ptr projectInfo = t.generate();
+
+ QVERIFY(projectInfo->projectParts().isEmpty());
+}
+
+void ProjectInfoGeneratorTest::testCreateSingleProjectPart()
+{
+ ProjectInfoGeneratorTestHelper t;
+ t.rawProjectPart.files = QStringList{ "foo.cpp", "foo.h"};
+ const ProjectInfo::Ptr projectInfo = t.generate();
+
+ QCOMPARE(projectInfo->projectParts().size(), 1);
+}
+
+void ProjectInfoGeneratorTest::testCreateMultipleProjectParts()
+{
+ ProjectInfoGeneratorTestHelper t;
+ t.rawProjectPart.files = QStringList{ "foo.cpp", "foo.h", "bar.c", "bar.h" };
+ const ProjectInfo::Ptr projectInfo = t.generate();
+
+ QCOMPARE(projectInfo->projectParts().size(), 2);
+}
+
+void ProjectInfoGeneratorTest::testProjectPartIndicatesObjectiveCExtensionsByDefault()
+{
+ ProjectInfoGeneratorTestHelper t;
+ t.rawProjectPart.files = QStringList{ "foo.mm" };
+ const ProjectInfo::Ptr projectInfo = t.generate();
+ QCOMPARE(projectInfo->projectParts().size(), 1);
+
+ const ProjectPart &projectPart = *projectInfo->projectParts().at(0);
+ QVERIFY(projectPart.languageExtensions & Utils::LanguageExtension::ObjectiveC);
+}
+
+void ProjectInfoGeneratorTest::testProjectPartHasLatestLanguageVersionByDefault()
+{
+ ProjectInfoGeneratorTestHelper t;
+ t.rawProjectPart.files = QStringList{ "foo.cpp" };
+ const ProjectInfo::Ptr projectInfo = t.generate();
+ QCOMPARE(projectInfo->projectParts().size(), 1);
+
+ const ProjectPart &projectPart = *projectInfo->projectParts().at(0);
+ QCOMPARE(projectPart.languageVersion, Utils::LanguageVersion::LatestCxx);
+}
+
+void ProjectInfoGeneratorTest::testUseMacroInspectionReportForLanguageVersion()
+{
+ ProjectInfoGeneratorTestHelper t;
+ t.projectUpdateInfo.cxxToolChainInfo.macroInspectionRunner = [](const QStringList &) {
+ return TestToolchain::MacroInspectionReport{Macros(), Utils::LanguageVersion::CXX17};
+ };
+ t.rawProjectPart.files = QStringList{ "foo.cpp" };
+ const ProjectInfo::Ptr projectInfo = t.generate();
+
+ QCOMPARE(projectInfo->projectParts().size(), 1);
+
+ const ProjectPart &projectPart = *projectInfo->projectParts().at(0);
+ QCOMPARE(projectPart.languageVersion, Utils::LanguageVersion::CXX17);
+}
+
+void ProjectInfoGeneratorTest::testUseCompilerFlagsForLanguageExtensions()
+{
+ ProjectInfoGeneratorTestHelper t;
+ t.rawProjectPart.files = QStringList{ "foo.cpp" };
+ t.rawProjectPart.flagsForCxx.languageExtensions = Utils::LanguageExtension::Microsoft;
+ const ProjectInfo::Ptr projectInfo = t.generate();
+
+ QCOMPARE(projectInfo->projectParts().size(), 1);
+
+ const ProjectPart &projectPart = *projectInfo->projectParts().at(0);
+ QVERIFY(projectPart.languageExtensions & Utils::LanguageExtension::Microsoft);
+}
+
+void ProjectInfoGeneratorTest::testProjectFileKindsMatchProjectPartVersion()
+{
+ ProjectInfoGeneratorTestHelper t;
+ t.rawProjectPart.files = QStringList{ "foo.h" };
+ const ProjectInfo::Ptr projectInfo = t.generate();
+
+ 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) {
+ return p->languageVersion == Utils::LanguageVersion::LatestC
+ && p->files.first().kind == ProjectFile::ObjCHeader;
+ }));
+ 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) {
+ return p->languageVersion == Utils::LanguageVersion::LatestCxx
+ && p->files.first().kind == ProjectFile::ObjCXXHeader;
+ }));
+}
+
+namespace {
+class HeaderPathFilterTestHelper
+{
+public:
+ const ProjectPart &finalize()
+ {
+ 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)
+ {
+ return HeaderPath{path, HeaderPathType::BuiltIn};
+ }
+ static HeaderPath system(const QString &path)
+ {
+ return HeaderPath{path, HeaderPathType::System};
+ }
+ static HeaderPath framework(const QString &path)
+ {
+ return HeaderPath{path, HeaderPathType::Framework};
+ }
+ static HeaderPath user(const QString &path)
+ {
+ return HeaderPath{path, HeaderPathType::User};
+ }
+
+ 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 HeaderPathFilterTest::testBuiltin()
+{
+ HeaderPathFilterTestHelper t;
+ t.finalize();
+ t.filter->process();
+
+ QCOMPARE(t.filter->builtInHeaderPaths, (HeaderPaths{t.builtIn("/builtin_path")}));
+}
+
+void HeaderPathFilterTest::testSystem()
+{
+ HeaderPathFilterTestHelper t;
+ t.finalize();
+ t.filter->process();
+
+ 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")}));
+}
+
+void HeaderPathFilterTest::testUser()
+{
+ HeaderPathFilterTestHelper t;
+ t.finalize();
+ t.filter->process();
+
+ QCOMPARE(t.filter->userHeaderPaths, (HeaderPaths{t.user("/build/user_path"),
+ t.user("/project/user_path")}));
+}
+
+void HeaderPathFilterTest::testNoProjectPathSet()
+{
+ HeaderPathFilterTestHelper t;
+ HeaderPathFilter filter{t.finalize(), UseTweakedHeaderPaths::No};
+ filter.process();
+
+ QCOMPARE(filter.userHeaderPaths, (HeaderPaths{
+ t.user("/outside_project_user_path"), t.user("/build/user_path"),
+ t.user("/buildb/user_path"), t.user("/projectb/user_path"),
+ t.user("/project/user_path")}));
+}
+
+void HeaderPathFilterTest::testDontAddInvalidPath()
+{
+ HeaderPathFilterTestHelper t;
+ 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")}));
+}
+
+void HeaderPathFilterTest::testClangHeadersPath()
+{
+ HeaderPathFilterTestHelper t;
+ HeaderPathFilter filter(t.finalize(), UseTweakedHeaderPaths::Yes, "6.0", "clang_dir");
+ filter.process();
+
+ QCOMPARE(filter.builtInHeaderPaths, (HeaderPaths{t.builtIn("clang_dir"),
+ t.builtIn("/builtin_path")}));
+}
+
+void HeaderPathFilterTest::testClangHeadersPathWitoutClangVersion()
+{
+ HeaderPathFilterTestHelper t;
+ HeaderPathFilter filter(t.finalize(), UseTweakedHeaderPaths::Yes);
+ filter.process();
+
+ QCOMPARE(filter.builtInHeaderPaths, (HeaderPaths{t.builtIn("/builtin_path")}));
+}
+
+void HeaderPathFilterTest::testClangHeadersAndCppIncludesPathsOrderMacOs()
+{
+ HeaderPathFilterTestHelper 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"),
+ 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")
+ };
+ std::copy(builtIns.begin(), builtIns.end(),
+ std::inserter(t.headerPaths, t.headerPaths.begin()));
+ HeaderPathFilter filter(t.finalize(), UseTweakedHeaderPaths::Yes, "6.0", "clang_dir");
+ filter.process();
+
+ QCOMPARE(filter.builtInHeaderPaths, (HeaderPaths{
+ t.builtIn("/usr/include/c++/4.2.1"), t.builtIn("/usr/include/c++/4.2.1/backward"),
+ t.builtIn("/usr/local/include"), t.builtIn("clang_dir"),
+ t.builtIn("/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include"),
+ t.builtIn("/usr/include"),
+ t.builtIn("/builtin_path")}));
+}
+
+void HeaderPathFilterTest::testClangHeadersAndCppIncludesPathsOrderLinux()
+{
+ HeaderPathFilterTestHelper 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.headerPaths, t.headerPaths.begin()));
+ HeaderPathFilter filter(t.finalize(), UseTweakedHeaderPaths::Yes, "6.0", "clang_dir");
+ filter.process();
+
+ QCOMPARE(filter.builtInHeaderPaths, (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("clang_dir"), 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.builtIn("/builtin_path")}));
+}
+
+// GCC-internal include paths like <installdir>/include and <installdir/include-next> might confuse
+// clang and should be filtered out. clang on the command line filters them out, too.
+void HeaderPathFilterTest::testRemoveGccInternalPaths()
+{
+ HeaderPathFilterTestHelper t;
+ 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.finalize(), UseTweakedHeaderPaths::Yes, "6.0", "clang_dir");
+ filter.process();
+
+ QCOMPARE(filter.builtInHeaderPaths, (HeaderPaths{t.builtIn("clang_dir")}));
+}
+
+// Some distributions ship the standard library headers in "<installdir>/include/c++" (MinGW)
+// or e.g. "<installdir>/include/g++-v8" (Gentoo).
+// Ensure that we do not remove include paths pointing there.
+void HeaderPathFilterTest::testRemoveGccInternalPathsExceptForStandardPaths()
+{
+ HeaderPathFilterTestHelper t;
+ 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.headerPaths;
+ expected.append(t.builtIn("clang_dir"));
+ HeaderPathFilter filter(t.finalize(), UseTweakedHeaderPaths::Yes, "6.0", "clang_dir");
+ filter.process();
+
+ QCOMPARE(filter.builtInHeaderPaths, expected);
+}
+
+void HeaderPathFilterTest::testClangHeadersAndCppIncludesPathsOrderNoVersion()
+{
+ HeaderPathFilterTestHelper t;
+ 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.targetTriple = "x86_64-w64-windows-gnu";
+ HeaderPathFilter filter(t.finalize(), UseTweakedHeaderPaths::Yes, "6.0", "clang_dir");
+ filter.process();
+
+ QCOMPARE(filter.builtInHeaderPaths, (HeaderPaths{
+ 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.builtIn("clang_dir"),
+ t.builtIn("C:/mingw/i686-w64-mingw32/include")}));
+}
+
+void HeaderPathFilterTest::testClangHeadersAndCppIncludesPathsOrderAndroidClang()
+{
+ HeaderPathFilterTestHelper t;
+ 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.targetTriple = "i686-linux-android";
+ HeaderPathFilter filter(t.finalize(), UseTweakedHeaderPaths::Yes, "6.0", "clang_dir");
+ filter.process();
+
+ QCOMPARE(filter.builtInHeaderPaths, (HeaderPaths{
+ t.builtIn("C:/Android/sdk/ndk-bundle/sources/cxx-stl/llvm-libc++/include"),
+ t.builtIn("C:/Android/sdk/ndk-bundle/sources/cxx-stl/llvm-libc++abi/include"),
+ t.builtIn("clang_dir"),
+ t.builtIn("C:/Android/sdk/ndk-bundle/sysroot/usr/include/i686-linux-android"),
+ t.builtIn("C:/Android/sdk/ndk-bundle/sources/android/support/include"),
+ t.builtIn("C:/Android/sdk/ndk-bundle/sysroot/usr/include")}));
+}
+
+void ProjectFileCategorizerTest::testC()
+{
+ const ProjectFileCategorizer categorizer({}, {"foo.c", "foo.h"});
+ const ProjectFiles expected {
+ ProjectFile("foo.c", ProjectFile::CSource),
+ ProjectFile("foo.h", ProjectFile::CHeader),
+ };
+
+ QCOMPARE(categorizer.cSources(), expected);
+ QVERIFY(categorizer.cxxSources().isEmpty());
+ QVERIFY(categorizer.objcSources().isEmpty());
+ QVERIFY(categorizer.objcxxSources().isEmpty());
+}
+
+void ProjectFileCategorizerTest::testCxxWithUnambiguousHeaderSuffix()
+{
+ const ProjectFileCategorizer categorizer({}, {"foo.cpp", "foo.hpp"});
+ const ProjectFiles expected {
+ ProjectFile("foo.cpp", ProjectFile::CXXSource),
+ ProjectFile("foo.hpp", ProjectFile::CXXHeader),
+ };
+
+ QCOMPARE(categorizer.cxxSources(), expected);
+ QVERIFY(categorizer.cSources().isEmpty());
+ QVERIFY(categorizer.objcSources().isEmpty());
+ QVERIFY(categorizer.objcxxSources().isEmpty());
+}
+
+void ProjectFileCategorizerTest::testCxxWithAmbiguousHeaderSuffix()
+{
+ const ProjectFiles expected {
+ ProjectFile("foo.cpp", ProjectFile::CXXSource),
+ ProjectFile("foo.h", ProjectFile::CXXHeader),
+ };
+
+ const ProjectFileCategorizer categorizer({}, {"foo.cpp", "foo.h"});
+
+ QCOMPARE(categorizer.cxxSources(), expected);
+ QVERIFY(categorizer.cSources().isEmpty());
+ QVERIFY(categorizer.objcSources().isEmpty());
+ QVERIFY(categorizer.objcxxSources().isEmpty());
+}
+
+void ProjectFileCategorizerTest::testObjectiveC()
+{
+ const ProjectFiles expected {
+ ProjectFile("foo.m", ProjectFile::ObjCSource),
+ ProjectFile("foo.h", ProjectFile::ObjCHeader),
+ };
+
+ const ProjectFileCategorizer categorizer({}, {"foo.m", "foo.h"});
+
+ QCOMPARE(categorizer.objcSources(), expected);
+ QVERIFY(categorizer.cxxSources().isEmpty());
+ QVERIFY(categorizer.cSources().isEmpty());
+ QVERIFY(categorizer.objcxxSources().isEmpty());
+}
+
+void ProjectFileCategorizerTest::testObjectiveCxx()
+{
+ const ProjectFiles expected {
+ ProjectFile("foo.mm", ProjectFile::ObjCXXSource),
+ ProjectFile("foo.h", ProjectFile::ObjCXXHeader),
+ };
+
+ const ProjectFileCategorizer categorizer({}, {"foo.mm", "foo.h"});
+
+ QCOMPARE(categorizer.objcxxSources(), expected);
+ QVERIFY(categorizer.objcSources().isEmpty());
+ QVERIFY(categorizer.cSources().isEmpty());
+ QVERIFY(categorizer.cxxSources().isEmpty());
+}
+
+void ProjectFileCategorizerTest::testMixedCAndCxx()
+{
+ const ProjectFiles expectedCxxSources {
+ ProjectFile("foo.cpp", ProjectFile::CXXSource),
+ ProjectFile("foo.h", ProjectFile::CXXHeader),
+ ProjectFile("bar.h", ProjectFile::CXXHeader),
+ };
+ const ProjectFiles expectedCSources {
+ ProjectFile("bar.c", ProjectFile::CSource),
+ ProjectFile("foo.h", ProjectFile::CHeader),
+ ProjectFile("bar.h", ProjectFile::CHeader),
+ };
+
+ const ProjectFileCategorizer categorizer({}, {"foo.cpp", "foo.h", "bar.c", "bar.h"});
+
+ QCOMPARE(categorizer.cxxSources(), expectedCxxSources);
+ QCOMPARE(categorizer.cSources(), expectedCSources);
+ QVERIFY(categorizer.objcSources().isEmpty());
+ QVERIFY(categorizer.objcxxSources().isEmpty());
+}
+
+void ProjectFileCategorizerTest::testAmbiguousHeaderOnly()
+{
+ const ProjectFileCategorizer categorizer({}, {"foo.h"});
+
+ QCOMPARE(categorizer.cSources(), {ProjectFile("foo.h", ProjectFile::CHeader)});
+ QCOMPARE(categorizer.cxxSources(), {ProjectFile("foo.h", ProjectFile::CXXHeader)});
+ QCOMPARE(categorizer.objcSources(), {ProjectFile("foo.h", ProjectFile::ObjCHeader)});
+ QCOMPARE(categorizer.objcxxSources(), {ProjectFile("foo.h", ProjectFile::ObjCXXHeader)});
+}
+
+} // namespace Internal
+} // namespace CppTools
diff --git a/src/plugins/cpptools/projectinfo_test.h b/src/plugins/cpptools/projectinfo_test.h
new file mode 100644
index 0000000000..cc32d513a8
--- /dev/null
+++ b/src/plugins/cpptools/projectinfo_test.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QObject>
+
+namespace CppTools::Internal {
+
+class ProjectPartChooserTest : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void testChooseManuallySet();
+ void testIndicateManuallySet();
+ void testIndicateManuallySetForFallbackToProjectPartFromDependencies();
+ void testDoNotIndicateNotManuallySet();
+ void testForMultipleChooseFromActiveProject();
+ void testForMultiplePreferSelectedForBuilding();
+ void testForMultipleFromDependenciesChooseFromActiveProject();
+ void testForMultipleCheckIfActiveProjectChanged();
+ void testForMultipleAndAmbigiousHeaderPreferCProjectPart();
+ void testForMultipleAndAmbigiousHeaderPreferCxxProjectPart();
+ void testIndicateMultiple();
+ void testIndicateMultipleForFallbackToProjectPartFromDependencies();
+ void testForMultipleChooseNewIfPreviousIsGone();
+ void testFallbackToProjectPartFromDependencies();
+ void testFallbackToProjectPartFromModelManager();
+ void testContinueUsingFallbackFromModelManagerIfProjectDoesNotChange();
+ void testStopUsingFallbackFromModelManagerIfProjectChanges1();
+ void testStopUsingFallbackFromModelManagerIfProjectChanges2();
+ void testIndicateFallbacktoProjectPartFromModelManager();
+ void testIndicateFromDependencies();
+ void testDoNotIndicateFromDependencies();
+};
+
+class ProjectInfoGeneratorTest : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void testCreateNoProjectPartsForEmptyFileList();
+ void testCreateSingleProjectPart();
+ void testCreateMultipleProjectParts();
+ void testProjectPartIndicatesObjectiveCExtensionsByDefault();
+ void testProjectPartHasLatestLanguageVersionByDefault();
+ void testUseMacroInspectionReportForLanguageVersion();
+ void testUseCompilerFlagsForLanguageExtensions();
+ void testProjectFileKindsMatchProjectPartVersion();
+};
+
+class HeaderPathFilterTest : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void testBuiltin();
+ void testSystem();
+ void testUser();
+ void testNoProjectPathSet();
+ void testDontAddInvalidPath();
+ void testClangHeadersPath();
+ void testClangHeadersPathWitoutClangVersion();
+ void testClangHeadersAndCppIncludesPathsOrderMacOs();
+ void testClangHeadersAndCppIncludesPathsOrderLinux();
+ void testRemoveGccInternalPaths();
+ void testRemoveGccInternalPathsExceptForStandardPaths();
+ void testClangHeadersAndCppIncludesPathsOrderNoVersion();
+ void testClangHeadersAndCppIncludesPathsOrderAndroidClang();
+};
+
+class ProjectFileCategorizerTest : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void testC();
+ void testCxxWithUnambiguousHeaderSuffix();
+ void testCxxWithAmbiguousHeaderSuffix();
+ void testObjectiveC();
+ void testObjectiveCxx();
+ void testMixedCAndCxx();
+ void testAmbiguousHeaderOnly();
+};
+
+} // namespace CppTools::Internal
diff --git a/src/plugins/cpptools/projectpart.cpp b/src/plugins/cpptools/projectpart.cpp
index d3d4668a81..8286412da5 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 &macro) { 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 &macro) { 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 010a21a312..4f1cee28aa 100644
--- a/src/plugins/cpptools/projectpart.h
+++ b/src/plugins/cpptools/projectpart.h
@@ -37,15 +37,13 @@
#include <cplusplus/Token.h>
#include <utils/cpplanguage_details.h>
-#include <utils/fileutils.h>
+#include <utils/filepath.h>
#include <utils/id.h>
#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/cpptools/senddocumenttracker.cpp b/src/plugins/cpptools/senddocumenttracker.cpp
index 619b3eeaea..d838424c52 100644
--- a/src/plugins/cpptools/senddocumenttracker.cpp
+++ b/src/plugins/cpptools/senddocumenttracker.cpp
@@ -27,6 +27,11 @@
#include <algorithm>
+#ifdef WITH_TESTS
+#include "cpptoolsplugin.h"
+#include <QtTest>
+#endif
+
namespace CppTools {
void SendDocumentTracker::setLastSentRevision(int revision)
@@ -81,4 +86,174 @@ bool SendDocumentTracker::changedBeforeCompletionPosition(int newCompletionPosit
return m_contentChangeStartPosition < newCompletionPosition;
}
+#ifdef WITH_TESTS
+namespace Internal {
+
+void DocumentTrackerTest::testDefaultLastSentRevision()
+{
+ SendDocumentTracker tracker;
+
+ QCOMPARE(tracker.lastSentRevision(), -1);
+ QCOMPARE(tracker.lastCompletionPosition(), -1);
+}
+
+void DocumentTrackerTest::testSetRevision()
+{
+ SendDocumentTracker tracker;
+ tracker.setLastSentRevision(46);
+
+ QCOMPARE(tracker.lastSentRevision(), 46);
+ QCOMPARE(tracker.lastCompletionPosition(), -1);
+}
+
+void DocumentTrackerTest::testSetLastCompletionPosition()
+{
+ SendDocumentTracker tracker;
+ tracker.setLastCompletionPosition(33);
+
+ QCOMPARE(tracker.lastSentRevision(), -1);
+ QCOMPARE(tracker.lastCompletionPosition(), 33);
+}
+
+void DocumentTrackerTest::testApplyContentChange()
+{
+ SendDocumentTracker tracker;
+ tracker.setLastSentRevision(46);
+ tracker.setLastCompletionPosition(33);
+ tracker.applyContentChange(10);
+
+ QCOMPARE(tracker.lastSentRevision(), 46);
+ QCOMPARE(tracker.lastCompletionPosition(), -1);
+}
+
+void DocumentTrackerTest::testDontSendCompletionIfPositionIsEqual()
+{
+ SendDocumentTracker tracker;
+ tracker.setLastCompletionPosition(33);
+
+ QVERIFY(!tracker.shouldSendCompletion(33));
+}
+
+void DocumentTrackerTest::testSendCompletionIfPositionIsDifferent()
+{
+ SendDocumentTracker tracker;
+ tracker.setLastSentRevision(46);
+ tracker.setLastCompletionPosition(33);
+
+ QVERIFY(tracker.shouldSendCompletion(22));
+}
+
+void DocumentTrackerTest::testSendCompletionIfChangeIsBeforeCompletionPositionAndPositionIsEqual()
+{
+ SendDocumentTracker tracker;
+ tracker.setLastSentRevision(46);
+ tracker.setLastCompletionPosition(33);
+ tracker.applyContentChange(10);
+
+ QVERIFY(tracker.shouldSendCompletion(33));
+}
+
+void DocumentTrackerTest::testDontSendCompletionIfChangeIsAfterCompletionPositionAndPositionIsEqual()
+{
+ SendDocumentTracker tracker;
+ tracker.setLastSentRevision(46);
+ tracker.setLastCompletionPosition(33);
+ tracker.applyContentChange(40);
+
+ QVERIFY(!tracker.shouldSendCompletion(33));
+}
+
+void DocumentTrackerTest::testDontSendRevisionIfRevisionIsEqual()
+{
+ SendDocumentTracker tracker;
+ tracker.setLastSentRevision(46);
+
+ QVERIFY(!tracker.shouldSendRevision(46));
+}
+
+void DocumentTrackerTest::testSendRevisionIfRevisionIsDifferent()
+{
+ SendDocumentTracker tracker;
+ tracker.setLastSentRevision(46);
+
+ QVERIFY(tracker.shouldSendRevision(21));
+}
+
+void DocumentTrackerTest::testDontSendRevisionWithDefaults()
+{
+ SendDocumentTracker tracker;
+ QVERIFY(!tracker.shouldSendRevisionWithCompletionPosition(21, 33));
+}
+
+void DocumentTrackerTest::testDontSendIfRevisionIsDifferentAndCompletionPositionIsEqualAndNoContentChange()
+{
+ SendDocumentTracker tracker;
+ tracker.setLastSentRevision(46);
+ tracker.setLastCompletionPosition(33);
+
+ QVERIFY(!tracker.shouldSendRevisionWithCompletionPosition(21, 33));
+}
+
+void DocumentTrackerTest::testDontSendIfRevisionIsDifferentAndCompletionPositionIsDifferentAndNoContentChange()
+{
+ SendDocumentTracker tracker;
+ tracker.setLastSentRevision(46);
+ tracker.setLastCompletionPosition(33);
+
+ QVERIFY(!tracker.shouldSendRevisionWithCompletionPosition(21, 44));
+}
+
+void DocumentTrackerTest::testDontSendIfRevisionIsEqualAndCompletionPositionIsDifferentAndNoContentChange()
+{
+ SendDocumentTracker tracker;
+ tracker.setLastSentRevision(46);
+ tracker.setLastCompletionPosition(33);
+
+ QVERIFY(!tracker.shouldSendRevisionWithCompletionPosition(46,44));
+}
+
+void DocumentTrackerTest::testSendIfChangeIsBeforeCompletionAndPositionIsEqualAndRevisionIsDifferent()
+{
+ SendDocumentTracker tracker;
+ tracker.setLastSentRevision(46);
+ tracker.setLastCompletionPosition(33);
+ tracker.applyContentChange(10);
+
+ QVERIFY(tracker.shouldSendRevisionWithCompletionPosition(45, 33));
+}
+
+void DocumentTrackerTest::testDontSendIfChangeIsAfterCompletionPositionAndRevisionIsDifferent()
+{
+ SendDocumentTracker tracker;
+ tracker.setLastSentRevision(46);
+ tracker.setLastCompletionPosition(50);
+ tracker.applyContentChange(40);
+
+ QVERIFY(!tracker.shouldSendRevisionWithCompletionPosition(45, 36));
+}
+
+void DocumentTrackerTest::testSendIfChangeIsBeforeCompletionPositionAndRevisionIsDifferent()
+{
+ SendDocumentTracker tracker;
+ tracker.setLastSentRevision(46);
+ tracker.setLastCompletionPosition(50);
+ tracker.applyContentChange(30);
+
+ QVERIFY(tracker.shouldSendRevisionWithCompletionPosition(45, 36));
+}
+
+void DocumentTrackerTest::testResetChangedContentStartPositionIfLastRevisionIsSet()
+{
+ SendDocumentTracker tracker;
+ tracker.setLastSentRevision(46);
+ tracker.setLastCompletionPosition(50);
+ tracker.applyContentChange(30);
+ tracker.setLastSentRevision(47);
+
+ QVERIFY(!tracker.shouldSendRevisionWithCompletionPosition(45, 36));
+}
+
+} // namespace Internal
+#endif
+
} // namespace CppTools
diff --git a/src/plugins/cpptools/senddocumenttracker.h b/src/plugins/cpptools/senddocumenttracker.h
index be84a8b16a..100b07e62f 100644
--- a/src/plugins/cpptools/senddocumenttracker.h
+++ b/src/plugins/cpptools/senddocumenttracker.h
@@ -27,6 +27,8 @@
#include "cpptools_global.h"
+#include <QObject>
+
#include <limits>
namespace CppTools {
@@ -55,4 +57,33 @@ private:
int m_contentChangeStartPosition = std::numeric_limits<int>::max();
};
+#ifdef WITH_TESTS
+namespace Internal {
+class DocumentTrackerTest : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void testDefaultLastSentRevision();
+ void testSetRevision();
+ void testSetLastCompletionPosition();
+ void testApplyContentChange();
+ void testDontSendCompletionIfPositionIsEqual();
+ void testSendCompletionIfPositionIsDifferent();
+ void testSendCompletionIfChangeIsBeforeCompletionPositionAndPositionIsEqual();
+ void testDontSendCompletionIfChangeIsAfterCompletionPositionAndPositionIsEqual();
+ void testDontSendRevisionIfRevisionIsEqual();
+ void testSendRevisionIfRevisionIsDifferent();
+ void testDontSendRevisionWithDefaults();
+ void testDontSendIfRevisionIsDifferentAndCompletionPositionIsEqualAndNoContentChange();
+ void testDontSendIfRevisionIsDifferentAndCompletionPositionIsDifferentAndNoContentChange();
+ void testDontSendIfRevisionIsEqualAndCompletionPositionIsDifferentAndNoContentChange();
+ void testSendIfChangeIsBeforeCompletionAndPositionIsEqualAndRevisionIsDifferent();
+ void testDontSendIfChangeIsAfterCompletionPositionAndRevisionIsDifferent();
+ void testSendIfChangeIsBeforeCompletionPositionAndRevisionIsDifferent();
+ void testResetChangedContentStartPositionIfLastRevisionIsSet();
+};
+} // namespace Internal
+#endif // WITH_TESTS
+
} // namespace CppTools
diff --git a/src/plugins/cpptools/symbolsearcher_test.cpp b/src/plugins/cpptools/symbolsearcher_test.cpp
index 44e13d9984..e9822291c1 100644
--- a/src/plugins/cpptools/symbolsearcher_test.cpp
+++ b/src/plugins/cpptools/symbolsearcher_test.cpp
@@ -23,7 +23,7 @@
**
****************************************************************************/
-#include "cpptoolsplugin.h"
+#include "symbolsearcher_test.h"
#include "builtinindexingsupport.h"
#include "cppmodelmanager.h"
@@ -86,19 +86,12 @@ public:
class SymbolSearcherTestCase : public Tests::TestCase
{
public:
- /// Takes no ownership of indexingSupportToUse
SymbolSearcherTestCase(const QString &testFile,
- CppIndexingSupport *indexingSupportToUse,
const SymbolSearcher::Parameters &searchParameters,
const ResultDataList &expectedResults)
- : m_indexingSupportToUse(indexingSupportToUse)
{
QVERIFY(succeededSoFar());
-
- QVERIFY(m_indexingSupportToUse);
QVERIFY(parseFiles(testFile));
- m_indexingSupportToRestore = m_modelManager->indexingSupport();
- m_modelManager->setIndexingSupport(m_indexingSupportToUse);
CppIndexingSupport *indexingSupport = m_modelManager->indexingSupport();
const QScopedPointer<SymbolSearcher> symbolSearcher(
@@ -109,16 +102,6 @@ public:
ResultDataList results = ResultData::fromSearchResultList(search.results());
QCOMPARE(results, expectedResults);
}
-
- ~SymbolSearcherTestCase()
- {
- if (m_indexingSupportToRestore)
- m_modelManager->setIndexingSupport(m_indexingSupportToRestore);
- }
-
-private:
- CppIndexingSupport *m_indexingSupportToRestore = nullptr;
- CppIndexingSupport *m_indexingSupportToUse = nullptr;
};
} // anonymous namespace
@@ -137,20 +120,16 @@ template<> char *toString(const ResultData &data)
} // namespace QTest
QT_END_NAMESPACE
-void CppToolsPlugin::test_builtinsymbolsearcher()
+void SymbolSearcherTest::test()
{
QFETCH(QString, testFile);
QFETCH(SymbolSearcher::Parameters, searchParameters);
QFETCH(ResultDataList, expectedResults);
- QScopedPointer<CppIndexingSupport> builtinIndexingSupport(new BuiltinIndexingSupport);
- SymbolSearcherTestCase(testFile,
- builtinIndexingSupport.data(),
- searchParameters,
- expectedResults);
+ SymbolSearcherTestCase(testFile, searchParameters, expectedResults);
}
-void CppToolsPlugin::test_builtinsymbolsearcher_data()
+void SymbolSearcherTest::test_data()
{
QTest::addColumn<QString>("testFile");
QTest::addColumn<SymbolSearcher::Parameters>("searchParameters");
diff --git a/src/plugins/cpptools/symbolsearcher_test.h b/src/plugins/cpptools/symbolsearcher_test.h
new file mode 100644
index 0000000000..d8a0a37054
--- /dev/null
+++ b/src/plugins/cpptools/symbolsearcher_test.h
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QObject>
+
+namespace CppTools::Internal {
+
+class SymbolSearcherTest : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void test();
+ void test_data();
+};
+
+} // namespace CppTools::Internal
diff --git a/src/plugins/cpptools/typehierarchybuilder_test.cpp b/src/plugins/cpptools/typehierarchybuilder_test.cpp
index 70b172acf9..ef6bec36e9 100644
--- a/src/plugins/cpptools/typehierarchybuilder_test.cpp
+++ b/src/plugins/cpptools/typehierarchybuilder_test.cpp
@@ -23,7 +23,7 @@
**
****************************************************************************/
-#include "cpptoolsplugin.h"
+#include "typehierarchybuilder_test.h"
#include "cppmodelmanager.h"
#include "cpptoolstestcase.h"
@@ -136,7 +136,7 @@ public:
} // anonymous namespace
-void CppToolsPlugin::test_typehierarchy_data()
+void TypeHierarchyBuilderTest::test_data()
{
QTest::addColumn<QList<TestDocument> >("documents");
QTest::addColumn<QString>("expectedHierarchy");
@@ -181,7 +181,7 @@ void CppToolsPlugin::test_typehierarchy_data()
);
}
-void CppToolsPlugin::test_typehierarchy()
+void TypeHierarchyBuilderTest::test()
{
QFETCH(QList<TestDocument>, documents);
QFETCH(QString, expectedHierarchy);
diff --git a/src/plugins/cpptools/typehierarchybuilder_test.h b/src/plugins/cpptools/typehierarchybuilder_test.h
new file mode 100644
index 0000000000..7ebf13a6ec
--- /dev/null
+++ b/src/plugins/cpptools/typehierarchybuilder_test.h
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QObject>
+
+namespace CppTools::Internal {
+
+class TypeHierarchyBuilderTest : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void test_data();
+ void test();
+};
+
+} // namespace CppTools::Internal