Index: clang/docs/ClangFormatStyleOptions.rst =================================================================== --- clang/docs/ClangFormatStyleOptions.rst +++ clang/docs/ClangFormatStyleOptions.rst @@ -2817,22 +2817,51 @@ string1 = "foo"; string2 = "bar"; +**JavaScriptWrapImports** (``Boolean``) :versionbadge:`clang-format 3.9` + Whether to wrap JavaScript import/export statements. If ``false``, then + every import statement will be unwrapped to a single line. + If ``JavaScriptWrapImports`` is ``true``, then the behavior depends on the + value of ``ColumnWidth``: -**JavaScriptWrapImports** (``Boolean``) :versionbadge:`clang-format 3.9` - Whether to wrap JavaScript import/export statements. + * If ``ColumnWidth`` is 0 (no limit on the number of columns), then import + statements will keep the number of lines they start with. + + * If ``ColumnWidth`` is non-zero (there is a limit on the number of + columns), then import statements will be wrapped to an appropriate number + of lines, or unwrapped into a single line if there is room. .. code-block:: js - true: + // Original + import {VeryLongImport, AnotherLongImport, LongImportsAreAnnoying} from 'some/module.js' import { - VeryLongImportsAreAnnoying, - VeryLongImportsAreAnnoying, - VeryLongImportsAreAnnoying, - } from 'some/module.js' + Foo, + Bar, + Baz, + } from 'another/module.js'; + + JavaScriptWrapImports: false + import {VeryLongImport, AnotherLongImport, LongImportsAreAnnoying} from 'some/module.js'; + import {Foo, Bar, Baz} from 'another/module.js'; + + JavaScriptWrapImports: true + ColumnWidth: 0 + import {VeryLongImport, AnotherLongImport, LongImportsAreAnnoying} from 'some/module.js' + import { + Foo, + Bar, + Baz, + } from 'another/module.js'; - false: - import {VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying,} from "some/module.js" + JavaScriptWrapImports: true + ColumnWidth: 80 + import { + VeryLongImport, + AnotherLongImport, + LongImportsAreAnnoying, + } from 'some/module.js' + import {Foo, Bar, Baz} from 'another/module.js'; **KeepEmptyLinesAtTheStartOfBlocks** (``Boolean``) :versionbadge:`clang-format 3.7` If true, the empty line at the start of blocks is kept. Index: clang/lib/Format/ContinuationIndenter.cpp =================================================================== --- clang/lib/Format/ContinuationIndenter.cpp +++ clang/lib/Format/ContinuationIndenter.cpp @@ -325,12 +325,19 @@ if (Previous.is(tok::l_square) && Previous.is(TT_ObjCMethodExpr)) return false; + if (Style.isJavaScript() && State.Line->Type == LT_ImportStatement && + !Style.JavaScriptWrapImports) + return false; + return !State.Stack.back().NoLineBreak; } bool ContinuationIndenter::mustBreak(const LineState &State) { const FormatToken &Current = *State.NextToken; const FormatToken &Previous = *Current.Previous; + if (Style.isJavaScript() && State.Line->Type == LT_ImportStatement && + Style.ColumnLimit == 0) + return false; if (Style.BraceWrapping.BeforeLambdaBody && Current.CanBreakBefore && Current.is(TT_LambdaLBrace) && Previous.isNot(TT_LineComment)) { auto LambdaBodyLength = getLengthToMatchingParen(Current, State.Stack); Index: clang/unittests/Format/FormatTestJS.cpp =================================================================== --- clang/unittests/Format/FormatTestJS.cpp +++ clang/unittests/Format/FormatTestJS.cpp @@ -1943,10 +1943,12 @@ } TEST_F(FormatTestJS, ImportWrapping) { + FormatStyle Style = getGoogleJSStyleWithColumns(80); + Style.JavaScriptWrapImports = false; verifyFormat("import {VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying," " VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying" - "} from 'some/module.js';"); - FormatStyle Style = getGoogleJSStyleWithColumns(80); + "} from 'some/module.js';", + Style); Style.JavaScriptWrapImports = true; verifyFormat("import {\n" " VeryLongImportsAreAnnoying,\n" @@ -1964,8 +1966,28 @@ " A,\n" "} from 'some/module.js';", Style); + Style.ColumnLimit = 0; + Style.JavaScriptWrapImports = false; + verifyFormat("import {VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying," + " VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying" + "} from 'some/module.js';", + Style); + // Using the input_code/expected version of verifyFormat because we can't + // indiscriminately test::messUp on these tests. + Style.JavaScriptWrapImports = true; + verifyFormat("import {\n" + " A,\n" + " A,\n" + "} from 'some/module.js';\n" + "import {B, B} from 'other/module.js';", + "import {\n" + " A,\n" + " A,\n" + "} from 'some/module.js';\n" + "import {B, B} from 'other/module.js';", + Style); Style.ColumnLimit = 40; - // Using this version of verifyFormat because test::messUp hides the issue. + Style.JavaScriptWrapImports = true; verifyFormat("import {\n" " A,\n" "} from\n"