aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIvan Donchevskii <ivan.donchevskii@qt.io>2019-03-05 13:12:44 +0100
committerIvan Donchevskii <ivan.donchevskii@qt.io>2019-03-05 14:48:59 +0000
commitbf972bcb01d57a7143eba4397e69e1db3a8d693b (patch)
tree1e65a329a86269d04a702e721c0e3e7179430240
parent2484a5e209a95bf5d369372ed85a80ca7bc90f03 (diff)
ClangFormat: Change the logic how configuration is picked
Let's use by default the configuration that clang-format picks itself for the source file. The Qt Creator configuration will now only override the default one with global or project settings and can be turned off with the checkbox. This behavior is clearer than always picking some configuration which Qt Creator prefers best. Change-Id: If5ed3d67eb6b4b47a6d0fd5259f7efbb608914d1 Reviewed-by: Marco Bubke <marco.bubke@qt.io> Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io>
-rw-r--r--src/plugins/clangformat/clangformatconfigwidget.cpp83
-rw-r--r--src/plugins/clangformat/clangformatconfigwidget.ui14
-rw-r--r--src/plugins/clangformat/clangformatconstants.h1
-rw-r--r--src/plugins/clangformat/clangformatindenter.cpp2
-rw-r--r--src/plugins/clangformat/clangformatsettings.cpp13
-rw-r--r--src/plugins/clangformat/clangformatsettings.h6
-rw-r--r--src/plugins/clangformat/clangformatutils.cpp92
-rw-r--r--src/plugins/clangformat/clangformatutils.h3
8 files changed, 142 insertions, 72 deletions
diff --git a/src/plugins/clangformat/clangformatconfigwidget.cpp b/src/plugins/clangformat/clangformatconfigwidget.cpp
index faaf6d937f..27192a67f6 100644
--- a/src/plugins/clangformat/clangformatconfigwidget.cpp
+++ b/src/plugins/clangformat/clangformatconfigwidget.cpp
@@ -59,6 +59,24 @@ ClangFormatConfigWidget::ClangFormatConfigWidget(ProjectExplorer::Project *proje
{
m_ui->setupUi(this);
+ m_preview = new TextEditor::SnippetEditorWidget(this);
+ m_ui->horizontalLayout_2->addWidget(m_preview);
+ if (m_project) {
+ m_ui->applyButton->show();
+ hideGlobalCheckboxes();
+ m_ui->overrideDefault->setChecked(
+ m_project->namedSettings(Constants::OVERRIDE_FILE_ID).toBool());
+ } else {
+ m_ui->applyButton->hide();
+ showGlobalCheckboxes();
+ m_ui->overrideDefault->setChecked(ClangFormatSettings::instance().overrideDefaultFile());
+ }
+
+ connect(m_ui->overrideDefault, &QCheckBox::toggled, this, [this](bool checked) {
+ if (checked)
+ createStyleFileIfNeeded(!m_project);
+ initialize();
+ });
initialize();
}
@@ -81,15 +99,18 @@ void ClangFormatConfigWidget::showGlobalCheckboxes()
m_ui->formatOnSave->show();
}
+static bool projectConfigExists()
+{
+ return Utils::FileName::fromString(Core::ICore::userResourcePath())
+ .appendPath(currentProjectUniqueId())
+ .appendPath((Constants::SETTINGS_FILE_NAME))
+ .exists();
+}
+
void ClangFormatConfigWidget::initialize()
{
- m_ui->projectHasClangFormat->show();
- m_ui->clangFormatOptionsTable->show();
- m_ui->applyButton->show();
- hideGlobalCheckboxes();
+ m_ui->projectHasClangFormat->hide();
- m_preview = new TextEditor::SnippetEditorWidget(this);
- m_ui->horizontalLayout_2->addWidget(m_preview);
m_preview->setPlainText(QLatin1String(CppTools::Constants::DEFAULT_CODE_STYLE_SNIPPETS[0]));
m_preview->textDocument()->setIndenter(new ClangFormatIndenter(m_preview->document()));
m_preview->textDocument()->setFontSettings(TextEditor::TextEditorSettings::fontSettings());
@@ -103,21 +124,15 @@ void ClangFormatConfigWidget::initialize()
if (lastItem->spacerItem())
m_ui->verticalLayout->removeItem(lastItem);
- if (m_project
- && !m_project->projectDirectory().appendPath(Constants::SETTINGS_FILE_NAME).exists()) {
- m_ui->projectHasClangFormat->setText(tr("No .clang-format file for the project."));
+ if (!m_ui->overrideDefault->isChecked()) {
m_ui->clangFormatOptionsTable->hide();
- m_ui->applyButton->hide();
+ m_preview->hide();
m_ui->verticalLayout->addStretch(1);
-
- connect(m_ui->createFileButton, &QPushButton::clicked, this, [this]() {
- createStyleFileIfNeeded(false);
- initialize();
- });
return;
}
- m_ui->createFileButton->hide();
+ m_ui->clangFormatOptionsTable->show();
+ m_preview->show();
Utils::FileName fileName;
if (m_project) {
@@ -126,19 +141,13 @@ void ClangFormatConfigWidget::initialize()
fileName = m_project->projectFilePath().appendPath("snippet.cpp");
} else {
const Project *currentProject = SessionManager::startupProject();
- if (!currentProject
- || !currentProject->projectDirectory()
- .appendPath(Constants::SETTINGS_FILE_NAME)
- .exists()) {
+ if (!currentProject || !projectConfigExists()) {
m_ui->projectHasClangFormat->hide();
} else {
m_ui->projectHasClangFormat->setText(
- tr("Current project has its own .clang-format file "
+ tr("Current project has its own overridden .clang-format file "
"and can be configured in Projects > Code Style > C++."));
}
- createStyleFileIfNeeded(true);
- showGlobalCheckboxes();
- m_ui->applyButton->hide();
fileName = Utils::FileName::fromString(Core::ICore::userResourcePath())
.appendPath("snippet.cpp");
}
@@ -160,7 +169,7 @@ void ClangFormatConfigWidget::fillTable()
{
clang::format::FormatStyle style = m_project ? currentProjectStyle() : currentGlobalStyle();
- std::string configText = clang::format::configurationAsText(style);
+ const std::string configText = clang::format::configurationAsText(style);
m_ui->clangFormatOptionsTable->setPlainText(QString::fromStdString(configText));
}
@@ -168,13 +177,16 @@ ClangFormatConfigWidget::~ClangFormatConfigWidget() = default;
void ClangFormatConfigWidget::apply()
{
+ ClangFormatSettings &settings = ClangFormatSettings::instance();
if (!m_project) {
- ClangFormatSettings &settings = ClangFormatSettings::instance();
settings.setFormatCodeInsteadOfIndent(m_ui->formatAlways->isChecked());
settings.setFormatWhileTyping(m_ui->formatWhileTyping->isChecked());
settings.setFormatOnSave(m_ui->formatOnSave->isChecked());
- settings.write();
+ settings.setOverrideDefaultFile(m_ui->overrideDefault->isChecked());
+ } else {
+ m_project->setNamedSettings(Constants::OVERRIDE_FILE_ID, m_ui->overrideDefault->isChecked());
}
+ settings.write();
const QString text = m_ui->clangFormatOptionsTable->toPlainText();
clang::format::FormatStyle style;
@@ -184,16 +196,18 @@ void ClangFormatConfigWidget::apply()
QMessageBox::warning(this,
tr("Error in ClangFormat configuration"),
QString::fromStdString(error.message()));
- fillTable();
- updatePreview();
+ if (m_ui->overrideDefault->isChecked()) {
+ fillTable();
+ updatePreview();
+ }
return;
}
- QString filePath;
+ QString filePath = Core::ICore::userResourcePath();
if (m_project)
- filePath = m_project->projectDirectory().appendPath(Constants::SETTINGS_FILE_NAME).toString();
- else
- filePath = Core::ICore::userResourcePath() + "/" + Constants::SETTINGS_FILE_NAME;
+ filePath += "/" + currentProjectUniqueId();
+ filePath += "/" + QLatin1String(Constants::SETTINGS_FILE_NAME);
+
QFile file(filePath);
if (!file.open(QFile::WriteOnly))
return;
@@ -201,7 +215,8 @@ void ClangFormatConfigWidget::apply()
file.write(text.toUtf8());
file.close();
- updatePreview();
+ if (m_ui->overrideDefault->isChecked())
+ updatePreview();
}
} // namespace ClangFormat
diff --git a/src/plugins/clangformat/clangformatconfigwidget.ui b/src/plugins/clangformat/clangformatconfigwidget.ui
index 41e40ef1fd..c8225981f5 100644
--- a/src/plugins/clangformat/clangformatconfigwidget.ui
+++ b/src/plugins/clangformat/clangformatconfigwidget.ui
@@ -55,6 +55,13 @@
</widget>
</item>
<item>
+ <widget class="QCheckBox" name="overrideDefault">
+ <property name="text">
+ <string>Override Clang Format configuration file</string>
+ </property>
+ </widget>
+ </item>
+ <item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QPlainTextEdit" name="clangFormatOptionsTable"/>
@@ -64,13 +71,6 @@
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
- <widget class="QPushButton" name="createFileButton">
- <property name="text">
- <string>Create Clang Format Configuration File</string>
- </property>
- </widget>
- </item>
- <item>
<widget class="QPushButton" name="applyButton">
<property name="text">
<string>Apply</string>
diff --git a/src/plugins/clangformat/clangformatconstants.h b/src/plugins/clangformat/clangformatconstants.h
index 8b7cbcf9bd..65ea9b6e81 100644
--- a/src/plugins/clangformat/clangformatconstants.h
+++ b/src/plugins/clangformat/clangformatconstants.h
@@ -34,5 +34,6 @@ static const char SETTINGS_ID[] = "ClangFormat";
static const char FORMAT_CODE_INSTEAD_OF_INDENT_ID[] = "ClangFormat.FormatCodeInsteadOfIndent";
static const char FORMAT_WHILE_TYPING_ID[] = "ClangFormat.FormatWhileTyping";
static const char FORMAT_CODE_ON_SAVE_ID[] = "ClangFormat.FormatCodeOnSave";
+static const char OVERRIDE_FILE_ID[] = "ClangFormat.OverrideFile";
} // namespace Constants
} // namespace ClangFormat
diff --git a/src/plugins/clangformat/clangformatindenter.cpp b/src/plugins/clangformat/clangformatindenter.cpp
index 42cedb7b6c..381762ee7f 100644
--- a/src/plugins/clangformat/clangformatindenter.cpp
+++ b/src/plugins/clangformat/clangformatindenter.cpp
@@ -57,7 +57,7 @@ bool ClangFormatIndenter::formatWhileTyping() const
Utils::optional<TabSettings> ClangFormatIndenter::tabSettings() const
{
- FormatStyle style = currentProjectStyle();
+ FormatStyle style = styleForFile();
TabSettings tabSettings;
switch (style.UseTab) {
diff --git a/src/plugins/clangformat/clangformatsettings.cpp b/src/plugins/clangformat/clangformatsettings.cpp
index 8be2b3cefe..8f70130ae3 100644
--- a/src/plugins/clangformat/clangformatsettings.cpp
+++ b/src/plugins/clangformat/clangformatsettings.cpp
@@ -46,6 +46,8 @@ ClangFormatSettings::ClangFormatSettings()
.toBool();
m_formatOnSave = settings->value(QLatin1String(Constants::FORMAT_CODE_ON_SAVE_ID), false)
.toBool();
+ m_overrideDefaultFile = settings->value(QLatin1String(Constants::OVERRIDE_FILE_ID), false)
+ .toBool();
settings->endGroup();
}
@@ -57,6 +59,7 @@ void ClangFormatSettings::write() const
m_formatCodeInsteadOfIndent);
settings->setValue(QLatin1String(Constants::FORMAT_WHILE_TYPING_ID), m_formatWhileTyping);
settings->setValue(QLatin1String(Constants::FORMAT_CODE_ON_SAVE_ID), m_formatOnSave);
+ settings->setValue(QLatin1String(Constants::OVERRIDE_FILE_ID), m_overrideDefaultFile);
settings->endGroup();
}
@@ -90,4 +93,14 @@ bool ClangFormatSettings::formatOnSave() const
return m_formatOnSave;
}
+void ClangFormatSettings::setOverrideDefaultFile(bool enable)
+{
+ m_overrideDefaultFile = enable;
+}
+
+bool ClangFormatSettings::overrideDefaultFile() const
+{
+ return m_overrideDefaultFile;
+}
+
} // namespace ClangFormat
diff --git a/src/plugins/clangformat/clangformatsettings.h b/src/plugins/clangformat/clangformatsettings.h
index 0ea9ed9747..9344cf34a9 100644
--- a/src/plugins/clangformat/clangformatsettings.h
+++ b/src/plugins/clangformat/clangformatsettings.h
@@ -25,6 +25,8 @@
#pragma once
+#include <QString>
+
namespace ClangFormat {
class ClangFormatSettings
@@ -43,10 +45,14 @@ public:
void setFormatOnSave(bool enable);
bool formatOnSave() const;
+
+ void setOverrideDefaultFile(bool enable);
+ bool overrideDefaultFile() const;
private:
bool m_formatCodeInsteadOfIndent = false;
bool m_formatWhileTyping = false;
bool m_formatOnSave = false;
+ bool m_overrideDefaultFile = false;
};
} // namespace ClangFormat
diff --git a/src/plugins/clangformat/clangformatutils.cpp b/src/plugins/clangformat/clangformatutils.cpp
index babe94da24..36bcf2f97d 100644
--- a/src/plugins/clangformat/clangformatutils.cpp
+++ b/src/plugins/clangformat/clangformatutils.cpp
@@ -26,6 +26,7 @@
#include "clangformatutils.h"
#include "clangformatconstants.h"
+#include "clangformatsettings.h"
#include <coreplugin/icore.h>
#include <cpptools/cppcodestylesettings.h>
@@ -33,6 +34,8 @@
#include <projectexplorer/project.h>
#include <projectexplorer/session.h>
+#include <QCryptographicHash>
+
using namespace clang;
using namespace format;
using namespace llvm;
@@ -92,13 +95,26 @@ static void applyCppCodeStyleSettings(clang::format::FormatStyle &style,
: - static_cast<int>(style.IndentWidth);
}
-static Utils::FileName projectPath()
+static bool useGlobalOverriddenSettings()
+{
+ return ClangFormatSettings::instance().overrideDefaultFile();
+}
+
+QString currentProjectUniqueId()
{
const Project *project = SessionManager::startupProject();
- if (project)
- return project->projectDirectory();
+ if (!project)
+ return QString();
- return Utils::FileName();
+ return QString::fromUtf8(QCryptographicHash::hash(project->projectFilePath().toString().toUtf8(),
+ QCryptographicHash::Md5)
+ .toHex(0));
+}
+
+static bool useProjectOverriddenSettings()
+{
+ const Project *project = SessionManager::startupProject();
+ return project ? project->namedSettings(Constants::OVERRIDE_FILE_ID).toBool() : false;
}
static Utils::FileName globalPath()
@@ -106,25 +122,40 @@ static Utils::FileName globalPath()
return Utils::FileName::fromString(Core::ICore::userResourcePath());
}
-static QString configForFile(Utils::FileName fileName)
+static Utils::FileName projectPath()
{
- Utils::FileName topProjectPath = projectPath();
- if (topProjectPath.isEmpty())
- return QString();
+ const Project *project = SessionManager::startupProject();
+ if (project)
+ return globalPath().appendPath("clang-format").appendPath(currentProjectUniqueId());
- QDir projectDir(fileName.parentDir().toString());
- while (!projectDir.exists(Constants::SETTINGS_FILE_NAME)
- && !projectDir.exists(Constants::SETTINGS_FILE_ALT_NAME)) {
- if (projectDir.path() == topProjectPath.toString()
- || !Utils::FileName::fromString(projectDir.path()).isChildOf(topProjectPath)
- || !projectDir.cdUp()) {
+ return Utils::FileName();
+}
+
+static QString configForFile(Utils::FileName fileName, bool checkForSettings)
+{
+ QDir overrideDir;
+ if (!checkForSettings || useProjectOverriddenSettings()) {
+ overrideDir = projectPath().toString();
+ if (!overrideDir.isEmpty() && overrideDir.exists(Constants::SETTINGS_FILE_NAME))
+ return overrideDir.filePath(Constants::SETTINGS_FILE_NAME);
+ }
+
+ if (!checkForSettings || useGlobalOverriddenSettings()) {
+ overrideDir = globalPath().toString();
+ if (!overrideDir.isEmpty() && overrideDir.exists(Constants::SETTINGS_FILE_NAME))
+ return overrideDir.filePath(Constants::SETTINGS_FILE_NAME);
+ }
+
+ QDir parentDir(fileName.parentDir().toString());
+ while (!parentDir.exists(Constants::SETTINGS_FILE_NAME)
+ && !parentDir.exists(Constants::SETTINGS_FILE_ALT_NAME)) {
+ if (!parentDir.cdUp())
return QString();
- }
}
- if (projectDir.exists(Constants::SETTINGS_FILE_NAME))
- return projectDir.filePath(Constants::SETTINGS_FILE_NAME);
- return projectDir.filePath(Constants::SETTINGS_FILE_ALT_NAME);
+ if (parentDir.exists(Constants::SETTINGS_FILE_NAME))
+ return parentDir.filePath(Constants::SETTINGS_FILE_NAME);
+ return parentDir.filePath(Constants::SETTINGS_FILE_ALT_NAME);
}
static clang::format::FormatStyle constructStyle(bool isGlobal,
@@ -169,6 +200,7 @@ void createStyleFileIfNeeded(bool isGlobal)
if (QFile::exists(configFile))
return;
+ QDir().mkpath(path.parentDir().toString());
std::fstream newStyleFile(configFile.toStdString(), std::fstream::out);
if (newStyleFile.is_open()) {
newStyleFile << clang::format::configurationAsText(constructStyle(isGlobal));
@@ -198,16 +230,11 @@ static QByteArray configBaseStyleName(const QString &configFile)
.trimmed();
}
-clang::format::FormatStyle styleForFile(Utils::FileName fileName)
+static clang::format::FormatStyle styleForFile(Utils::FileName fileName, bool checkForSettings)
{
- bool isGlobal = false;
- QString configFile = configForFile(fileName);
- if (configFile.isEmpty()) {
- Utils::FileName path = fileName = globalPath();
- fileName.appendPath(Constants::SAMPLE_FILE_NAME);
- createStyleFileIfNeeded(true);
- configFile = path.appendPath(Constants::SETTINGS_FILE_NAME).toString();
- }
+ QString configFile = configForFile(fileName, checkForSettings);
+ if (configFile.isEmpty())
+ return constructStyle(true);
Expected<FormatStyle> style = format::getStyle("file",
fileName.toString().toStdString(),
@@ -219,17 +246,22 @@ clang::format::FormatStyle styleForFile(Utils::FileName fileName)
// do nothing
});
- return constructStyle(isGlobal, configBaseStyleName(configFile));
+ return constructStyle(true, configBaseStyleName(configFile));
+}
+
+clang::format::FormatStyle styleForFile(Utils::FileName fileName)
+{
+ return styleForFile(fileName, true);
}
clang::format::FormatStyle currentProjectStyle()
{
- return styleForFile(projectPath().appendPath(Constants::SAMPLE_FILE_NAME));
+ return styleForFile(projectPath().appendPath(Constants::SAMPLE_FILE_NAME), false);
}
clang::format::FormatStyle currentGlobalStyle()
{
- return styleForFile(globalPath().appendPath(Constants::SAMPLE_FILE_NAME));
+ return styleForFile(globalPath().appendPath(Constants::SAMPLE_FILE_NAME), false);
}
}
diff --git a/src/plugins/clangformat/clangformatutils.h b/src/plugins/clangformat/clangformatutils.h
index 41e2b5611f..2c818ffe6a 100644
--- a/src/plugins/clangformat/clangformatutils.h
+++ b/src/plugins/clangformat/clangformatutils.h
@@ -25,6 +25,7 @@
#pragma once
+#include <coreplugin/id.h>
#include <utils/fileutils.h>
#include <clang/Format/Format.h>
@@ -37,6 +38,8 @@ namespace ClangFormat {
// Creates the style for the current project or the global style if needed.
void createStyleFileIfNeeded(bool isGlobal);
+QString currentProjectUniqueId();
+
clang::format::FormatStyle currentProjectStyle();
clang::format::FormatStyle currentGlobalStyle();