forked from qt-creator/qt-creator
ClangFormat: Replace checks widget with editor
The existing approach utilizing the widget poses maintenance challenges, primarily due to the dynamic nature of clang-format settings across versions. The widget necessitates regeneration for each new version, and compatibility issues arise when users have different clang-format versions on their devices. The updated solution adopts an Editor integrated with a yaml language server, offering the ability to highlight and provide code completion for the .clang-format file. This resolves the widget regeneration issue and ensures compatibility with various clang-format versions. - Replaced the checks widget with an editor - Introduced a line for yaml language server schema in .clang-format files to enable autocompletion. ToDo: Enhance schema accessibility without relying on this line. - Added Ctrl+Space shortcut for autocompletion - Added Ctrl+S shortcut for saving - Eliminated outdated logic related to the checks widget - Fixed copying and removal of clang-format settings Change-Id: I2e3fbf19abe2f4df031f6ba5faffd47e07274346 Reviewed-by: hjk <hjk@qt.io> Reviewed-by: Christian Kandeler <christian.kandeler@qt.io> Reviewed-by: David Schulz <david.schulz@qt.io> Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
This commit is contained in:
@@ -1,229 +0,0 @@
|
|||||||
#!/usr/bin/env python3.10
|
|
||||||
# Copyright (C) 2022 The Qt Company Ltd.
|
|
||||||
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
import os
|
|
||||||
# for installing use pip3 install robotpy-cppheaderparse
|
|
||||||
import CppHeaderParser
|
|
||||||
|
|
||||||
def parse_arguments():
|
|
||||||
parser = argparse.ArgumentParser(description='Clang-Format checks header file \
|
|
||||||
generator')
|
|
||||||
parser.add_argument('--clang-format-header-file', help='path to \
|
|
||||||
Format.h usually /usr/lib/llvm-x/include/clang/Format/Format.h',
|
|
||||||
default=None, dest='options_header', required=True)
|
|
||||||
return parser.parse_args()
|
|
||||||
|
|
||||||
|
|
||||||
def full_header_content(header_code):
|
|
||||||
return '''// Copyright (C) 2023 The Qt Company Ltd.
|
|
||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
|
||||||
|
|
||||||
// THIS FILE IS AUTOMATICALLY GENERATED by generateClangFormatChecksLayout. DO NOT EDIT!
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
|
||||||
class QCheckBox;
|
|
||||||
class QComboBox;
|
|
||||||
class QLabel;
|
|
||||||
class QLineEdit;
|
|
||||||
class QPlainTextEdit;
|
|
||||||
class QPushButton;
|
|
||||||
class QWidget;
|
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
||||||
namespace ClangFormat {
|
|
||||||
|
|
||||||
class ClangFormatChecks : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
ClangFormatChecks(QWidget *parent = nullptr);
|
|
||||||
|
|
||||||
private:
|
|
||||||
''' + header_code + '''
|
|
||||||
};
|
|
||||||
|
|
||||||
} //ClangFormat
|
|
||||||
'''
|
|
||||||
|
|
||||||
|
|
||||||
def full_source_content(source_code, layout_code):
|
|
||||||
return '''// Copyright (C) 2023 The Qt Company Ltd.
|
|
||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
|
||||||
|
|
||||||
// THIS FILE IS AUTOMATICALLY GENERATED by generateClangFormatChecksLayout. DO NOT EDIT!
|
|
||||||
|
|
||||||
#include "clangformatchecks.h"
|
|
||||||
|
|
||||||
#include <utils/layoutbuilder.h>
|
|
||||||
|
|
||||||
#include <QCheckBox>
|
|
||||||
#include <QComboBox>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QLineEdit>
|
|
||||||
#include <QPlainTextEdit>
|
|
||||||
#include <QPushButton>
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
using namespace ClangFormat;
|
|
||||||
|
|
||||||
ClangFormatChecks::ClangFormatChecks(QWidget *parent)
|
|
||||||
: QWidget(parent)
|
|
||||||
{
|
|
||||||
''' + source_code + '''
|
|
||||||
using namespace Layouting;
|
|
||||||
|
|
||||||
Grid {
|
|
||||||
''' + layout_code + ''' }.attachTo(this);
|
|
||||||
}
|
|
||||||
'''
|
|
||||||
|
|
||||||
# Combobox UI
|
|
||||||
def combobox_header(name):
|
|
||||||
header = " QComboBox *m_" + name + " = nullptr;\n"
|
|
||||||
return header
|
|
||||||
|
|
||||||
def combobox_source(name, values, offset):
|
|
||||||
source = ""
|
|
||||||
source += " m_" + name + " = new QComboBox(this);\n"
|
|
||||||
|
|
||||||
list = ""
|
|
||||||
for value in values:
|
|
||||||
list += "\"" + value + "\","
|
|
||||||
|
|
||||||
source += " m_" + name + "->addItems({" + list + "});\n"
|
|
||||||
source += " m_" + name + "->setObjectName(\"" + name + "\");\n\n"
|
|
||||||
return source
|
|
||||||
|
|
||||||
def combobox_source_bool(name, offset):
|
|
||||||
return combobox_source(name, ["Default", "true", "false"], offset)
|
|
||||||
|
|
||||||
def combobox_layout(name, field_name, offset):
|
|
||||||
layout = " new QLabel(\"" + offset + field_name + "\"), m_" + name + ", br,\n"
|
|
||||||
return layout
|
|
||||||
|
|
||||||
# String UI
|
|
||||||
def string_header(name):
|
|
||||||
header = " QLineEdit *m_" + name + " = nullptr;\n"
|
|
||||||
header += " QPushButton *m_set" + name + " = nullptr;\n"
|
|
||||||
return header
|
|
||||||
|
|
||||||
def string_source(name, offset):
|
|
||||||
source = ""
|
|
||||||
source += " m_" + name + " = new QLineEdit(this);\n"
|
|
||||||
source += " m_" + name + "->setObjectName(\"" + name + "\");\n"
|
|
||||||
source += " m_set" + name + " = new QPushButton(\"Set\", this);\n\n"
|
|
||||||
source += " m_set" + name + "->setObjectName(\"set" + name + "\");\n"
|
|
||||||
return source
|
|
||||||
|
|
||||||
def string_layout(name, field_name, offset):
|
|
||||||
layout = " new QLabel(\"" + offset + field_name + "\"), Row {m_" + name + ", m_set" + name + "}, br,\n"
|
|
||||||
return layout
|
|
||||||
|
|
||||||
# Vector UI
|
|
||||||
def vector_header(name):
|
|
||||||
header = " QPlainTextEdit *m_" + name + " = nullptr;\n"
|
|
||||||
header += " QPushButton *m_set" + name + " = nullptr;\n"
|
|
||||||
return header
|
|
||||||
|
|
||||||
def vector_source(name, offset):
|
|
||||||
source = ""
|
|
||||||
source += " m_" + name + " = new QPlainTextEdit(this);\n"
|
|
||||||
source += " m_" + name + "->setObjectName(\"" + name + "\");\n"
|
|
||||||
source += " m_" + name + "->setFixedHeight(100);\n"
|
|
||||||
source += " m_set" + name + " = new QPushButton(\"Set\", this);\n\n"
|
|
||||||
source += " m_set" + name + "->setObjectName(\"set" + name + "\");\n"
|
|
||||||
# source += "m_" + name + "->setObjectName(\"" + offset + name + "\");\n\n"
|
|
||||||
return source
|
|
||||||
|
|
||||||
def vector_layout(name, field_name, offset):
|
|
||||||
layout = " new QLabel(\"" + offset + field_name + "\"), Row {m_" + name + ", m_set" + name + "}, br,\n"
|
|
||||||
return layout
|
|
||||||
|
|
||||||
# Struct Layout
|
|
||||||
def struct_layout(name, offset):
|
|
||||||
layout = " new QLabel(\"" + offset + name + "\"), br,\n"
|
|
||||||
return layout
|
|
||||||
|
|
||||||
|
|
||||||
def in_list(list, type):
|
|
||||||
for element in list:
|
|
||||||
if element["name"] == type:
|
|
||||||
return element;
|
|
||||||
return
|
|
||||||
|
|
||||||
def create_private_variables(variables, enums, structs, offset = "", parent_name = ""):
|
|
||||||
header = ""
|
|
||||||
source = ""
|
|
||||||
layout = ""
|
|
||||||
|
|
||||||
# create BasedOnStyle combobox ussually not presented in FormatStyle struct
|
|
||||||
if offset == "":
|
|
||||||
header += combobox_header("BasedOnStyle")
|
|
||||||
source += combobox_source("BasedOnStyle", ["LLVM", "Google", "Chromium", "Mozilla", "WebKit", "Microsoft", "GNU"], offset)
|
|
||||||
layout += combobox_layout("BasedOnStyle", "BasedOnStyle", offset)
|
|
||||||
|
|
||||||
for variable in variables:
|
|
||||||
if "doxygen" in variable.keys():
|
|
||||||
if ("**deprecated**" in variable['doxygen']):
|
|
||||||
continue;
|
|
||||||
|
|
||||||
type = variable["type"]
|
|
||||||
field_name = variable["name"]
|
|
||||||
variable_name = parent_name + variable["name"]
|
|
||||||
enum = in_list(enums, type)
|
|
||||||
struct = in_list(structs, type)
|
|
||||||
if enum:
|
|
||||||
header += combobox_header(variable_name)
|
|
||||||
source += combobox_source(variable_name, [value["name"].split("_")[1] for value in enum["values"]], offset)
|
|
||||||
layout += combobox_layout(variable_name, field_name, offset)
|
|
||||||
elif struct:
|
|
||||||
layout += struct_layout(variable_name, offset)
|
|
||||||
header_tmp, source_tmp, layout_tmp = create_private_variables(struct["properties"]["public"], enums, structs, " ", variable_name)
|
|
||||||
header += header_tmp
|
|
||||||
source += source_tmp
|
|
||||||
layout += layout_tmp
|
|
||||||
elif "std::string" == type or "unsigned" == type or "int" == type:
|
|
||||||
header += string_header(variable_name)
|
|
||||||
source += string_source(variable_name, offset)
|
|
||||||
layout += string_layout(variable_name, field_name, offset)
|
|
||||||
elif "std::vector<std::string>" == type:
|
|
||||||
header += vector_header(variable_name)
|
|
||||||
source += vector_source(variable_name, offset)
|
|
||||||
layout += vector_layout(variable_name, field_name, offset)
|
|
||||||
elif "bool" == type:
|
|
||||||
header += combobox_header(variable_name)
|
|
||||||
source += combobox_source_bool(variable_name, offset)
|
|
||||||
layout += combobox_layout(variable_name, field_name, offset);
|
|
||||||
return header, source, layout
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
arguments = parse_arguments()
|
|
||||||
header = CppHeaderParser.CppHeader(arguments.options_header)
|
|
||||||
|
|
||||||
enums = header.classes["FormatStyle"]["enums"]["public"]
|
|
||||||
structs = header.classes["FormatStyle"]["nested_classes"]
|
|
||||||
variables = header.classes["FormatStyle"]["properties"]["public"]
|
|
||||||
|
|
||||||
current_path = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
source_path = os.path.abspath(os.path.join(current_path, '..', 'src',
|
|
||||||
'plugins', 'clangformat', 'clangformatchecks.cpp'))
|
|
||||||
header_path = os.path.abspath(os.path.join(current_path, '..', 'src',
|
|
||||||
'plugins', 'clangformat', 'clangformatchecks.h'))
|
|
||||||
|
|
||||||
header, source, layout = create_private_variables(variables, enums, structs)
|
|
||||||
with open(source_path, 'w') as f:
|
|
||||||
f.write(full_source_content(source, layout))
|
|
||||||
|
|
||||||
with open(header_path, 'w') as f:
|
|
||||||
f.write(full_header_content(header))
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
@@ -46,7 +46,6 @@ add_subdirectory(vcsbase)
|
|||||||
add_subdirectory(autotoolsprojectmanager)
|
add_subdirectory(autotoolsprojectmanager)
|
||||||
add_subdirectory(bazaar)
|
add_subdirectory(bazaar)
|
||||||
add_subdirectory(beautifier)
|
add_subdirectory(beautifier)
|
||||||
add_subdirectory(clangformat)
|
|
||||||
add_subdirectory(clearcase)
|
add_subdirectory(clearcase)
|
||||||
add_subdirectory(cmakeprojectmanager)
|
add_subdirectory(cmakeprojectmanager)
|
||||||
add_subdirectory(cvs)
|
add_subdirectory(cvs)
|
||||||
@@ -79,6 +78,7 @@ if (WITH_QMLDESIGNER)
|
|||||||
add_subdirectory(qmlprojectmanager)
|
add_subdirectory(qmlprojectmanager)
|
||||||
endif()
|
endif()
|
||||||
add_subdirectory(python)
|
add_subdirectory(python)
|
||||||
|
add_subdirectory(clangformat)
|
||||||
|
|
||||||
# Level 7:
|
# Level 7:
|
||||||
add_subdirectory(android)
|
add_subdirectory(android)
|
||||||
|
@@ -4,7 +4,6 @@ add_qtc_plugin(ClangFormat
|
|||||||
PLUGIN_DEPENDS Core TextEditor CppEditor ProjectExplorer
|
PLUGIN_DEPENDS Core TextEditor CppEditor ProjectExplorer
|
||||||
SOURCES
|
SOURCES
|
||||||
clangformatbaseindenter.cpp clangformatbaseindenter.h
|
clangformatbaseindenter.cpp clangformatbaseindenter.h
|
||||||
clangformatchecks.cpp clangformatchecks.h
|
|
||||||
clangformatconfigwidget.cpp clangformatconfigwidget.h
|
clangformatconfigwidget.cpp clangformatconfigwidget.h
|
||||||
clangformatglobalconfigwidget.cpp clangformatglobalconfigwidget.h
|
clangformatglobalconfigwidget.cpp clangformatglobalconfigwidget.h
|
||||||
clangformatconstants.h
|
clangformatconstants.h
|
||||||
|
@@ -34,8 +34,6 @@ QtcPlugin {
|
|||||||
files: [
|
files: [
|
||||||
"clangformatbaseindenter.h",
|
"clangformatbaseindenter.h",
|
||||||
"clangformatbaseindenter.cpp",
|
"clangformatbaseindenter.cpp",
|
||||||
"clangformatchecks.cpp",
|
|
||||||
"clangformatchecks.h",
|
|
||||||
"clangformatconfigwidget.cpp",
|
"clangformatconfigwidget.cpp",
|
||||||
"clangformatconfigwidget.h",
|
"clangformatconfigwidget.h",
|
||||||
"clangformatconstants.h",
|
"clangformatconstants.h",
|
||||||
|
@@ -539,6 +539,7 @@ public:
|
|||||||
|
|
||||||
clang::format::FormatStyle customSettingsStyle(const FilePath &fileName) const;
|
clang::format::FormatStyle customSettingsStyle(const FilePath &fileName) const;
|
||||||
ICodeStylePreferences *m_overriddenPreferences = nullptr;
|
ICodeStylePreferences *m_overriddenPreferences = nullptr;
|
||||||
|
clang::format::FormatStyle m_overriddenStyle = clang::format::getNoStyle();
|
||||||
};
|
};
|
||||||
|
|
||||||
ClangFormatBaseIndenter::ClangFormatBaseIndenter(QTextDocument *doc)
|
ClangFormatBaseIndenter::ClangFormatBaseIndenter(QTextDocument *doc)
|
||||||
@@ -870,6 +871,9 @@ const clang::format::FormatStyle &ClangFormatBaseIndenterPrivate::styleForFile()
|
|||||||
{
|
{
|
||||||
static const milliseconds cacheTimeout = getCacheTimeout();
|
static const milliseconds cacheTimeout = getCacheTimeout();
|
||||||
|
|
||||||
|
if (!(m_overriddenStyle == clang::format::getNoStyle()))
|
||||||
|
return m_overriddenStyle;
|
||||||
|
|
||||||
QDateTime time = QDateTime::currentDateTime();
|
QDateTime time = QDateTime::currentDateTime();
|
||||||
if (m_cachedStyle.expirationTime > time && !(m_cachedStyle.style == clang::format::getNoStyle()))
|
if (m_cachedStyle.expirationTime > time && !(m_cachedStyle.style == clang::format::getNoStyle()))
|
||||||
return m_cachedStyle.style;
|
return m_cachedStyle.style;
|
||||||
@@ -907,4 +911,9 @@ void ClangFormatBaseIndenter::setOverriddenPreferences(ICodeStylePreferences *pr
|
|||||||
d->m_overriddenPreferences = preferences;
|
d->m_overriddenPreferences = preferences;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClangFormatBaseIndenter::setOverriddenStyle(const clang::format::FormatStyle &style)
|
||||||
|
{
|
||||||
|
d->m_overriddenStyle = style;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ClangFormat
|
} // namespace ClangFormat
|
||||||
|
@@ -49,6 +49,7 @@ public:
|
|||||||
const clang::format::FormatStyle &styleForFile() const;
|
const clang::format::FormatStyle &styleForFile() const;
|
||||||
|
|
||||||
void setOverriddenPreferences(TextEditor::ICodeStylePreferences *preferences);
|
void setOverriddenPreferences(TextEditor::ICodeStylePreferences *preferences);
|
||||||
|
void setOverriddenStyle(const clang::format::FormatStyle &style);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool formatCodeInsteadOfIndent() const { return false; }
|
virtual bool formatCodeInsteadOfIndent() const { return false; }
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,256 +0,0 @@
|
|||||||
// Copyright (C) 2023 The Qt Company Ltd.
|
|
||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
|
||||||
|
|
||||||
// THIS FILE IS AUTOMATICALLY GENERATED by generateClangFormatChecksLayout. DO NOT EDIT!
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
|
||||||
class QCheckBox;
|
|
||||||
class QComboBox;
|
|
||||||
class QLabel;
|
|
||||||
class QLineEdit;
|
|
||||||
class QPlainTextEdit;
|
|
||||||
class QPushButton;
|
|
||||||
class QWidget;
|
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
||||||
namespace ClangFormat {
|
|
||||||
|
|
||||||
class ClangFormatChecks : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
ClangFormatChecks(QWidget *parent = nullptr);
|
|
||||||
|
|
||||||
private:
|
|
||||||
QComboBox *m_BasedOnStyle = nullptr;
|
|
||||||
QComboBox *m_InheritsParentConfig = nullptr;
|
|
||||||
QLineEdit *m_AccessModifierOffset = nullptr;
|
|
||||||
QPushButton *m_setAccessModifierOffset = nullptr;
|
|
||||||
QComboBox *m_AlignAfterOpenBracket = nullptr;
|
|
||||||
QComboBox *m_AlignArrayOfStructures = nullptr;
|
|
||||||
QComboBox *m_AlignConsecutiveMacrosEnabled = nullptr;
|
|
||||||
QComboBox *m_AlignConsecutiveMacrosAcrossEmptyLines = nullptr;
|
|
||||||
QComboBox *m_AlignConsecutiveMacrosAcrossComments = nullptr;
|
|
||||||
QComboBox *m_AlignConsecutiveMacrosAlignCompound = nullptr;
|
|
||||||
QComboBox *m_AlignConsecutiveMacrosPadOperators = nullptr;
|
|
||||||
QComboBox *m_AlignConsecutiveAssignmentsEnabled = nullptr;
|
|
||||||
QComboBox *m_AlignConsecutiveAssignmentsAcrossEmptyLines = nullptr;
|
|
||||||
QComboBox *m_AlignConsecutiveAssignmentsAcrossComments = nullptr;
|
|
||||||
QComboBox *m_AlignConsecutiveAssignmentsAlignCompound = nullptr;
|
|
||||||
QComboBox *m_AlignConsecutiveAssignmentsPadOperators = nullptr;
|
|
||||||
QComboBox *m_AlignConsecutiveBitFieldsEnabled = nullptr;
|
|
||||||
QComboBox *m_AlignConsecutiveBitFieldsAcrossEmptyLines = nullptr;
|
|
||||||
QComboBox *m_AlignConsecutiveBitFieldsAcrossComments = nullptr;
|
|
||||||
QComboBox *m_AlignConsecutiveBitFieldsAlignCompound = nullptr;
|
|
||||||
QComboBox *m_AlignConsecutiveBitFieldsPadOperators = nullptr;
|
|
||||||
QComboBox *m_AlignConsecutiveDeclarationsEnabled = nullptr;
|
|
||||||
QComboBox *m_AlignConsecutiveDeclarationsAcrossEmptyLines = nullptr;
|
|
||||||
QComboBox *m_AlignConsecutiveDeclarationsAcrossComments = nullptr;
|
|
||||||
QComboBox *m_AlignConsecutiveDeclarationsAlignCompound = nullptr;
|
|
||||||
QComboBox *m_AlignConsecutiveDeclarationsPadOperators = nullptr;
|
|
||||||
QComboBox *m_AlignConsecutiveShortCaseStatementsEnabled = nullptr;
|
|
||||||
QComboBox *m_AlignConsecutiveShortCaseStatementsAcrossEmptyLines = nullptr;
|
|
||||||
QComboBox *m_AlignConsecutiveShortCaseStatementsAcrossComments = nullptr;
|
|
||||||
QComboBox *m_AlignConsecutiveShortCaseStatementsAlignCaseColons = nullptr;
|
|
||||||
QComboBox *m_AlignEscapedNewlines = nullptr;
|
|
||||||
QComboBox *m_AlignOperands = nullptr;
|
|
||||||
QComboBox *m_AlignTrailingCommentsKind = nullptr;
|
|
||||||
QLineEdit *m_AlignTrailingCommentsOverEmptyLines = nullptr;
|
|
||||||
QPushButton *m_setAlignTrailingCommentsOverEmptyLines = nullptr;
|
|
||||||
QComboBox *m_AllowAllArgumentsOnNextLine = nullptr;
|
|
||||||
QComboBox *m_AllowShortBlocksOnASingleLine = nullptr;
|
|
||||||
QComboBox *m_AllowShortCaseLabelsOnASingleLine = nullptr;
|
|
||||||
QComboBox *m_AllowShortEnumsOnASingleLine = nullptr;
|
|
||||||
QComboBox *m_AllowShortFunctionsOnASingleLine = nullptr;
|
|
||||||
QComboBox *m_AllowShortIfStatementsOnASingleLine = nullptr;
|
|
||||||
QComboBox *m_AllowShortLambdasOnASingleLine = nullptr;
|
|
||||||
QComboBox *m_AllowShortLoopsOnASingleLine = nullptr;
|
|
||||||
QComboBox *m_AlwaysBreakAfterReturnType = nullptr;
|
|
||||||
QComboBox *m_AlwaysBreakBeforeMultilineStrings = nullptr;
|
|
||||||
QComboBox *m_AlwaysBreakTemplateDeclarations = nullptr;
|
|
||||||
QPlainTextEdit *m_AttributeMacros = nullptr;
|
|
||||||
QPushButton *m_setAttributeMacros = nullptr;
|
|
||||||
QComboBox *m_BinPackArguments = nullptr;
|
|
||||||
QComboBox *m_BinPackParameters = nullptr;
|
|
||||||
QComboBox *m_BitFieldColonSpacing = nullptr;
|
|
||||||
QComboBox *m_BraceWrappingAfterCaseLabel = nullptr;
|
|
||||||
QComboBox *m_BraceWrappingAfterClass = nullptr;
|
|
||||||
QComboBox *m_BraceWrappingAfterControlStatement = nullptr;
|
|
||||||
QComboBox *m_BraceWrappingAfterEnum = nullptr;
|
|
||||||
QComboBox *m_BraceWrappingAfterFunction = nullptr;
|
|
||||||
QComboBox *m_BraceWrappingAfterNamespace = nullptr;
|
|
||||||
QComboBox *m_BraceWrappingAfterObjCDeclaration = nullptr;
|
|
||||||
QComboBox *m_BraceWrappingAfterStruct = nullptr;
|
|
||||||
QComboBox *m_BraceWrappingAfterUnion = nullptr;
|
|
||||||
QComboBox *m_BraceWrappingAfterExternBlock = nullptr;
|
|
||||||
QComboBox *m_BraceWrappingBeforeCatch = nullptr;
|
|
||||||
QComboBox *m_BraceWrappingBeforeElse = nullptr;
|
|
||||||
QComboBox *m_BraceWrappingBeforeLambdaBody = nullptr;
|
|
||||||
QComboBox *m_BraceWrappingBeforeWhile = nullptr;
|
|
||||||
QComboBox *m_BraceWrappingIndentBraces = nullptr;
|
|
||||||
QComboBox *m_BraceWrappingSplitEmptyFunction = nullptr;
|
|
||||||
QComboBox *m_BraceWrappingSplitEmptyRecord = nullptr;
|
|
||||||
QComboBox *m_BraceWrappingSplitEmptyNamespace = nullptr;
|
|
||||||
QComboBox *m_BreakAfterAttributes = nullptr;
|
|
||||||
QComboBox *m_BreakArrays = nullptr;
|
|
||||||
QComboBox *m_BreakBeforeBinaryOperators = nullptr;
|
|
||||||
QComboBox *m_BreakBeforeBraces = nullptr;
|
|
||||||
QComboBox *m_BreakBeforeConceptDeclarations = nullptr;
|
|
||||||
QComboBox *m_BreakBeforeInlineASMColon = nullptr;
|
|
||||||
QComboBox *m_BreakBeforeTernaryOperators = nullptr;
|
|
||||||
QComboBox *m_BreakConstructorInitializers = nullptr;
|
|
||||||
QComboBox *m_BreakAfterJavaFieldAnnotations = nullptr;
|
|
||||||
QComboBox *m_BreakStringLiterals = nullptr;
|
|
||||||
QLineEdit *m_ColumnLimit = nullptr;
|
|
||||||
QPushButton *m_setColumnLimit = nullptr;
|
|
||||||
QLineEdit *m_CommentPragmas = nullptr;
|
|
||||||
QPushButton *m_setCommentPragmas = nullptr;
|
|
||||||
QComboBox *m_BreakInheritanceList = nullptr;
|
|
||||||
QComboBox *m_CompactNamespaces = nullptr;
|
|
||||||
QLineEdit *m_ContinuationIndentWidth = nullptr;
|
|
||||||
QPushButton *m_setContinuationIndentWidth = nullptr;
|
|
||||||
QComboBox *m_Cpp11BracedListStyle = nullptr;
|
|
||||||
QComboBox *m_DisableFormat = nullptr;
|
|
||||||
QComboBox *m_EmptyLineAfterAccessModifier = nullptr;
|
|
||||||
QComboBox *m_EmptyLineBeforeAccessModifier = nullptr;
|
|
||||||
QComboBox *m_ExperimentalAutoDetectBinPacking = nullptr;
|
|
||||||
QComboBox *m_FixNamespaceComments = nullptr;
|
|
||||||
QPlainTextEdit *m_ForEachMacros = nullptr;
|
|
||||||
QPushButton *m_setForEachMacros = nullptr;
|
|
||||||
QPlainTextEdit *m_IfMacros = nullptr;
|
|
||||||
QPushButton *m_setIfMacros = nullptr;
|
|
||||||
QComboBox *m_IndentAccessModifiers = nullptr;
|
|
||||||
QComboBox *m_IndentCaseBlocks = nullptr;
|
|
||||||
QComboBox *m_IndentCaseLabels = nullptr;
|
|
||||||
QComboBox *m_IndentGotoLabels = nullptr;
|
|
||||||
QComboBox *m_IndentExternBlock = nullptr;
|
|
||||||
QComboBox *m_IndentPPDirectives = nullptr;
|
|
||||||
QComboBox *m_IndentRequiresClause = nullptr;
|
|
||||||
QLineEdit *m_IndentWidth = nullptr;
|
|
||||||
QPushButton *m_setIndentWidth = nullptr;
|
|
||||||
QComboBox *m_IndentWrappedFunctionNames = nullptr;
|
|
||||||
QComboBox *m_InsertBraces = nullptr;
|
|
||||||
QComboBox *m_InsertNewlineAtEOF = nullptr;
|
|
||||||
QComboBox *m_InsertTrailingCommas = nullptr;
|
|
||||||
QPlainTextEdit *m_JavaImportGroups = nullptr;
|
|
||||||
QPushButton *m_setJavaImportGroups = nullptr;
|
|
||||||
QComboBox *m_JavaScriptQuotes = nullptr;
|
|
||||||
QComboBox *m_JavaScriptWrapImports = nullptr;
|
|
||||||
QComboBox *m_KeepEmptyLinesAtEOF = nullptr;
|
|
||||||
QComboBox *m_KeepEmptyLinesAtTheStartOfBlocks = nullptr;
|
|
||||||
QComboBox *m_LambdaBodyIndentation = nullptr;
|
|
||||||
QComboBox *m_Language = nullptr;
|
|
||||||
QComboBox *m_LineEnding = nullptr;
|
|
||||||
QLineEdit *m_MacroBlockBegin = nullptr;
|
|
||||||
QPushButton *m_setMacroBlockBegin = nullptr;
|
|
||||||
QLineEdit *m_MacroBlockEnd = nullptr;
|
|
||||||
QPushButton *m_setMacroBlockEnd = nullptr;
|
|
||||||
QPlainTextEdit *m_Macros = nullptr;
|
|
||||||
QPushButton *m_setMacros = nullptr;
|
|
||||||
QLineEdit *m_MaxEmptyLinesToKeep = nullptr;
|
|
||||||
QPushButton *m_setMaxEmptyLinesToKeep = nullptr;
|
|
||||||
QComboBox *m_NamespaceIndentation = nullptr;
|
|
||||||
QPlainTextEdit *m_NamespaceMacros = nullptr;
|
|
||||||
QPushButton *m_setNamespaceMacros = nullptr;
|
|
||||||
QComboBox *m_ObjCBinPackProtocolList = nullptr;
|
|
||||||
QLineEdit *m_ObjCBlockIndentWidth = nullptr;
|
|
||||||
QPushButton *m_setObjCBlockIndentWidth = nullptr;
|
|
||||||
QComboBox *m_ObjCBreakBeforeNestedBlockParam = nullptr;
|
|
||||||
QComboBox *m_ObjCSpaceAfterProperty = nullptr;
|
|
||||||
QComboBox *m_ObjCSpaceBeforeProtocolList = nullptr;
|
|
||||||
QComboBox *m_PackConstructorInitializers = nullptr;
|
|
||||||
QLineEdit *m_PenaltyBreakAssignment = nullptr;
|
|
||||||
QPushButton *m_setPenaltyBreakAssignment = nullptr;
|
|
||||||
QLineEdit *m_PenaltyBreakBeforeFirstCallParameter = nullptr;
|
|
||||||
QPushButton *m_setPenaltyBreakBeforeFirstCallParameter = nullptr;
|
|
||||||
QLineEdit *m_PenaltyBreakComment = nullptr;
|
|
||||||
QPushButton *m_setPenaltyBreakComment = nullptr;
|
|
||||||
QLineEdit *m_PenaltyBreakFirstLessLess = nullptr;
|
|
||||||
QPushButton *m_setPenaltyBreakFirstLessLess = nullptr;
|
|
||||||
QLineEdit *m_PenaltyBreakOpenParenthesis = nullptr;
|
|
||||||
QPushButton *m_setPenaltyBreakOpenParenthesis = nullptr;
|
|
||||||
QLineEdit *m_PenaltyBreakString = nullptr;
|
|
||||||
QPushButton *m_setPenaltyBreakString = nullptr;
|
|
||||||
QLineEdit *m_PenaltyBreakTemplateDeclaration = nullptr;
|
|
||||||
QPushButton *m_setPenaltyBreakTemplateDeclaration = nullptr;
|
|
||||||
QLineEdit *m_PenaltyExcessCharacter = nullptr;
|
|
||||||
QPushButton *m_setPenaltyExcessCharacter = nullptr;
|
|
||||||
QLineEdit *m_PenaltyIndentedWhitespace = nullptr;
|
|
||||||
QPushButton *m_setPenaltyIndentedWhitespace = nullptr;
|
|
||||||
QLineEdit *m_PenaltyReturnTypeOnItsOwnLine = nullptr;
|
|
||||||
QPushButton *m_setPenaltyReturnTypeOnItsOwnLine = nullptr;
|
|
||||||
QComboBox *m_PointerAlignment = nullptr;
|
|
||||||
QLineEdit *m_PPIndentWidth = nullptr;
|
|
||||||
QPushButton *m_setPPIndentWidth = nullptr;
|
|
||||||
QComboBox *m_QualifierAlignment = nullptr;
|
|
||||||
QPlainTextEdit *m_QualifierOrder = nullptr;
|
|
||||||
QPushButton *m_setQualifierOrder = nullptr;
|
|
||||||
QComboBox *m_ReferenceAlignment = nullptr;
|
|
||||||
QComboBox *m_ReflowComments = nullptr;
|
|
||||||
QComboBox *m_RemoveBracesLLVM = nullptr;
|
|
||||||
QComboBox *m_RemoveParentheses = nullptr;
|
|
||||||
QComboBox *m_RemoveSemicolon = nullptr;
|
|
||||||
QComboBox *m_RequiresClausePosition = nullptr;
|
|
||||||
QComboBox *m_RequiresExpressionIndentation = nullptr;
|
|
||||||
QComboBox *m_SeparateDefinitionBlocks = nullptr;
|
|
||||||
QLineEdit *m_ShortNamespaceLines = nullptr;
|
|
||||||
QPushButton *m_setShortNamespaceLines = nullptr;
|
|
||||||
QComboBox *m_SortIncludes = nullptr;
|
|
||||||
QComboBox *m_SortJavaStaticImport = nullptr;
|
|
||||||
QComboBox *m_SortUsingDeclarations = nullptr;
|
|
||||||
QComboBox *m_SpaceAfterCStyleCast = nullptr;
|
|
||||||
QComboBox *m_SpaceAfterLogicalNot = nullptr;
|
|
||||||
QComboBox *m_SpaceAfterTemplateKeyword = nullptr;
|
|
||||||
QComboBox *m_SpaceAroundPointerQualifiers = nullptr;
|
|
||||||
QComboBox *m_SpaceBeforeAssignmentOperators = nullptr;
|
|
||||||
QComboBox *m_SpaceBeforeCaseColon = nullptr;
|
|
||||||
QComboBox *m_SpaceBeforeCpp11BracedList = nullptr;
|
|
||||||
QComboBox *m_SpaceBeforeCtorInitializerColon = nullptr;
|
|
||||||
QComboBox *m_SpaceBeforeInheritanceColon = nullptr;
|
|
||||||
QComboBox *m_SpaceBeforeJsonColon = nullptr;
|
|
||||||
QComboBox *m_SpaceBeforeParens = nullptr;
|
|
||||||
QComboBox *m_SpaceBeforeParensOptionsAfterControlStatements = nullptr;
|
|
||||||
QComboBox *m_SpaceBeforeParensOptionsAfterForeachMacros = nullptr;
|
|
||||||
QComboBox *m_SpaceBeforeParensOptionsAfterFunctionDeclarationName = nullptr;
|
|
||||||
QComboBox *m_SpaceBeforeParensOptionsAfterFunctionDefinitionName = nullptr;
|
|
||||||
QComboBox *m_SpaceBeforeParensOptionsAfterIfMacros = nullptr;
|
|
||||||
QComboBox *m_SpaceBeforeParensOptionsAfterOverloadedOperator = nullptr;
|
|
||||||
QComboBox *m_SpaceBeforeParensOptionsAfterRequiresInClause = nullptr;
|
|
||||||
QComboBox *m_SpaceBeforeParensOptionsAfterRequiresInExpression = nullptr;
|
|
||||||
QComboBox *m_SpaceBeforeParensOptionsBeforeNonEmptyParentheses = nullptr;
|
|
||||||
QComboBox *m_SpaceBeforeSquareBrackets = nullptr;
|
|
||||||
QComboBox *m_SpaceBeforeRangeBasedForLoopColon = nullptr;
|
|
||||||
QComboBox *m_SpaceInEmptyBlock = nullptr;
|
|
||||||
QComboBox *m_SpacesInAngles = nullptr;
|
|
||||||
QLineEdit *m_SpacesInLineCommentPrefixMinimum = nullptr;
|
|
||||||
QPushButton *m_setSpacesInLineCommentPrefixMinimum = nullptr;
|
|
||||||
QLineEdit *m_SpacesInLineCommentPrefixMaximum = nullptr;
|
|
||||||
QPushButton *m_setSpacesInLineCommentPrefixMaximum = nullptr;
|
|
||||||
QComboBox *m_SpacesInParensOptionsInConditionalStatements = nullptr;
|
|
||||||
QComboBox *m_SpacesInParensOptionsInCStyleCasts = nullptr;
|
|
||||||
QComboBox *m_SpacesInParensOptionsInEmptyParentheses = nullptr;
|
|
||||||
QComboBox *m_SpacesInParensOptionsOther = nullptr;
|
|
||||||
QComboBox *m_SpacesInSquareBrackets = nullptr;
|
|
||||||
QComboBox *m_Standard = nullptr;
|
|
||||||
QPlainTextEdit *m_StatementAttributeLikeMacros = nullptr;
|
|
||||||
QPushButton *m_setStatementAttributeLikeMacros = nullptr;
|
|
||||||
QPlainTextEdit *m_StatementMacros = nullptr;
|
|
||||||
QPushButton *m_setStatementMacros = nullptr;
|
|
||||||
QLineEdit *m_TabWidth = nullptr;
|
|
||||||
QPushButton *m_setTabWidth = nullptr;
|
|
||||||
QPlainTextEdit *m_TypeNames = nullptr;
|
|
||||||
QPushButton *m_setTypeNames = nullptr;
|
|
||||||
QPlainTextEdit *m_TypenameMacros = nullptr;
|
|
||||||
QPushButton *m_setTypenameMacros = nullptr;
|
|
||||||
QComboBox *m_UseTab = nullptr;
|
|
||||||
QComboBox *m_VerilogBreakBetweenInstancePorts = nullptr;
|
|
||||||
QPlainTextEdit *m_WhitespaceSensitiveMacros = nullptr;
|
|
||||||
QPushButton *m_setWhitespaceSensitiveMacros = nullptr;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
} //ClangFormat
|
|
@@ -3,15 +3,16 @@
|
|||||||
|
|
||||||
#include "clangformatconfigwidget.h"
|
#include "clangformatconfigwidget.h"
|
||||||
|
|
||||||
// the file below was generated by scripts/generateClangFormatChecksLayout.py
|
|
||||||
#include "clangformatchecks.h"
|
|
||||||
#include "clangformatconstants.h"
|
#include "clangformatconstants.h"
|
||||||
#include "clangformatfile.h"
|
#include "clangformatfile.h"
|
||||||
#include "clangformatindenter.h"
|
#include "clangformatindenter.h"
|
||||||
#include "clangformattr.h"
|
#include "clangformattr.h"
|
||||||
#include "clangformatutils.h"
|
#include "clangformatutils.h"
|
||||||
|
|
||||||
|
#include <coreplugin/editormanager/ieditor.h>
|
||||||
|
#include <coreplugin/editormanager/ieditorfactory.h>
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
|
#include <coreplugin/idocument.h>
|
||||||
|
|
||||||
#include <cppeditor/cppcodestylepreferences.h>
|
#include <cppeditor/cppcodestylepreferences.h>
|
||||||
#include <cppeditor/cppcodestylesettings.h>
|
#include <cppeditor/cppcodestylesettings.h>
|
||||||
@@ -20,6 +21,8 @@
|
|||||||
#include <cppeditor/cpphighlighter.h>
|
#include <cppeditor/cpphighlighter.h>
|
||||||
#include <cppeditor/cpptoolssettings.h>
|
#include <cppeditor/cpptoolssettings.h>
|
||||||
|
|
||||||
|
#include <extensionsystem/pluginmanager.h>
|
||||||
|
|
||||||
#include <projectexplorer/editorconfiguration.h>
|
#include <projectexplorer/editorconfiguration.h>
|
||||||
#include <projectexplorer/project.h>
|
#include <projectexplorer/project.h>
|
||||||
|
|
||||||
@@ -27,6 +30,7 @@
|
|||||||
#include <texteditor/icodestylepreferences.h>
|
#include <texteditor/icodestylepreferences.h>
|
||||||
#include <texteditor/snippets/snippeteditor.h>
|
#include <texteditor/snippets/snippeteditor.h>
|
||||||
#include <texteditor/textdocument.h>
|
#include <texteditor/textdocument.h>
|
||||||
|
#include <texteditor/texteditor.h>
|
||||||
#include <texteditor/texteditorsettings.h>
|
#include <texteditor/texteditorsettings.h>
|
||||||
|
|
||||||
#include <utils/guard.h>
|
#include <utils/guard.h>
|
||||||
@@ -37,26 +41,43 @@
|
|||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
|
#include <QMessageBox>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QScrollArea>
|
#include <QScrollArea>
|
||||||
|
#include <QShortcut>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
using namespace ProjectExplorer;
|
using namespace ProjectExplorer;
|
||||||
using namespace Utils;
|
using namespace Utils;
|
||||||
|
|
||||||
namespace ClangFormat {
|
namespace ClangFormat {
|
||||||
|
|
||||||
|
static QObject *languageClientPlugin()
|
||||||
|
{
|
||||||
|
return ExtensionSystem::PluginManager::getObjectByName("LanguageClient");
|
||||||
|
}
|
||||||
|
|
||||||
class ClangFormatConfigWidget final : public TextEditor::CodeStyleEditorWidget
|
class ClangFormatConfigWidget final : public TextEditor::CodeStyleEditorWidget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ClangFormatConfigWidget(TextEditor::ICodeStylePreferences *codeStyle,
|
ClangFormatConfigWidget(TextEditor::ICodeStylePreferences *codeStyle,
|
||||||
Project *project,
|
Project *project,
|
||||||
QWidget *parent);
|
QWidget *parent);
|
||||||
|
|
||||||
|
~ClangFormatConfigWidget()
|
||||||
|
{
|
||||||
|
auto doc = qobject_cast<TextEditor::TextDocument *>(m_editor->document());
|
||||||
|
QMetaObject::invokeMethod(languageClientPlugin(),
|
||||||
|
"closeClientForDocument",
|
||||||
|
Q_ARG(TextEditor::TextDocument *, doc));
|
||||||
|
QMetaObject::invokeMethod(languageClientPlugin(),
|
||||||
|
"closeDocument",
|
||||||
|
Q_ARG(Core::IDocument *, doc));
|
||||||
|
}
|
||||||
|
|
||||||
void apply() final;
|
void apply() final;
|
||||||
void finish() final;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool eventFilter(QObject *object, QEvent *event) final;
|
bool eventFilter(QObject *object, QEvent *event) final;
|
||||||
@@ -64,28 +85,28 @@ private:
|
|||||||
FilePath globalPath();
|
FilePath globalPath();
|
||||||
FilePath projectPath();
|
FilePath projectPath();
|
||||||
void createStyleFileIfNeeded(bool isGlobal);
|
void createStyleFileIfNeeded(bool isGlobal);
|
||||||
void showOrHideWidgets();
|
|
||||||
void initChecksAndPreview();
|
|
||||||
void connectChecks();
|
|
||||||
|
|
||||||
void fillTable();
|
void initPreview(TextEditor::ICodeStylePreferences *codeStyle);
|
||||||
std::string readFile(const QString &path);
|
void initEditor(TextEditor::ICodeStylePreferences *codeStyle);
|
||||||
void saveChanges(QObject *sender);
|
|
||||||
|
void reopenClangFormatDocument();
|
||||||
|
|
||||||
void updatePreview();
|
void updatePreview();
|
||||||
void slotCodeStyleChanged(TextEditor::ICodeStylePreferences *currentPreferences);
|
void slotCodeStyleChanged(TextEditor::ICodeStylePreferences *currentPreferences);
|
||||||
|
|
||||||
ProjectExplorer::Project *m_project = nullptr;
|
ProjectExplorer::Project *m_project = nullptr;
|
||||||
QWidget *m_checksWidget = nullptr;
|
QWidget *m_editorWidget = nullptr;
|
||||||
QScrollArea *m_checksScrollArea = nullptr;
|
QScrollArea *m_editorScrollArea = nullptr;
|
||||||
TextEditor::SnippetEditorWidget *m_preview = nullptr;
|
TextEditor::SnippetEditorWidget *m_preview = nullptr;
|
||||||
|
Core::IEditor *m_editor = nullptr;
|
||||||
|
|
||||||
std::unique_ptr<ClangFormatFile> m_config;
|
std::unique_ptr<ClangFormatFile> m_config;
|
||||||
clang::format::FormatStyle m_style;
|
|
||||||
Guard m_ignoreChanges;
|
Guard m_ignoreChanges;
|
||||||
QLabel *m_fallbackConfig;
|
|
||||||
QLabel *m_clangVersion;
|
QLabel *m_clangVersion;
|
||||||
QLabel *m_clangWarningText;
|
QLabel *m_clangFileIsCorrectText;
|
||||||
QLabel *m_clangWarningIcon;
|
QLabel *m_clangFileIsCorrectIcon;
|
||||||
|
ClangFormatIndenter *m_indenter;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool ClangFormatConfigWidget::eventFilter(QObject *object, QEvent *event)
|
bool ClangFormatConfigWidget::eventFilter(QObject *object, QEvent *event)
|
||||||
@@ -105,75 +126,32 @@ ClangFormatConfigWidget::ClangFormatConfigWidget(TextEditor::ICodeStylePreferenc
|
|||||||
m_project = project;
|
m_project = project;
|
||||||
m_config = std::make_unique<ClangFormatFile>(codeStyle->currentPreferences());
|
m_config = std::make_unique<ClangFormatFile>(codeStyle->currentPreferences());
|
||||||
|
|
||||||
m_fallbackConfig = new QLabel(Tr::tr("Clang-Format Style"));
|
createStyleFileIfNeeded(!m_project);
|
||||||
m_checksScrollArea = new QScrollArea();
|
|
||||||
m_checksWidget = new ClangFormatChecks();
|
|
||||||
|
|
||||||
m_checksScrollArea->setWidget(m_checksWidget);
|
initPreview(codeStyle);
|
||||||
m_checksScrollArea->setWidgetResizable(true);
|
initEditor(codeStyle);
|
||||||
m_checksWidget->setEnabled(!codeStyle->isReadOnly() && !codeStyle->isTemporarilyReadOnly()
|
|
||||||
&& codeStyle->isAdditionalTabVisible());
|
|
||||||
|
|
||||||
|
|
||||||
static const int expectedMajorVersion = 17;
|
|
||||||
m_clangVersion = new QLabel(Tr::tr("Current ClangFormat version: %1.").arg(LLVM_VERSION_STRING),
|
|
||||||
this);
|
|
||||||
m_clangWarningText
|
|
||||||
= new QLabel(Tr::tr("The widget was generated for ClangFormat %1. "
|
|
||||||
"If you use a different version, the widget may work incorrectly.")
|
|
||||||
.arg(expectedMajorVersion),
|
|
||||||
this);
|
|
||||||
|
|
||||||
QPalette palette = m_clangWarningText->palette();
|
|
||||||
palette.setColor(QPalette::WindowText, Qt::red);
|
|
||||||
m_clangWarningText->setPalette(palette);
|
|
||||||
|
|
||||||
m_clangWarningIcon = new QLabel(this);
|
|
||||||
m_clangWarningIcon->setPixmap(Icons::WARNING.icon().pixmap(16, 16));
|
|
||||||
|
|
||||||
if (LLVM_VERSION_MAJOR == expectedMajorVersion) {
|
|
||||||
m_clangWarningText->hide();
|
|
||||||
m_clangWarningIcon->hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
FilePath fileName;
|
|
||||||
if (m_project)
|
|
||||||
fileName = m_project->projectFilePath().pathAppended("snippet.cpp");
|
|
||||||
else
|
|
||||||
fileName = Core::ICore::userResourcePath("snippet.cpp");
|
|
||||||
|
|
||||||
m_preview = new TextEditor::SnippetEditorWidget(this);
|
|
||||||
TextEditor::DisplaySettings displaySettings = m_preview->displaySettings();
|
|
||||||
displaySettings.m_visualizeWhitespace = true;
|
|
||||||
m_preview->setDisplaySettings(displaySettings);
|
|
||||||
m_preview->setPlainText(QLatin1String(CppEditor::Constants::DEFAULT_CODE_STYLE_SNIPPETS[0]));
|
|
||||||
auto *indenter = new ClangFormatIndenter(m_preview->document());
|
|
||||||
indenter->setOverriddenPreferences(codeStyle);
|
|
||||||
m_preview->textDocument()->setIndenter(indenter);
|
|
||||||
m_preview->textDocument()->setFontSettings(TextEditor::TextEditorSettings::fontSettings());
|
|
||||||
m_preview->textDocument()->resetSyntaxHighlighter(
|
|
||||||
[] { return new CppEditor::CppHighlighter(); });
|
|
||||||
m_preview->textDocument()->indenter()->setFileName(fileName);
|
|
||||||
|
|
||||||
using namespace Layouting;
|
using namespace Layouting;
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
m_fallbackConfig,
|
|
||||||
Row {m_clangWarningIcon, m_clangWarningText, st},
|
|
||||||
m_clangVersion,
|
m_clangVersion,
|
||||||
Row { m_checksScrollArea, m_preview },
|
Row { m_editorScrollArea, m_preview },
|
||||||
|
Row {m_clangFileIsCorrectIcon, m_clangFileIsCorrectText, st}
|
||||||
}.attachTo(this);
|
}.attachTo(this);
|
||||||
|
|
||||||
connect(codeStyle, &TextEditor::ICodeStylePreferences::currentPreferencesChanged,
|
connect(codeStyle, &TextEditor::ICodeStylePreferences::currentPreferencesChanged,
|
||||||
this, &ClangFormatConfigWidget::slotCodeStyleChanged);
|
this, &ClangFormatConfigWidget::slotCodeStyleChanged);
|
||||||
|
|
||||||
|
connect(codeStyle, &TextEditor::ICodeStylePreferences::aboutToBeRemoved,
|
||||||
|
this, &ClangFormatFile::removeClangFormatFileForStylePreferences);
|
||||||
|
|
||||||
|
connect(codeStyle, &TextEditor::ICodeStylePreferences::aboutToBeCopied,
|
||||||
|
this, &ClangFormatFile::copyClangFormatFileBasedOnStylePreferences);
|
||||||
|
|
||||||
slotCodeStyleChanged(codeStyle->currentPreferences());
|
slotCodeStyleChanged(codeStyle->currentPreferences());
|
||||||
|
|
||||||
showOrHideWidgets();
|
reopenClangFormatDocument();
|
||||||
fillTable();
|
|
||||||
updatePreview();
|
updatePreview();
|
||||||
|
|
||||||
connectChecks();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClangFormatConfigWidget::slotCodeStyleChanged(
|
void ClangFormatConfigWidget::slotCodeStyleChanged(
|
||||||
@@ -183,35 +161,112 @@ void ClangFormatConfigWidget::slotCodeStyleChanged(
|
|||||||
return;
|
return;
|
||||||
m_config.reset(new ClangFormatFile(codeStyle));
|
m_config.reset(new ClangFormatFile(codeStyle));
|
||||||
m_config->setIsReadOnly(codeStyle->isReadOnly());
|
m_config->setIsReadOnly(codeStyle->isReadOnly());
|
||||||
m_style = m_config->style();
|
|
||||||
|
|
||||||
m_checksWidget->setEnabled(!codeStyle->isReadOnly() && !codeStyle->isTemporarilyReadOnly()
|
m_editorWidget->setEnabled(!codeStyle->isReadOnly() && !codeStyle->isTemporarilyReadOnly()
|
||||||
&& codeStyle->isAdditionalTabVisible());
|
&& codeStyle->isAdditionalTabVisible());
|
||||||
|
|
||||||
fillTable();
|
reopenClangFormatDocument();
|
||||||
updatePreview();
|
updatePreview();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClangFormatConfigWidget::connectChecks()
|
void ClangFormatConfigWidget::initEditor(TextEditor::ICodeStylePreferences *codeStyle)
|
||||||
{
|
{
|
||||||
auto doSaveChanges = [this](QObject *sender) {
|
m_editorScrollArea = new QScrollArea();
|
||||||
if (!m_ignoreChanges.isLocked())
|
Core::EditorFactories factories = Core::IEditorFactory::preferredEditorTypes(
|
||||||
saveChanges(sender);
|
m_config->filePath());
|
||||||
};
|
Core::IEditorFactory *factory = factories.takeFirst();
|
||||||
|
m_editor = factory->createEditor();
|
||||||
|
|
||||||
for (QObject *child : m_checksWidget->children()) {
|
QString errorString;
|
||||||
auto comboBox = qobject_cast<QComboBox *>(child);
|
m_editor->document()->open(&errorString, m_config->filePath(), m_config->filePath());
|
||||||
if (comboBox != nullptr) {
|
m_editor->widget()->adjustSize();
|
||||||
connect(comboBox, &QComboBox::currentIndexChanged,
|
|
||||||
this, std::bind(doSaveChanges, comboBox));
|
QMetaObject::invokeMethod(languageClientPlugin(),
|
||||||
comboBox->installEventFilter(this);
|
"openDocument",
|
||||||
continue;
|
Q_ARG(Core::IDocument *, m_editor->document()));
|
||||||
|
QMetaObject::invokeMethod(languageClientPlugin(),
|
||||||
|
"openEditor",
|
||||||
|
Q_ARG(Core::IEditor *, m_editor));
|
||||||
|
|
||||||
|
m_editorWidget = m_editor->widget();
|
||||||
|
m_editorWidget->setEnabled(!codeStyle->isReadOnly() && !codeStyle->isTemporarilyReadOnly()
|
||||||
|
&& codeStyle->isAdditionalTabVisible());
|
||||||
|
|
||||||
|
m_editorScrollArea->setWidget(m_editor->widget());
|
||||||
|
m_editorScrollArea->setWidgetResizable(true);
|
||||||
|
|
||||||
|
m_clangFileIsCorrectText = new QLabel(Tr::tr("Clang-Format is configured correctly."));
|
||||||
|
QPalette paletteCorrect = m_clangFileIsCorrectText->palette();
|
||||||
|
paletteCorrect.setColor(QPalette::WindowText, Qt::darkGreen);
|
||||||
|
m_clangFileIsCorrectText->setPalette(paletteCorrect);
|
||||||
|
|
||||||
|
m_clangFileIsCorrectIcon = new QLabel(this);
|
||||||
|
m_clangFileIsCorrectIcon->setPixmap(Icons::OK.icon().pixmap(16, 16));
|
||||||
|
|
||||||
|
m_clangVersion = new QLabel(Tr::tr("Current ClangFormat version: %1.").arg(LLVM_VERSION_STRING),
|
||||||
|
this);
|
||||||
|
|
||||||
|
connect(m_editor->document(), &TextEditor::TextDocument::contentsChanged, this, [this] {
|
||||||
|
clang::format::FormatStyle currentSettingsStyle;
|
||||||
|
const bool success
|
||||||
|
= parseConfigurationContent(m_editor->document()->contents().toStdString(),
|
||||||
|
currentSettingsStyle);
|
||||||
|
|
||||||
|
QString text = "";
|
||||||
|
Qt::GlobalColor currentColor;
|
||||||
|
QPixmap pixmap;
|
||||||
|
if (success) {
|
||||||
|
text = Tr::tr("Clang-Format is configured correctly.");
|
||||||
|
currentColor = Qt::darkGreen;
|
||||||
|
pixmap = Icons::OK.icon().pixmap(16, 16);
|
||||||
|
} else {
|
||||||
|
text = Tr::tr("Clang-Format is not configured correctly.");
|
||||||
|
currentColor = Qt::red;
|
||||||
|
pixmap = Icons::WARNING.icon().pixmap(16, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto button = qobject_cast<QPushButton *>(child);
|
m_clangFileIsCorrectText->setText(text);
|
||||||
if (button != nullptr)
|
QPalette paletteCorrect = m_clangFileIsCorrectText->palette();
|
||||||
connect(button, &QPushButton::clicked, this, std::bind(doSaveChanges, button));
|
paletteCorrect.setColor(QPalette::WindowText, currentColor);
|
||||||
}
|
m_clangFileIsCorrectText->setPalette(paletteCorrect);
|
||||||
|
m_clangFileIsCorrectIcon->setPixmap(pixmap);
|
||||||
|
|
||||||
|
if (!success)
|
||||||
|
return;
|
||||||
|
m_indenter->setOverriddenStyle(currentSettingsStyle);
|
||||||
|
updatePreview();
|
||||||
|
});
|
||||||
|
|
||||||
|
QShortcut *completionSC = new QShortcut(QKeySequence("Ctrl+Space"), this);
|
||||||
|
connect(completionSC, &QShortcut::activated, this, [this] {
|
||||||
|
if (auto *editor = qobject_cast<TextEditor::BaseTextEditor *>(m_editor))
|
||||||
|
editor->editorWidget()->invokeAssist(TextEditor::Completion);
|
||||||
|
});
|
||||||
|
|
||||||
|
QShortcut *saveSC = new QShortcut(QKeySequence("Ctrl+S"), this);
|
||||||
|
connect(saveSC, &QShortcut::activated, this, [this] { apply(); });
|
||||||
|
|
||||||
|
m_editorScrollArea->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClangFormatConfigWidget::initPreview(TextEditor::ICodeStylePreferences *codeStyle)
|
||||||
|
{
|
||||||
|
FilePath fileName = m_project ? m_project->projectFilePath().pathAppended("snippet.cpp")
|
||||||
|
: Core::ICore::userResourcePath("snippet.cpp");
|
||||||
|
|
||||||
|
m_preview = new TextEditor::SnippetEditorWidget(this);
|
||||||
|
TextEditor::DisplaySettings displaySettings = m_preview->displaySettings();
|
||||||
|
displaySettings.m_visualizeWhitespace = true;
|
||||||
|
m_preview->setDisplaySettings(displaySettings);
|
||||||
|
m_preview->setPlainText(QLatin1String(CppEditor::Constants::DEFAULT_CODE_STYLE_SNIPPETS[0]));
|
||||||
|
m_indenter = new ClangFormatIndenter(m_preview->document());
|
||||||
|
m_indenter->setOverriddenPreferences(codeStyle);
|
||||||
|
m_preview->textDocument()->setIndenter(m_indenter);
|
||||||
|
m_preview->textDocument()->setFontSettings(TextEditor::TextEditorSettings::fontSettings());
|
||||||
|
m_preview->textDocument()->resetSyntaxHighlighter(
|
||||||
|
[] { return new CppEditor::CppHighlighter(); });
|
||||||
|
m_preview->textDocument()->indenter()->setFileName(fileName);
|
||||||
|
m_preview->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
static clang::format::FormatStyle constructStyle(const QByteArray &baseStyle = QByteArray())
|
static clang::format::FormatStyle constructStyle(const QByteArray &baseStyle = QByteArray())
|
||||||
@@ -257,7 +312,7 @@ void ClangFormatConfigWidget::createStyleFileIfNeeded(bool isGlobal)
|
|||||||
FilePath possibleProjectConfig = m_project->rootProjectDirectory()
|
FilePath possibleProjectConfig = m_project->rootProjectDirectory()
|
||||||
/ Constants::SETTINGS_FILE_NAME;
|
/ Constants::SETTINGS_FILE_NAME;
|
||||||
if (possibleProjectConfig.exists()) {
|
if (possibleProjectConfig.exists()) {
|
||||||
// Just copy th .clang-format if current project has one.
|
// Just copy the .clang-format if current project has one.
|
||||||
possibleProjectConfig.copyFile(configFile);
|
possibleProjectConfig.copyFile(configFile);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -267,21 +322,6 @@ void ClangFormatConfigWidget::createStyleFileIfNeeded(bool isGlobal)
|
|||||||
configFile.writeFileContents(QByteArray::fromStdString(config));
|
configFile.writeFileContents(QByteArray::fromStdString(config));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClangFormatConfigWidget::showOrHideWidgets()
|
|
||||||
{
|
|
||||||
auto verticalLayout = qobject_cast<QVBoxLayout *>(layout());
|
|
||||||
QTC_ASSERT(verticalLayout, return);
|
|
||||||
|
|
||||||
QLayoutItem *lastItem = verticalLayout->itemAt(verticalLayout->count() - 1);
|
|
||||||
if (lastItem->spacerItem())
|
|
||||||
verticalLayout->removeItem(lastItem);
|
|
||||||
|
|
||||||
createStyleFileIfNeeded(!m_project);
|
|
||||||
m_fallbackConfig->show();
|
|
||||||
m_checksScrollArea->show();
|
|
||||||
m_preview->show();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClangFormatConfigWidget::updatePreview()
|
void ClangFormatConfigWidget::updatePreview()
|
||||||
{
|
{
|
||||||
QTextCursor cursor(m_preview->document());
|
QTextCursor cursor(m_preview->document());
|
||||||
@@ -290,208 +330,51 @@ void ClangFormatConfigWidget::updatePreview()
|
|||||||
m_preview->textDocument()->autoFormatOrIndent(cursor);
|
m_preview->textDocument()->autoFormatOrIndent(cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ClangFormatConfigWidget::readFile(const QString &path)
|
void ClangFormatConfigWidget::reopenClangFormatDocument()
|
||||||
{
|
|
||||||
const std::string defaultStyle = clang::format::configurationAsText(qtcStyle());
|
|
||||||
|
|
||||||
QFile file(path);
|
|
||||||
if (!file.open(QFile::ReadOnly))
|
|
||||||
return defaultStyle;
|
|
||||||
|
|
||||||
const std::string content = file.readAll().toStdString();
|
|
||||||
file.close();
|
|
||||||
|
|
||||||
clang::format::FormatStyle style;
|
|
||||||
bool success = parseConfigurationFile(FilePath::fromString(path), style);
|
|
||||||
QTC_ASSERT(success, return defaultStyle);
|
|
||||||
|
|
||||||
addQtcStatementMacros(style);
|
|
||||||
std::string settings = clang::format::configurationAsText(style);
|
|
||||||
|
|
||||||
// Needed workaround because parseConfiguration remove BasedOnStyle field
|
|
||||||
// ToDo: standardize this behavior for future
|
|
||||||
const size_t index = content.find("BasedOnStyle");
|
|
||||||
if (index != std::string::npos) {
|
|
||||||
const size_t size = content.find("\n", index) - index;
|
|
||||||
const size_t insert_index = settings.find("\n");
|
|
||||||
settings.insert(insert_index, "\n" + content.substr(index, size));
|
|
||||||
}
|
|
||||||
|
|
||||||
return settings;
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::map<QString, QString> getMapFromString(const QString &text)
|
|
||||||
{
|
|
||||||
std::map<QString, QString> objectNameMap;
|
|
||||||
|
|
||||||
QString parentName;
|
|
||||||
for (QString line : text.split('\n')) {
|
|
||||||
if (line.isEmpty())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
QStringList list = line.split(':');
|
|
||||||
QString key = !list.isEmpty() ? list[0] : "";
|
|
||||||
QString value = line.mid(key.size() + 1).trimmed();
|
|
||||||
|
|
||||||
if (line.contains(':') && value.isEmpty()) {
|
|
||||||
parentName = key;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!value.isEmpty() && !line.startsWith(" "))
|
|
||||||
parentName = "";
|
|
||||||
|
|
||||||
if (line.startsWith(" - ") || line.startsWith(" ")) {
|
|
||||||
line.remove(0, 2);
|
|
||||||
if (objectNameMap.find(parentName) == objectNameMap.end())
|
|
||||||
objectNameMap[parentName] = line + "\n";
|
|
||||||
else
|
|
||||||
objectNameMap[parentName] += line + "\n";
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (line.startsWith(" ")) {
|
|
||||||
key.remove(0, 2);
|
|
||||||
key = parentName + key;
|
|
||||||
objectNameMap.insert(std::make_pair(key, value));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
objectNameMap.insert(std::make_pair(key, value));
|
|
||||||
}
|
|
||||||
|
|
||||||
return objectNameMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClangFormatConfigWidget::fillTable()
|
|
||||||
{
|
{
|
||||||
GuardLocker locker(m_ignoreChanges);
|
GuardLocker locker(m_ignoreChanges);
|
||||||
|
|
||||||
const QString configText = QString::fromStdString(readFile(m_config->filePath().path()));
|
QString errorString;
|
||||||
std::map<QString, QString> objectNameMap = getMapFromString(configText);
|
if (m_editor->document()->open(&errorString, m_config->filePath(), m_config->filePath())
|
||||||
|
== Core::IDocument::OpenResult::Success) {
|
||||||
for (QObject *child : m_checksWidget->children()) {
|
QMetaObject::invokeMethod(languageClientPlugin(),
|
||||||
if (!qobject_cast<QComboBox *>(child) && !qobject_cast<QLineEdit *>(child)
|
"openDocument",
|
||||||
&& !qobject_cast<QPlainTextEdit *>(child)) {
|
Q_ARG(Core::IDocument *, m_editor->document()));
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (objectNameMap.find(child->objectName()) == objectNameMap.end())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (QPlainTextEdit *plainText = qobject_cast<QPlainTextEdit *>(child)) {
|
|
||||||
plainText->setPlainText(objectNameMap[child->objectName()]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (QComboBox *comboBox = qobject_cast<QComboBox *>(child)) {
|
|
||||||
if (comboBox->findText(objectNameMap[child->objectName()]) == -1) {
|
|
||||||
comboBox->setCurrentIndex(0);
|
|
||||||
} else {
|
|
||||||
comboBox->setCurrentText(objectNameMap[child->objectName()]);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (QLineEdit *lineEdit = qobject_cast<QLineEdit *>(child)) {
|
|
||||||
lineEdit->setText(objectNameMap[child->objectName()]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClangFormatConfigWidget::saveChanges(QObject *sender)
|
|
||||||
{
|
|
||||||
if (sender->objectName() == "BasedOnStyle") {
|
|
||||||
const auto *basedOnStyle = m_checksWidget->findChild<QComboBox *>("BasedOnStyle");
|
|
||||||
m_config->setBasedOnStyle(basedOnStyle->currentText());
|
|
||||||
} else {
|
|
||||||
QList<ClangFormatFile::Field> fields;
|
|
||||||
QString parentName;
|
|
||||||
|
|
||||||
for (QObject *child : m_checksWidget->children()) {
|
|
||||||
if (child->objectName() == "BasedOnStyle")
|
|
||||||
continue;
|
|
||||||
auto *label = qobject_cast<QLabel *>(child);
|
|
||||||
if (!label)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// reset parent name if label starts without " "
|
|
||||||
if (!label->text().startsWith(" "))
|
|
||||||
parentName = "";
|
|
||||||
|
|
||||||
QList<QWidget *> valueWidgets = m_checksWidget->findChildren<QWidget *>(
|
|
||||||
parentName + label->text().trimmed());
|
|
||||||
|
|
||||||
if (valueWidgets.empty()) {
|
|
||||||
// Currently BraceWrapping only.
|
|
||||||
fields.append({label->text(), ""});
|
|
||||||
// save parent name
|
|
||||||
parentName = label->text().trimmed();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
QWidget *valueWidget = valueWidgets.first();
|
|
||||||
if (valueWidgets.size() > 1) {
|
|
||||||
for (QWidget *w : valueWidgets) {
|
|
||||||
if (w->objectName() == parentName + label->text().trimmed()) {
|
|
||||||
valueWidget = w;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!qobject_cast<QComboBox *>(valueWidget) && !qobject_cast<QLineEdit *>(valueWidget)
|
|
||||||
&& !qobject_cast<QPlainTextEdit *>(valueWidget)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto *plainText = qobject_cast<QPlainTextEdit *>(valueWidget);
|
|
||||||
if (plainText) {
|
|
||||||
if (plainText->toPlainText().trimmed().isEmpty())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
std::stringstream content;
|
|
||||||
QStringList list = plainText->toPlainText().split('\n');
|
|
||||||
for (const QString &line : list)
|
|
||||||
content << "\n " << line.toStdString();
|
|
||||||
|
|
||||||
fields.append({label->text(), QString::fromStdString(content.str())});
|
|
||||||
} else {
|
|
||||||
QString text;
|
|
||||||
if (auto *comboBox = qobject_cast<QComboBox *>(valueWidget)) {
|
|
||||||
text = comboBox->currentText();
|
|
||||||
} else {
|
|
||||||
auto *lineEdit = qobject_cast<QLineEdit *>(valueWidget);
|
|
||||||
QTC_ASSERT(lineEdit, continue;);
|
|
||||||
text = lineEdit->text();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!text.isEmpty() && text != "Default")
|
|
||||||
fields.append({label->text(), text});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_config->changeFields(fields);
|
|
||||||
}
|
|
||||||
|
|
||||||
fillTable();
|
|
||||||
updatePreview();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClangFormatConfigWidget::apply()
|
void ClangFormatConfigWidget::apply()
|
||||||
{
|
{
|
||||||
if (!m_checksWidget->isVisible() && !m_checksWidget->isEnabled())
|
if (!m_editorWidget->isEnabled())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_style = m_config->style();
|
clang::format::FormatStyle currentSettingsStyle;
|
||||||
}
|
const bool success = parseConfigurationContent(m_editor->document()->contents().toStdString(),
|
||||||
|
currentSettingsStyle);
|
||||||
|
|
||||||
void ClangFormatConfigWidget::finish()
|
auto saveSettings = [this] {
|
||||||
{
|
QString errorString;
|
||||||
if (!m_checksWidget->isVisible() && !m_checksWidget->isEnabled())
|
m_editor->document()->save(&errorString, m_config->filePath());
|
||||||
|
};
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
saveSettings();
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_config->setStyle(m_style);
|
QMessageBox mBox;
|
||||||
|
mBox.setText(Tr::tr("The current settings are not valid. Are you sure you want to apply them?"));
|
||||||
|
mBox.setStandardButtons(QMessageBox::No | QMessageBox::Yes);
|
||||||
|
mBox.setDefaultButton(QMessageBox::No);
|
||||||
|
int ret = mBox.exec();
|
||||||
|
switch (ret) {
|
||||||
|
case QMessageBox::Yes:
|
||||||
|
saveSettings();
|
||||||
|
break;
|
||||||
|
case QMessageBox::No:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TextEditor::CodeStyleEditorWidget *createClangFormatConfigWidget(
|
TextEditor::CodeStyleEditorWidget *createClangFormatConfigWidget(
|
||||||
|
@@ -2,7 +2,6 @@
|
|||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
#include "clangformatfile.h"
|
#include "clangformatfile.h"
|
||||||
#include "clangformatsettings.h"
|
|
||||||
#include "clangformatutils.h"
|
#include "clangformatutils.h"
|
||||||
|
|
||||||
#include <cppeditor/cppcodestylepreferences.h>
|
#include <cppeditor/cppcodestylepreferences.h>
|
||||||
@@ -15,30 +14,27 @@
|
|||||||
|
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
using namespace ClangFormat;
|
using namespace ClangFormat;
|
||||||
|
|
||||||
ClangFormatFile::ClangFormatFile(const TextEditor::ICodeStylePreferences *preferences)
|
ClangFormatFile::ClangFormatFile(const TextEditor::ICodeStylePreferences *preferences)
|
||||||
: m_filePath(filePathToCurrentSettings(preferences))
|
: m_filePath(filePathToCurrentSettings(preferences))
|
||||||
{
|
{
|
||||||
if (!m_filePath.exists()) {
|
if (m_filePath.exists())
|
||||||
// create file and folder
|
return;
|
||||||
m_filePath.parentDir().createDir();
|
|
||||||
std::fstream newStyleFile(m_filePath.path().toStdString(), std::fstream::out);
|
// create file and folder
|
||||||
if (newStyleFile.is_open()) {
|
m_filePath.parentDir().createDir();
|
||||||
newStyleFile.close();
|
std::fstream newStyleFile(m_filePath.path().toStdString(), std::fstream::out);
|
||||||
}
|
if (newStyleFile.is_open())
|
||||||
resetStyleToQtC(preferences);
|
newStyleFile.close();
|
||||||
|
|
||||||
|
if (preferences->displayName() == "GNU") { // For build-in GNU style
|
||||||
|
m_style = clang::format::getGNUStyle();
|
||||||
|
saveStyleToFile(m_style, m_filePath);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!parseConfigurationFile(m_filePath, m_style))
|
resetStyleToQtC(preferences);
|
||||||
resetStyleToQtC(preferences);
|
|
||||||
}
|
|
||||||
|
|
||||||
clang::format::FormatStyle ClangFormatFile::style() {
|
|
||||||
return m_style;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Utils::FilePath ClangFormatFile::filePath()
|
Utils::FilePath ClangFormatFile::filePath()
|
||||||
@@ -46,12 +42,6 @@ Utils::FilePath ClangFormatFile::filePath()
|
|||||||
return m_filePath;
|
return m_filePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClangFormatFile::setStyle(clang::format::FormatStyle style)
|
|
||||||
{
|
|
||||||
m_style = style;
|
|
||||||
saveNewFormat();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ClangFormatFile::isReadOnly() const
|
bool ClangFormatFile::isReadOnly() const
|
||||||
{
|
{
|
||||||
return m_isReadOnly;
|
return m_isReadOnly;
|
||||||
@@ -68,56 +58,6 @@ void ClangFormatFile::resetStyleToQtC(const TextEditor::ICodeStylePreferences *p
|
|||||||
saveStyleToFile(m_style, m_filePath);
|
saveStyleToFile(m_style, m_filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClangFormatFile::setBasedOnStyle(QString styleName)
|
|
||||||
{
|
|
||||||
changeField({"BasedOnStyle", styleName});
|
|
||||||
saveNewFormat();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString ClangFormatFile::setStyle(QString style)
|
|
||||||
{
|
|
||||||
const std::error_code error = clang::format::parseConfiguration(style.toStdString(), &m_style);
|
|
||||||
if (error.value() != static_cast<int>(clang::format::ParseError::Success)) {
|
|
||||||
return QString::fromStdString(error.message());
|
|
||||||
}
|
|
||||||
|
|
||||||
saveNewFormat(style.toUtf8());
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
QString ClangFormatFile::changeField(Field field)
|
|
||||||
{
|
|
||||||
return changeFields({field});
|
|
||||||
}
|
|
||||||
|
|
||||||
QString ClangFormatFile::changeFields(QList<Field> fields)
|
|
||||||
{
|
|
||||||
std::stringstream content;
|
|
||||||
content << "---" << "\n";
|
|
||||||
|
|
||||||
for (const auto &field : fields) {
|
|
||||||
content << field.first.toStdString() << ": " << field.second.toStdString() << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
return setStyle(QString::fromStdString(content.str()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClangFormatFile::saveNewFormat()
|
|
||||||
{
|
|
||||||
if (m_isReadOnly)
|
|
||||||
return;
|
|
||||||
|
|
||||||
saveStyleToFile(m_style, m_filePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClangFormatFile::saveNewFormat(QByteArray style)
|
|
||||||
{
|
|
||||||
if (m_isReadOnly)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_filePath.writeFileContents(style);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClangFormatFile::saveStyleToFile(clang::format::FormatStyle style, Utils::FilePath filePath)
|
void ClangFormatFile::saveStyleToFile(clang::format::FormatStyle style, Utils::FilePath filePath)
|
||||||
{
|
{
|
||||||
std::string styleStr = clang::format::configurationAsText(style);
|
std::string styleStr = clang::format::configurationAsText(style);
|
||||||
@@ -127,5 +67,27 @@ void ClangFormatFile::saveStyleToFile(clang::format::FormatStyle style, Utils::F
|
|||||||
if (pos != int(std::string::npos))
|
if (pos != int(std::string::npos))
|
||||||
styleStr.erase(pos, 2);
|
styleStr.erase(pos, 2);
|
||||||
styleStr.append("\n");
|
styleStr.append("\n");
|
||||||
|
styleStr
|
||||||
|
.insert(0,
|
||||||
|
"# yaml-language-server: $schema=https://json.schemastore.org/clang-format.json\n");
|
||||||
filePath.writeFileContents(QByteArray::fromStdString(styleStr));
|
filePath.writeFileContents(QByteArray::fromStdString(styleStr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClangFormatFile::removeClangFormatFileForStylePreferences(
|
||||||
|
const TextEditor::ICodeStylePreferences *preferences)
|
||||||
|
{
|
||||||
|
filePathToCurrentSettings(preferences).parentDir().removeRecursively();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClangFormatFile::copyClangFormatFileBasedOnStylePreferences(
|
||||||
|
const TextEditor::ICodeStylePreferences *current,
|
||||||
|
const TextEditor::ICodeStylePreferences *target)
|
||||||
|
{
|
||||||
|
Utils::FilePath currentFP = filePathToCurrentSettings(current);
|
||||||
|
if (!currentFP.exists())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Utils::FilePath targetFP = filePathToCurrentSettings(target);
|
||||||
|
targetFP.parentDir().createDir();
|
||||||
|
currentFP.copyFile(targetFP);
|
||||||
|
}
|
||||||
|
@@ -24,20 +24,17 @@ public:
|
|||||||
|
|
||||||
Utils::FilePath filePath();
|
Utils::FilePath filePath();
|
||||||
void resetStyleToQtC(const TextEditor::ICodeStylePreferences *codeStyle);
|
void resetStyleToQtC(const TextEditor::ICodeStylePreferences *codeStyle);
|
||||||
void setBasedOnStyle(QString styleName);
|
|
||||||
void setStyle(clang::format::FormatStyle style);
|
|
||||||
QString setStyle(QString style);
|
|
||||||
void clearBasedOnStyle();
|
|
||||||
|
|
||||||
using Field = std::pair<QString, QString>;
|
|
||||||
QString changeFields(QList<Field> fields);
|
|
||||||
QString changeField(Field field);
|
|
||||||
bool isReadOnly() const;
|
bool isReadOnly() const;
|
||||||
void setIsReadOnly(bool isReadOnly);
|
void setIsReadOnly(bool isReadOnly);
|
||||||
|
|
||||||
|
static void removeClangFormatFileForStylePreferences(
|
||||||
|
const TextEditor::ICodeStylePreferences *preferences);
|
||||||
|
static void copyClangFormatFileBasedOnStylePreferences(
|
||||||
|
const TextEditor::ICodeStylePreferences *current,
|
||||||
|
const TextEditor::ICodeStylePreferences *target);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void saveNewFormat();
|
|
||||||
void saveNewFormat(QByteArray style);
|
|
||||||
void saveStyleToFile(clang::format::FormatStyle style, Utils::FilePath filePath);
|
void saveStyleToFile(clang::format::FormatStyle style, Utils::FilePath filePath);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@@ -417,13 +417,18 @@ Utils::FilePath filePathToCurrentSettings(const TextEditor::ICodeStylePreference
|
|||||||
/ QLatin1String(Constants::SETTINGS_FILE_NAME);
|
/ QLatin1String(Constants::SETTINGS_FILE_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool parseConfigurationFile(const Utils::FilePath &filePath, clang::format::FormatStyle &style)
|
bool parseConfigurationContent(const std::string &fileContent, clang::format::FormatStyle &style)
|
||||||
{
|
{
|
||||||
style.Language = clang::format::FormatStyle::LK_Cpp;
|
style.Language = clang::format::FormatStyle::LK_Cpp;
|
||||||
const std::error_code error
|
const std::error_code error = parseConfiguration(fileContent, &style);
|
||||||
= parseConfiguration(filePath.fileContents().value_or(QByteArray()).toStdString(), &style);
|
|
||||||
|
|
||||||
return error.value() == static_cast<int>(ParseError::Success);
|
return error.value() == static_cast<int>(ParseError::Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool parseConfigurationFile(const Utils::FilePath &filePath, clang::format::FormatStyle &style)
|
||||||
|
{
|
||||||
|
return parseConfigurationContent(filePath.fileContents().value_or(QByteArray()).toStdString(),
|
||||||
|
style);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ClangFormat
|
} // namespace ClangFormat
|
||||||
|
@@ -48,6 +48,7 @@ clang::format::FormatStyle currentQtStyle(const TextEditor::ICodeStylePreference
|
|||||||
|
|
||||||
Utils::FilePath filePathToCurrentSettings(const TextEditor::ICodeStylePreferences *codeStyle);
|
Utils::FilePath filePathToCurrentSettings(const TextEditor::ICodeStylePreferences *codeStyle);
|
||||||
|
|
||||||
|
bool parseConfigurationContent(const std::string &fileContent, clang::format::FormatStyle &style);
|
||||||
bool parseConfigurationFile(const Utils::FilePath &filePath, clang::format::FormatStyle &style);
|
bool parseConfigurationFile(const Utils::FilePath &filePath, clang::format::FormatStyle &style);
|
||||||
|
|
||||||
} // ClangFormat
|
} // ClangFormat
|
||||||
|
@@ -537,6 +537,21 @@ void LanguageClientManager::editorOpened(Core::IEditor *editor)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LanguageClientManager::openEditor(Core::IEditor *editor)
|
||||||
|
{
|
||||||
|
instance()->editorOpened(editor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LanguageClientManager::openDocument(Core::IDocument *document)
|
||||||
|
{
|
||||||
|
instance()->documentOpened(document);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LanguageClientManager::closeDocument(Core::IDocument *document)
|
||||||
|
{
|
||||||
|
instance()->documentClosed(document);
|
||||||
|
}
|
||||||
|
|
||||||
static QList<BaseSettings *> sortedSettingsForDocument(Core::IDocument *document)
|
static QList<BaseSettings *> sortedSettingsForDocument(Core::IDocument *document)
|
||||||
{
|
{
|
||||||
const QList<BaseSettings *> prefilteredSettings
|
const QList<BaseSettings *> prefilteredSettings
|
||||||
|
@@ -76,6 +76,9 @@ public:
|
|||||||
const LanguageServerProtocol::JsonRpcMessage &message);
|
const LanguageServerProtocol::JsonRpcMessage &message);
|
||||||
|
|
||||||
static void showInspector();
|
static void showInspector();
|
||||||
|
static void openDocument(Core::IDocument *document);
|
||||||
|
static void closeDocument(Core::IDocument *document);
|
||||||
|
static void openEditor(Core::IEditor *editor);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void clientAdded(Client *client);
|
void clientAdded(Client *client);
|
||||||
|
@@ -12,6 +12,7 @@
|
|||||||
#include <coreplugin/actionmanager/actionmanager.h>
|
#include <coreplugin/actionmanager/actionmanager.h>
|
||||||
|
|
||||||
#include <extensionsystem/iplugin.h>
|
#include <extensionsystem/iplugin.h>
|
||||||
|
#include <extensionsystem/pluginmanager.h>
|
||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
@@ -26,6 +27,7 @@ class LanguageClientPlugin final : public ExtensionSystem::IPlugin
|
|||||||
public:
|
public:
|
||||||
LanguageClientPlugin()
|
LanguageClientPlugin()
|
||||||
{
|
{
|
||||||
|
setObjectName("LanguageClient");
|
||||||
qRegisterMetaType<LanguageServerProtocol::JsonRpcMessage>();
|
qRegisterMetaType<LanguageServerProtocol::JsonRpcMessage>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,6 +36,24 @@ private:
|
|||||||
void extensionsInitialized() final;
|
void extensionsInitialized() final;
|
||||||
ShutdownFlag aboutToShutdown() final;
|
ShutdownFlag aboutToShutdown() final;
|
||||||
|
|
||||||
|
Q_SLOT void openDocument(Core::IDocument *document)
|
||||||
|
{
|
||||||
|
LanguageClientManager::openDocument(document);
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_SLOT void closeDocument(Core::IDocument *document)
|
||||||
|
{
|
||||||
|
LanguageClientManager::closeDocument(document);
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_SLOT void openEditor(Core::IEditor *editor) { LanguageClientManager::openEditor(editor); }
|
||||||
|
|
||||||
|
Q_SLOT void closeClientForDocument(TextEditor::TextDocument *document)
|
||||||
|
{
|
||||||
|
if (auto client = LanguageClientManager::clientForDocument(document))
|
||||||
|
client->closeDocument(document);
|
||||||
|
}
|
||||||
|
|
||||||
LanguageClientOutlineWidgetFactory m_outlineFactory;
|
LanguageClientOutlineWidgetFactory m_outlineFactory;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -57,6 +77,8 @@ void LanguageClientPlugin::initialize()
|
|||||||
inspectAction.setText(Tr::tr("Inspect Language Clients..."));
|
inspectAction.setText(Tr::tr("Inspect Language Clients..."));
|
||||||
inspectAction.addToContainer(Core::Constants::M_TOOLS_DEBUG);
|
inspectAction.addToContainer(Core::Constants::M_TOOLS_DEBUG);
|
||||||
inspectAction.addOnTriggered(this, &LanguageClientManager::showInspector);
|
inspectAction.addOnTriggered(this, &LanguageClientManager::showInspector);
|
||||||
|
|
||||||
|
ExtensionSystem::PluginManager::addObject(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LanguageClientPlugin::extensionsInitialized()
|
void LanguageClientPlugin::extensionsInitialized()
|
||||||
@@ -66,6 +88,7 @@ void LanguageClientPlugin::extensionsInitialized()
|
|||||||
|
|
||||||
ExtensionSystem::IPlugin::ShutdownFlag LanguageClientPlugin::aboutToShutdown()
|
ExtensionSystem::IPlugin::ShutdownFlag LanguageClientPlugin::aboutToShutdown()
|
||||||
{
|
{
|
||||||
|
ExtensionSystem::PluginManager::removeObject(this);
|
||||||
LanguageClientManager::shutdown();
|
LanguageClientManager::shutdown();
|
||||||
if (LanguageClientManager::isShutdownFinished())
|
if (LanguageClientManager::isShutdownFinished())
|
||||||
return ExtensionSystem::IPlugin::SynchronousShutdown;
|
return ExtensionSystem::IPlugin::SynchronousShutdown;
|
||||||
|
@@ -165,6 +165,7 @@ void CodeStyleSelectorWidget::slotCopyClicked()
|
|||||||
ICodeStylePreferences *copy = codeStylePool->cloneCodeStyle(currentPreferences);
|
ICodeStylePreferences *copy = codeStylePool->cloneCodeStyle(currentPreferences);
|
||||||
if (copy) {
|
if (copy) {
|
||||||
copy->setDisplayName(newName);
|
copy->setDisplayName(newName);
|
||||||
|
emit m_codeStyle->aboutToBeCopied(currentPreferences, copy);
|
||||||
m_codeStyle->setCurrentDelegate(copy);
|
m_codeStyle->setCurrentDelegate(copy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -241,6 +241,8 @@ void ICodeStylePreferences::fromMap(const Store &map)
|
|||||||
void ICodeStylePreferences::codeStyleRemoved(ICodeStylePreferences *preferences)
|
void ICodeStylePreferences::codeStyleRemoved(ICodeStylePreferences *preferences)
|
||||||
{
|
{
|
||||||
if (currentDelegate() == preferences) {
|
if (currentDelegate() == preferences) {
|
||||||
|
emit aboutToBeRemoved(preferences);
|
||||||
|
|
||||||
CodeStylePool *pool = delegatingPool();
|
CodeStylePool *pool = delegatingPool();
|
||||||
QList<ICodeStylePreferences *> codeStyles = pool->codeStyles();
|
QList<ICodeStylePreferences *> codeStyles = pool->codeStyles();
|
||||||
const int idx = codeStyles.indexOf(preferences);
|
const int idx = codeStyles.indexOf(preferences);
|
||||||
|
@@ -80,6 +80,9 @@ signals:
|
|||||||
void currentDelegateChanged(TextEditor::ICodeStylePreferences *currentDelegate);
|
void currentDelegateChanged(TextEditor::ICodeStylePreferences *currentDelegate);
|
||||||
void currentPreferencesChanged(TextEditor::ICodeStylePreferences *currentPreferences);
|
void currentPreferencesChanged(TextEditor::ICodeStylePreferences *currentPreferences);
|
||||||
void displayNameChanged(const QString &newName);
|
void displayNameChanged(const QString &newName);
|
||||||
|
void aboutToBeRemoved(TextEditor::ICodeStylePreferences *preferences);
|
||||||
|
void aboutToBeCopied(TextEditor::ICodeStylePreferences *current,
|
||||||
|
TextEditor::ICodeStylePreferences *target);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void codeStyleRemoved(ICodeStylePreferences *preferences);
|
void codeStyleRemoved(ICodeStylePreferences *preferences);
|
||||||
|
@@ -292,6 +292,8 @@ TextDocument *TextDocument::currentTextDocument()
|
|||||||
|
|
||||||
TextDocument *TextDocument::textDocumentForFilePath(const Utils::FilePath &filePath)
|
TextDocument *TextDocument::textDocumentForFilePath(const Utils::FilePath &filePath)
|
||||||
{
|
{
|
||||||
|
if (filePath.isEmpty())
|
||||||
|
return nullptr;
|
||||||
return qobject_cast<TextDocument *>(DocumentModel::documentForFilePath(filePath));
|
return qobject_cast<TextDocument *>(DocumentModel::documentForFilePath(filePath));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user