// Copyright (C) 2018 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "clangtoolsprojectsettings.h" #include "clangtoolsdiagnostic.h" #include #include #include #include using namespace Utils; namespace ClangTools { namespace Internal { static const char SETTINGS_KEY_MAIN[] = "ClangTools"; static const char SETTINGS_PREFIX[] = "ClangTools."; static const char SETTINGS_KEY_USE_GLOBAL_SETTINGS[] = "ClangTools.UseGlobalSettings"; static const char SETTINGS_KEY_SELECTED_DIRS[] = "ClangTools.SelectedDirs"; static const char SETTINGS_KEY_SELECTED_FILES[] = "ClangTools.SelectedFiles"; static const char SETTINGS_KEY_SUPPRESSED_DIAGS[] = "ClangTools.SuppressedDiagnostics"; static const char SETTINGS_KEY_SUPPRESSED_DIAGS_FILEPATH[] = "ClangTools.SuppressedDiagnosticFilePath"; static const char SETTINGS_KEY_SUPPRESSED_DIAGS_MESSAGE[] = "ClangTools.SuppressedDiagnosticMessage"; static const char SETTINGS_KEY_SUPPRESSED_DIAGS_UNIQIFIER[] = "ClangTools.SuppressedDiagnosticUniquifier"; ClangToolsProjectSettings::ClangToolsProjectSettings(ProjectExplorer::Project *project) : m_project(project) { load(); connect(this, &ClangToolsProjectSettings::suppressedDiagnosticsChanged, this, &ClangToolsProjectSettings::changed); connect(project, &ProjectExplorer::Project::settingsLoaded, this, &ClangToolsProjectSettings::load); connect(project, &ProjectExplorer::Project::aboutToSaveSettings, this, &ClangToolsProjectSettings::store); } ClangToolsProjectSettings::~ClangToolsProjectSettings() { store(); } void ClangToolsProjectSettings::setUseGlobalSettings(bool useGlobalSettings) { if (m_useGlobalSettings == useGlobalSettings) return; m_useGlobalSettings = useGlobalSettings; emit changed(); } void ClangToolsProjectSettings::setRunSettings(const RunSettings &settings) { if (m_runSettings == settings) return; m_runSettings = settings; emit changed(); } void ClangToolsProjectSettings::setSelectedDirs(const QSet &value) { if (m_selectedDirs == value) return; m_selectedDirs = value; emit changed(); } void ClangToolsProjectSettings::setSelectedFiles(const QSet &value) { if (m_selectedFiles == value) return; m_selectedFiles = value; emit changed(); } void ClangToolsProjectSettings::addSuppressedDiagnostics(const SuppressedDiagnosticsList &diags) { m_suppressedDiagnostics << diags; emit suppressedDiagnosticsChanged(); } void ClangToolsProjectSettings::addSuppressedDiagnostic(const SuppressedDiagnostic &diag) { QTC_ASSERT(!m_suppressedDiagnostics.contains(diag), return); m_suppressedDiagnostics << diag; emit suppressedDiagnosticsChanged(); } void ClangToolsProjectSettings::removeSuppressedDiagnostic(const SuppressedDiagnostic &diag) { const bool wasPresent = m_suppressedDiagnostics.removeOne(diag); QTC_ASSERT(wasPresent, return); emit suppressedDiagnosticsChanged(); } void ClangToolsProjectSettings::removeAllSuppressedDiagnostics() { m_suppressedDiagnostics.clear(); emit suppressedDiagnosticsChanged(); } static Store convertToMapFromVersionBefore410(ProjectExplorer::Project *p) { // These keys haven't changed. const Key keys[] = { SETTINGS_KEY_SELECTED_DIRS, SETTINGS_KEY_SELECTED_FILES, SETTINGS_KEY_SUPPRESSED_DIAGS, SETTINGS_KEY_USE_GLOBAL_SETTINGS, "ClangTools.BuildBeforeAnalysis", }; Store map; for (const Key &key : keys) map.insert(key, p->namedSettings(key)); map.insert(SETTINGS_PREFIX + Key(diagnosticConfigIdKey), p->namedSettings("ClangTools.DiagnosticConfig")); return map; } void ClangToolsProjectSettings::load() { // Load map Store map = storeFromVariant(m_project->namedSettings(SETTINGS_KEY_MAIN)); bool write = false; if (map.isEmpty()) { if (!m_project->namedSettings(SETTINGS_KEY_SELECTED_DIRS).isNull()) { map = convertToMapFromVersionBefore410(m_project); write = true; } else { return; // Use defaults } } // Read map m_useGlobalSettings = map.value(SETTINGS_KEY_USE_GLOBAL_SETTINGS).toBool(); const QVariantList dirs = map.value(SETTINGS_KEY_SELECTED_DIRS).toList(); m_selectedDirs = Utils::transform(dirs, Utils::FilePath::fromSettings); const QVariantList files = map.value(SETTINGS_KEY_SELECTED_FILES).toList(); m_selectedFiles = Utils::transform(files, Utils::FilePath::fromSettings); const QVariantList list = map.value(SETTINGS_KEY_SUPPRESSED_DIAGS).toList(); for (const QVariant &v : list) { const Store diag = storeFromVariant(v); const auto fp = Utils::FilePath::fromSettings( diag.value(SETTINGS_KEY_SUPPRESSED_DIAGS_FILEPATH)); if (fp.isEmpty()) continue; const QString message = diag.value(SETTINGS_KEY_SUPPRESSED_DIAGS_MESSAGE).toString(); if (message.isEmpty()) continue; const Utils::FilePath fullPath = m_project->projectDirectory().resolvePath(fp); if (!fullPath.exists()) continue; const int uniquifier = diag.value(SETTINGS_KEY_SUPPRESSED_DIAGS_UNIQIFIER).toInt(); m_suppressedDiagnostics << SuppressedDiagnostic(fp, message, uniquifier); } emit suppressedDiagnosticsChanged(); m_runSettings.fromMap(map, SETTINGS_PREFIX); if (write) store(); // Store new settings format } void ClangToolsProjectSettings::store() { Store map; map.insert(SETTINGS_KEY_USE_GLOBAL_SETTINGS, m_useGlobalSettings); const QVariantList dirs = Utils::transform(m_selectedDirs, &Utils::FilePath::toSettings); map.insert(SETTINGS_KEY_SELECTED_DIRS, dirs); const QVariantList files = Utils::transform(m_selectedFiles, &Utils::FilePath::toSettings); map.insert(SETTINGS_KEY_SELECTED_FILES, files); QVariantList list; for (const SuppressedDiagnostic &diag : std::as_const(m_suppressedDiagnostics)) { Store diagMap; diagMap.insert(SETTINGS_KEY_SUPPRESSED_DIAGS_FILEPATH, diag.filePath.toSettings()); diagMap.insert(SETTINGS_KEY_SUPPRESSED_DIAGS_MESSAGE, diag.description); diagMap.insert(SETTINGS_KEY_SUPPRESSED_DIAGS_UNIQIFIER, diag.uniquifier); list << variantFromStore(diagMap); } map.insert(SETTINGS_KEY_SUPPRESSED_DIAGS, list); m_runSettings.toMap(map, SETTINGS_PREFIX); m_project->setNamedSettings(SETTINGS_KEY_MAIN, variantFromStore(map)); } ClangToolsProjectSettings::ClangToolsProjectSettingsPtr ClangToolsProjectSettings::getSettings(ProjectExplorer::Project *project) { const Key key = "ClangToolsProjectSettings"; QVariant v = project->extraData(key); if (v.isNull()) { v = QVariant::fromValue( ClangToolsProjectSettingsPtr{new ClangToolsProjectSettings(project)}); project->setExtraData(key, v); } return v.value>(); } SuppressedDiagnostic::SuppressedDiagnostic(const Diagnostic &diag) : filePath(diag.location.filePath) , description(diag.description) , uniquifier(diag.explainingSteps.count()) { } } // namespace Internal } // namespace ClangTools