From 35345da15f1af6ac2b2af23b3643da503cb2bb98 Mon Sep 17 00:00:00 2001 From: bradfordcsmith Date: Mon, 11 Sep 2023 16:28:30 -0700 Subject: [PATCH] Use LinkedHash(Map|Set) in more places for deterministic behavior It's important that the compiler always iterate over maps and sets in a deterministic order. PiperOrigin-RevId: 564534609 --- .../javascript/jscomp/CheckConformance.java | 8 +-- .../javascript/jscomp/ConformanceRules.java | 4 +- .../jscomp/CrossChunkCodeMotion.java | 12 ++--- .../jscomp/CrossChunkReferenceCollector.java | 3 +- .../javascript/jscomp/DotFormatter.java | 50 +++++++++++-------- .../javascript/jscomp/GenerateExports.java | 4 +- .../javascript/jscomp/IdMappingUtil.java | 43 ++++++---------- .../jscomp/InlineSimpleMethods.java | 4 +- .../google/javascript/jscomp/Normalize.java | 10 ++-- .../javascript/jscomp/PerformanceTracker.java | 17 +++---- .../javascript/jscomp/PhaseOptimizer.java | 14 +++--- .../google/javascript/jscomp/RenameVars.java | 19 ++++--- .../jscomp/RescopeGlobalSymbols.java | 6 +-- .../javascript/jscomp/TemplateAstMatcher.java | 8 +-- .../google/javascript/jscomp/Timeline.java | 6 +-- src/com/google/javascript/jscomp/Tracer.java | 8 +-- .../javascript/jscomp/XtbMessageBundle.java | 4 +- 17 files changed, 107 insertions(+), 113 deletions(-) diff --git a/src/com/google/javascript/jscomp/CheckConformance.java b/src/com/google/javascript/jscomp/CheckConformance.java index 43d8bf94146..59c32dc799b 100644 --- a/src/com/google/javascript/jscomp/CheckConformance.java +++ b/src/com/google/javascript/jscomp/CheckConformance.java @@ -26,7 +26,7 @@ import com.google.protobuf.Descriptors; import com.google.protobuf.TextFormat; import java.util.ArrayList; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.jspecify.nullness.Nullable; @@ -106,7 +106,9 @@ private static final class Category { } } - /** @param configs The rules to check. */ + /** + * @param configs The rules to check. + */ CheckConformance(AbstractCompiler compiler, ImmutableList configs) { this.compiler = compiler; // Initialize the map of functions to inspect for renaming candidates. @@ -183,7 +185,7 @@ private static ImmutableList initRules( static List mergeRequirements( AbstractCompiler compiler, List configs) { List builders = new ArrayList<>(); - Map extendable = new HashMap<>(); + Map extendable = new LinkedHashMap<>(); for (ConformanceConfig config : configs) { for (Requirement requirement : config.getRequirementList()) { Requirement.Builder builder = requirement.toBuilder(); diff --git a/src/com/google/javascript/jscomp/ConformanceRules.java b/src/com/google/javascript/jscomp/ConformanceRules.java index 8b71e77084d..a76b9f5aa5e 100644 --- a/src/com/google/javascript/jscomp/ConformanceRules.java +++ b/src/com/google/javascript/jscomp/ConformanceRules.java @@ -57,7 +57,7 @@ import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Collection; -import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.List; import java.util.Locale; import java.util.Set; @@ -2021,7 +2021,7 @@ public static final class BanCreateElement extends AbstractRule { public BanCreateElement(AbstractCompiler compiler, Requirement requirement) throws InvalidRequirementSpec { super(compiler, requirement); - bannedTags = new HashSet<>(); + bannedTags = new LinkedHashSet<>(); for (String value : requirement.getValueList()) { bannedTags.add(Ascii.toLowerCase(value)); } diff --git a/src/com/google/javascript/jscomp/CrossChunkCodeMotion.java b/src/com/google/javascript/jscomp/CrossChunkCodeMotion.java index 8a8f55b8223..3f2e0a92d8d 100644 --- a/src/com/google/javascript/jscomp/CrossChunkCodeMotion.java +++ b/src/com/google/javascript/jscomp/CrossChunkCodeMotion.java @@ -31,8 +31,7 @@ import java.util.BitSet; import java.util.Collection; import java.util.Deque; -import java.util.HashMap; -import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; @@ -79,7 +78,7 @@ class CrossChunkCodeMotion implements CompilerPass { * Map from chunk to the node in that chunk that should parent variable declarations that have to * be moved into that chunk */ - private final Map moduleInsertionPointMap = new HashMap<>(); + private final Map moduleInsertionPointMap = new LinkedHashMap<>(); private final boolean parentModuleCanSeeSymbolsDeclaredInChildren; @@ -132,7 +131,7 @@ private void addInstanceofGuards(Collection globalSymbols) { /** Collects all global symbols, their declaration statements and references. */ private class GlobalSymbolCollector { - final Map globalSymbolforVar = new HashMap<>(); + final Map globalSymbolforVar = new LinkedHashMap<>(); /** * Returning the symbols in the reverse order in which they are defined helps to minimize @@ -251,9 +250,10 @@ private class GlobalSymbol { * *

