[clang] 4d195f1 - review comments
Martin Probst via cfe-commits
cfe-commits at lists.llvm.org
Wed Apr 14 08:20:34 PDT 2021
Author: Martin Probst
Date: 2021-04-14T17:20:08+02:00
New Revision: 4d195f1b4dd6e3978776d69f49840439933a2543
URL: https://github.com/llvm/llvm-project/commit/4d195f1b4dd6e3978776d69f49840439933a2543
DIFF: https://github.com/llvm/llvm-project/commit/4d195f1b4dd6e3978776d69f49840439933a2543.diff
LOG: review comments
track symbol merge status in references to avoid excesive rewrites
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 c1cf3de15325..fdc2408ec1ec 100644
--- a/clang/lib/Format/SortJavaScriptImports.cpp
+++ b/clang/lib/Format/SortJavaScriptImports.cpp
@@ -87,6 +87,9 @@ struct JsModuleReference {
StringRef DefaultImport;
// Symbols from `import {SymbolA, SymbolB, ...} from ...;`.
SmallVector<JsImportedSymbol, 1> Symbols;
+ // Whether some symbols were merged into this one. Controls if the module
+ // reference needs re-formatting.
+ bool SymbolsMerged;
// The source location just after { and just before } in the import.
// Extracted eagerly to allow modification of Symbols later on.
SourceLocation SymbolsStart, SymbolsEnd;
@@ -151,40 +154,7 @@ class JavaScriptImportSorter : public TokenAnalyzer {
});
bool ReferencesInOrder = llvm::is_sorted(Indices);
- // Merge module references:
- // After sorting, find all references that import named symbols from the
- // same URL and merge their names. E.g.
- // import {X} from 'a';
- // import {Y} from 'a';
- // should be rewritten to:
- // import {X, Y} from 'a';
- // Note: this removes merged imports from Indices, but not from References.
- // The loop below iterates Indices, so things work out.
- JsModuleReference *PreviousReference = &References[Indices[0]];
- auto *it = std::next(Indices.begin());
- bool ImportsMerged = false;
- while (it != std::end(Indices)) {
- JsModuleReference *Reference = &References[*it];
- // Skip:
- // import 'foo';
- // import * as foo from 'foo'; on either previous or this.
- // import Default from 'foo'; on either previous or this.
- // mismatching
- if (Reference->Category == JsModuleReference::SIDE_EFFECT ||
- !PreviousReference->Prefix.empty() || !Reference->Prefix.empty() ||
- !PreviousReference->DefaultImport.empty() ||
- !Reference->DefaultImport.empty() || Reference->Symbols.empty() ||
- PreviousReference->URL != Reference->URL) {
- PreviousReference = Reference;
- ++it;
- continue;
- }
- // Merge symbols from identical imports.
- PreviousReference->Symbols.append(Reference->Symbols);
- ImportsMerged = true;
- // Remove the merged import.
- it = Indices.erase(it);
- }
+ mergeModuleReferences(References, Indices);
std::string ReferencesText;
bool SymbolsInOrder = true;
@@ -203,8 +173,7 @@ class JavaScriptImportSorter : public TokenAnalyzer {
ReferencesText += "\n";
}
}
-
- if (ReferencesInOrder && SymbolsInOrder && !ImportsMerged)
+ if (ReferencesInOrder && SymbolsInOrder)
return {Result, 0};
SourceRange InsertionPoint = References[0].Range;
@@ -279,22 +248,61 @@ class JavaScriptImportSorter : public TokenAnalyzer {
SM.getFileOffset(End) - SM.getFileOffset(Begin));
}
+ // Merge module references.
+ // After sorting, find all references that import named symbols from the
+ // same URL and merge their names. E.g.
+ // import {X} from 'a';
+ // import {Y} from 'a';
+ // should be rewritten to:
+ // import {X, Y} from 'a';
+ // Note: this modifies the passed in ``Indices`` vector (by removing no longer
+ // needed references), but not ``References``.
+ // ``JsModuleReference``s that get merged have the ``SymbolsMerged`` flag
+ // flipped to true.
+ void mergeModuleReferences(SmallVector<JsModuleReference, 16> &References,
+ SmallVector<unsigned, 16> &Indices) {
+ JsModuleReference *PreviousReference = &References[Indices[0]];
+ auto *It = std::next(Indices.begin());
+ while (It != std::end(Indices)) {
+ JsModuleReference *Reference = &References[*It];
+ // Skip:
+ // import 'foo';
+ // import * as foo from 'foo'; on either previous or this.
+ // import Default from 'foo'; on either previous or this.
+ // mismatching
+ if (Reference->Category == JsModuleReference::SIDE_EFFECT ||
+ !PreviousReference->Prefix.empty() || !Reference->Prefix.empty() ||
+ !PreviousReference->DefaultImport.empty() ||
+ !Reference->DefaultImport.empty() || Reference->Symbols.empty() ||
+ PreviousReference->URL != Reference->URL) {
+ PreviousReference = Reference;
+ ++It;
+ continue;
+ }
+ // Merge symbols from identical imports.
+ PreviousReference->Symbols.append(Reference->Symbols);
+ PreviousReference->SymbolsMerged = true;
+ // Remove the merged import.
+ It = Indices.erase(It);
+ }
+ }
+
// Appends ``Reference`` to ``Buffer``, returning true if text within the
// ``Reference`` changed (e.g. symbol order).
bool appendReference(std::string &Buffer, JsModuleReference &Reference) {
// Sort the individual symbols within the import.
// E.g. `import {b, a} from 'x';` -> `import {a, b} from 'x';`
SmallVector<JsImportedSymbol, 1> Symbols = Reference.Symbols;
- if (Symbols.empty()) {
- // No symbol imports, just emit the entire module reference.
- StringRef ReferenceStmt = getSourceText(Reference.Range);
- Buffer += ReferenceStmt;
- return false;
- }
llvm::stable_sort(
Symbols, [&](const JsImportedSymbol &LHS, const JsImportedSymbol &RHS) {
return LHS.Symbol.compare_lower(RHS.Symbol) < 0;
});
+ if (!Reference.SymbolsMerged && Symbols == Reference.Symbols) {
+ // Symbols didn't change, just emit the entire module reference.
+ StringRef ReferenceStmt = getSourceText(Reference.Range);
+ Buffer += ReferenceStmt;
+ return false;
+ }
// Stitch together the module reference start...
Buffer += getSourceText(Reference.Range.getBegin(), Reference.SymbolsStart);
// ... then the references in order ...
diff --git a/clang/unittests/Format/SortImportsTestJS.cpp b/clang/unittests/Format/SortImportsTestJS.cpp
index 9f4904426cc8..a0bd76877b9e 100644
--- a/clang/unittests/Format/SortImportsTestJS.cpp
+++ b/clang/unittests/Format/SortImportsTestJS.cpp
@@ -319,6 +319,10 @@ TEST_F(SortImportsTestJS, MergeImports) {
"\n"
"X + Y + Z;\n");
+ // merge only, no resorting.
+ verifySort("import {A, B} from 'foo';\n", "import {A} from 'foo';\n"
+ "import {B} from 'foo';");
+
// empty imports
verifySort("import {A} from 'foo';\n", "import {} from 'foo';\n"
"import {A} from 'foo';");
More information about the cfe-commits
mailing list