CppEditor: Introduce per-project code model settings

Change-Id: I325cc39e60d4b1f0fba1651502d772bfb9c6a91c
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
Christian Kandeler
2024-02-22 16:26:13 +01:00
parent 812326eadc
commit faa595e38b
24 changed files with 430 additions and 69 deletions

View File

@@ -419,7 +419,7 @@ ClangdClient::ClangdClient(Project *project, const Utils::FilePath &jsonDbDir, c
*CppEditor::CppModelManager::fallbackProjectPart(),
warningsConfigForProject(nullptr), includeDir, {});
const CppEditor::UsePrecompiledHeaders usePch
= CppEditor::CppCodeModelSettings::instance().usePrecompiledHeaders();
= CppEditor::CppCodeModelSettings::usePrecompiledHeaders(nullptr);
const QJsonArray projectPartOptions = fullProjectPartOptions(
optionsBuilder, globalClangOptions());
const QJsonArray clangOptions = clangOptionsForFile({}, optionsBuilder.projectPart(),
@@ -600,7 +600,7 @@ void ClangdClient::findUsages(const CppEditor::CursorInEditor &cursor,
}
}
const bool categorize = CppEditor::CppCodeModelSettings::instance().categorizeFindReferences();
const bool categorize = CppEditor::CppCodeModelSettings::categorizeFindReferences();
// If it's a "normal" symbol, go right ahead.
if (searchTerm != "operator" && Utils::allOf(searchTerm, [](const QChar &c) {
@@ -920,9 +920,11 @@ void ClangdClient::updateParserConfig(const Utils::FilePath &filePath,
CppEditor::ProjectFile::classify(filePath.toString()));
const QJsonArray projectPartOptions = fullProjectPartOptions(
optionsBuilder, globalClangOptions());
const auto cppSettings = CppEditor::CppCodeModelSettings::settingsForProject(
projectPart->topLevelProject);
addToCompilationDb(cdbChanges,
*projectPart,
CppEditor::CppCodeModelSettings::instance().usePrecompiledHeaders(),
cppSettings.usePrecompiledHeaders(),
projectPartOptions,
filePath.parentDir(),
file,

View File

@@ -166,7 +166,6 @@ GenerateCompilationDbResult generateCompilationDB(QList<ProjectInfo::ConstPtr> p
}
compileCommandsFile.write("[");
const UsePrecompiledHeaders usePch = CppCodeModelSettings::instance().usePrecompiledHeaders();
const QJsonArray jsonProjectOptions = QJsonArray::fromStringList(projectOptions);
for (const ProjectInfo::ConstPtr &projectInfo : std::as_const(projectInfoList)) {
QTC_ASSERT(projectInfo, continue);
@@ -183,8 +182,14 @@ GenerateCompilationDbResult generateCompilationDB(QList<ProjectInfo::ConstPtr> p
jsonProjectOptions);
}
for (const ProjectFile &projFile : projectPart->files) {
const QJsonObject json = createFileObject(baseDir, args, *projectPart, projFile,
purpose, ppOptions, usePch,
const QJsonObject json
= createFileObject(baseDir,
args,
*projectPart,
projFile,
purpose,
ppOptions,
projectInfo->settings().usePrecompiledHeaders(),
optionsBuilder.isClStyle());
if (compileCommandsFile.size() > 1)
compileCommandsFile.write(",");

View File

@@ -249,7 +249,7 @@ private:
void ClangdTestFindReferences::initTestCase()
{
ClangdTest::initTestCase();
CppEditor::CppCodeModelSettings::instance().setCategorizeFindReferences(true);
CppEditor::CppCodeModelSettings::setCategorizeFindReferences(true);
connect(client(), &ClangdClient::foundReferences, this,
[this](const SearchResultItems &results) {
if (results.isEmpty())

View File

@@ -3,6 +3,7 @@
#pragma once
#include <cppeditor/cppcodemodelsettings.h>
#include <cppeditor/cppprojectfile.h>
#include <cppeditor/projectpart.h>
@@ -19,9 +20,11 @@ public:
FileInfo() = default;
FileInfo(Utils::FilePath file,
CppEditor::ProjectFile::Kind kind,
const CppEditor::CppCodeModelSettings &settings,
CppEditor::ProjectPart::ConstPtr projectPart)
: file(std::move(file))
, kind(kind)
, settings(settings.data())
, projectPart(projectPart)
{}
@@ -31,6 +34,7 @@ public:
Utils::FilePath file;
CppEditor::ProjectFile::Kind kind;
CppEditor::CppCodeModelSettings::Data settings;
CppEditor::ProjectPart::ConstPtr projectPart;
};
using FileInfos = std::vector<FileInfo>;

View File

@@ -341,7 +341,8 @@ private:
QMap<FilePath, RefactoringFileInfo> m_refactoringFileInfos;
};
static FileInfos sortedFileInfos(const QVector<ProjectPart::ConstPtr> &projectParts)
static FileInfos sortedFileInfos(const CppCodeModelSettings &settings,
const QVector<ProjectPart::ConstPtr> &projectParts)
{
FileInfos fileInfos;
@@ -359,7 +360,7 @@ static FileInfos sortedFileInfos(const QVector<ProjectPart::ConstPtr> &projectPa
if (file.active && (ProjectFile::isSource(file.kind)
|| ProjectFile::isHeader(file.kind))) {
ProjectFile::Kind sourceKind = ProjectFile::sourceKind(file.kind);
fileInfos.emplace_back(file.path, sourceKind, projectPart);
fileInfos.emplace_back(file.path, sourceKind, settings, projectPart);
}
}
}
@@ -901,7 +902,8 @@ FileInfos ClangTool::collectFileInfos(Project *project, FileSelection fileSelect
const auto projectInfo = CppModelManager::projectInfo(project);
QTC_ASSERT(projectInfo, return FileInfos());
const FileInfos allFileInfos = sortedFileInfos(projectInfo->projectParts());
const FileInfos allFileInfos = sortedFileInfos(projectInfo->settings(),
projectInfo->projectParts());
if (selectionType && *selectionType == FileSelectionType::AllFiles)
return allFileInfos;

View File

@@ -51,7 +51,7 @@ AnalyzeUnit::AnalyzeUnit(const FileInfo &fileInfo,
arguments = extraClangToolsPrependOptions();
arguments.append(
optionsBuilder.build(fileInfo.kind,
CppEditor::CppCodeModelSettings::instance().usePrecompiledHeaders()));
CppCodeModelSettings(fileInfo.settings).usePrecompiledHeaders()));
arguments.append(extraClangToolsAppendOptions());
}

View File

@@ -132,10 +132,12 @@ static FileInfo getFileInfo(const FilePath &file, Project *project)
// found the best candidate, early return
ProjectFile::Kind sourceKind = ProjectFile::sourceKind(projectFile.kind);
if (projectPart->buildTargetType != BuildTargetType::Unknown)
return FileInfo(projectFile.path, sourceKind, projectPart);
return FileInfo(projectFile.path, sourceKind, projectInfo->settings(), projectPart);
// found something but keep looking for better candidates
if (candidate.projectPart.isNull())
candidate = FileInfo(projectFile.path, sourceKind, projectPart);
if (candidate.projectPart.isNull()) {
candidate
= FileInfo(projectFile.path, sourceKind, projectInfo->settings(), projectPart);
}
}
}

View File

@@ -27,7 +27,8 @@ namespace CppEditor {
BaseEditorDocumentProcessor::BaseEditorDocumentProcessor(QTextDocument *textDocument,
const Utils::FilePath &filePath)
: m_filePath(filePath),
m_textDocument(textDocument)
m_textDocument(textDocument),
m_settings(CppCodeModelSettings::settingsForFile(filePath))
{
}
@@ -35,9 +36,11 @@ BaseEditorDocumentProcessor::~BaseEditorDocumentProcessor() = default;
void BaseEditorDocumentProcessor::run(bool projectsUpdated)
{
if (projectsUpdated)
m_settings.setData(CppCodeModelSettings::settingsForFile(m_filePath).data());
const Utils::Language languagePreference
= CppCodeModelSettings::instance().interpretAmbigiousHeadersAsC() ? Utils::Language::C
: Utils::Language::Cxx;
= m_settings.interpretAmbigiousHeadersAsC() ? Utils::Language::C : Utils::Language::Cxx;
runImpl({CppModelManager::workingCopy(),
ProjectExplorer::ProjectManager::startupProject(),

View File

@@ -4,6 +4,7 @@
#pragma once
#include "baseeditordocumentparser.h"
#include "cppcodemodelsettings.h"
#include "cppcursorinfo.h"
#include "cppeditor_global.h"
#include "cppsemanticinfo.h"
@@ -72,6 +73,7 @@ public:
virtual QFuture<CursorInfo> cursorInfo(const CursorInfoParams &params) = 0;
const Utils::FilePath &filePath() const { return m_filePath; }
const CppCodeModelSettings &settings() const { return m_settings; }
signals:
// Signal interface to implement
@@ -102,6 +104,7 @@ private:
private:
Utils::FilePath m_filePath;
QTextDocument *m_textDocument;
CppCodeModelSettings m_settings;
};
} // namespace CppEditor

View File

@@ -144,16 +144,14 @@ QList<TextEditor::BlockRange> toTextEditorBlocks(
BuiltinEditorDocumentProcessor::BuiltinEditorDocumentProcessor(TextEditor::TextDocument *document)
: BaseEditorDocumentProcessor(document->document(), document->filePath())
, m_parser(new BuiltinEditorDocumentParser(document->filePath(),
CppCodeModelSettings::instance()
.effectiveIndexerFileSizeLimitInMb()))
settings().effectiveIndexerFileSizeLimitInMb()))
, m_codeWarningsUpdated(false)
, m_semanticHighlighter(new SemanticHighlighter(document))
{
using namespace Internal;
BaseEditorDocumentParser::Configuration config = m_parser->configuration();
config.usePrecompiledHeaders = CppCodeModelSettings::instance().pchUsage()
!= CppCodeModelSettings::PchUse_None;
config.usePrecompiledHeaders = settings().pchUsage() != CppCodeModelSettings::PchUse_None;
m_parser->setConfiguration(config);
m_semanticHighlighter->setHighlightingRunner(

View File

@@ -13,6 +13,7 @@
#include <coreplugin/session.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectmanager.h>
#include <utils/algorithm.h>
#include <utils/hostosinfo.h>
@@ -28,6 +29,7 @@
#include <QSettings>
#include <QStandardPaths>
using namespace ProjectExplorer;
using namespace Utils;
namespace CppEditor {
@@ -56,7 +58,7 @@ static Key clangdThreadLimitKey() { return "ClangdThreadLimit"; }
static Key clangdDocumentThresholdKey() { return "ClangdDocumentThreshold"; }
static Key clangdSizeThresholdEnabledKey() { return "ClangdSizeThresholdEnabled"; }
static Key clangdSizeThresholdKey() { return "ClangdSizeThreshold"; }
static Key clangdUseGlobalSettingsKey() { return "useGlobalSettings"; }
static Key useGlobalSettingsKey() { return "useGlobalSettings"; }
static Key clangdblockIndexingSettingsKey() { return "blockIndexing"; }
static Key sessionsWithOneClangdKey() { return "SessionsWithOneClangd"; }
static Key diagnosticConfigIdKey() { return "diagnosticConfigId"; }
@@ -116,48 +118,118 @@ void CppCodeModelSettings::Data::fromMap(const Utils::Store &store)
void CppCodeModelSettings::fromSettings(QtcSettings *s)
{
m_data.fromMap(storeFromSettings(Constants::CPPEDITOR_SETTINGSGROUP, s));
emit changed();
}
void CppCodeModelSettings::toSettings(QtcSettings *s)
{
const Data def;
storeToSettingsWithDefault(Constants::CPPEDITOR_SETTINGSGROUP, s, m_data.toMap(), def.toMap());
emit changed(); // TODO: Why?
storeToSettingsWithDefault(Constants::CPPEDITOR_SETTINGSGROUP, s, m_data.toMap(), Data().toMap());
}
CppCodeModelSettings &CppCodeModelSettings::instance()
CppCodeModelSettings &CppCodeModelSettings::globalInstance()
{
static CppCodeModelSettings theCppCodeModelSettings(Core::ICore::settings());
return theCppCodeModelSettings;
}
void CppCodeModelSettings::setData(const Data &data)
CppCodeModelSettings CppCodeModelSettings::settingsForProject(const ProjectExplorer::Project *project)
{
if (m_data != data) {
m_data = data;
toSettings(Core::ICore::settings());
emit changed();
}
return {CppCodeModelProjectSettings(const_cast<ProjectExplorer::Project *>(project)).data()};
}
CppCodeModelSettings CppCodeModelSettings::settingsForProject(const Utils::FilePath &projectFile)
{
return settingsForProject(ProjectManager::projectWithProjectFilePath(projectFile));
}
CppCodeModelSettings CppCodeModelSettings::settingsForFile(const Utils::FilePath &file)
{
return settingsForProject(ProjectManager::projectForFile(file));
}
void CppCodeModelSettings::setGlobalData(const Data &data)
{
if (globalInstance().m_data == data)
return;
globalInstance().m_data = data;
globalInstance().toSettings(Core::ICore::settings());
emit globalInstance().changed(nullptr);
}
CppCodeModelSettings::PCHUsage CppCodeModelSettings::pchUsage(const Project *project)
{
return CppCodeModelSettings::settingsForProject(project).pchUsage();
}
UsePrecompiledHeaders CppCodeModelSettings::usePrecompiledHeaders() const
{
if (instance().pchUsage() == CppCodeModelSettings::PchUse_None)
return UsePrecompiledHeaders::No;
return UsePrecompiledHeaders::Yes;
return pchUsage() == CppCodeModelSettings::PchUse_None ? UsePrecompiledHeaders::No
: UsePrecompiledHeaders::Yes;
}
UsePrecompiledHeaders CppCodeModelSettings::usePrecompiledHeaders(const Project *project)
{
return CppCodeModelSettings::settingsForProject(project).usePrecompiledHeaders();
}
int CppCodeModelSettings::effectiveIndexerFileSizeLimitInMb() const
{
return instance().skipIndexingBigFiles() ? instance().indexerFileSizeLimitInMb() : -1;
return skipIndexingBigFiles() ? indexerFileSizeLimitInMb() : -1;
}
bool CppCodeModelSettings::categorizeFindReferences()
{
return globalInstance().m_data.categorizeFindReferences;
}
void CppCodeModelSettings::setCategorizeFindReferences(bool categorize)
{
Data d = data();
Data d = globalInstance().data();
d.categorizeFindReferences = categorize;
setData(d);
globalInstance().setGlobalData(d);
}
CppCodeModelProjectSettings::CppCodeModelProjectSettings(ProjectExplorer::Project *project)
: m_project(project)
{
loadSettings();
}
CppCodeModelSettings::Data CppCodeModelProjectSettings::data() const
{
return m_useGlobalSettings ? CppCodeModelSettings::globalInstance().data() : m_customSettings;
}
void CppCodeModelProjectSettings::setData(const CppCodeModelSettings::Data &data)
{
m_customSettings = data;
saveSettings();
emit CppCodeModelSettings::globalInstance().changed(m_project);
}
void CppCodeModelProjectSettings::setUseGlobalSettings(bool useGlobal)
{
m_useGlobalSettings = useGlobal;
saveSettings();
emit CppCodeModelSettings::globalInstance().changed(m_project);
}
void CppCodeModelProjectSettings::loadSettings()
{
if (!m_project)
return;
const Store data = storeFromVariant(m_project->namedSettings(Constants::CPPEDITOR_SETTINGSGROUP));
m_useGlobalSettings = data.value(useGlobalSettingsKey(), true).toBool();
m_customSettings.fromMap(data);
}
void CppCodeModelProjectSettings::saveSettings()
{
if (!m_project)
return;
Store data = m_customSettings.toMap();
data.insert(useGlobalSettingsKey(), m_useGlobalSettings);
m_project->setNamedSettings(Constants::CPPEDITOR_SETTINGSGROUP, variantFromStore(data));
}
QString ClangdSettings::priorityToString(const IndexingPriority &priority)
@@ -513,7 +585,7 @@ void ClangdProjectSettings::loadSettings()
if (!m_project)
return;
const Store data = storeFromVariant(m_project->namedSettings(clangdSettingsKey()));
m_useGlobalSettings = data.value(clangdUseGlobalSettingsKey(), true).toBool();
m_useGlobalSettings = data.value(useGlobalSettingsKey(), true).toBool();
m_blockIndexing = data.value(clangdblockIndexingSettingsKey(), false).toBool();
if (!m_useGlobalSettings)
m_customSettings.fromMap(data);
@@ -526,7 +598,7 @@ void ClangdProjectSettings::saveSettings()
Store data;
if (!m_useGlobalSettings)
data = m_customSettings.toMap();
data.insert(clangdUseGlobalSettingsKey(), m_useGlobalSettings);
data.insert(useGlobalSettingsKey(), m_useGlobalSettings);
data.insert(clangdblockIndexingSettingsKey(), m_blockIndexing);
m_project->setNamedSettings(clangdSettingsKey(), variantFromStore(data));
}

View File

@@ -37,6 +37,8 @@ public:
class Data
{
public:
Data() = default;
Data(const Utils::Store &store) { fromMap(store); }
Utils::Store toMap() const;
void fromMap(const Utils::Store &store);
@@ -53,26 +55,35 @@ public:
QString ignorePattern;
};
static CppCodeModelSettings &instance();
CppCodeModelSettings(const Data &data) : m_data(data) {}
void setData(const Data &data);
static CppCodeModelSettings &globalInstance(); // TODO: Make inaccessible.
static CppCodeModelSettings settingsForProject(const ProjectExplorer::Project *project);
static CppCodeModelSettings settingsForProject(const Utils::FilePath &projectFile);
static CppCodeModelSettings settingsForFile(const Utils::FilePath &file);
static void setGlobalData(const Data &data); // TODO: Make inaccessible.
void setData(const Data &data) { m_data = data; }
Data data() const { return m_data; }
PCHUsage pchUsage() const { return m_data.pchUsage; }
static PCHUsage pchUsage(const ProjectExplorer::Project *project);
UsePrecompiledHeaders usePrecompiledHeaders() const;
static UsePrecompiledHeaders usePrecompiledHeaders(const ProjectExplorer::Project *project);
bool interpretAmbigiousHeadersAsC() const { return m_data.interpretAmbigiousHeadersAsC; }
bool skipIndexingBigFiles() const { return m_data.skipIndexingBigFiles; }
bool useBuiltinPreprocessor() const { return m_data.useBuiltinPreprocessor; }
int indexerFileSizeLimitInMb() const { return m_data.indexerFileSizeLimitInMb; }
int effectiveIndexerFileSizeLimitInMb() const;
bool categorizeFindReferences() const { return m_data.categorizeFindReferences; }
bool ignoreFiles() const { return m_data.ignoreFiles; }
QString ignorePattern() const { return m_data.ignorePattern; }
void setCategorizeFindReferences(bool categorize);
static bool categorizeFindReferences();
static void setCategorizeFindReferences(bool categorize);
signals:
void changed();
void changed(ProjectExplorer::Project *project);
private:
CppCodeModelSettings() = default;
@@ -84,6 +95,25 @@ private:
Data m_data;
};
class CppCodeModelProjectSettings
{
public:
CppCodeModelProjectSettings(ProjectExplorer::Project *project);
CppCodeModelSettings::Data data() const;
void setData(const CppCodeModelSettings::Data &data);
bool useGlobalSettings() const { return m_useGlobalSettings; }
void setUseGlobalSettings(bool useGlobal);
private:
void loadSettings();
void saveSettings();
ProjectExplorer::Project * const m_project;
CppCodeModelSettings::Data m_customSettings;
bool m_useGlobalSettings = true;
};
class CPPEDITOR_EXPORT ClangdSettings : public QObject
{
Q_OBJECT

View File

@@ -50,14 +50,18 @@ namespace CppEditor::Internal {
class CppCodeModelSettingsWidget final : public Core::IOptionsPageWidget
{
Q_OBJECT
public:
CppCodeModelSettingsWidget(const CppCodeModelSettings::Data &data);
private:
void apply() final { CppCodeModelSettings::instance().setData(data()); }
CppCodeModelSettings::Data data() const;
signals:
void settingsDataChanged();
private:
void apply() final { CppCodeModelSettings::globalInstance().setGlobalData(data()); }
QCheckBox *m_interpretAmbiguousHeadersAsCHeaders;
QCheckBox *m_ignorePchCheckBox;
QCheckBox *m_useBuiltinPreprocessorCheckBox;
@@ -126,6 +130,23 @@ CppCodeModelSettingsWidget::CppCodeModelSettingsWidget(const CppCodeModelSetting
},
st
}.attachTo(this);
for (const QCheckBox *const b : {m_interpretAmbiguousHeadersAsCHeaders,
m_ignorePchCheckBox,
m_useBuiltinPreprocessorCheckBox,
m_skipIndexingBigFilesCheckBox,
m_ignoreFilesCheckBox}) {
connect(b, &QCheckBox::toggled, this, &CppCodeModelSettingsWidget::settingsDataChanged);
}
connect(m_bigFilesLimitSpinBox, &QSpinBox::valueChanged,
this, &CppCodeModelSettingsWidget::settingsDataChanged);
const auto timer = new QTimer(this);
timer->setSingleShot(true);
timer->setInterval(1000);
connect(timer, &QTimer::timeout, this, &CppCodeModelSettingsWidget::settingsDataChanged);
connect(m_ignorePatternTextEdit, &QPlainTextEdit::textChanged,
timer, qOverload<>(&QTimer::start));
}
CppCodeModelSettings::Data CppCodeModelSettingsWidget::data() const
@@ -153,15 +174,62 @@ public:
setDisplayCategory(Tr::tr("C++"));
setCategoryIconPath(":/projectexplorer/images/settingscategory_cpp.png");
setWidgetCreator(
[] { return new CppCodeModelSettingsWidget(CppCodeModelSettings::instance().data()); });
[] { return new CppCodeModelSettingsWidget(CppCodeModelSettings::globalInstance().data()); });
}
};
void setupCppCodeModelSettings()
void setupCppCodeModelSettingsPage()
{
static CppCodeModelSettingsPage theCppCodeModelSettingsPage;
}
class CppCodeModelProjectSettingsWidget : public ProjectSettingsWidget
{
public:
CppCodeModelProjectSettingsWidget(const CppCodeModelProjectSettings &settings)
: m_settings(settings), m_widget(settings.data())
{
setGlobalSettingsId(Constants::CPP_CODE_MODEL_SETTINGS_ID);
const auto layout = new QVBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0);
layout->addWidget(&m_widget);
setUseGlobalSettings(m_settings.useGlobalSettings());
m_widget.setEnabled(!useGlobalSettings());
connect(this, &ProjectSettingsWidget::useGlobalSettingsChanged, this,
[this](bool checked) {
m_widget.setEnabled(!checked);
m_settings.setUseGlobalSettings(checked);
if (!checked)
m_settings.setData(m_widget.data());
});
connect(&m_widget, &CppCodeModelSettingsWidget::settingsDataChanged,
this, [this] { m_settings.setData(m_widget.data()); });
}
private:
CppCodeModelProjectSettings m_settings;
CppCodeModelSettingsWidget m_widget;
};
class CppCodeModelProjectSettingsPanelFactory final : public ProjectPanelFactory
{
public:
CppCodeModelProjectSettingsPanelFactory()
{
setPriority(100);
setDisplayName(Tr::tr("C++ Code Model"));
setCreateWidgetFunction([](Project *project) {
return new CppCodeModelProjectSettingsWidget(project);
});
}
};
void setupCppCodeModelProjectSettingsPanel()
{
static CppCodeModelProjectSettingsPanelFactory factory;
}
class ClangdSettingsWidget final : public QWidget
{
Q_OBJECT

View File

@@ -5,7 +5,8 @@
namespace CppEditor::Internal {
void setupCppCodeModelSettings();
void setupCppCodeModelSettingsPage();
void setupCppCodeModelProjectSettingsPanel();
void setupClangdProjectSettingsPanel();
void setupClangdSettingsPage();

View File

@@ -70,6 +70,7 @@
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/projectmanager.h>
#include <projectexplorer/projecttree.h>
#include <projectexplorer/rawprojectpart.h>
#include <texteditor/colorpreviewhoverhandler.h>
#include <texteditor/snippets/snippetprovider.h>
@@ -202,7 +203,10 @@ void CppEditorPlugin::initialize()
d = new CppEditorPluginPrivate;
setupCppQuickFixSettings();
setupCppCodeModelSettings();
setupCppCodeModelSettingsPage();
provideCppSettingsRetriever([](const Project *p) {
return CppCodeModelSettings::settingsForProject(p).data().toMap();
});
setupCppOutline();
setupCppCodeStyleSettings();
setupCppProjectUpdater();
@@ -227,6 +231,7 @@ void CppEditorPlugin::extensionsInitialized()
{
setupCppQuickFixProjectPanel();
setupCppFileSettings();
setupCppCodeModelProjectSettingsPanel();
if (CppModelManager::isClangCodeModelActive()) {
setupClangdProjectSettingsPanel();
@@ -349,9 +354,9 @@ void CppEditorPlugin::addPerSymbolActions()
findRefsCategorized.addToContainers(menus, Constants::G_SYMBOL);
findRefsCategorized.addOnTriggered(this, [] {
if (const auto w = currentCppEditorWidget()) {
CppCodeModelSettings::instance().setCategorizeFindReferences(true);
CppCodeModelSettings::setCategorizeFindReferences(true);
w->findUsages();
CppCodeModelSettings::instance().setCategorizeFindReferences(false);
CppCodeModelSettings::setCategorizeFindReferences(false);
}
});

View File

@@ -388,7 +388,7 @@ void CppFindReferences::findUsages(CPlusPlus::Symbol *symbol,
search->setTextToReplace(replacement);
if (callback)
search->makeNonInteractive(callback);
if (CppCodeModelSettings::instance().categorizeFindReferences())
if (CppCodeModelSettings::categorizeFindReferences())
search->setFilter(new CppSearchResultFilter);
setupSearch(search);
search->setSearchAgainSupported(true);
@@ -397,7 +397,7 @@ void CppFindReferences::findUsages(CPlusPlus::Symbol *symbol,
CppFindReferencesParameters parameters;
parameters.symbolId = fullIdForSymbol(symbol);
parameters.symbolFilePath = symbol->filePath();
parameters.categorize = CppCodeModelSettings::instance().categorizeFindReferences();
parameters.categorize = CppCodeModelSettings::categorizeFindReferences();
parameters.preferLowerCaseFileNames = preferLowerCaseFileNames(
ProjectManager::projectForFile(symbol->filePath()));
@@ -408,8 +408,7 @@ void CppFindReferences::findUsages(CPlusPlus::Symbol *symbol,
}
search->setUserData(QVariant::fromValue(parameters));
findAll_helper(search, symbol, context,
CppCodeModelSettings::instance().categorizeFindReferences());
findAll_helper(search, symbol, context, CppCodeModelSettings::categorizeFindReferences());
}
void CppFindReferences::renameUsages(CPlusPlus::Symbol *symbol,

View File

@@ -407,7 +407,7 @@ void CppModelManager::showPreprocessedFile(bool inNextSplit)
saveAndOpen(outFilePath, content.append(preprocessedDoc->utf8Source()), inNextSplit);
};
if (CppCodeModelSettings::instance().useBuiltinPreprocessor()) {
if (CppCodeModelSettings::settingsForFile(filePath).useBuiltinPreprocessor()) {
useBuiltinPreprocessor();
return;
}
@@ -1023,6 +1023,9 @@ CppModelManager::CppModelManager()
connect(ICore::instance(), &ICore::coreAboutToClose,
this, &CppModelManager::onCoreAboutToClose);
connect(&CppCodeModelSettings::globalInstance(), &CppCodeModelSettings::changed,
this, &CppModelManager::onSettingsChange);
d->m_fallbackProjectPartTimer.setSingleShot(true);
d->m_fallbackProjectPartTimer.setInterval(5000);
connect(&d->m_fallbackProjectPartTimer, &QTimer::timeout,
@@ -1349,12 +1352,17 @@ QFuture<void> CppModelManager::updateSourceFiles(const QSet<FilePath> &sourceFil
if (sourceFiles.isEmpty() || !d->m_indexerEnabled)
return QFuture<void>();
const CppCodeModelSettings &settings = CppCodeModelSettings::instance();
const QSet<QString> filteredFiles
= filteredFilesRemoved(transform(sourceFiles, &FilePath::toString),
QHash<Project *, QSet<QString>> sourcesPerProject; // TODO: Work with QList from here on?
for (const FilePath &fp : sourceFiles)
sourcesPerProject[ProjectManager::projectForFile(fp)] << fp.toString();
QSet<QString> filteredFiles;
for (auto it = sourcesPerProject.cbegin(); it != sourcesPerProject.cend(); ++it) {
const CppCodeModelSettings settings = CppCodeModelSettings::settingsForProject(it.key());
filteredFiles.unite(filteredFilesRemoved(it.value(),
settings.effectiveIndexerFileSizeLimitInMb(),
settings.ignoreFiles(),
settings.ignorePattern());
settings.ignorePattern()));
}
return d->m_internalIndexingSupport->refreshSourceFiles(filteredFiles, mode);
}
@@ -1992,6 +2000,21 @@ void CppModelManager::onCoreAboutToClose()
d->m_enableGC = false;
}
void CppModelManager::onSettingsChange(Project *project)
{
ProjectInfoList info;
if (project)
info << projectInfo(project);
else
info << projectInfos();
for (const ProjectInfo::ConstPtr &pi : std::as_const(info)) {
const CppCodeModelSettings newSettings = CppCodeModelSettings::settingsForProject(
pi->projectFilePath());
if (pi->settings().data() != newSettings.data())
updateProjectInfo(ProjectInfo::cloneWithNewSettings(pi, newSettings));
}
}
void CppModelManager::setupFallbackProjectPart()
{
ToolchainInfo tcInfo;

View File

@@ -288,6 +288,7 @@ private:
static void onSourceFilesRefreshed();
static void onCurrentEditorChanged(Core::IEditor *editor);
static void onCoreAboutToClose();
static void onSettingsChange(ProjectExplorer::Project *project);
static void setupFallbackProjectPart();
static void delayedGC();

View File

@@ -19,6 +19,7 @@
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projectmanager.h>
#include <projectexplorer/projectnodes.h>
#include <utils/hostosinfo.h>
#include <utils/qtcassert.h>
@@ -1174,4 +1175,105 @@ void ModelManagerTest::testDocumentsAndRevisions()
VERIFY_DOCUMENT_REVISION(CppModelManager::document(filePath2), 4U);
}
void ModelManagerTest::testSettingsChanges()
{
ModelManagerTestHelper helper;
int refreshCount = 0;
QSet<QString> refreshedFiles;
connect(CppModelManager::instance(), &CppModelManager::sourceFilesRefreshed,
&helper, [&](const QSet<QString> &files) {
++refreshCount;
refreshedFiles.unite(files);
});
const auto waitForRefresh = [] {
return ::CppEditor::Tests::waitForSignalOrTimeout(CppModelManager::instance(),
&CppModelManager::sourceFilesRefreshed,
5000);
};
const auto setupProjectNodes = [](Project &p, const ProjectFiles &projectFiles) {
auto rootNode = std::make_unique<ProjectNode>(p.projectFilePath());
for (const ProjectFile &sourceFile : projectFiles) {
rootNode->addNestedNode(std::make_unique<FileNode>(sourceFile.path,
sourceFile.isHeader()
? FileType::Header
: FileType::Source));
}
p.setRootProjectNode(std::move(rootNode));
};
// Set up projects.
const MyTestDataDir p1Dir("testdata_project1");
const FilePaths p1Files
= Utils::transform({"baz.h", "baz2.h", "baz3.h", "foo.cpp", "foo.h", "main.cpp"},
[&](const QString &fn) { return p1Dir.filePath(fn); });
const ProjectFiles p1ProjectFiles = Utils::transform(p1Files, [](const FilePath &fp) {
return ProjectFile(fp, ProjectFile::classify(fp.toString()));
});
Project * const p1 = helper.createProject("testdata_project1", FilePath::fromString("p1.pro"));
setupProjectNodes(*p1, p1ProjectFiles);
RawProjectPart rpp1;
const auto part1 = ProjectPart::create(p1->projectFilePath(), rpp1, {}, p1ProjectFiles);
const auto pi1 = ProjectInfo::create(ProjectUpdateInfo(p1, KitInfo(nullptr), {}, {}), {part1});
const auto p1Sources = Utils::transform<QSet<QString>>(p1Files, &FilePath::toString);
CppModelManager::updateProjectInfo(pi1);
const MyTestDataDir p2Dir("testdata_project2");
const FilePaths p2Files
= Utils::transform({"bar.h", "bar.cpp", "foobar2000.h", "foobar4000.h", "main.cpp"},
[&](const QString &fn) { return p1Dir.filePath(fn); });
const ProjectFiles p2ProjectFiles = Utils::transform(p2Files, [](const FilePath &fp) {
return ProjectFile(fp, ProjectFile::classify(fp.toString()));
});
Project * const p2 = helper.createProject("testdata_project2", FilePath::fromString("p2.pro"));
setupProjectNodes(*p2, p2ProjectFiles);
RawProjectPart rpp2;
const auto part2 = ProjectPart::create(p2->projectFilePath(), rpp2, {}, p2ProjectFiles);
const auto pi2 = ProjectInfo::create(ProjectUpdateInfo(p2, KitInfo(nullptr), {}, {}), {part2});
const auto p2Sources = Utils::transform<QSet<QString>>(p2Files, &FilePath::toString);
CppModelManager::updateProjectInfo(pi2);
// Initial check: Have all files been indexed?
while (refreshCount < 2)
QVERIFY(waitForRefresh());
const auto allSources = p1Sources + p2Sources;
QCOMPARE(refreshedFiles, allSources);
// Switch first project from global to local settings. Nothing should get re-indexed,
// as the default values are the same.
refreshCount = 0;
refreshedFiles.clear();
CppCodeModelProjectSettings p1Settings(p1);
QVERIFY(p1Settings.useGlobalSettings());
p1Settings.setUseGlobalSettings(false);
QCOMPARE(refreshCount, 0);
QVERIFY(!waitForRefresh());
// Change global settings. Only the second project should get re-indexed, as the first one
// has its own settings, which are still the same.
CppCodeModelSettings::Data globalSettings
= CppCodeModelSettings::settingsForProject(nullptr).data();
globalSettings.indexerFileSizeLimitInMb = 1;
CppCodeModelSettings::setGlobalData(globalSettings);
if (refreshCount == 0)
QVERIFY(waitForRefresh());
QVERIFY(!waitForRefresh());
QCOMPARE(refreshedFiles, p2Sources);
// Change first project's settings. Only this project should get re-indexed.
refreshCount = 0;
refreshedFiles.clear();
CppCodeModelSettings::Data p1Data = p1Settings.data();
p1Data.ignoreFiles = true;
p1Data.ignorePattern = "baz3.h";
p1Settings.setData(p1Data);
if (refreshCount == 0)
QVERIFY(waitForRefresh());
QVERIFY(!waitForRefresh());
QSet<QString> filteredP1Sources = p1Sources;
filteredP1Sources -= p1Dir.filePath("baz3.h").toString();
QCOMPARE(refreshedFiles, filteredP1Sources);
}
} // CppEditor::Internal

View File

@@ -31,6 +31,7 @@ private slots:
void testRenameIncludes();
void testRenameIncludesInEditor();
void testDocumentsAndRevisions();
void testSettingsChanges();
};
} // namespace CppEditor::Internal

View File

@@ -19,6 +19,12 @@ ProjectInfo::ConstPtr ProjectInfo::create(const ProjectExplorer::ProjectUpdateIn
return ConstPtr(new ProjectInfo(updateInfo, projectParts));
}
ProjectInfo::ConstPtr ProjectInfo::cloneWithNewSettings(const ConstPtr &pi,
const CppCodeModelSettings &settings)
{
return ConstPtr(new ProjectInfo(pi, settings));
}
bool ProjectInfo::operator ==(const ProjectInfo &other) const
{
return m_projectName == other.m_projectName
@@ -27,6 +33,7 @@ bool ProjectInfo::operator ==(const ProjectInfo &other) const
&& m_projectParts == other.m_projectParts
&& m_headerPaths == other.m_headerPaths
&& m_sourceFiles == other.m_sourceFiles
&& m_settings.data() == other.m_settings.data()
&& m_defines == other.m_defines;
}
@@ -42,7 +49,8 @@ bool ProjectInfo::definesChanged(const ProjectInfo &other) const
bool ProjectInfo::configurationChanged(const ProjectInfo &other) const
{
return definesChanged(other) || m_headerPaths != other.m_headerPaths;
return definesChanged(other) || m_headerPaths != other.m_headerPaths
|| m_settings.data() != other.settings().data();
}
bool ProjectInfo::configurationOrFilesChanged(const ProjectInfo &other) const
@@ -89,7 +97,20 @@ ProjectInfo::ProjectInfo(const ProjectExplorer::ProjectUpdateInfo &updateInfo,
m_buildRoot(updateInfo.buildRoot),
m_headerPaths(getHeaderPaths(projectParts)),
m_sourceFiles(getSourceFiles(projectParts)),
m_defines(getDefines(projectParts))
m_defines(getDefines(projectParts)),
m_settings(CppCodeModelSettings::Data(updateInfo.cppSettings))
{
}
ProjectInfo::ProjectInfo(const ConstPtr &pi, const CppCodeModelSettings &settings)
: m_projectParts(pi->projectParts()),
m_projectName(pi->projectName()),
m_projectFilePath(pi->projectFilePath()),
m_buildRoot(pi->buildRoot()),
m_headerPaths(pi->m_headerPaths),
m_sourceFiles(pi->sourceFiles()),
m_defines(pi->m_defines),
m_settings(settings.data())
{
}

View File

@@ -5,6 +5,7 @@
#include "cppeditor_global.h"
#include "cppcodemodelsettings.h"
#include "projectpart.h"
#include <projectexplorer/project.h>
@@ -28,6 +29,8 @@ public:
using ConstPtr = std::shared_ptr<const ProjectInfo>;
static ConstPtr create(const ProjectExplorer::ProjectUpdateInfo &updateInfo,
const QVector<ProjectPart::ConstPtr> &projectParts);
static ConstPtr cloneWithNewSettings(const ProjectInfo::ConstPtr &pi,
const CppCodeModelSettings &settings);
const QVector<ProjectPart::ConstPtr> &projectParts() const { return m_projectParts; }
const QSet<Utils::FilePath> &sourceFiles() const { return m_sourceFiles; }
@@ -35,6 +38,7 @@ public:
Utils::FilePath projectFilePath() const { return m_projectFilePath; }
Utils::FilePath projectRoot() const { return m_projectFilePath.parentDir(); }
Utils::FilePath buildRoot() const { return m_buildRoot; }
const CppCodeModelSettings &settings() const { return m_settings; }
// Comparisons
bool operator ==(const ProjectInfo &other) const;
@@ -46,6 +50,7 @@ public:
private:
ProjectInfo(const ProjectExplorer::ProjectUpdateInfo &updateInfo,
const QVector<ProjectPart::ConstPtr> &projectParts);
ProjectInfo(const ProjectInfo::ConstPtr &pi, const CppCodeModelSettings &settings);
const QVector<ProjectPart::ConstPtr> m_projectParts;
const QString m_projectName;
@@ -54,6 +59,7 @@ private:
const ProjectExplorer::HeaderPaths m_headerPaths;
const QSet<Utils::FilePath> m_sourceFiles;
const ProjectExplorer::Macros m_defines;
const CppCodeModelSettings m_settings;
};
using ProjectInfoList = QList<ProjectInfo::ConstPtr>;

View File

@@ -178,6 +178,12 @@ ToolchainInfo::ToolchainInfo(const Toolchain *toolChain,
}
}
static CppSettingsRetriever g_cppSettingsRetriever;
void provideCppSettingsRetriever(const CppSettingsRetriever &retriever)
{
g_cppSettingsRetriever = retriever;
}
ProjectUpdateInfo::ProjectUpdateInfo(Project *project,
const KitInfo &kitInfo,
const Utils::Environment &env,
@@ -188,6 +194,8 @@ ProjectUpdateInfo::ProjectUpdateInfo(Project *project,
, cToolchainInfo(ToolchainInfo(kitInfo.cToolchain, kitInfo.sysRootPath, env))
, cxxToolchainInfo(ToolchainInfo(kitInfo.cxxToolchain, kitInfo.sysRootPath, env))
{
if (g_cppSettingsRetriever)
cppSettings = g_cppSettingsRetriever(project);
if (project) {
projectName = project->displayName();
projectFilePath = project->projectFilePath();

View File

@@ -14,6 +14,7 @@
#include <utils/cpplanguage_details.h>
#include <utils/environment.h>
#include <utils/fileutils.h>
#include <utils/store.h>
#include <QPointer>
@@ -170,9 +171,13 @@ public:
Utils::FilePath buildRoot;
RawProjectParts rawProjectParts;
RppGenerator rppGenerator;
Utils::Store cppSettings;
ToolchainInfo cToolchainInfo;
ToolchainInfo cxxToolchainInfo;
};
using CppSettingsRetriever = std::function<Utils::Store(const Project *)>;
void PROJECTEXPLORER_EXPORT provideCppSettingsRetriever(const CppSettingsRetriever &retriever);
} // namespace ProjectExplorer