[clang] c6d5efb - clang-format: [JS] sort import aliases.

Martin Probst via cfe-commits cfe-commits at lists.llvm.org
Thu Jan 27 07:17:01 PST 2022


Author: Martin Probst
Date: 2022-01-27T16:16:37+01:00
New Revision: c6d5efb5d98093c4bd7578b2ea52c9032d20dea3

URL: https://github.com/llvm/llvm-project/commit/c6d5efb5d98093c4bd7578b2ea52c9032d20dea3
DIFF: https://github.com/llvm/llvm-project/commit/c6d5efb5d98093c4bd7578b2ea52c9032d20dea3.diff

LOG: clang-format: [JS] sort import aliases.

Users can define aliases for long symbols using import aliases:

    import X = A.B.C;

Previously, these were unhandled and would terminate import sorting.
With this change, aliases sort as their own group, coming last after all
other imports.

Aliases are not sorted within their group, as they may reference each
other, so order is significant.

Revision URI: https://reviews.llvm.org/D118361

Added: 
    

Modified: 
    clang/lib/Format/SortJavaScriptImports.cpp
    clang/unittests/Format/SortImportsTestJS.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Format/SortJavaScriptImports.cpp b/clang/lib/Format/SortJavaScriptImports.cpp
index 37e79bb15b58..e4107525a7ff 100644
--- a/clang/lib/Format/SortJavaScriptImports.cpp
+++ b/clang/lib/Format/SortJavaScriptImports.cpp
@@ -78,6 +78,7 @@ struct JsModuleReference {
     ABSOLUTE,        // from 'something'
     RELATIVE_PARENT, // from '../*'
     RELATIVE,        // from './*'
+    ALIAS,           // import X = A.B;
   };
   ReferenceCategory Category = ReferenceCategory::SIDE_EFFECT;
   // The URL imported, e.g. `import .. from 'url';`. Empty for `export {a, b};`.
@@ -105,10 +106,12 @@ bool operator<(const JsModuleReference &LHS, const JsModuleReference &RHS) {
     return LHS.IsExport < RHS.IsExport;
   if (LHS.Category != RHS.Category)
     return LHS.Category < RHS.Category;
-  if (LHS.Category == JsModuleReference::ReferenceCategory::SIDE_EFFECT)
-    // Side effect imports might be ordering sensitive. Consider them equal so
-    // that they maintain their relative order in the stable sort below.
-    // This retains transitivity because LHS.Category == RHS.Category here.
+  if (LHS.Category == JsModuleReference::ReferenceCategory::SIDE_EFFECT ||
+      LHS.Category == JsModuleReference::ReferenceCategory::ALIAS)
+    // Side effect imports and aliases might be ordering sensitive. Consider
+    // them equal so that they maintain their relative order in the stable sort
+    // below. This retains transitivity because LHS.Category == RHS.Category
+    // here.
     return false;
   // Empty URLs sort *last* (for export {...};).
   if (LHS.URL.empty() != RHS.URL.empty())
@@ -398,6 +401,8 @@ class JavaScriptImportSorter : public TokenAnalyzer {
       JsModuleReference Reference;
       Reference.FormattingOff = FormattingOff;
       Reference.Range.setBegin(Start);
+      // References w/o a URL, e.g. export {A}, groups with RELATIVE.
+      Reference.Category = JsModuleReference::ReferenceCategory::RELATIVE;
       if (!parseModuleReference(Keywords, Reference)) {
         if (!FirstNonImportLine)
           FirstNonImportLine = Line; // if no comment before.
@@ -463,9 +468,6 @@ class JavaScriptImportSorter : public TokenAnalyzer {
         Reference.Category = JsModuleReference::ReferenceCategory::RELATIVE;
       else
         Reference.Category = JsModuleReference::ReferenceCategory::ABSOLUTE;
-    } else {
-      // w/o URL groups with "empty".
-      Reference.Category = JsModuleReference::ReferenceCategory::RELATIVE;
     }
     return true;
   }
@@ -501,6 +503,21 @@ class JavaScriptImportSorter : public TokenAnalyzer {
       nextToken();
       if (Current->is(Keywords.kw_from))
         return true;
+      // import X = A.B.C;
+      if (Current->is(tok::equal)) {
+        Reference.Category = JsModuleReference::ReferenceCategory::ALIAS;
+        nextToken();
+        while (Current->is(tok::identifier)) {
+          nextToken();
+          if (Current->is(tok::semi)) {
+            nextToken();
+            return true;
+          }
+          if (!Current->is(tok::period))
+            return false;
+          nextToken();
+        }
+      }
       if (Current->isNot(tok::comma))
         return false;
       nextToken(); // eat comma.

diff  --git a/clang/unittests/Format/SortImportsTestJS.cpp b/clang/unittests/Format/SortImportsTestJS.cpp
index 6fe8bba53549..1c7e50863036 100644
--- a/clang/unittests/Format/SortImportsTestJS.cpp
+++ b/clang/unittests/Format/SortImportsTestJS.cpp
@@ -446,6 +446,25 @@ TEST_F(SortImportsTestJS, RespectsClangFormatOffInNamedImports) {
              "const x =   1;");
 }
 
+TEST_F(SortImportsTestJS, ImportEqAliases) {
+  verifySort("import {B} from 'bar';\n"
+             "import {A} from 'foo';\n"
+             "\n"
+             "import Z = A.C;\n"
+             "import Y = B.C.Z;\n"
+             "\n"
+             "export {Z};\n"
+             "\n"
+             "console.log(Z);\n",
+             "import {A} from 'foo';\n"
+             "import Z = A.C;\n"
+             "export {Z};\n"
+             "import {B} from 'bar';\n"
+             "import Y = B.C.Z;\n"
+             "\n"
+             "console.log(Z);\n");
+}
+
 } // end namespace
 } // end namespace format
 } // end namespace clang


        


More information about the cfe-commits mailing list