diff --git a/clang/docs/ClangFormat.rst b/clang/docs/ClangFormat.rst index b932007dd703..b9fa76aaafa9 100644 --- a/clang/docs/ClangFormat.rst +++ b/clang/docs/ClangFormat.rst @@ -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 =============== diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst new file mode 100644 index 000000000000..f7f2413f2e02 --- /dev/null +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -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 +`_ +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 + `_ + * ``Google`` + A style complying with `Google's C++ style guide + `_ + * ``Chromium`` + A style complying with `Chromium's style guide + `_ + * ``Mozilla`` + A style complying with `Mozilla's style guide + `_ + * ``WebKit`` + A style complying with `WebKit's style guide + `_ + +.. 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 `` instead of ``Foo``. + +**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 >`` instead of ``A>`` 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>`` instead of + ``A >``). + * ``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 +`_: + +.. 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(); + } + } + diff --git a/clang/docs/index.rst b/clang/docs/index.rst index 2b8d92e91d32..853fcc1ccb6b 100644 --- a/clang/docs/index.rst +++ b/clang/docs/index.rst @@ -53,6 +53,7 @@ Using Clang Tools ClangTools ClangCheck ClangFormat + ClangFormatStyleOptions Design Documents ================ diff --git a/clang/docs/tools/dump_format_style.py b/clang/docs/tools/dump_format_style.py new file mode 100644 index 000000000000..0c8ca6d610f1 --- /dev/null +++ b/clang/docs/tools/dump_format_style.py @@ -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'\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) +