andmis updated this revision to Diff 397579.
andmis added a comment.

- Move source code for option documentation to `Format.h`, from which the RST 
is autogenerated.
- Clean up tests in response to review feedback.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D116638/new/

https://reviews.llvm.org/D116638

Files:
  clang/docs/ClangFormatStyleOptions.rst
  clang/include/clang/Format/Format.h
  clang/lib/Format/ContinuationIndenter.cpp
  clang/unittests/Format/FormatTestJS.cpp

Index: clang/unittests/Format/FormatTestJS.cpp
===================================================================
--- clang/unittests/Format/FormatTestJS.cpp
+++ clang/unittests/Format/FormatTestJS.cpp
@@ -1946,6 +1946,7 @@
   verifyFormat("import {VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying,"
                " VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying"
                "} from 'some/module.js';");
+
   FormatStyle Style = getGoogleJSStyleWithColumns(80);
   Style.JavaScriptWrapImports = true;
   verifyFormat("import {\n"
@@ -1954,18 +1955,76 @@
                "  VeryLongImportsAreAnnoying,\n"
                "} from 'some/module.js';",
                Style);
+  verifyFormat("import {A, B} from 'some/module.js';", Style);
+  Style.JavaScriptWrapImports = false;
+  verifyFormat("import {VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying,"
+               " VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying"
+               "} from 'some/module.js';",
+               Style);
+  verifyFormat("import {A, B} from 'some/module.js';", Style);
+
+  // For ColumnLimit: 0 tests, we use the code/expected_output form of
+  // verifyFormat because the output format depends on the input format, so we
+  // can't let test::messUp modify the input indiscriminately.
+  Style.ColumnLimit = 0;
+  Style.JavaScriptWrapImports = true;
+  verifyFormat("import {\n"
+               "  VeryLongImportsAreAnnoying,\n"
+               "  VeryLongImportsAreAnnoying,\n"
+               "  VeryLongImportsAreAnnoying,\n"
+               "  VeryLongImportsAreAnnoying,\n"
+               "} from 'some/module.js';",
+               "import {\n"
+               "  VeryLongImportsAreAnnoying,\n"
+               "  VeryLongImportsAreAnnoying,\n"
+               "  VeryLongImportsAreAnnoying,\n"
+               "  VeryLongImportsAreAnnoying,\n"
+               "} from 'some/module.js';",
+               Style);
+  verifyFormat("import {VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying,"
+               " VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying"
+               "} from 'some/module.js';",
+               "import {VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying,"
+               " VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying"
+               "} from 'some/module.js';",
+               Style);
   verifyFormat("import {\n"
                "  A,\n"
+               "  B\n"
+               "} from 'some/module.js';",
+               "import {\n"
                "  A,\n"
+               "  B\n"
                "} from 'some/module.js';",
                Style);
-  verifyFormat("export {\n"
-               "  A,\n"
+  verifyFormat("import {A, B} from 'some/module.js';",
+               "import {A, B} from 'some/module.js';",
+               Style);
+  Style.JavaScriptWrapImports = false;
+  verifyFormat("import {VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying,"
+               " VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying"
+               "} from 'some/module.js';",
+               "import {\n"
+               "  VeryLongImportsAreAnnoying,\n"
+               "  VeryLongImportsAreAnnoying,\n"
+               "  VeryLongImportsAreAnnoying,\n"
+               "  VeryLongImportsAreAnnoying\n"
+               "} from 'some/module.js';",
+               Style);
+  verifyFormat("import {A, B} from 'some/module.js';",
+               "import {\n"
                "  A,\n"
+               "  B\n"
                "} from 'some/module.js';",
                Style);
+  verifyFormat("import {A, B} from 'some/module.js';",
+               "import {A, B} from 'some/module.js';",
+               Style);
+
+  // Here we use the code/expected_output form of verifyFormat because
+  // test::messUp would mess up the case being tested.
   Style.ColumnLimit = 40;
-  // Using this version of verifyFormat because test::messUp hides the issue.
+  Style.JavaScriptWrapImports = true;
   verifyFormat("import {\n"
                "  A,\n"
                "} from\n"
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/include/clang/Format/Format.h
===================================================================
--- clang/include/clang/Format/Format.h
+++ clang/include/clang/Format/Format.h
@@ -2610,17 +2610,52 @@
   JavaScriptQuoteStyle JavaScriptQuotes;
 
   // clang-format off
-  /// Whether to wrap JavaScript import/export statements.
+  /// 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``:
+  ///
+  /// * 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{.js}
-  ///    true:
+  ///    // Before running clang-format
+  ///    import {VeryLongImport, AnotherLongImport, LongImportsAreAnnoying} from 'some/module.js';
+  ///    import {
+  ///        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 {
-  ///        VeryLongImportsAreAnnoying,
-  ///        VeryLongImportsAreAnnoying,
-  ///        VeryLongImportsAreAnnoying,
-  ///    } from 'some/module.js'
+  ///        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';
   /// \endcode
   /// \version 3.9
   bool JavaScriptWrapImports;
Index: clang/docs/ClangFormatStyleOptions.rst
===================================================================
--- clang/docs/ClangFormatStyleOptions.rst
+++ clang/docs/ClangFormatStyleOptions.rst
@@ -2820,19 +2820,54 @@
 
 
 **JavaScriptWrapImports** (``Boolean``) :versionbadge:`clang-format 3.9`
-  Whether to wrap JavaScript import/export statements.
+  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``:
+
+  * 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:
+     // Before running clang-format
+     import {VeryLongImport, AnotherLongImport, LongImportsAreAnnoying} from 'some/module.js';
+     import {
+         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 {
-         VeryLongImportsAreAnnoying,
-         VeryLongImportsAreAnnoying,
-         VeryLongImportsAreAnnoying,
-     } from 'some/module.js'
+         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.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to