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:
Artem Sokolovskii
2024-01-03 14:56:54 +01:00
committed by hjk
parent 78a909390c
commit e1f7469afb
20 changed files with 288 additions and 1892 deletions

View File

@@ -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()

View File

@@ -46,7 +46,6 @@ add_subdirectory(vcsbase)
add_subdirectory(autotoolsprojectmanager)
add_subdirectory(bazaar)
add_subdirectory(beautifier)
add_subdirectory(clangformat)
add_subdirectory(clearcase)
add_subdirectory(cmakeprojectmanager)
add_subdirectory(cvs)
@@ -79,6 +78,7 @@ if (WITH_QMLDESIGNER)
add_subdirectory(qmlprojectmanager)
endif()
add_subdirectory(python)
add_subdirectory(clangformat)
# Level 7:
add_subdirectory(android)

View File

@@ -4,7 +4,6 @@ add_qtc_plugin(ClangFormat
PLUGIN_DEPENDS Core TextEditor CppEditor ProjectExplorer
SOURCES
clangformatbaseindenter.cpp clangformatbaseindenter.h
clangformatchecks.cpp clangformatchecks.h
clangformatconfigwidget.cpp clangformatconfigwidget.h
clangformatglobalconfigwidget.cpp clangformatglobalconfigwidget.h
clangformatconstants.h

View File

@@ -34,8 +34,6 @@ QtcPlugin {
files: [
"clangformatbaseindenter.h",
"clangformatbaseindenter.cpp",
"clangformatchecks.cpp",
"clangformatchecks.h",
"clangformatconfigwidget.cpp",
"clangformatconfigwidget.h",
"clangformatconstants.h",

View File

@@ -539,6 +539,7 @@ public:
clang::format::FormatStyle customSettingsStyle(const FilePath &fileName) const;
ICodeStylePreferences *m_overriddenPreferences = nullptr;
clang::format::FormatStyle m_overriddenStyle = clang::format::getNoStyle();
};
ClangFormatBaseIndenter::ClangFormatBaseIndenter(QTextDocument *doc)
@@ -870,6 +871,9 @@ const clang::format::FormatStyle &ClangFormatBaseIndenterPrivate::styleForFile()
{
static const milliseconds cacheTimeout = getCacheTimeout();
if (!(m_overriddenStyle == clang::format::getNoStyle()))
return m_overriddenStyle;
QDateTime time = QDateTime::currentDateTime();
if (m_cachedStyle.expirationTime > time && !(m_cachedStyle.style == clang::format::getNoStyle()))
return m_cachedStyle.style;
@@ -907,4 +911,9 @@ void ClangFormatBaseIndenter::setOverriddenPreferences(ICodeStylePreferences *pr
d->m_overriddenPreferences = preferences;
}
void ClangFormatBaseIndenter::setOverriddenStyle(const clang::format::FormatStyle &style)
{
d->m_overriddenStyle = style;
}
} // namespace ClangFormat

View File

@@ -49,6 +49,7 @@ public:
const clang::format::FormatStyle &styleForFile() const;
void setOverriddenPreferences(TextEditor::ICodeStylePreferences *preferences);
void setOverriddenStyle(const clang::format::FormatStyle &style);
protected:
virtual bool formatCodeInsteadOfIndent() const { return false; }

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

@@ -3,15 +3,16 @@
#include "clangformatconfigwidget.h"
// the file below was generated by scripts/generateClangFormatChecksLayout.py
#include "clangformatchecks.h"
#include "clangformatconstants.h"
#include "clangformatfile.h"
#include "clangformatindenter.h"
#include "clangformattr.h"
#include "clangformatutils.h"
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/editormanager/ieditorfactory.h>
#include <coreplugin/icore.h>
#include <coreplugin/idocument.h>
#include <cppeditor/cppcodestylepreferences.h>
#include <cppeditor/cppcodestylesettings.h>
@@ -20,6 +21,8 @@
#include <cppeditor/cpphighlighter.h>
#include <cppeditor/cpptoolssettings.h>
#include <extensionsystem/pluginmanager.h>
#include <projectexplorer/editorconfiguration.h>
#include <projectexplorer/project.h>
@@ -27,6 +30,7 @@
#include <texteditor/icodestylepreferences.h>
#include <texteditor/snippets/snippeteditor.h>
#include <texteditor/textdocument.h>
#include <texteditor/texteditor.h>
#include <texteditor/texteditorsettings.h>
#include <utils/guard.h>
@@ -37,26 +41,43 @@
#include <QComboBox>
#include <QLabel>
#include <QLineEdit>
#include <QMessageBox>
#include <QPushButton>
#include <QScrollArea>
#include <QShortcut>
#include <QVBoxLayout>
#include <memory>
#include <sstream>
using namespace ProjectExplorer;
using namespace Utils;
namespace ClangFormat {
static QObject *languageClientPlugin()
{
return ExtensionSystem::PluginManager::getObjectByName("LanguageClient");
}
class ClangFormatConfigWidget final : public TextEditor::CodeStyleEditorWidget
{
public:
ClangFormatConfigWidget(TextEditor::ICodeStylePreferences *codeStyle,
Project *project,
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 finish() final;
private:
bool eventFilter(QObject *object, QEvent *event) final;
@@ -64,28 +85,28 @@ private:
FilePath globalPath();
FilePath projectPath();
void createStyleFileIfNeeded(bool isGlobal);
void showOrHideWidgets();
void initChecksAndPreview();
void connectChecks();
void fillTable();
std::string readFile(const QString &path);
void saveChanges(QObject *sender);
void initPreview(TextEditor::ICodeStylePreferences *codeStyle);
void initEditor(TextEditor::ICodeStylePreferences *codeStyle);
void reopenClangFormatDocument();
void updatePreview();
void slotCodeStyleChanged(TextEditor::ICodeStylePreferences *currentPreferences);
ProjectExplorer::Project *m_project = nullptr;
QWidget *m_checksWidget = nullptr;
QScrollArea *m_checksScrollArea = nullptr;
QWidget *m_editorWidget = nullptr;
QScrollArea *m_editorScrollArea = nullptr;
TextEditor::SnippetEditorWidget *m_preview = nullptr;
Core::IEditor *m_editor = nullptr;
std::unique_ptr<ClangFormatFile> m_config;
clang::format::FormatStyle m_style;
Guard m_ignoreChanges;
QLabel *m_fallbackConfig;
QLabel *m_clangVersion;
QLabel *m_clangWarningText;
QLabel *m_clangWarningIcon;
QLabel *m_clangFileIsCorrectText;
QLabel *m_clangFileIsCorrectIcon;
ClangFormatIndenter *m_indenter;
};
bool ClangFormatConfigWidget::eventFilter(QObject *object, QEvent *event)
@@ -105,75 +126,32 @@ ClangFormatConfigWidget::ClangFormatConfigWidget(TextEditor::ICodeStylePreferenc
m_project = project;
m_config = std::make_unique<ClangFormatFile>(codeStyle->currentPreferences());
m_fallbackConfig = new QLabel(Tr::tr("Clang-Format Style"));
m_checksScrollArea = new QScrollArea();
m_checksWidget = new ClangFormatChecks();
createStyleFileIfNeeded(!m_project);
m_checksScrollArea->setWidget(m_checksWidget);
m_checksScrollArea->setWidgetResizable(true);
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);
initPreview(codeStyle);
initEditor(codeStyle);
using namespace Layouting;
Column {
m_fallbackConfig,
Row {m_clangWarningIcon, m_clangWarningText, st},
m_clangVersion,
Row { m_checksScrollArea, m_preview },
Row { m_editorScrollArea, m_preview },
Row {m_clangFileIsCorrectIcon, m_clangFileIsCorrectText, st}
}.attachTo(this);
connect(codeStyle, &TextEditor::ICodeStylePreferences::currentPreferencesChanged,
this, &ClangFormatConfigWidget::slotCodeStyleChanged);
connect(codeStyle, &TextEditor::ICodeStylePreferences::aboutToBeRemoved,
this, &ClangFormatFile::removeClangFormatFileForStylePreferences);
connect(codeStyle, &TextEditor::ICodeStylePreferences::aboutToBeCopied,
this, &ClangFormatFile::copyClangFormatFileBasedOnStylePreferences);
slotCodeStyleChanged(codeStyle->currentPreferences());
showOrHideWidgets();
fillTable();
reopenClangFormatDocument();
updatePreview();
connectChecks();
}
void ClangFormatConfigWidget::slotCodeStyleChanged(
@@ -183,35 +161,112 @@ void ClangFormatConfigWidget::slotCodeStyleChanged(
return;
m_config.reset(new ClangFormatFile(codeStyle));
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());
fillTable();
reopenClangFormatDocument();
updatePreview();
}
void ClangFormatConfigWidget::connectChecks()
void ClangFormatConfigWidget::initEditor(TextEditor::ICodeStylePreferences *codeStyle)
{
auto doSaveChanges = [this](QObject *sender) {
if (!m_ignoreChanges.isLocked())
saveChanges(sender);
};
m_editorScrollArea = new QScrollArea();
Core::EditorFactories factories = Core::IEditorFactory::preferredEditorTypes(
m_config->filePath());
Core::IEditorFactory *factory = factories.takeFirst();
m_editor = factory->createEditor();
for (QObject *child : m_checksWidget->children()) {
auto comboBox = qobject_cast<QComboBox *>(child);
if (comboBox != nullptr) {
connect(comboBox, &QComboBox::currentIndexChanged,
this, std::bind(doSaveChanges, comboBox));
comboBox->installEventFilter(this);
continue;
QString errorString;
m_editor->document()->open(&errorString, m_config->filePath(), m_config->filePath());
m_editor->widget()->adjustSize();
QMetaObject::invokeMethod(languageClientPlugin(),
"openDocument",
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);
if (button != nullptr)
connect(button, &QPushButton::clicked, this, std::bind(doSaveChanges, button));
m_clangFileIsCorrectText->setText(text);
QPalette paletteCorrect = m_clangFileIsCorrectText->palette();
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())
@@ -257,7 +312,7 @@ void ClangFormatConfigWidget::createStyleFileIfNeeded(bool isGlobal)
FilePath possibleProjectConfig = m_project->rootProjectDirectory()
/ Constants::SETTINGS_FILE_NAME;
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);
return;
}
@@ -267,21 +322,6 @@ void ClangFormatConfigWidget::createStyleFileIfNeeded(bool isGlobal)
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()
{
QTextCursor cursor(m_preview->document());
@@ -290,208 +330,51 @@ void ClangFormatConfigWidget::updatePreview()
m_preview->textDocument()->autoFormatOrIndent(cursor);
}
std::string ClangFormatConfigWidget::readFile(const QString &path)
{
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()
void ClangFormatConfigWidget::reopenClangFormatDocument()
{
GuardLocker locker(m_ignoreChanges);
const QString configText = QString::fromStdString(readFile(m_config->filePath().path()));
std::map<QString, QString> objectNameMap = getMapFromString(configText);
for (QObject *child : m_checksWidget->children()) {
if (!qobject_cast<QComboBox *>(child) && !qobject_cast<QLineEdit *>(child)
&& !qobject_cast<QPlainTextEdit *>(child)) {
continue;
QString errorString;
if (m_editor->document()->open(&errorString, m_config->filePath(), m_config->filePath())
== Core::IDocument::OpenResult::Success) {
QMetaObject::invokeMethod(languageClientPlugin(),
"openDocument",
Q_ARG(Core::IDocument *, m_editor->document()));
}
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()
{
if (!m_checksWidget->isVisible() && !m_checksWidget->isEnabled())
if (!m_editorWidget->isEnabled())
return;
m_style = m_config->style();
clang::format::FormatStyle currentSettingsStyle;
const bool success = parseConfigurationContent(m_editor->document()->contents().toStdString(),
currentSettingsStyle);
auto saveSettings = [this] {
QString errorString;
m_editor->document()->save(&errorString, m_config->filePath());
};
if (success) {
saveSettings();
return;
}
void ClangFormatConfigWidget::finish()
{
if (!m_checksWidget->isVisible() && !m_checksWidget->isEnabled())
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(

View File

@@ -2,7 +2,6 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "clangformatfile.h"
#include "clangformatsettings.h"
#include "clangformatutils.h"
#include <cppeditor/cppcodestylepreferences.h>
@@ -15,43 +14,34 @@
#include <utils/qtcassert.h>
#include <sstream>
using namespace ClangFormat;
ClangFormatFile::ClangFormatFile(const TextEditor::ICodeStylePreferences *preferences)
: m_filePath(filePathToCurrentSettings(preferences))
{
if (!m_filePath.exists()) {
if (m_filePath.exists())
return;
// create file and folder
m_filePath.parentDir().createDir();
std::fstream newStyleFile(m_filePath.path().toStdString(), std::fstream::out);
if (newStyleFile.is_open()) {
if (newStyleFile.is_open())
newStyleFile.close();
}
resetStyleToQtC(preferences);
if (preferences->displayName() == "GNU") { // For build-in GNU style
m_style = clang::format::getGNUStyle();
saveStyleToFile(m_style, m_filePath);
return;
}
if (!parseConfigurationFile(m_filePath, m_style))
resetStyleToQtC(preferences);
}
clang::format::FormatStyle ClangFormatFile::style() {
return m_style;
}
Utils::FilePath ClangFormatFile::filePath()
{
return m_filePath;
}
void ClangFormatFile::setStyle(clang::format::FormatStyle style)
{
m_style = style;
saveNewFormat();
}
bool ClangFormatFile::isReadOnly() const
{
return m_isReadOnly;
@@ -68,56 +58,6 @@ void ClangFormatFile::resetStyleToQtC(const TextEditor::ICodeStylePreferences *p
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)
{
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))
styleStr.erase(pos, 2);
styleStr.append("\n");
styleStr
.insert(0,
"# yaml-language-server: $schema=https://json.schemastore.org/clang-format.json\n");
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);
}

View File

@@ -24,20 +24,17 @@ public:
Utils::FilePath filePath();
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;
void setIsReadOnly(bool isReadOnly);
static void removeClangFormatFileForStylePreferences(
const TextEditor::ICodeStylePreferences *preferences);
static void copyClangFormatFileBasedOnStylePreferences(
const TextEditor::ICodeStylePreferences *current,
const TextEditor::ICodeStylePreferences *target);
private:
void saveNewFormat();
void saveNewFormat(QByteArray style);
void saveStyleToFile(clang::format::FormatStyle style, Utils::FilePath filePath);
private:

View File

@@ -417,13 +417,18 @@ Utils::FilePath filePathToCurrentSettings(const TextEditor::ICodeStylePreference
/ 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;
const std::error_code error
= parseConfiguration(filePath.fileContents().value_or(QByteArray()).toStdString(), &style);
const std::error_code error = parseConfiguration(fileContent, &style);
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

View File

@@ -48,6 +48,7 @@ clang::format::FormatStyle currentQtStyle(const TextEditor::ICodeStylePreference
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);
} // ClangFormat

View File

@@ -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)
{
const QList<BaseSettings *> prefilteredSettings

View File

@@ -76,6 +76,9 @@ public:
const LanguageServerProtocol::JsonRpcMessage &message);
static void showInspector();
static void openDocument(Core::IDocument *document);
static void closeDocument(Core::IDocument *document);
static void openEditor(Core::IEditor *editor);
signals:
void clientAdded(Client *client);

View File

@@ -12,6 +12,7 @@
#include <coreplugin/actionmanager/actionmanager.h>
#include <extensionsystem/iplugin.h>
#include <extensionsystem/pluginmanager.h>
#include <QAction>
#include <QMenu>
@@ -26,6 +27,7 @@ class LanguageClientPlugin final : public ExtensionSystem::IPlugin
public:
LanguageClientPlugin()
{
setObjectName("LanguageClient");
qRegisterMetaType<LanguageServerProtocol::JsonRpcMessage>();
}
@@ -34,6 +36,24 @@ private:
void extensionsInitialized() 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;
};
@@ -57,6 +77,8 @@ void LanguageClientPlugin::initialize()
inspectAction.setText(Tr::tr("Inspect Language Clients..."));
inspectAction.addToContainer(Core::Constants::M_TOOLS_DEBUG);
inspectAction.addOnTriggered(this, &LanguageClientManager::showInspector);
ExtensionSystem::PluginManager::addObject(this);
}
void LanguageClientPlugin::extensionsInitialized()
@@ -66,6 +88,7 @@ void LanguageClientPlugin::extensionsInitialized()
ExtensionSystem::IPlugin::ShutdownFlag LanguageClientPlugin::aboutToShutdown()
{
ExtensionSystem::PluginManager::removeObject(this);
LanguageClientManager::shutdown();
if (LanguageClientManager::isShutdownFinished())
return ExtensionSystem::IPlugin::SynchronousShutdown;

View File

@@ -165,6 +165,7 @@ void CodeStyleSelectorWidget::slotCopyClicked()
ICodeStylePreferences *copy = codeStylePool->cloneCodeStyle(currentPreferences);
if (copy) {
copy->setDisplayName(newName);
emit m_codeStyle->aboutToBeCopied(currentPreferences, copy);
m_codeStyle->setCurrentDelegate(copy);
}
}

View File

@@ -241,6 +241,8 @@ void ICodeStylePreferences::fromMap(const Store &map)
void ICodeStylePreferences::codeStyleRemoved(ICodeStylePreferences *preferences)
{
if (currentDelegate() == preferences) {
emit aboutToBeRemoved(preferences);
CodeStylePool *pool = delegatingPool();
QList<ICodeStylePreferences *> codeStyles = pool->codeStyles();
const int idx = codeStyles.indexOf(preferences);

View File

@@ -80,6 +80,9 @@ signals:
void currentDelegateChanged(TextEditor::ICodeStylePreferences *currentDelegate);
void currentPreferencesChanged(TextEditor::ICodeStylePreferences *currentPreferences);
void displayNameChanged(const QString &newName);
void aboutToBeRemoved(TextEditor::ICodeStylePreferences *preferences);
void aboutToBeCopied(TextEditor::ICodeStylePreferences *current,
TextEditor::ICodeStylePreferences *target);
private:
void codeStyleRemoved(ICodeStylePreferences *preferences);

View File

@@ -292,6 +292,8 @@ TextDocument *TextDocument::currentTextDocument()
TextDocument *TextDocument::textDocumentForFilePath(const Utils::FilePath &filePath)
{
if (filePath.isEmpty())
return nullptr;
return qobject_cast<TextDocument *>(DocumentModel::documentForFilePath(filePath));
}