ClangFormat: Synchronize with C++ code style settings

And remove UI for default code style settings because
it does not affect anything when ClangFormat plugin is
enabled.

Change-Id: Ie348b7d2691b09ea2b4868da987f2a27347ea0f3
Reviewed-by: Marco Bubke <marco.bubke@qt.io>
This commit is contained in:
Ivan Donchevskii
2018-11-08 10:35:23 +01:00
parent 3de607f4e0
commit 0e5c7f51fa
9 changed files with 253 additions and 69 deletions

View File

@@ -18,7 +18,8 @@ QMAKE_CXXFLAGS += $$LLVM_CXXFLAGS
SOURCES = \
clangformatconfigwidget.cpp \
clangformatindenter.cpp \
clangformatplugin.cpp
clangformatplugin.cpp \
clangformatutils.cpp
HEADERS = \
clangformatconfigwidget.h \

View File

@@ -138,7 +138,7 @@ void ClangFormatConfigWidget::initialize()
connect(m_ui->createFileButton, &QPushButton::clicked,
this, [this]() {
createStyleFileIfNeeded(m_project->projectDirectory());
createStyleFileIfNeeded(m_project->projectDirectory(), false);
initialize();
});
return;
@@ -146,10 +146,8 @@ void ClangFormatConfigWidget::initialize()
m_ui->createFileButton->hide();
std::string testFilePath;
if (m_project) {
m_ui->projectHasClangFormat->hide();
testFilePath = m_project->projectDirectory().appendPath("t.cpp").toString().toStdString();
connect(m_ui->applyButton, &QPushButton::clicked, this, &ClangFormatConfigWidget::apply);
} else {
const Project *currentProject = SessionManager::startupProject();
@@ -162,34 +160,20 @@ void ClangFormatConfigWidget::initialize()
"and can be configured in Projects > Clang Format."));
}
const QString settingsDir = Core::ICore::userResourcePath();
createStyleFileIfNeeded(Utils::FileName::fromString(settingsDir));
testFilePath = settingsDir.toStdString() + "/t.cpp";
createStyleFileIfNeeded(Utils::FileName::fromString(settingsDir), true);
m_ui->applyButton->hide();
}
fillTable(testFilePath);
fillTable();
}
void ClangFormatConfigWidget::fillTable(const std::string &testFilePath)
void ClangFormatConfigWidget::fillTable()
{
llvm::Expected<clang::format::FormatStyle> formatStyle =
clang::format::getStyle("file", testFilePath, "LLVM");
std::string configText;
bool brokenConfig = false;
if (!formatStyle) {
handleAllErrors(formatStyle.takeError(), [](const llvm::ErrorInfoBase &) {
// do nothing
});
configText = clang::format::configurationAsText(clang::format::getLLVMStyle());
brokenConfig = true;
} else {
configText = clang::format::configurationAsText(*formatStyle);
}
clang::format::FormatStyle style = m_project ? currentProjectStyle() : currentGlobalStyle();
std::string configText = clang::format::configurationAsText(style);
std::istringstream stream(configText);
readTable(m_ui->clangFormatOptionsTable, stream);
if (brokenConfig)
apply();
}

View File

@@ -49,7 +49,7 @@ public:
private:
void initialize();
void fillTable(const std::string &testFilePath);
void fillTable();
ProjectExplorer::Project *m_project;
std::unique_ptr<Ui::ClangFormatConfigWidget> m_ui;

View File