This is a LinkedHashSet in order to enforce a consistent ordering when we iterate over * these to identify cycles. This guarantees that the order in which statements are moved won't - * depend on the arbitrary ordering of HashSet. + * depend on the arbitrary ordering of LinkedHashSet. */ final Set referencingGlobalSymbols = new LinkedHashSet<>(); + /** Instanceof references we may need to update with a guard after moving declarations. */ final Deque instanceofReferencesToGuard = new ArrayDeque<>(); /** Used by OrderAndCombineGlobalSymbols to find reference cycles. */ @@ -422,7 +422,7 @@ private void addGuardToInstanceofReference(Node referenceNode) { private static class DeclarationStatementGroup { final GlobalSymbol declaredGlobalSymbol; - final Set referencedGlobalSymbols = new HashSet<>(); + final Set referencedGlobalSymbols = new LinkedHashSet<>(); /** chunk containing the statements */ JSChunk currentChunk; diff --git a/src/com/google/javascript/jscomp/CrossChunkReferenceCollector.java b/src/com/google/javascript/jscomp/CrossChunkReferenceCollector.java index 533d079a97d..347c961800b 100644 --- a/src/com/google/javascript/jscomp/CrossChunkReferenceCollector.java +++ b/src/com/google/javascript/jscomp/CrossChunkReferenceCollector.java @@ -26,7 +26,6 @@ import com.google.javascript.rhino.Node; import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -37,7 +36,7 @@ public final class CrossChunkReferenceCollector implements ScopedCallback, CompilerPass { /** Maps global variable name to the corresponding {@link Var} object. */ - private final Map varsByName = new HashMap<>(); + private final Map varsByName = new LinkedHashMap<>(); /** * Maps a given variable to a collection of references to that name. Note that Var objects are not diff --git a/src/com/google/javascript/jscomp/DotFormatter.java b/src/com/google/javascript/jscomp/DotFormatter.java index 076a4f50350..06200345e10 100644 --- a/src/com/google/javascript/jscomp/DotFormatter.java +++ b/src/com/google/javascript/jscomp/DotFormatter.java @@ -28,18 +28,19 @@ import com.google.javascript.rhino.jstype.JSType; import java.io.IOException; import java.util.Arrays; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import org.jspecify.nullness.Nullable; /** - *

DotFormatter prints out a dot file of the Abstract Syntax Tree. - * For a detailed description of the dot format and visualization tool refer - * to Graphviz.

- *

Typical usage of this class

- * System.out.println(new DotFormatter().toDot(node)); - *

This class is not thread safe and should not be used without proper - * external synchronization.

+ * DotFormatter prints out a dot file of the Abstract Syntax Tree. For a detailed description of the + * dot format and visualization tool refer to Graphviz. + * + *

Typical usage of this class logfile.write(new DotFormatter().toDot(node)); + * + * + *

