Added documentation for clang-format style options.
Summary: The main contents is in the ClangFormatStyleOptions.rst, which can be updated from the Format.h by the dump_format_style.py script. Reviewers: djasper, klimek Reviewed By: klimek CC: cfe-commits Differential Revision: http://llvm-reviews.chandlerc.com/D1597 llvm-svn: 189946
This commit is contained in:
parent
fd9a9415f5
commit
d278e0eee3
|
@ -70,6 +70,20 @@ to format C/C++/Obj-C code.
|
|||
-version - Display the version of this program
|
||||
|
||||
|
||||
When the desired code formatting style is different from the available options,
|
||||
the style can be customized using the ``-style="{key: value, ...}"`` option or
|
||||
by putting your style configuration to the ``.clang-format`` file in your
|
||||
project's directory and using ``clang-format -style=file``.
|
||||
|
||||
An easy way to create the ``.clang-format`` file is:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
clang-format -style=llvm -dump-config > .clang-format
|
||||
|
||||
Available style options are described in :doc:`ClangFormatStyleOptions`.
|
||||
|
||||
|
||||
Vim Integration
|
||||
===============
|
||||
|
||||
|
|
|
@ -0,0 +1,375 @@
|
|||
==========================
|
||||
Clang-Format Style Options
|
||||
==========================
|
||||
|
||||
:doc:`ClangFormatStyleOptions` describes configurable formatting style options
|
||||
supported by :doc:`LibFormat` and :doc:`ClangFormat`.
|
||||
|
||||
When using :program:`clang-format` command line utility or
|
||||
``clang::format::reformat(...)`` functions from code, one can either use one of
|
||||
the predefined styles (LLVM, Google, Chromium, Mozilla, WebKit) or create a
|
||||
custom style by configuring specific style options.
|
||||
|
||||
|
||||
Configuring Style with clang-format
|
||||
===================================
|
||||
|
||||
:program:`clang-format` supports two ways to provide custom style options:
|
||||
directly specify style configuration in the ``-style=`` command line option or
|
||||
use ``-style=file`` and put style configuration in the ``.clang-format`` file
|
||||
in the project directory.
|
||||
|
||||
When using ``-style=file``, :program:`clang-format` for each input file will
|
||||
try to find the ``.clang-format`` file located in the closest parent directory
|
||||
of the input file. When the standard input is used, the search is started from
|
||||
the current directory.
|
||||
|
||||
The ``.clang-format`` file uses YAML format:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
key1: value1
|
||||
key2: value2
|
||||
# A comment.
|
||||
...
|
||||
|
||||
An easy way to get a valid ``.clang-format`` file containing all configuration
|
||||
options of a certain predefined style is:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
clang-format -style=llvm -dump-config > .clang-format
|
||||
|
||||
When specifying configuration in the ``-style=`` option, the same configuration
|
||||
is applied for all input files. The format of the configuration is:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
-style='{key1: value1, key2: value2, ...}'
|
||||
|
||||
|
||||
Configuring Style in Code
|
||||
=========================
|
||||
|
||||
When using ``clang::format::reformat(...)`` functions, the format is specified
|
||||
by supplying the `clang::format::FormatStyle
|
||||
<http://clang.llvm.org/doxygen/structclang_1_1format_1_1FormatStyle.html>`_
|
||||
structure.
|
||||
|
||||
|
||||
Configurable Format Style Options
|
||||
=================================
|
||||
|
||||
This section lists the supported style options. Value type is specified for
|
||||
each option. For enumeration types possible values are specified both as a C++
|
||||
enumeration member (with a prefix, e.g. LS_Auto), and as a value usable in the
|
||||
configuration (without a prefix).
|
||||
|
||||
|
||||
**BasedOnStyle** (``string``)
|
||||
The style used for all options not specifically set in the configuration.
|
||||
|
||||
This option is supported only in the :program:`clang-format` configuration
|
||||
(both within ``-style='{...}'`` and the ``.clang-format`` file).
|
||||
|
||||
Possible values:
|
||||
|
||||
* ``LLVM``
|
||||
A style complying with the `LLVM coding standards
|
||||
<http://llvm.org/docs/CodingStandards.html>`_
|
||||
* ``Google``
|
||||
A style complying with `Google's C++ style guide
|
||||
<http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml>`_
|
||||
* ``Chromium``
|
||||
A style complying with `Chromium's style guide
|
||||
<http://www.chromium.org/developers/coding-style>`_
|
||||
* ``Mozilla``
|
||||
A style complying with `Mozilla's style guide
|
||||
<https://developer.mozilla.org/en-US/docs/Developer_Guide/Coding_Style>`_
|
||||
* ``WebKit``
|
||||
A style complying with `WebKit's style guide
|
||||
<http://www.webkit.org/coding/coding-style.html>`_
|
||||
|
||||
.. START_FORMAT_STYLE_OPTIONS
|
||||
|
||||
**AccessModifierOffset** (``int``)
|
||||
The extra indent or outdent of access modifiers, e.g. ``public:``.
|
||||
|
||||
**AlignEscapedNewlinesLeft** (``bool``)
|
||||
If ``true``, aligns escaped newlines as far left as possible.
|
||||
Otherwise puts them into the right-most column.
|
||||
|
||||
**AlignTrailingComments** (``bool``)
|
||||
If ``true``, aligns trailing comments.
|
||||
|
||||
**AllowAllParametersOfDeclarationOnNextLine** (``bool``)
|
||||
Allow putting all parameters of a function declaration onto
|
||||
the next line even if ``BinPackParameters`` is ``false``.
|
||||
|
||||
**AllowShortIfStatementsOnASingleLine** (``bool``)
|
||||
If ``true``, ``if (a) return;`` can be put on a single
|
||||
line.
|
||||
|
||||
**AllowShortLoopsOnASingleLine** (``bool``)
|
||||
If ``true``, ``while (true) continue;`` can be put on a
|
||||
single line.
|
||||
|
||||
**AlwaysBreakBeforeMultilineStrings** (``bool``)
|
||||
If ``true``, always break before multiline string literals.
|
||||
|
||||
**AlwaysBreakTemplateDeclarations** (``bool``)
|
||||
If ``true``, always break after the ``template<...>`` of a
|
||||
template declaration.
|
||||
|
||||
**BinPackParameters** (``bool``)
|
||||
If ``false``, a function call's or function definition's parameters
|
||||
will either all be on the same line or will have one line each.
|
||||
|
||||
**BreakBeforeBinaryOperators** (``bool``)
|
||||
If ``true``, binary operators will be placed after line breaks.
|
||||
|
||||
**BreakBeforeBraces** (``BraceBreakingStyle``)
|
||||
The brace breaking style to use.
|
||||
|
||||
Possible values:
|
||||
|
||||
* ``BS_Attach`` (in configuration: ``Attach``)
|
||||
Always attach braces to surrounding context.
|
||||
* ``BS_Linux`` (in configuration: ``Linux``)
|
||||
Like ``Attach``, but break before braces on function, namespace and
|
||||
class definitions.
|
||||
* ``BS_Stroustrup`` (in configuration: ``Stroustrup``)
|
||||
Like ``Attach``, but break before function definitions.
|
||||
* ``BS_Allman`` (in configuration: ``Allman``)
|
||||
Always break before braces.
|
||||
|
||||
|
||||
**BreakConstructorInitializersBeforeComma** (``bool``)
|
||||
Always break constructor initializers before commas and align
|
||||
the commas with the colon.
|
||||
|
||||
**ColumnLimit** (``unsigned``)
|
||||
The column limit.
|
||||
|
||||
A column limit of ``0`` means that there is no column limit. In this case,
|
||||
clang-format will respect the input's line breaking decisions within
|
||||
statements.
|
||||
|
||||
**ConstructorInitializerAllOnOneLineOrOnePerLine** (``bool``)
|
||||
If the constructor initializers don't fit on a line, put each
|
||||
initializer on its own line.
|
||||
|
||||
**ConstructorInitializerIndentWidth** (``unsigned``)
|
||||
The number of characters to use for indentation of constructor
|
||||
initializer lists.
|
||||
|
||||
**Cpp11BracedListStyle** (``bool``)
|
||||
If ``true``, format braced lists as best suited for C++11 braced
|
||||
lists.
|
||||
|
||||
Important differences:
|
||||
- No spaces inside the braced list.
|
||||
- No line break before the closing brace.
|
||||
- Indentation with the continuation indent, not with the block indent.
|
||||
|
||||
Fundamentally, C++11 braced lists are formatted exactly like function
|
||||
calls would be formatted in their place. If the braced list follows a name
|
||||
(e.g. a type or variable name), clang-format formats as if the ``{}`` were
|
||||
the parentheses of a function call with that name. If there is no name,
|
||||
a zero-length name is assumed.
|
||||
|
||||
**DerivePointerBinding** (``bool``)
|
||||
If ``true``, analyze the formatted file for the most common binding.
|
||||
|
||||
**ExperimentalAutoDetectBinPacking** (``bool``)
|
||||
If ``true``, clang-format detects whether function calls and
|
||||
definitions are formatted with one parameter per line.
|
||||
|
||||
Each call can be bin-packed, one-per-line or inconclusive. If it is
|
||||
inconclusive, e.g. completely on one line, but a decision needs to be
|
||||
made, clang-format analyzes whether there are other bin-packed cases in
|
||||
the input file and act accordingly.
|
||||
|
||||
NOTE: This is an experimental flag, that might go away or be renamed. Do
|
||||
not use this in config files, etc. Use at your own risk.
|
||||
|
||||
**IndentCaseLabels** (``bool``)
|
||||
Indent case labels one level from the switch statement.
|
||||
|
||||
When ``false``, use the same indentation level as for the switch statement.
|
||||
Switch statement body is always indented one level more than case labels.
|
||||
|
||||
**IndentFunctionDeclarationAfterType** (``bool``)
|
||||
If ``true``, indent when breaking function declarations which
|
||||
are not also definitions after the type.
|
||||
|
||||
**IndentWidth** (``unsigned``)
|
||||
The number of characters to use for indentation.
|
||||
|
||||
**MaxEmptyLinesToKeep** (``unsigned``)
|
||||
The maximum number of consecutive empty lines to keep.
|
||||
|
||||
**NamespaceIndentation** (``NamespaceIndentationKind``)
|
||||
The indentation used for namespaces.
|
||||
|
||||
Possible values:
|
||||
|
||||
* ``NI_None`` (in configuration: ``None``)
|
||||
Don't indent in namespaces.
|
||||
* ``NI_Inner`` (in configuration: ``Inner``)
|
||||
Indent only in inner namespaces (nested in other namespaces).
|
||||
* ``NI_All`` (in configuration: ``All``)
|
||||
Indent in all namespaces.
|
||||
|
||||
|
||||
**ObjCSpaceBeforeProtocolList** (``bool``)
|
||||
Add a space in front of an Objective-C protocol list, i.e. use
|
||||
``Foo <Protocol>`` instead of ``Foo<Protocol>``.
|
||||
|
||||
**PenaltyBreakComment** (``unsigned``)
|
||||
The penalty for each line break introduced inside a comment.
|
||||
|
||||
**PenaltyBreakFirstLessLess** (``unsigned``)
|
||||
The penalty for breaking before the first ``<<``.
|
||||
|
||||
**PenaltyBreakString** (``unsigned``)
|
||||
The penalty for each line break introduced inside a string literal.
|
||||
|
||||
**PenaltyExcessCharacter** (``unsigned``)
|
||||
The penalty for each character outside of the column limit.
|
||||
|
||||
**PenaltyReturnTypeOnItsOwnLine** (``unsigned``)
|
||||
Penalty for putting the return type of a function onto its own
|
||||
line.
|
||||
|
||||
**PointerBindsToType** (``bool``)
|
||||
Set whether & and * bind to the type as opposed to the variable.
|
||||
|
||||
**SpaceAfterControlStatementKeyword** (``bool``)
|
||||
If ``true``, spaces will be inserted between 'for'/'if'/'while'/...
|
||||
and '('.
|
||||
|
||||
**SpaceInEmptyParentheses** (``bool``)
|
||||
If ``false``, spaces may be inserted into '()'.
|
||||
|
||||
**SpacesBeforeTrailingComments** (``unsigned``)
|
||||
The number of spaces to before trailing line comments.
|
||||
|
||||
**SpacesInCStyleCastParentheses** (``bool``)
|
||||
If ``false``, spaces may be inserted into C style casts.
|
||||
|
||||
**SpacesInParentheses** (``bool``)
|
||||
If ``true``, spaces will be inserted after every '(' and before
|
||||
every ')'.
|
||||
|
||||
**Standard** (``LanguageStandard``)
|
||||
Format compatible with this standard, e.g. use
|
||||
``A<A<int> >`` instead of ``A<A<int>>`` for LS_Cpp03.
|
||||
|
||||
Possible values:
|
||||
|
||||
* ``LS_Cpp03`` (in configuration: ``Cpp03``)
|
||||
Use C++03-compatible syntax.
|
||||
* ``LS_Cpp11`` (in configuration: ``Cpp11``)
|
||||
Use features of C++11 (e.g. ``A<A<int>>`` instead of
|
||||
``A<A<int> >``).
|
||||
* ``LS_Auto`` (in configuration: ``Auto``)
|
||||
Automatic detection based on the input.
|
||||
|
||||
|
||||
**UseTab** (``bool``)
|
||||
If ``true``, ``IndentWidth`` consecutive spaces will be replaced
|
||||
with tab characters.
|
||||
|
||||
.. END_FORMAT_STYLE_OPTIONS
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
A style similar to the `Linux Kernel style
|
||||
<https://www.kernel.org/doc/Documentation/CodingStyle>`_:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
BasedOnStyle: LLVM
|
||||
IndentWidth: 8
|
||||
UseTab: true
|
||||
BreakBeforeBraces: Linux
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
IndentCaseLabels: false
|
||||
|
||||
The result is (imagine that tabs are used for indentation here):
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
void test()
|
||||
{
|
||||
switch (x) {
|
||||
case 0:
|
||||
case 1:
|
||||
do_something();
|
||||
break;
|
||||
case 2:
|
||||
do_something_else();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (condition)
|
||||
do_something_completely_different();
|
||||
|
||||
if (x == y) {
|
||||
q();
|
||||
} else if (x > y) {
|
||||
w();
|
||||
} else {
|
||||
r();
|
||||
}
|
||||
}
|
||||
|
||||
A style similar to the default Visual Studio formatting style:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
UseTab: false
|
||||
IndentWidth: 4
|
||||
BreakBeforeBraces: Allman
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
IndentCaseLabels: false
|
||||
ColumnLimit: 0
|
||||
|
||||
The result is:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
void test()
|
||||
{
|
||||
switch (suffix)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
do_something();
|
||||
break;
|
||||
case 2:
|
||||
do_something_else();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (condition)
|
||||
do_somthing_completely_different();
|
||||
|
||||
if (x == y)
|
||||
{
|
||||
q();
|
||||
}
|
||||
else if (x > y)
|
||||
{
|
||||
w();
|
||||
}
|
||||
else
|
||||
{
|
||||
r();
|
||||
}
|
||||
}
|
||||
|
|
@ -53,6 +53,7 @@ Using Clang Tools
|
|||
ClangTools
|
||||
ClangCheck
|
||||
ClangFormat
|
||||
ClangFormatStyleOptions
|
||||
|
||||
Design Documents
|
||||
================
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
#!/usr/bin/env python
|
||||
# A tool to parse the FormatStyle struct from Format.h and update the
|
||||
# documentation in ../ClangFormatStyleOptions.rst automatically.
|
||||
# Run from the directory in which this file is located to update the docs.
|
||||
|
||||
import collections
|
||||
import re
|
||||
import urllib2
|
||||
|
||||
FORMAT_STYLE_FILE = '../../include/clang/Format/Format.h'
|
||||
DOC_FILE = '../ClangFormatStyleOptions.rst'
|
||||
|
||||
|
||||
def substitute(text, tag, contents):
|
||||
replacement = '\n.. START_%s\n\n%s\n\n.. END_%s\n' % (tag, contents, tag)
|
||||
pattern = r'\n\.\. START_%s\n.*\n\.\. END_%s\n' % (tag, tag)
|
||||
return re.sub(pattern, '%s', text, flags=re.S) % replacement
|
||||
|
||||
def doxygen2rst(text):
|
||||
text = re.sub(r'<tt>\s*(.*?)\s*<\/tt>', r'``\1``', text)
|
||||
text = re.sub(r'\\c ([^ ,;\.]+)', r'``\1``', text)
|
||||
text = re.sub(r'\\\w+ ', '', text)
|
||||
return text
|
||||
|
||||
def indent(text, columns):
|
||||
indent = ' ' * columns
|
||||
s = re.sub(r'\n([^\n])', '\n' + indent + '\\1', text, flags=re.S)
|
||||
if s.startswith('\n'):
|
||||
return s
|
||||
return indent + s
|
||||
|
||||
class Option:
|
||||
def __init__(self, name, type, comment):
|
||||
self.name = name
|
||||
self.type = type
|
||||
self.comment = comment.strip()
|
||||
self.enum = None
|
||||
|
||||
def __str__(self):
|
||||
s = '**%s** (``%s``)\n%s' % (self.name, self.type,
|
||||
doxygen2rst(indent(self.comment, 2)))
|
||||
if self.enum:
|
||||
s += indent('\n\nPossible values:\n\n%s\n' % self.enum, 2)
|
||||
return s
|
||||
|
||||
class Enum:
|
||||
def __init__(self, name, comment):
|
||||
self.name = name
|
||||
self.comment = comment.strip()
|
||||
self.values = []
|
||||
|
||||
def __str__(self):
|
||||
return '\n'.join(map(str, self.values))
|
||||
|
||||
class EnumValue:
|
||||
def __init__(self, name, comment):
|
||||
self.name = name
|
||||
self.comment = comment.strip()
|
||||
|
||||
def __str__(self):
|
||||
return '* ``%s`` (in configuration: ``%s``)\n%s' % (
|
||||
self.name,
|
||||
re.sub('.*_', '', self.name),
|
||||
doxygen2rst(indent(self.comment, 2)))
|
||||
|
||||
def clean_comment_line(line):
|
||||
return line[3:].strip() + '\n'
|
||||
|
||||
def read_options(header):
|
||||
class State:
|
||||
BeforeStruct, Finished, InStruct, InFieldComment, InEnum, \
|
||||
InEnumMemberComment = range(6)
|
||||
state = State.BeforeStruct
|
||||
|
||||
options = []
|
||||
enums = {}
|
||||
comment = ''
|
||||
enum = None
|
||||
|
||||
for line in header:
|
||||
line = line.strip()
|
||||
if state == State.BeforeStruct:
|
||||
if line == 'struct FormatStyle {':
|
||||
state = State.InStruct
|
||||
elif state == State.InStruct:
|
||||
if line.startswith('///'):
|
||||
state = State.InFieldComment
|
||||
comment = clean_comment_line(line)
|
||||
elif line == '};':
|
||||
state = State.Finished
|
||||
break
|
||||
elif state == State.InFieldComment:
|
||||
if line.startswith('///'):
|
||||
comment += clean_comment_line(line)
|
||||
elif line.startswith('enum'):
|
||||
state = State.InEnum
|
||||
name = re.sub(r'enum\s+(\w+)\s*\{', '\\1', line)
|
||||
enum = Enum(name, comment)
|
||||
elif line.endswith(';'):
|
||||
state = State.InStruct
|
||||
field_type, field_name = re.match(r'(\w+)\s+(\w+);', line).groups()
|
||||
option = Option(str(field_name), str(field_type), comment)
|
||||
options.append(option)
|
||||
else:
|
||||
raise Exception('Invalid format, expected comment, field or enum')
|
||||
elif state == State.InEnum:
|
||||
if line.startswith('///'):
|
||||
state = State.InEnumMemberComment
|
||||
comment = clean_comment_line(line)
|
||||
elif line == '};':
|
||||
state = State.InStruct
|
||||
enums[enum.name] = enum
|
||||
else:
|
||||
raise Exception('Invalid format, expected enum field comment or };')
|
||||
elif state == State.InEnumMemberComment:
|
||||
if line.startswith('///'):
|
||||
comment += clean_comment_line(line)
|
||||
else:
|
||||
state = State.InEnum
|
||||
enum.values.append(EnumValue(line.replace(',', ''), comment))
|
||||
if state != State.Finished:
|
||||
raise Exception('Not finished by the end of file')
|
||||
|
||||
for option in options:
|
||||
if not option.type in ['bool', 'unsigned', 'int']:
|
||||
if enums.has_key(option.type):
|
||||
option.enum = enums[option.type]
|
||||
else:
|
||||
raise Exception('Unknown type: %s' % option.type)
|
||||
return options
|
||||
|
||||
options = read_options(open(FORMAT_STYLE_FILE))
|
||||
|
||||
options = sorted(options, key=lambda x: x.name)
|
||||
options_text = '\n\n'.join(map(str, options))
|
||||
|
||||
contents = open(DOC_FILE).read()
|
||||
|
||||
contents = substitute(contents, 'FORMAT_STYLE_OPTIONS', options_text)
|
||||
|
||||
with open(DOC_FILE, 'w') as output:
|
||||
output.write(contents)
|
||||
|
Loading…
Reference in New Issue