forked from qt-creator/qt-creator
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:
@@ -18,7 +18,8 @@ QMAKE_CXXFLAGS += $$LLVM_CXXFLAGS
|
||||
SOURCES = \
|
||||
clangformatconfigwidget.cpp \
|
||||
clangformatindenter.cpp \
|
||||
clangformatplugin.cpp
|
||||
clangformatplugin.cpp \
|
||||
clangformatutils.cpp
|
||||
|
||||
HEADERS = \
|
||||
clangformatconfigwidget.h \
|
||||
|
||||
@@ -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();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 ¤tBlock)
|
||||
{
|
||||
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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
179
src/plugins/clangformat/clangformatutils.cpp
Normal file
179
src/plugins/clangformat/clangformatutils.cpp
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user