This class is not thread safe and should not be used without proper external + * synchronization. */ public final class DotFormatter { private static final String INDENT = " "; @@ -48,7 +49,7 @@ public final class DotFormatter { private static final int MAX_LABEL_NAME_LENGTH = 10; // stores the current assignment of node to keys - private final HashMap assignments = new HashMap<>(); + private final LinkedHashMap assignments = new LinkedHashMap<>(); // key count in order to assign a unique key to each node private int keyCount = 0; @@ -67,8 +68,9 @@ private DotFormatter() { this.printAnnotations = false; } - private DotFormatter(Node n, ControlFlowGraph cfg, - Appendable builder, boolean printAnnotations) throws IOException { + private DotFormatter( + Node n, ControlFlowGraph cfg, Appendable builder, boolean printAnnotations) + throws IOException { this.cfg = cfg; this.builder = builder; this.printAnnotations = printAnnotations; @@ -80,10 +82,11 @@ private DotFormatter(Node n, ControlFlowGraph cfg, /** * Converts an AST to dot representation. + * * @param n the root of the AST described in the dot formatted string * @return the dot representation of the AST */ - public static String toDot(Node n) throws IOException { + public static String toDot(Node n) throws IOException { return toDot(n, null); } @@ -166,18 +169,17 @@ public static String toDot(GraphvizGraph graph) { /** * Converts an AST to dot representation and appends it to the given buffer. + * * @param n the root of the AST described in the dot formatted string * @param inCFG Control Flow Graph. * @param builder A place to dump the graph. */ - static void appendDot(Node n, ControlFlowGraph inCFG, - Appendable builder) throws IOException { + static void appendDot(Node n, ControlFlowGraph inCFG, Appendable builder) + throws IOException { DotFormatter unused = new DotFormatter(n, inCFG, builder, false); } - /** - * Creates a DotFormatter purely for testing DotFormatter's internal methods. - */ + /** Creates a DotFormatter purely for testing DotFormatter's internal methods. */ static DotFormatter newInstanceForTesting() { return new DotFormatter(); } @@ -187,8 +189,7 @@ private void traverseNodes(Node parent) throws IOException { int keyParent = key(parent); // edges - for (Node child = parent.getFirstChild(); child != null; - child = child.getNext()) { + for (Node child = parent.getFirstChild(); child != null; child = child.getNext()) { int keyChild = key(child); builder.append(INDENT); builder.append(formatNodeName(keyParent)); @@ -216,9 +217,14 @@ private void traverseNodes(Node parent) throws IOException { } edgeList[i] = - formatNodeName(keyParent) + ARROW + toNode + " [label=\"" + edge.getValue() + "\", " - + "fontcolor=\"red\", " - + "weight=0.01, color=\"red\"];\n"; + formatNodeName(keyParent) + + ARROW + + toNode + + " [label=\"" + + edge.getValue() + + "\", " + + "fontcolor=\"red\", " + + "weight=0.01, color=\"red\"];\n"; } Arrays.sort(edgeList); diff --git a/src/com/google/javascript/jscomp/GenerateExports.java b/src/com/google/javascript/jscomp/GenerateExports.java index cf1aeb5d108..338ad672dbb 100644 --- a/src/com/google/javascript/jscomp/GenerateExports.java +++ b/src/com/google/javascript/jscomp/GenerateExports.java @@ -24,7 +24,7 @@ import com.google.javascript.rhino.Node; import com.google.javascript.rhino.jstype.JSType; import com.google.javascript.rhino.jstype.JSTypeNative; -import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; import org.jspecify.nullness.Nullable; @@ -42,7 +42,7 @@ public class GenerateExports implements CompilerPass { private final boolean allowNonGlobalExports; - private final Set exportedVariables = new HashSet<>(); + private final Set exportedVariables = new LinkedHashSet<>(); static final DiagnosticType MISSING_EXPORT_CONVENTION = DiagnosticType.error( diff --git a/src/com/google/javascript/jscomp/IdMappingUtil.java b/src/com/google/javascript/jscomp/IdMappingUtil.java index 8be12cfab97..3cb848d5178 100644 --- a/src/com/google/javascript/jscomp/IdMappingUtil.java +++ b/src/com/google/javascript/jscomp/IdMappingUtil.java @@ -23,16 +23,13 @@ import com.google.common.collect.HashBiMap; import com.google.common.collect.ImmutableMap; import com.google.javascript.jscomp.base.format.SimpleFormat; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; -/** - * A utility class for generating and parsing id mappings held by {@link ReplaceIdGenerators}. - */ +/** A utility class for generating and parsing id mappings held by {@link ReplaceIdGenerators}. */ public final class IdMappingUtil { - @VisibleForTesting - static final char NEW_LINE = '\n'; + @VisibleForTesting static final char NEW_LINE = '\n'; private static final Splitter LINE_SPLITTER = Splitter.on(NEW_LINE).omitEmptyStrings(); @@ -40,21 +37,15 @@ public final class IdMappingUtil { private IdMappingUtil() {} /** - * @return The serialize map of generators and their ids and their - * replacements. + * @return The serialize map of generators and their ids and their replacements. */ static String generateSerializedIdMappings(Map> idGeneratorMaps) { StringBuilder sb = new StringBuilder(); for (Map.Entry> replacements : idGeneratorMaps.entrySet()) { if (!replacements.getValue().isEmpty()) { - sb.append('[') - .append(replacements.getKey()) - .append(']') - .append(NEW_LINE) - .append(NEW_LINE); + sb.append('[').append(replacements.getKey()).append(']').append(NEW_LINE).append(NEW_LINE); - for (Map.Entry replacement : - replacements.getValue().entrySet()) { + for (Map.Entry replacement : replacements.getValue().entrySet()) { sb.append(replacement.getKey()) .append(':') .append(replacement.getValue()) @@ -69,27 +60,23 @@ static String generateSerializedIdMappings(Map> idGe /** * The expected format looks like this: * - *

[generatorName1] - * someId1:someFile:theLine:theColumn - * ... + *

[generatorName1] someId1:someFile:theLine:theColumn ... * - *

[[generatorName2] - * someId2:someFile:theLine:theColumn] - * ... + *

[[generatorName2] someId2:someFile:theLine:theColumn] ... * *

The returned data is grouped by generator name (the map key). The inner map provides - * mappings from id to content (file, line and column info). In a glimpse, the structure is - * {@code Map>}. + * mappings from id to content (file, line and column info). In a glimpse, the structure is {@code + * Map>}. * *

@throws IllegalArgumentException malformed input where there it 1) has duplicate generator - * name, or 2) the line has no ':' for id and its content. + * name, or 2) the line has no ':' for id and its content. */ public static Map> parseSerializedIdMappings(String idMappings) { if (Strings.isNullOrEmpty(idMappings)) { return ImmutableMap.of(); } - Map> resultMap = new HashMap<>(); + Map> resultMap = new LinkedHashMap<>(); BiMap currentSectionMap = null; int lineIndex = 0; @@ -106,7 +93,8 @@ public static Map> parseSerializedIdMappings(Strin resultMap.put(currentSection, currentSectionMap); } else { throw new IllegalArgumentException( - SimpleFormat.format("Cannot parse id map: %s\n Line: $s, lineIndex: %s", + SimpleFormat.format( + "Cannot parse id map: %s\n Line: $s, lineIndex: %s", idMappings, line, lineIndex)); } } else { @@ -117,7 +105,8 @@ public static Map> parseSerializedIdMappings(Strin currentSectionMap.put(name, location); } else { throw new IllegalArgumentException( - SimpleFormat.format("Cannot parse id map: %s\n Line: $s, lineIndex: %s", + SimpleFormat.format( + "Cannot parse id map: %s\n Line: $s, lineIndex: %s", idMappings, line, lineIndex)); } } diff --git a/src/com/google/javascript/jscomp/InlineSimpleMethods.java b/src/com/google/javascript/jscomp/InlineSimpleMethods.java index 03545fe9eed..5dfa3247101 100644 --- a/src/com/google/javascript/jscomp/InlineSimpleMethods.java +++ b/src/com/google/javascript/jscomp/InlineSimpleMethods.java @@ -23,7 +23,7 @@ import com.google.javascript.rhino.IR; import com.google.javascript.rhino.JSDocInfo; import com.google.javascript.rhino.Node; -import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.Set; import org.jspecify.nullness.Nullable; @@ -61,7 +61,7 @@ class InlineSimpleMethods implements CompilerPass { // - non-method properties // - methods with @noinline // - methods with multiple, non-equivalent definitions - private final Set nonInlineableProperties = new HashSet<>(); + private final Set nonInlineableProperties = new LinkedHashSet<>(); // Use a linked map here to keep the output deterministic. Otherwise, // the choice of method bodies is random when multiple identical definitions diff --git a/src/com/google/javascript/jscomp/Normalize.java b/src/com/google/javascript/jscomp/Normalize.java index f5a9837e536..24cc234e7fe 100644 --- a/src/com/google/javascript/jscomp/Normalize.java +++ b/src/com/google/javascript/jscomp/Normalize.java @@ -27,8 +27,8 @@ import com.google.javascript.rhino.JSDocInfo; import com.google.javascript.rhino.Node; import com.google.javascript.rhino.Token; -import java.util.HashMap; -import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; import org.jspecify.nullness.Nullable; @@ -167,7 +167,7 @@ public void process(Node externs, Node root) { public void visit(NodeTraversal t, Node n, Node parent) { // Note: Constant properties annotations are not propagated. if (!n.isName() || n.getString().isEmpty()) { - return; + return; } // Find the JSDocInfo for a top-level variable @@ -214,7 +214,7 @@ public void process(Node externs, Node root) { NodeTraversal.traverseRoots(compiler, this, externs, root); } - private final Map constantMap = new HashMap<>(); + private final Map constantMap = new LinkedHashMap<>(); @Override public void visit(NodeTraversal t, Node n, Node parent) { @@ -683,7 +683,7 @@ private void removeDuplicateDeclarations(Node externs, Node root) { private final class DuplicateDeclarationHandler implements SyntacticScopeCreator.RedeclarationHandler { - private final Set hasOkDuplicateDeclaration = new HashSet<>(); + private final Set hasOkDuplicateDeclaration = new LinkedHashSet<>(); /** Remove duplicate VAR declarations discovered during scope creation. */ @Override diff --git a/src/com/google/javascript/jscomp/PerformanceTracker.java b/src/com/google/javascript/jscomp/PerformanceTracker.java index 3215159989b..4e0699186a6 100644 --- a/src/com/google/javascript/jscomp/PerformanceTracker.java +++ b/src/com/google/javascript/jscomp/PerformanceTracker.java @@ -36,14 +36,13 @@ import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Deque; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map.Entry; /** - * A PerformanceTracker collects statistics about the runtime of each pass, and - * how much a pass impacts the size of the compiled output, before and after - * gzip. + * A PerformanceTracker collects statistics about the runtime of each pass, and how much a pass + * impacts the size of the compiled output, before and after gzip. */ public final class PerformanceTracker { private static final int DEFAULT_WHEN_SIZE_UNTRACKED = -1; @@ -139,8 +138,8 @@ void updateAfterDeserialize(Node jsRoot) { } /** - * Collects information about a pass P after P finishes running, eg, how much - * time P took and what was its impact on code size. + * Collects information about a pass P after P finishes running, eg, how much time P took and what + * was its impact on code size. * * @param passName short name of the pass * @param runtime execution time in milliseconds @@ -318,7 +317,7 @@ private void calcTotalStats() { } private void populatePassSummary() { - HashMap tmpPassSummary = new HashMap<>(); + LinkedHashMap tmpPassSummary = new LinkedHashMap<>(); for (Stats logStat : this.log) { String passName = logStat.pass; @@ -472,14 +471,14 @@ public void outputTracerReport(PrintStream output) { } /** - * A Stats object contains statistics about a pass run, such as running time, - * size changes, etc + * A Stats object contains statistics about a pass run, such as running time, size changes, etc */ public static class Stats { Stats(String pass, boolean iot) { this.pass = pass; this.isOneTime = iot; } + public final String pass; public final boolean isOneTime; public long runtime = 0; diff --git a/src/com/google/javascript/jscomp/PhaseOptimizer.java b/src/com/google/javascript/jscomp/PhaseOptimizer.java index c0bc2967ad6..43ba6b2b9ff 100644 --- a/src/com/google/javascript/jscomp/PhaseOptimizer.java +++ b/src/com/google/javascript/jscomp/PhaseOptimizer.java @@ -23,8 +23,8 @@ import com.google.common.collect.ImmutableList; import com.google.javascript.rhino.Node; import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -304,7 +304,7 @@ private boolean hasCodeChangedSinceLastCall() { @VisibleForTesting class Loop implements CompilerPass { private final List myPasses = new ArrayList<>(); - private final Set myNames = new HashSet<>(); + private final Set myNames = new LinkedHashSet<>(); private ScopedChangeHandler scopeHandler; private boolean isCodeRemovalLoop = false; private int howmanyIterationsUnderThreshold = 0; @@ -329,18 +329,18 @@ public void process(Node externs, Node root) { // lastRuns is initialized before each loop. This way, when a pass is run // in the 2nd loop for the 1st time, it looks at all scopes. - lastRuns = new HashMap<>(); + lastRuns = new LinkedHashMap<>(); for (NamedPass pass : myPasses) { lastRuns.put(pass, START_TIME); } // Contains a pass iff it made changes the last time it was run. - Set madeChanges = new HashSet<>(); + Set madeChanges = new LinkedHashSet<>(); // Contains a pass iff it was run during the last inner loop. - Set runInPrevIter = new HashSet<>(); + Set runInPrevIter = new LinkedHashSet<>(); // Contains a pass iff it did not make changes. This set is cleared each time any pass makes // changes. The purpose of this is to ensure we do not rerun any passes that did not make // changes unless a later run pass did make changes. - Set didNotMakeChanges = new HashSet<>(); + Set didNotMakeChanges = new LinkedHashSet<>(); State state = State.RUN_PASSES_NOT_RUN_IN_PREV_ITER; boolean lastIterMadeChanges; int count = 1; diff --git a/src/com/google/javascript/jscomp/RenameVars.java b/src/com/google/javascript/jscomp/RenameVars.java index 4e9b8c35606..724bd99fbb3 100644 --- a/src/com/google/javascript/jscomp/RenameVars.java +++ b/src/com/google/javascript/jscomp/RenameVars.java @@ -30,8 +30,8 @@ import com.google.javascript.rhino.Node; import java.util.ArrayList; import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -60,7 +60,7 @@ final class RenameVars implements CompilerPass { private final ArrayList localNameNodes = new ArrayList<>(); /** Mapping of original names for change detection */ - private final Map originalNameByNode = new HashMap<>(); + private final Map originalNameByNode = new LinkedHashMap<>(); /** * Maps a name node to its pseudo name, null if we are not generating so there will be no overhead @@ -75,7 +75,7 @@ final class RenameVars implements CompilerPass { private final Set reservedNames; /** The renaming map */ - private final Map renameMap = new HashMap<>(); + private final Map renameMap = new LinkedHashMap<>(); /** The previously used rename map. */ private final VariableMap prevUsedRenameMap; @@ -88,7 +88,7 @@ final class RenameVars implements CompilerPass { // Logic for bleeding functions, where the name leaks into the outer // scope on IE but not on other browsers. - private final Set localBleedingFunctions = new HashSet<>(); + private final Set localBleedingFunctions = new LinkedHashSet<>(); private final ListMultimap localBleedingFunctionsPerScope = ArrayListMultimap.create(); @@ -119,8 +119,7 @@ void setNewName(String newName) { } /** Maps an old name to a new name assignment */ - private final Map assignments = - new HashMap<>(); + private final Map assignments = new LinkedHashMap<>(); /** Whether renaming should apply to local variables only. */ private final boolean localRenamingOnly; @@ -155,7 +154,7 @@ void setNewName(String newName) { this.prefix = nullToEmpty(prefix); this.localRenamingOnly = localRenamingOnly; if (generatePseudoNames) { - this.pseudoNameMap = new HashMap<>(); + this.pseudoNameMap = new LinkedHashMap<>(); } else { this.pseudoNameMap = null; } @@ -163,9 +162,9 @@ void setNewName(String newName) { this.reservedCharacters = reservedCharacters; this.preferStableNames = preferStableNames; if (reservedNames == null) { - this.reservedNames = new HashSet<>(); + this.reservedNames = new LinkedHashSet<>(); } else { - this.reservedNames = new HashSet<>(reservedNames); + this.reservedNames = new LinkedHashSet<>(reservedNames); } this.nameGenerator = nameGenerator; } diff --git a/src/com/google/javascript/jscomp/RescopeGlobalSymbols.java b/src/com/google/javascript/jscomp/RescopeGlobalSymbols.java index 48e47ff225d..8f5fe67ac54 100644 --- a/src/com/google/javascript/jscomp/RescopeGlobalSymbols.java +++ b/src/com/google/javascript/jscomp/RescopeGlobalSymbols.java @@ -23,7 +23,7 @@ import com.google.javascript.rhino.IR; import com.google.javascript.rhino.Node; import java.util.ArrayList; -import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.List; import java.util.Set; @@ -61,10 +61,10 @@ final class RescopeGlobalSymbols implements CompilerPass { private final String globalSymbolNamespace; private final boolean addExtern; private final boolean assumeCrossChunkNames; - private final Set crossChunkNames = new HashSet<>(); + private final Set crossChunkNames = new LinkedHashSet<>(); /** Global identifiers that may be a non-arrow function referencing "this" */ - private final Set maybeReferencesThis = new HashSet<>(); + private final Set maybeReferencesThis = new LinkedHashSet<>(); private ImmutableSet externNames; diff --git a/src/com/google/javascript/jscomp/TemplateAstMatcher.java b/src/com/google/javascript/jscomp/TemplateAstMatcher.java index 8989a95dc5b..bf875ca2541 100644 --- a/src/com/google/javascript/jscomp/TemplateAstMatcher.java +++ b/src/com/google/javascript/jscomp/TemplateAstMatcher.java @@ -30,7 +30,7 @@ import com.google.javascript.rhino.jstype.JSTypeRegistry; import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -79,7 +79,7 @@ public final class TemplateAstMatcher { *

This re-uses strings already present in the AST, which is faster and simpler than keeping an * additional layer of indirection. */ - private final HashMap stringLiteralMatches = new HashMap<>(); + private final LinkedHashMap stringLiteralMatches = new LinkedHashMap<>(); /** * Record whether the last successful was a loosely matched type, only valid @@ -144,7 +144,7 @@ public boolean isLooseMatch() { * template. */ public Map getTemplateNodeToMatchMap() { - Map map = new HashMap<>(stringLiteralMatches); + Map map = new LinkedHashMap<>(stringLiteralMatches); for (int i = 0; i < templateParams.size(); i++) { String name = templateParams.get(i); @@ -200,7 +200,7 @@ private Node initTemplate(Node templateFunctionNode) { private void prepTemplatePlaceholders(Node fn) { final List locals = templateLocals; final List params = templateParams; - final Map paramTypes = new HashMap<>(); + final Map paramTypes = new LinkedHashMap<>(); // drop the function name so it isn't include in the name maps String fnName = fn.getFirstChild().getString(); diff --git a/src/com/google/javascript/jscomp/Timeline.java b/src/com/google/javascript/jscomp/Timeline.java index b3db44dca14..3a06bcade72 100644 --- a/src/com/google/javascript/jscomp/Timeline.java +++ b/src/com/google/javascript/jscomp/Timeline.java @@ -18,7 +18,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import java.util.ArrayList; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.jspecify.nullness.Nullable; @@ -64,8 +64,8 @@ public int hashCode() { } } - private final Map> eventsByTime = new HashMap<>(); - private final Map> eventsByValue = new HashMap<>(); + private final Map> eventsByTime = new LinkedHashMap<>(); + private final Map> eventsByValue = new LinkedHashMap<>(); // In practice headEvent is Event