@@ -30,10 +30,7 @@
#include <clang/Format/Format.h>
#include <clang/Tooling/Core/Replacement.h>
#include <coreplugin/icore.h>
#include <cpptools/cppmodelmanager.h>
#include <projectexplorer/project.h>
#include <projectexplorer/session.h>
#include <texteditor/textdocument.h>
#include <texteditor/texteditor.h>
@@ -95,31 +92,6 @@ Replacements filteredReplacements(const Replacements &replacements,
return filtered;
}
Utils::FileName styleConfigPath()
{
const Project *project = SessionManager::startupProject();
if (project && project->projectDirectory().appendPath(".clang-format").exists())
return project->projectDirectory();
return Utils::FileName::fromString(Core::ICore::userResourcePath());
}
FormatStyle formatStyle(Utils::FileName styleConfigPath)
{
createStyleFileIfNeeded(styleConfigPath);
Expected<FormatStyle> style = format::getStyle(
"file", styleConfigPath.appendPath("test.cpp").toString().toStdString(), "LLVM");
if (style)
return *style;
handleAllErrors(style.takeError(), [](const ErrorInfoBase &) {
// do nothing
});
return format::getLLVMStyle();
}
void trimFirstNonEmptyBlock(const QTextBlock &currentBlock)
{
QTextBlock prevBlock = currentBlock.previous();
@@ -198,8 +170,7 @@ Replacements replacements(QByteArray buffer,
const QTextBlock *block = nullptr,
const QChar &typedChar = QChar::Null)
{
Utils::FileName stylePath = styleConfigPath();
FormatStyle style = formatStyle(stylePath);
FormatStyle style = currentStyle();
int extraOffset = 0;
if (block) {
@@ -227,6 +198,7 @@ Replacements replacements(QByteArray buffer,
static_cast<unsigned int>(utf8Length)}};
FormattingAttemptStatus status;
Utils::FileName stylePath = currentStyleConfigPath();
const std::string assumedFilePath
= stylePath.appendPath("test.cpp").toString().toStdString();
Replacements replacements = reformat(style, buffer.data(), ranges, assumedFilePath, &status);
@@ -451,7 +423,7 @@ int ClangFormatIndenter::indentFor(const QTextBlock &block, const TextEditor::Ta
TabSettings ClangFormatIndenter::tabSettings() const
{
FormatStyle style = formatStyle(styleConfigPath());
FormatStyle style = currentStyle();
TabSettings tabSettings;
switch (style.UseTab) {
@@ -468,8 +440,8 @@ TabSettings ClangFormatIndenter::tabSettings() const
tabSettings.m_tabSize = static_cast<int>(style.TabWidth);
tabSettings.m_indentSize = static_cast<int>(style.IndentWidth);
if (style.AlignAfterOpenBracket)
tabSettings.m_continuationAlignBehavior = TabSettings::ContinuationAlignWithSpaces;
if (style.AlignAfterOpenBracket == FormatStyle::BAS_DontAlign)
tabSettings.m_continuationAlignBehavior = TabSettings::NoContinuationAlign;
else
tabSettings.m_continuationAlignBehavior = TabSettings::ContinuationAlignWithIndent;

View File

@@ -45,8 +45,12 @@
#include <projectexplorer/projectpanelfactory.h>
#include <projectexplorer/target.h>
#include <texteditor/texteditorsettings.h>
#include <clang/Format/Format.h>
#include <utils/algorithm.h>
#include <QAction>
#include <QDebug>
#include <QMainWindow>
@@ -95,6 +99,24 @@ private:
ClangFormatPlugin::ClangFormatPlugin() = default;
ClangFormatPlugin::~ClangFormatPlugin() = default;
static void disableCppCodeStyle()
{
using namespace TextEditor;
TextEditorSettings::unregisterCodeStyleFactory(CppTools::Constants::CPP_SETTINGS_ID);
TextEditorSettings::unregisterCodeStylePool(CppTools::Constants::CPP_SETTINGS_ID);
TextEditorSettings::unregisterCodeStyle(CppTools::Constants::CPP_SETTINGS_ID);
QList<Core::IOptionsPage *> pages = Core::IOptionsPage::allOptionsPages();
int codeStylePageIndex = Utils::indexOf(pages, [](Core::IOptionsPage *page) {
return page->id() == CppTools::Constants::CPP_CODE_STYLE_SETTINGS_ID;
});
if (codeStylePageIndex >= 0) {
auto *page = pages[codeStylePageIndex];
page->finish();
page->deleteLater();
}
}
bool ClangFormatPlugin::initialize(const QStringList &arguments, QString *errorString)
{
Q_UNUSED(arguments);
@@ -113,6 +135,8 @@ bool ClangFormatPlugin::initialize(const QStringList &arguments, QString *errorS
CppTools::CppModelManager::instance()->setCppIndenterCreator([]() {
return new ClangFormatIndenter();
});
disableCppCodeStyle();
#endif
return true;
}

View File

@@ -0,0 +1,179 @@
/****************************************************************************
**
** Copyright (C) 2018 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 "clangformatutils.h"
#include <coreplugin/icore.h>
#include <cpptools/cppcodestylesettings.h>
#include <texteditor/tabsettings.h>
#include <projectexplorer/project.h>
#include <projectexplorer/session.h>
using namespace clang;
using namespace format;
using namespace llvm;
using namespace CppTools;
using namespace ProjectExplorer;
using namespace TextEditor;
namespace ClangFormat {
static void applyTabSettings(clang::format::FormatStyle &style, const TabSettings &settings)
{
style.IndentWidth = static_cast<unsigned>(settings.m_indentSize);
style.TabWidth = static_cast<unsigned>(settings.m_tabSize);
if (settings.m_tabPolicy == TabSettings::TabsOnlyTabPolicy)
style.UseTab = FormatStyle::UT_Always;
else if (settings.m_tabPolicy == TabSettings::SpacesOnlyTabPolicy)
style.UseTab = FormatStyle::UT_Never;
else
style.UseTab = FormatStyle::UT_ForContinuationAndIndentation;
if (settings.m_continuationAlignBehavior == TabSettings::NoContinuationAlign) {
style.ContinuationIndentWidth = 0;
style.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign;
} else {
style.ContinuationIndentWidth = style.IndentWidth;
style.AlignAfterOpenBracket = FormatStyle::BAS_Align;
}
}
static void applyCppCodeStyleSettings(clang::format::FormatStyle &style,
const CppCodeStyleSettings &settings)
{
style.IndentCaseLabels = settings.indentSwitchLabels;
style.AlignOperands = settings.alignAssignments;
style.NamespaceIndentation = FormatStyle::NI_None;
if (settings.indentNamespaceBody)
style.NamespaceIndentation = FormatStyle::NI_All;
style.BraceWrapping.IndentBraces = false;
if (settings.indentBlockBraces) {
if (settings.indentClassBraces && settings.indentEnumBraces
&& settings.indentNamespaceBraces && settings.indentFunctionBraces) {
style.BraceWrapping.IndentBraces = true;
} else {
style.BreakBeforeBraces = FormatStyle::BS_GNU;
}
}
if (settings.bindStarToIdentifier || settings.bindStarToRightSpecifier)
style.PointerAlignment = FormatStyle::PAS_Right;
else
style.PointerAlignment = FormatStyle::PAS_Left;
style.AccessModifierOffset = settings.indentAccessSpecifiers
? 0
: - static_cast<int>(style.IndentWidth);
}
static Utils::FileName projectStylePath()
{
const Project *project = SessionManager::startupProject();
if (project)
return project->projectDirectory();
return Utils::FileName();
}
static Utils::FileName globalStylePath()
{
return Utils::FileName::fromString(Core::ICore::userResourcePath());
}
Utils::FileName currentStyleConfigPath()
{
Utils::FileName path = projectStylePath();
if (!path.isEmpty())
return path;
return globalStylePath();
}
static clang::format::FormatStyle constructStyle(bool isGlobal)
{
FormatStyle style = getLLVMStyle();
const CppCodeStyleSettings codeStyleSettings = isGlobal
? CppCodeStyleSettings::currentGlobalCodeStyle()
: CppCodeStyleSettings::currentProjectCodeStyle();
const TabSettings tabSettings = isGlobal
? CppCodeStyleSettings::currentGlobalTabSettings()
: CppCodeStyleSettings::currentProjectTabSettings();
applyTabSettings(style, tabSettings);
applyCppCodeStyleSettings(style, codeStyleSettings);
return style;
}
void createStyleFileIfNeeded(Utils::FileName styleConfigPath, bool isGlobal)
{
const QString configFile = styleConfigPath.appendPath(".clang-format").toString();
if (QFile::exists(configFile))
return;
std::fstream newStyleFile(configFile.toStdString(), std::fstream::out);
if (newStyleFile.is_open()) {
newStyleFile << clang::format::configurationAsText(constructStyle(isGlobal));
newStyleFile.close();
}
}
static clang::format::FormatStyle currentStyle(bool isGlobal)
{
Utils::FileName styleConfigPath = isGlobal ? globalStylePath() : projectStylePath();
createStyleFileIfNeeded(styleConfigPath, isGlobal);
Expected<FormatStyle> style = format::getStyle(
"file", styleConfigPath.appendPath("test.cpp").toString().toStdString(), "LLVM");
if (style)
return *style;
handleAllErrors(style.takeError(), [](const ErrorInfoBase &) {
// do nothing
});
return constructStyle(isGlobal);
}
clang::format::FormatStyle currentProjectStyle()
{
return currentStyle(false);
}
clang::format::FormatStyle currentGlobalStyle()
{
return currentStyle(true);
}
clang::format::FormatStyle currentStyle()
{
const bool isGlobal = (CppCodeStyleSettings::currentProjectCodeStyle()
== CppCodeStyleSettings::currentGlobalCodeStyle());
return currentStyle(isGlobal);
}
}

View File

@@ -34,18 +34,12 @@
namespace ClangFormat {
inline void createStyleFileIfNeeded(Utils::FileName styleConfigPath)
{
const QString configFile = styleConfigPath.appendPath(".clang-format").toString();
if (QFile::exists(configFile))
return;
void createStyleFileIfNeeded(Utils::FileName styleConfigPath, bool isGlobal);
clang::format::FormatStyle newStyle = clang::format::getLLVMStyle();
std::fstream newStyleFile(configFile.toStdString(), std::fstream::out);
if (newStyleFile.is_open()) {
newStyleFile << clang::format::configurationAsText(newStyle);
newStyleFile.close();
}
}
clang::format::FormatStyle currentProjectStyle();
clang::format::FormatStyle currentGlobalStyle();
Utils::FileName currentStyleConfigPath();
clang::format::FormatStyle currentStyle();
}

View File

@@ -33,6 +33,8 @@
#include <projectexplorer/project.h>
#include <projectexplorer/projecttree.h>
#include <texteditor/tabsettings.h>
#include <cplusplus/Overview.h>
#include <utils/qtcassert.h>
@@ -226,6 +228,31 @@ CppCodeStyleSettings CppCodeStyleSettings::currentGlobalCodeStyle()
return cppCodeStylePreferences->currentCodeStyleSettings();
}
TextEditor::TabSettings CppCodeStyleSettings::currentProjectTabSettings()
{
ProjectExplorer::Project *project = ProjectExplorer::ProjectTree::currentProject();
if (!project)
return currentGlobalTabSettings();
ProjectExplorer::EditorConfiguration *editorConfiguration = project->editorConfiguration();
QTC_ASSERT(editorConfiguration, return currentGlobalTabSettings());
TextEditor::ICodeStylePreferences *codeStylePreferences
= editorConfiguration->codeStyle(CppTools::Constants::CPP_SETTINGS_ID);
QTC_ASSERT(codeStylePreferences, return currentGlobalTabSettings());
return codeStylePreferences->tabSettings();
}
TextEditor::TabSettings CppCodeStyleSettings::currentGlobalTabSettings()
{
CppTools::CppCodeStylePreferences *cppCodeStylePreferences
= CppTools::CppToolsSettings::instance()->cppCodeStyle();
QTC_ASSERT(cppCodeStylePreferences, return TextEditor::TabSettings());
return cppCodeStylePreferences->tabSettings();
}
static void configureOverviewWithCodeStyleSettings(CPlusPlus::Overview &overview,
const CppCodeStyleSettings &settings)
{

View File

@@ -34,6 +34,7 @@ class QSettings;
QT_END_NAMESPACE
namespace CPlusPlus { class Overview; }
namespace TextEditor { class TabSettings; }
namespace CppTools {
@@ -94,6 +95,8 @@ public:
static CppCodeStyleSettings currentProjectCodeStyle();
static CppCodeStyleSettings currentGlobalCodeStyle();
static TextEditor::TabSettings currentProjectTabSettings();
static TextEditor::TabSettings currentGlobalTabSettings();
/*! Returns an Overview configured by the current project's code style.