/*
 * Copyright 2009 The Closure Compiler Authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.javascript.jscomp;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.javascript.jscomp.PassFactory.createEmptyPass;
import static com.google.javascript.jscomp.parsing.parser.FeatureSet.ES2018;
import static com.google.javascript.jscomp.parsing.parser.FeatureSet.ES5;
import static com.google.javascript.jscomp.parsing.parser.FeatureSet.ES6;
import static com.google.javascript.jscomp.parsing.parser.FeatureSet.ES8;
import static com.google.javascript.jscomp.parsing.parser.FeatureSet.ES8_MODULES;
import static com.google.javascript.jscomp.parsing.parser.FeatureSet.ES_NEXT;
import static com.google.javascript.jscomp.parsing.parser.FeatureSet.TYPESCRIPT;
import static com.google.javascript.jscomp.parsing.parser.FeatureSet.TYPE_CHECK_SUPPORTED;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.javascript.jscomp.AbstractCompiler.LifeCycleStage;
import com.google.javascript.jscomp.CompilerOptions.ExtractPrototypeMemberDeclarationsMode;
import com.google.javascript.jscomp.CompilerOptions.Reach;
import com.google.javascript.jscomp.CoverageInstrumentationPass.CoverageReach;
import com.google.javascript.jscomp.CoverageInstrumentationPass.InstrumentOption;
import com.google.javascript.jscomp.ExtractPrototypeMemberDeclarations.Pattern;
import com.google.javascript.jscomp.NodeTraversal.Callback;
import com.google.javascript.jscomp.PassFactory.HotSwapPassFactory;
import com.google.javascript.jscomp.ijs.ConvertToTypedInterface;
import com.google.javascript.jscomp.lint.CheckArrayWithGoogObject;
import com.google.javascript.jscomp.lint.CheckDuplicateCase;
import com.google.javascript.jscomp.lint.CheckEmptyStatements;
import com.google.javascript.jscomp.lint.CheckEnums;
import com.google.javascript.jscomp.lint.CheckEs6ModuleFileStructure;
import com.google.javascript.jscomp.lint.CheckEs6Modules;
import com.google.javascript.jscomp.lint.CheckInterfaces;
import com.google.javascript.jscomp.lint.CheckJSDocStyle;
import com.google.javascript.jscomp.lint.CheckMissingSemicolon;
import com.google.javascript.jscomp.lint.CheckNoMutatedEs6Exports;
import com.google.javascript.jscomp.lint.CheckNullabilityModifiers;
import com.google.javascript.jscomp.lint.CheckNullableReturn;
import com.google.javascript.jscomp.lint.CheckPrimitiveAsObject;
import com.google.javascript.jscomp.lint.CheckPrototypeProperties;
import com.google.javascript.jscomp.lint.CheckRequiresAndProvidesSorted;
import com.google.javascript.jscomp.lint.CheckUnusedLabels;
import com.google.javascript.jscomp.lint.CheckUselessBlocks;
import com.google.javascript.jscomp.parsing.ParserRunner;
import com.google.javascript.jscomp.parsing.parser.FeatureSet;
import com.google.javascript.rhino.IR;
import com.google.javascript.rhino.JSDocInfo;
import com.google.javascript.rhino.JSDocInfoBuilder;
import com.google.javascript.rhino.Node;
import com.google.javascript.rhino.Token;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;

/**
 * Pass factories and meta-data for native JSCompiler passes.
 *
 * @author nicksantos@google.com (Nick Santos)
 *
 * Apache Royale copied DefaultPassConfig and modified it to replace
 * two passes with "WithModuleSupport" passes.
 * 
 * NOTE(dimvar): this needs some non-trivial refactoring. The pass config should
 * use as little state as possible. The recommended way for a pass to leave
 * behind some state for a subsequent pass is through the compiler object.
 * Any other state remaining here should only be used when the pass config is
 * creating the list of checks and optimizations, not after passes have started
 * executing. For example, the field namespaceForChecks should be in Compiler.
 */
public final class RoyaleClosurePassConfig extends PassConfig {

  /* For the --mark-as-compiled pass */
  private static final String COMPILED_CONSTANT_NAME = "COMPILED";

  /* Constant name for Closure's locale */
  private static final String CLOSURE_LOCALE_CONSTANT_NAME = "goog.LOCALE";

  static final DiagnosticType CANNOT_USE_PROTOTYPE_AND_VAR =
      DiagnosticType.error("JSC_CANNOT_USE_PROTOTYPE_AND_VAR",
          "Rename prototypes and inline variables cannot be used together.");

  // Miscellaneous errors.
  private static final java.util.regex.Pattern GLOBAL_SYMBOL_NAMESPACE_PATTERN =
    java.util.regex.Pattern.compile("^[a-zA-Z0-9$_]+$");

  /**
   * A global namespace to share across checking passes.
   */
  private transient GlobalNamespace namespaceForChecks = null;

  /** A symbol table for registering references that get removed during preprocessing. */
  private final transient PreprocessorSymbolTable.CachedInstanceFactory
      preprocessorSymbolTableFactory;

  /**
   * Global state necessary for doing hotswap recompilation of files with references to
   * processed goog.modules.
   */
  private transient ClosureRewriteModule.GlobalRewriteState moduleRewriteState = null;

  /**
   * Whether to protect "hidden" side-effects.
   * @see CheckSideEffects
   */
  private final boolean protectHiddenSideEffects;
  
  /** name of a source file we can use to inject other code */
  private String sourceFileName;

  /** file of already renamed vars */
  private File varRenameMapFile;

  private Set<String> propertyNamesToKeep;

  private Set<String> extraSymbolNamesToExport;
  
  public RoyaleClosurePassConfig(CompilerOptions options, String sourceFileName, File varRenameMapFile, Set<String> propertyNamesToKeep, Set<String> extraSymbolNamesToExport) {
    super(options);

    // The current approach to protecting "hidden" side-effects is to
    // wrap them in a function call that is stripped later, this shouldn't
    // be done in IDE mode where AST changes may be unexpected.
    protectHiddenSideEffects = options != null && options.shouldProtectHiddenSideEffects();
    preprocessorSymbolTableFactory = new PreprocessorSymbolTable.CachedInstanceFactory();
    this.varRenameMapFile = varRenameMapFile;
    this.sourceFileName = sourceFileName;
    this.propertyNamesToKeep = propertyNamesToKeep;
    this.extraSymbolNamesToExport = extraSymbolNamesToExport;
  }

  GlobalNamespace getGlobalNamespace() {
    return namespaceForChecks;
  }

  @Nullable
  PreprocessorSymbolTable getPreprocessorSymbolTable() {
    return preprocessorSymbolTableFactory.getInstanceOrNull();
  }

  void maybeInitializeModuleRewriteState() {
    if (options.allowsHotswapReplaceScript() && this.moduleRewriteState == null) {
      this.moduleRewriteState = new ClosureRewriteModule.GlobalRewriteState();
    }
  }

  @Override
  protected List<PassFactory> getTranspileOnlyPasses() {
    List<PassFactory> passes = new ArrayList<PassFactory>();

    if (options.needsTranspilationFrom(TYPESCRIPT)) {
      passes.add(convertEs6TypedToEs6);
    }

    passes.add(checkVariableReferencesForTranspileOnly);
    passes.add(gatherModuleMetadataPass);

    if (options.getLanguageIn().toFeatureSet().has(FeatureSet.Feature.MODULES)) {
      passes.add(rewriteGoogJsImports);
      switch (options.getEs6ModuleTranspilation()) {
        case COMPILE:
          TranspilationPasses.addEs6ModulePass(passes, preprocessorSymbolTableFactory);
          break;
        case TO_COMMON_JS_LIKE_MODULES:
          TranspilationPasses.addEs6ModuleToCjsPass(passes);
          break;
        case RELATIVIZE_IMPORT_PATHS:
          TranspilationPasses.addEs6RewriteImportPathPass(passes);
          break;
        case NONE:
          // nothing
          break;
      }
    }

    passes.add(checkSuper);

    // It's important that the Dart super accessors pass run *before* es6ConvertSuper,
    // which is a "late" ES6 pass. This is enforced in the assertValidOrder method.
    if (options.dartPass && options.needsTranspilationFrom(ES6)) {
      passes.add(dartSuperAccessorsPass);
    }

    TranspilationPasses.addPreTypecheckTranspilationPasses(passes, options);

    TranspilationPasses.addPostCheckTranspilationPasses(passes, options);

    if (options.needsTranspilationFrom(ES6)) {
      if (options.rewritePolyfills) {
        TranspilationPasses.addRewritePolyfillPass(passes);
      }
    }

    passes.add(injectRuntimeLibraries);

    assertAllOneTimePasses(passes);
    assertValidOrderForChecks(passes);
    return passes;
  }

  @Override
  protected List<PassFactory> getWhitespaceOnlyPasses() {
    List<PassFactory> passes = new ArrayList<PassFactory>();

    if (options.processCommonJSModules) {
      passes.add(rewriteCommonJsModules);
    } else if (options.getLanguageIn().toFeatureSet().has(FeatureSet.Feature.MODULES)) {
      passes.add(rewriteScriptsToEs6Modules);
    }

    if (options.wrapGoogModulesForWhitespaceOnly) {
      passes.add(whitespaceWrapGoogModules);
    }
    return passes;
  }

  private void addTypeCheckerPasses(List<PassFactory> checks, CompilerOptions options) {
    if (!options.allowsHotswapReplaceScript()) {
      checks.add(inlineTypeAliases);
    }
    if (options.checkTypes || options.inferTypes) {
      checks.add(resolveTypes);
      checks.add(inferTypes);
      if (options.checkTypes) {
        checks.add(checkTypes);
      } else {
        checks.add(inferJsDocInfo);
      }

      // We assume that only clients who are going to re-compile, or do in-depth static analysis,
      // will need the typed scope creator after the compile job.
      if (!options.preservesDetailedSourceInfo() && !options.allowsHotswapReplaceScript()) {
        checks.add(clearTypedScopePass);
      }
    }
  }

  @Override
  protected List<PassFactory> getChecks() {
    List<PassFactory> checks = new ArrayList<PassFactory>();

    checks.add(gatherGettersAndSetters);

    if (options.shouldGenerateTypedExterns()) {
      checks.add(closureGoogScopeAliases);
      checks.add(closureRewriteClass);
      checks.add(generateIjs);
      checks.add(whitespaceWrapGoogModules);
      return checks;
    }

    checks.add(createEmptyPass("beforeStandardChecks"));

    if (options.processCommonJSModules) {
      checks.add(rewriteCommonJsModules);
    } else if (options.getLanguageIn().toFeatureSet().has(FeatureSet.Feature.MODULES)) {
      checks.add(rewriteScriptsToEs6Modules);
    }

    // Note: ChromePass can rewrite invalid @type annotations into valid ones, so should run before
    // JsDoc checks.
    if (options.isChromePassEnabled()) {
      checks.add(chromePass);
    }

    // Verify JsDoc annotations and check ES6 modules
    checks.add(checkJsDocAndEs6Modules);

    if (options.needsTranspilationFrom(TYPESCRIPT)) {
      checks.add(convertEs6TypedToEs6);
    }

    checks.add(gatherModuleMetadataPass);

    if (options.enables(DiagnosticGroups.LINT_CHECKS)) {
      checks.add(lintChecks);
    }

    if (options.closurePass && options.enables(DiagnosticGroups.LINT_CHECKS)) {
      checks.add(checkRequiresAndProvidesSorted);
    }

    if (options.enables(DiagnosticGroups.MISSING_REQUIRE)
        || options.enables(DiagnosticGroups.STRICT_MISSING_REQUIRE)
        || options.enables(DiagnosticGroups.EXTRA_REQUIRE)) {
      checks.add(checkRequires);
    }

    checks.add(checkVariableReferences);

    if (options.getLanguageIn().toFeatureSet().has(FeatureSet.Feature.MODULES)) {
      checks.add(rewriteGoogJsImports);
      TranspilationPasses.addEs6ModulePass(checks, preprocessorSymbolTableFactory);
    }

    checks.add(checkStrictMode);

    if (options.closurePass) {
      checks.add(closureCheckModule);
      checks.add(closureRewriteModule);
    }

    if (options.declaredGlobalExternsOnWindow) {
      checks.add(declaredGlobalExternsOnWindow);
    }

    checks.add(checkSuper);

    if (options.closurePass) {
      checks.add(closureGoogScopeAliases);
      checks.add(closureRewriteClass);
    }

    checks.add(checkSideEffects);

    if (options.enables(DiagnosticGroups.MISSING_PROVIDE)) {
      checks.add(checkProvides);
    }

    if (options.angularPass) {
      checks.add(angularPass);
    }

    if (!options.generateExportsAfterTypeChecking && options.generateExports) {
      checks.add(generateExports);
    }

    if (options.exportTestFunctions) {
      checks.add(exportTestFunctions);
    }

    if (options.closurePass) {
      checks.add(closurePrimitives);
    }

    // It's important that the PolymerPass run *after* the ClosurePrimitives and ChromePass rewrites
    // and *before* the suspicious code checks. This is enforced in the assertValidOrder method.
    if (options.polymerVersion != null) {
      checks.add(polymerPass);
    }

    if (extraSymbolNamesToExport != null) {
      checks.add(extraSymbolsPass);
    }

    if (options.checkSuspiciousCode
        || options.enables(DiagnosticGroups.GLOBAL_THIS)
        || options.enables(DiagnosticGroups.DEBUGGER_STATEMENT_PRESENT)) {
      checks.add(suspiciousCode);
    }

    if (options.closurePass && options.checkMissingGetCssNameLevel.isOn()) {
      checks.add(closureCheckGetCssName);
    }

    if (options.syntheticBlockStartMarker != null) {
      // This pass must run before the first fold constants pass.
      checks.add(createSyntheticBlocks);
    }

    checks.add(checkVars);

    if (options.inferConsts) {
      checks.add(inferConsts);
    }

    if (options.computeFunctionSideEffects) {
      checks.add(checkRegExp);
    }

    // This pass should run before types are assigned.
    if (options.processObjectPropertyString) {
      checks.add(objectPropertyStringPreprocess);
    }

    // It's important that the Dart super accessors pass run *before* es6ConvertSuper,
    // which is a "late" ES6 pass. This is enforced in the assertValidOrder method.
    if (options.dartPass && !options.getOutputFeatureSet().contains(ES6)) {
      checks.add(dartSuperAccessorsPass);
    }

    // Passes running before this point should expect to see language features up to ES_2017.
    checks.add(createEmptyPass(PassNames.BEFORE_ES_2017_TRANSPILATION));

    TranspilationPasses.addPreTypecheckTranspilationPasses(checks, options);

    if (options.rewritePolyfills && !options.checksOnly) {
      TranspilationPasses.addRewritePolyfillPass(checks);
    }

    checks.add(injectRuntimeLibraries);
    checks.add(createEmptyPass(PassNames.BEFORE_TYPE_CHECKING));

    addTypeCheckerPasses(checks, options);

    if (options.j2clPassMode.shouldAddJ2clPasses()) {
      checks.add(j2clSourceFileChecker);
    }

    if (!options.disables(DiagnosticGroups.CHECK_USELESS_CODE)
        || !options.disables(DiagnosticGroups.MISSING_RETURN)) {
      checks.add(checkControlFlow);
    }
    
    /* The AS compiler should have checked the same thing
     * that CheckAccessControls checks.  CheckAccessControls
     * also outputs false positives when compiling modules.

    // CheckAccessControls only works if check types is on.
    if (options.isTypecheckingEnabled()
        && (!options.disables(DiagnosticGroups.ACCESS_CONTROLS)
            || options.enables(DiagnosticGroups.CONSTANT_PROPERTY))) {
      checks.add(checkAccessControls);
    }
     */

    /* The AS compiler should have checked the same thing
     * that CheckConsts checks.  CheckConsts
     * also outputs false positives when compiling modules.
    checks.add(checkConsts);
     */

    // Analyzer checks must be run after typechecking.
    if (options.enables(DiagnosticGroups.ANALYZER_CHECKS) && options.isTypecheckingEnabled()) {
      checks.add(analyzerChecks);
    }

    if (options.checkGlobalNamesLevel.isOn()) {
      checks.add(checkGlobalNames);
    }

    if (!options.getConformanceConfigs().isEmpty()) {
      checks.add(checkConformance);
    }

    // Replace 'goog.getCssName' before processing defines but after the
    // other checks have been done.
    if (options.closurePass && !options.shouldPreserveGoogLibraryPrimitives()) {
      checks.add(closureReplaceGetCssName);
    }

    if (options.getTweakProcessing().isOn()) {
      checks.add(processTweaks);
    }

    if (options.instrumentationTemplate != null || options.recordFunctionInformation) {
      checks.add(computeFunctionNames);
    }

    if (options.checksOnly) {
      // Run process defines here so that warnings/errors from that pass are emitted as part of
      // checks.
      // TODO(rluble): Split process defines into two stages, one that performs only checks to be
      // run here, and the one that actually changes the AST that would run in the optimization
      // phase.
      checks.add(processDefines);
    }

    if (options.j2clPassMode.shouldAddJ2clPasses()) {
      checks.add(j2clChecksPass);
    }

    if (options.shouldRunTypeSummaryChecksLate()) {
      checks.add(generateIjs);
    }

    // When options.generateExportsAfterTypeChecking is true, run GenerateExports after
    // both type checkers, not just after NTI.
    if (options.generateExportsAfterTypeChecking && options.generateExports) {
      checks.add(generateExports);
    }

    checks.add(createEmptyPass(PassNames.AFTER_STANDARD_CHECKS));

    if (!options.checksOnly) {
      // At this point all checks have been done.
      // There's no need to complete transpilation if we're only running checks.
      TranspilationPasses.addPostCheckTranspilationPasses(checks, options);

      if (options.needsTranspilationFrom(ES6)) {
        // This pass used to be necessary to make the typechecker happy with class-side inheritance.
        // It's not necessary for typechecking now that class transpilation is post-typechecking,
        // but it turned out to be necessary to avoid CollapseProperties breaking static inheritance
        // TODO(b/116054203): try to only run this pass when property collapsing is enabled during
        // the optimizations. Even better, find a way to get rid of this pass completely.
        checks.add(convertStaticInheritance);
      }
    }

    assertAllOneTimePasses(checks);
    assertValidOrderForChecks(checks);

    return checks;
  }

  @Override
  protected List<PassFactory> getOptimizations() {
    List<PassFactory> passes = new ArrayList<PassFactory>();

    if (options.skipNonTranspilationPasses) {
      return passes;
    }

    passes.add(removeWeakSources);

    passes.add(garbageCollectChecks);

    // i18n
    // If you want to customize the compiler to use a different i18n pass,
    // you can create a PassConfig that calls replacePassFactory
    // to replace this.
    if (options.replaceMessagesWithChromeI18n) {
      passes.add(replaceMessagesForChrome);
    } else if (options.messageBundle != null) {
      passes.add(replaceMessages);
    }

    // Defines in code always need to be processed.
    passes.add(processDefines);

    if (options.getTweakProcessing().shouldStrip()
        || !options.stripTypes.isEmpty()
        || !options.stripNameSuffixes.isEmpty()
        || !options.stripTypePrefixes.isEmpty()
        || !options.stripNamePrefixes.isEmpty()) {
      passes.add(stripCode);
    }

    passes.add(normalize);

    // Create extern exports after the normalize because externExports depends on unique names.
    if (options.isExternExportsEnabled() || options.externExportsPath != null) {
      passes.add(externExports);
    }

    // Gather property names in externs so they can be queried by the
    // optimizing passes.
    passes.add(gatherExternProperties);

    // Should be run before runtimeTypeCheck and instrumentForCoverage as they rewrite code that
    // this pass expects to see.
    if (options.j2clPassMode.shouldAddJ2clPasses()) {
      passes.add(j2clPass);
      passes.add(j2clUtilGetDefineRewriterPass);
    }

    if (options.instrumentForCoverage) {
      passes.add(instrumentForCodeCoverage);
    }

    if (options.runtimeTypeCheck) {
      passes.add(runtimeTypeCheck);
    }

    passes.add(createEmptyPass(PassNames.BEFORE_STANDARD_OPTIMIZATIONS));

    if (options.replaceIdGenerators) {
      passes.add(replaceIdGenerators);
    }

    // Optimizes references to the arguments variable.
    if (options.optimizeArgumentsArray) {
      passes.add(optimizeArgumentsArray);
    }

    // Abstract method removal works best on minimally modified code, and also
    // only needs to run once.
    if (options.closurePass && (options.removeAbstractMethods || options.removeClosureAsserts)) {
      passes.add(closureCodeRemoval);
    }

    if (options.removeJ2clAsserts) {
      passes.add(j2clAssertRemovalPass);
    }

    // Property disambiguation should only run once and needs to be done
    // soon after type checking, both so that it can make use of type
    // information and so that other passes can take advantage of the renamed
    // properties.
    if (options.disambiguatePrivateProperties) {
      passes.add(disambiguatePrivateProperties);
    }

    assertAllOneTimePasses(passes);

    // Inline aliases so that following optimizations don't have to understand alias chains.
    if (options.shouldCollapseProperties()) {
      passes.add(aggressiveInlineAliases);
    }

    // Inline getters/setters in J2CL classes so that Object.defineProperties() calls (resulting
    // from desugaring) don't block class stripping.
    if (options.j2clPassMode.shouldAddJ2clPasses() && options.shouldCollapseProperties()) {
      // Relies on collapseProperties-triggered aggressive alias inlining.
      passes.add(j2clPropertyInlinerPass);
    }

    // Collapsing properties can undo constant inlining, so we do this before
    // the main optimization loop.
    if (options.shouldCollapseProperties()) {
      passes.add(collapseProperties);
    }

    if (options.inferConsts) {
      passes.add(inferConsts);
    }

    // TODO(mlourenco): Ideally this would be in getChecks() instead of getOptimizations(). But
    // for that it needs to understand constant properties as well. See b/31301233#10.
    // Needs to happen after inferConsts and collapseProperties. Detects whether invocations of
    // the method goog.string.Const.from are done with an argument which is a string literal.
    passes.add(checkConstParams);

    // Running RemoveUnusedCode before disambiguate properties allows disambiguate properties to be
    // more effective if code that would prevent disambiguation can be removed.
    // TODO(b/66971163): Rename options since we're not actually using smartNameRemoval here now.
    if (options.extraSmartNameRemoval && options.smartNameRemoval) {

      // These passes remove code that is dead because of define flags.
      // If the dead code is weakly typed, running these passes before property
      // disambiguation results in more code removal.
      // The passes are one-time on purpose. (The later runs are loopable.)
      if (options.foldConstants && (options.inlineVariables || options.inlineLocalVariables)) {
        passes.add(earlyInlineVariables);
        passes.add(earlyPeepholeOptimizations);
      }

      passes.add(removeUnusedCodeOnce);
    }

    // RewritePolyfills is overly generous in the polyfills it adds.  After type
    // checking and early smart name removal, we can use the new type information
    // to figure out which polyfilled prototype methods are actually called, and
    // which were "false alarms" (i.e. calling a method of the same name on a
    // user-provided class).  We also remove any polyfills added by code that
    // was smart-name-removed.  This is a one-time pass, since it does not work
    // after inlining - we do not attempt to aggressively remove polyfills used
    // by code that is only flow-sensitively dead.
    if (options.rewritePolyfills) {
      passes.add(removeUnusedPolyfills);
    }

    // Property disambiguation should only run once and needs to be done
    // soon after type checking, both so that it can make use of type
    // information and so that other passes can take advantage of the renamed
    // properties.
    if (options.shouldDisambiguateProperties() && options.isTypecheckingEnabled()) {
      passes.add(disambiguateProperties);
    }

    if (options.computeFunctionSideEffects) {
      passes.add(markPureFunctions);
    } else if (options.markNoSideEffectCalls) {
      // TODO(user) The properties that this pass adds to CALL and NEW
      // AST nodes increase the AST's in-memory size.  Given that we are
      // already running close to our memory limits, we could run into
      // trouble if we end up using the @nosideeffects annotation a lot
      // or compute @nosideeffects annotations by looking at function
      // bodies.  It should be easy to propagate @nosideeffects
      // annotations as part of passes that depend on this property and
      // store the result outside the AST (which would allow garbage
      // collection once the pass is done).
      passes.add(markNoSideEffectCalls);
    }

    if (options.smartNameRemoval) {
      passes.addAll(getCodeRemovingPasses());
      // TODO(b/66971163): Remove this early loop or rename the option that enables it
      // to something more appropriate.
    }

    // This needs to come after the inline constants pass, which is run within
    // the code removing passes.
    if (options.closurePass) {
      passes.add(closureOptimizePrimitives);
    }

    // ReplaceStrings runs after CollapseProperties in order to simplify
    // pulling in values of constants defined in enums structures. It also runs
    // after disambiguate properties and smart name removal so that it can
    // correctly identify logging types and can replace references to string
    // expressions.
    if (!options.replaceStringsFunctionDescriptions.isEmpty()) {
      passes.add(replaceStrings);
    }

    // TODO(user): This forces a first crack at crossChunkCodeMotion
    // before devirtualization. Once certain functions are devirtualized,
    // it confuses crossChunkCodeMotion ability to recognized that
    // it is recursive.

    // TODO(user): This is meant for a temporary quick win.
    // In the future, we might want to improve our analysis in
    // CrossChunkCodeMotion so we don't need to do this.
    if (options.shouldRunCrossChunkCodeMotion()) {
      passes.add(crossModuleCodeMotion);
    }

    // Method devirtualization benefits from property disambiguation so
    // it should run after that pass but before passes that do
    // optimizations based on global names (like cross module code motion
    // and inline functions).  Smart Name Removal does better if run before
    // this pass.
    if (options.devirtualizePrototypeMethods) {
      passes.add(devirtualizePrototypeMethods);
    }

    if (options.customPasses != null) {
      passes.add(getCustomPasses(
          CustomPassExecutionTime.BEFORE_OPTIMIZATION_LOOP));
    }

    passes.add(createEmptyPass(PassNames.BEFORE_MAIN_OPTIMIZATIONS));

    // Because FlowSensitiveInlineVariables does not operate on the global scope due to compilation
    // time, we need to run it once before InlineFunctions so that we don't miss inlining
    // opportunities when a function will be inlined into the global scope.
    if (options.inlineVariables || options.inlineLocalVariables) {
      passes.add(flowSensitiveInlineVariables);
    }

    passes.addAll(getMainOptimizationLoop());
    passes.add(createEmptyPass(PassNames.AFTER_MAIN_OPTIMIZATIONS));

    passes.add(createEmptyPass("beforeModuleMotion"));

    if (options.shouldRunCrossChunkCodeMotion()) {
      passes.add(crossModuleCodeMotion);
    }

    if (options.shouldRunCrossChunkMethodMotion()) {
      passes.add(crossModuleMethodMotion);
    }

    passes.add(createEmptyPass("afterModuleMotion"));

    // Some optimizations belong outside the loop because running them more
    // than once would either have no benefit or be incorrect.
    if (options.customPasses != null) {
      passes.add(getCustomPasses(
          CustomPassExecutionTime.AFTER_OPTIMIZATION_LOOP));
    }

    if (options.inlineVariables || options.inlineLocalVariables) {
      passes.add(flowSensitiveInlineVariables);

      // After inlining some of the variable uses, some variables are unused.
      // Re-run remove unused vars to clean it up.
      if (shouldRunRemoveUnusedCode()) {
        passes.add(removeUnusedCodeOnce);
      }
    }

    if (options.collapseAnonymousFunctions) {
      passes.add(collapseAnonymousFunctions);
    }

    // Move functions before extracting prototype member declarations.
    if (options.moveFunctionDeclarations
        // renamePrefixNamescape relies on moveFunctionDeclarations
        // to preserve semantics.
        || options.renamePrefixNamespace != null) {
      passes.add(moveFunctionDeclarations);
    }

    if (options.anonymousFunctionNaming == AnonymousFunctionNamingPolicy.MAPPED) {
      passes.add(nameMappedAnonymousFunctions);
    }

    // The mapped name anonymous function pass makes use of information that
    // the extract prototype member declarations pass removes so the former
    // happens before the latter.
    if (options.extractPrototypeMemberDeclarations != ExtractPrototypeMemberDeclarationsMode.OFF) {
      passes.add(extractPrototypeMemberDeclarations);
    }

    if (options.shouldAmbiguateProperties()
        && options.propertyRenaming == PropertyRenamingPolicy.ALL_UNQUOTED
        && options.isTypecheckingEnabled()) {
      passes.add(ambiguateProperties);
    }

    if (options.propertyRenaming == PropertyRenamingPolicy.ALL_UNQUOTED) {
      passes.add(renameProperties);
    }

    // Reserve global names added to the "windows" object.
    if (options.reserveRawExports) {
      passes.add(gatherRawExports);
    }

    // This comes after property renaming because quoted property names must
    // not be renamed.
    if (options.convertToDottedProperties) {
      passes.add(convertToDottedProperties);
    }

    // Property renaming must happen before this pass runs since this
    // pass may convert dotted properties into quoted properties.  It
    // is beneficial to run before alias strings, alias keywords and
    // variable renaming.
    if (options.rewriteFunctionExpressions) {
      passes.add(rewriteFunctionExpressions);
    }

    // This comes after converting quoted property accesses to dotted property
    // accesses in order to avoid aliasing property names.
    if (!options.aliasableStrings.isEmpty() || options.aliasAllStrings) {
      passes.add(aliasStrings);
    }

    if (options.coalesceVariableNames) {
      // Passes after this point can no longer depend on normalized AST
      // assumptions because the code is marked as un-normalized
      passes.add(coalesceVariableNames);

      // coalesceVariables creates identity assignments and more redundant code
      // that can be removed, rerun the peephole optimizations to clean them
      // up.
      if (options.foldConstants) {
        passes.add(peepholeOptimizationsOnce);
      }
    }

    // Passes after this point can no longer depend on normalized AST assumptions.
    passes.add(markUnnormalized);

    if (options.collapseVariableDeclarations) {
      passes.add(exploitAssign);
      passes.add(collapseVariableDeclarations);
    }

    // This pass works best after collapseVariableDeclarations.
    passes.add(denormalize);

    if (options.instrumentationTemplate != null) {
      passes.add(instrumentFunctions);
    }

    if (options.variableRenaming != VariableRenamingPolicy.ALL) {
      // If we're leaving some (or all) variables with their old names,
      // then we need to undo any of the markers we added for distinguishing
      // local variables ("x" -> "x$jscomp$1").
      passes.add(invertContextualRenaming);
    }

    if (options.variableRenaming != VariableRenamingPolicy.OFF) {
      passes.add(renameVars);
    }

    // This pass should run after names stop changing.
    if (options.processObjectPropertyString) {
      passes.add(objectPropertyStringPostprocess);
    }

    if (options.labelRenaming) {
      passes.add(renameLabels);
    }

    if (options.foldConstants) {
      passes.add(latePeepholeOptimizations);
    }

    if (options.anonymousFunctionNaming == AnonymousFunctionNamingPolicy.UNMAPPED) {
      passes.add(nameUnmappedAnonymousFunctions);
    }

    if (protectHiddenSideEffects) {
      passes.add(stripSideEffectProtection);
    }

    if (options.renamePrefixNamespace != null) {
      if (!GLOBAL_SYMBOL_NAMESPACE_PATTERN.matcher(
          options.renamePrefixNamespace).matches()) {
        throw new IllegalArgumentException(
            "Illegal character in renamePrefixNamespace name: "
            + options.renamePrefixNamespace);
      }
      passes.add(rescopeGlobalSymbols);
    }

    // Safety checks
    passes.add(checkAstValidity);
    passes.add(varCheckValidity);

    // Raise to ES6, if allowed
    if (options.getOutputFeatureSet().contains(ES6)) {
      passes.add(optimizeToEs6);
    }

    assertValidOrderForOptimizations(passes);
    return passes;
  }

  /** Creates the passes for the main optimization loop. */
  private List<PassFactory> getMainOptimizationLoop() {
    List<PassFactory> passes = new ArrayList<PassFactory>();
    if (options.inlineGetters) {
      passes.add(inlineSimpleMethods);
    }

    passes.addAll(getCodeRemovingPasses());

    if (options.getInlineFunctionsLevel() != Reach.NONE) {
      passes.add(inlineFunctions);
    }

    if (options.shouldInlineProperties() && options.isTypecheckingEnabled()) {
      passes.add(inlineProperties);
    }

    if (options.removeUnusedVars || options.removeUnusedLocalVars) {
      if (options.deadAssignmentElimination) {
        passes.add(deadAssignmentsElimination);

        // The Polymer source is usually not included in the compilation, but it creates
        // getters/setters for many properties in compiled code. Dead property assignment
        // elimination is only safe when it knows about getters/setters. Therefore, we skip
        // it if the polymer pass is enabled.
        if (options.polymerVersion == null) {
          passes.add(deadPropertyAssignmentElimination);
        }
      }
    }

    if (options.optimizeCalls) {
      passes.add(optimizeCalls);
    }

    if (options.j2clPassMode.shouldAddJ2clPasses()) {
      passes.add(j2clConstantHoisterPass);
      passes.add(j2clClinitPass);
    }

    assertAllLoopablePasses(passes);
    return passes;
  }

  /** Creates several passes aimed at removing code. */
  private List<PassFactory> getCodeRemovingPasses() {
    List<PassFactory> passes = new ArrayList<PassFactory>();
    if (options.collapseObjectLiterals) {
      passes.add(collapseObjectLiterals);
    }

    if (options.inlineVariables || options.inlineLocalVariables) {
      passes.add(inlineVariables);
    } else if (options.inlineConstantVars) {
      passes.add(inlineConstants);
    }

    if (options.foldConstants) {
      passes.add(peepholeOptimizations);
    }

    if (options.removeDeadCode) {
      passes.add(removeUnreachableCode);
    }

    if (shouldRunRemoveUnusedCode()) {
      passes.add(removeUnusedCode);
    }

    assertAllLoopablePasses(passes);
    return passes;
  }

  private boolean shouldRunRemoveUnusedCode() {
    return options.removeUnusedVars
        || options.removeUnusedLocalVars
        || options.removeUnusedPrototypeProperties
        || options.isRemoveUnusedClassProperties()
        || options.isRemoveUnusedConstructorProperties();
  }

  private final HotSwapPassFactory checkSideEffects =
      new HotSwapPassFactory("checkSideEffects") {
        @Override
        protected HotSwapCompilerPass create(final AbstractCompiler compiler) {
          return new CheckSideEffects(
              compiler, options.checkSuspiciousCode, protectHiddenSideEffects);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES_NEXT;
        }
      };

  /** Removes the "protector" functions that were added by CheckSideEffects. */
  private final PassFactory stripSideEffectProtection =
      new PassFactory(PassNames.STRIP_SIDE_EFFECT_PROTECTION, true) {
        @Override
        protected CompilerPass create(final AbstractCompiler compiler) {
          return new CheckSideEffects.StripProtection(compiler);
        }

        @Override
        public FeatureSet featureSet() {
          return FeatureSet.latest();
        }
      };

  /** Checks for code that is probably wrong (such as stray expressions). */
  private final HotSwapPassFactory suspiciousCode =
      new HotSwapPassFactory("suspiciousCode") {
        @Override
        protected HotSwapCompilerPass create(final AbstractCompiler compiler) {
          List<Callback> sharedCallbacks = new ArrayList<Callback>();
          if (options.checkSuspiciousCode) {
            sharedCallbacks.add(new CheckSuspiciousCode());
            sharedCallbacks.add(new CheckDuplicateCase(compiler));
          }

          if (options.enables(DiagnosticGroups.GLOBAL_THIS)) {
            sharedCallbacks.add(new CheckGlobalThis(compiler));
          }

          if (options.enables(DiagnosticGroups.DEBUGGER_STATEMENT_PRESENT)) {
            sharedCallbacks.add(new CheckDebuggerStatement(compiler));
          }

          return combineChecks(compiler, sharedCallbacks);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES_NEXT;
        }
      };

  /** Verify that all the passes are one-time passes. */
  private static void assertAllOneTimePasses(List<PassFactory> passes) {
    for (PassFactory pass : passes) {
      checkState(pass.isOneTimePass());
    }
  }

  /** Verify that all the passes are multi-run passes. */
  private static void assertAllLoopablePasses(List<PassFactory> passes) {
    for (PassFactory pass : passes) {
      checkState(!pass.isOneTimePass());
    }
  }

  /**
   * Checks that {@code pass1} comes before {@code pass2} in {@code passList}, if both are present.
   */
  private void assertPassOrder(
      List<PassFactory> passList, PassFactory pass1, PassFactory pass2, String msg) {
    int pass1Index = passList.indexOf(pass1);
    int pass2Index = passList.indexOf(pass2);
    if (pass1Index != -1 && pass2Index != -1) {
      checkState(pass1Index < pass2Index, msg);
    }
  }

  /**
   * Certain checks need to run in a particular order. For example, the PolymerPass
   * will not work correctly unless it runs after the goog.provide() processing.
   * This enforces those constraints.
   * @param checks The list of check passes
   */
  private void assertValidOrderForChecks(List<PassFactory> checks) {
    assertPassOrder(
        checks,
        chromePass,
        checkJsDocAndEs6Modules,
        "The ChromePass must run before after JsDoc and Es6 module checking.");
    assertPassOrder(
        checks,
        closureRewriteModule,
        processDefines,
        "Must rewrite goog.module before processing @define's, so that @defines in modules work.");
    assertPassOrder(
        checks,
        closurePrimitives,
        polymerPass,
        "The Polymer pass must run after goog.provide processing.");
    assertPassOrder(
        checks,
        chromePass,
        polymerPass,
        "The Polymer pass must run after ChromePass processing.");
    assertPassOrder(
        checks,
        polymerPass,
        suspiciousCode,
        "The Polymer pass must run before suspiciousCode processing.");
    assertPassOrder(
        checks,
        dartSuperAccessorsPass,
        TranspilationPasses.es6ConvertSuper,
        "The Dart super accessors pass must run before ES6->ES3 super lowering.");

    if (checks.contains(closureGoogScopeAliases)) {
      checkState(
          checks.contains(checkVariableReferences),
          "goog.scope processing requires variable checking");
    }
    assertPassOrder(
        checks,
        checkVariableReferences,
        closureGoogScopeAliases,
        "Variable checking must happen before goog.scope processing.");

    assertPassOrder(
        checks,
        gatherModuleMetadataPass,
        closureCheckModule,
        "Need to gather module metadata before checking closure modules.");
  }

  /**
   * Certain optimizations need to run in a particular order. For example, OptimizeCalls must run
   * before RemoveSuperMethodsPass, because the former can invalidate assumptions in the latter.
   * This enforces those constraints.
   * @param optimizations The list of optimization passes
   */
  private void assertValidOrderForOptimizations(List<PassFactory> optimizations) {
    assertPassOrder(
        optimizations,
        processDefines,
        j2clUtilGetDefineRewriterPass,
        "J2CL define re-writing should be done after processDefines since it relies on "
            + "collectDefines which has side effects.");
  }

  /** Checks that all constructed classes are goog.require()d. */
  private final HotSwapPassFactory checkRequires =
      new HotSwapPassFactory("checkMissingAndExtraRequires") {
        @Override
        protected HotSwapCompilerPass create(AbstractCompiler compiler) {
          return new CheckMissingAndExtraRequires(
              compiler, CheckMissingAndExtraRequires.Mode.FULL_COMPILE);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES_NEXT;
        }
      };

  /** Makes sure @constructor is paired with goog.provides(). */
  private final HotSwapPassFactory checkProvides =
      new HotSwapPassFactory("checkProvides") {
        @Override
        protected HotSwapCompilerPass create(AbstractCompiler compiler) {
          return new CheckProvides(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES_NEXT;
        }
      };

  private static final DiagnosticType GENERATE_EXPORTS_ERROR =
      DiagnosticType.error(
          "JSC_GENERATE_EXPORTS_ERROR",
          "Exports can only be generated if export symbol/property functions are set.");

  /** Verifies JSDoc annotations are used properly and checks for ES6 modules. */
  private final HotSwapPassFactory checkJsDocAndEs6Modules =
      new HotSwapPassFactory("checkJsDocAndEs6Modules") {
        @Override
        protected HotSwapCompilerPass create(AbstractCompiler compiler) {
          ImmutableList.Builder<Callback> callbacks =
              ImmutableList.<Callback>builder()
                  .add(new CheckJSDoc(compiler))
                  .add(new Es6CheckModule(compiler));
          return combineChecks(compiler, callbacks.build());
        }

        @Override
        protected FeatureSet featureSet() {
          return FeatureSet.latest();
        }
      };

  /** Generates exports for @export annotations. */
  private final PassFactory generateExports =
      new PassFactory(PassNames.GENERATE_EXPORTS, true) {
        @Override
        protected CompilerPass create(final AbstractCompiler compiler) {
          CodingConvention convention = compiler.getCodingConvention();
          if (convention.getExportSymbolFunction() != null
              && convention.getExportPropertyFunction() != null) {
            final GenerateExports pass =
                new GenerateExports(
                    compiler,
                    options.exportLocalPropertyDefinitions,
                    convention.getExportSymbolFunction(),
                    convention.getExportPropertyFunction());
            return new CompilerPass() {
              @Override
              public void process(Node externs, Node root) {
                pass.process(externs, root);
                compiler.addExportedNames(pass.getExportedVariableNames());
              }
            };
          } else {
            return new ErrorPass(compiler, GENERATE_EXPORTS_ERROR);
          }
        }

        @Override
        protected FeatureSet featureSet() {
          return ES2018;
        }
      };

  private final PassFactory generateIjs =
      new PassFactory("generateIjs", true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new ConvertToTypedInterface(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  /** Generates exports for functions associated with JsUnit. */
  private final PassFactory exportTestFunctions =
      new PassFactory(PassNames.EXPORT_TEST_FUNCTIONS, true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          CodingConvention convention = compiler.getCodingConvention();
          if (convention.getExportSymbolFunction() != null) {
            return new ExportTestFunctions(
                compiler,
                convention.getExportSymbolFunction(),
                convention.getExportPropertyFunction());
          } else {
            return new ErrorPass(compiler, GENERATE_EXPORTS_ERROR);
          }
        }

        @Override
        protected FeatureSet featureSet() {
          return ES_NEXT;
        }
      };
  
  private final PassFactory extraSymbolsPass = 
    new PassFactory("extra-symbols-to-export", true) {
      @Override
      protected CompilerPass create(final AbstractCompiler compiler) {
        return new CompilerPass() {
          @Override
          public void process(Node externs, Node root) {
            Node scriptNode = compiler.getScriptNode(sourceFileName);
            for(String nameToExport : extraSymbolNamesToExport)
            {
              Node exportCallTarget = NodeUtil.newQName(compiler,
                  compiler.getCodingConvention().getExportSymbolFunction(), scriptNode, nameToExport);
              Node call = IR.call(exportCallTarget);
              if (exportCallTarget.isName()) {
                call.putBooleanProp(Node.FREE_CALL, true);
              }
              call.addChildToBack(IR.string(nameToExport));
              call.addChildToBack(NodeUtil.newQName(compiler,
              nameToExport, scriptNode, nameToExport));

              Node expression = IR.exprResult(call);

              scriptNode.addChildToBack(expression);
              compiler.reportChangeToEnclosingScope(expression);
            }
          }
        };
      }

      @Override
      protected FeatureSet featureSet() {
        return ES_NEXT;
      }
    };

  /** Raw exports processing pass. */
  private final PassFactory gatherRawExports =
      new PassFactory(PassNames.GATHER_RAW_EXPORTS, true) {
        @Override
        protected CompilerPass create(final AbstractCompiler compiler) {
          final GatherRawExports pass = new GatherRawExports(compiler);

          return new CompilerPass() {
            @Override
            public void process(Node externs, Node root) {
              pass.process(externs, root);
              compiler.addExportedNames(pass.getExportedVariableNames());
            }
          };
        }

        @Override
        public FeatureSet featureSet() {
          // Should be FeatureSet.latest() since it's a trivial pass, but must match "normalize"
          // TODO(johnlenz): Update this and normalize to latest()
          return ES8_MODULES;
        }
      };

  /** Closure pre-processing pass. */
  private final HotSwapPassFactory closurePrimitives =
      new HotSwapPassFactory("closurePrimitives") {
        @SuppressWarnings("deprecation")
		@Override
        protected HotSwapCompilerPass create(final AbstractCompiler compiler) {
          preprocessorSymbolTableFactory.maybeInitialize(compiler);
          final ProcessClosurePrimitivesWithModuleSupport pass =
              new ProcessClosurePrimitivesWithModuleSupport(
                  compiler,
                  preprocessorSymbolTableFactory.getInstanceOrNull(),
                  options.brokenClosureRequiresLevel,
                  options.shouldPreservesGoogProvidesAndRequires());

          return new HotSwapCompilerPass() {
            @Override
            public void process(Node externs, Node root) {
              pass.process(externs, root);
              compiler.addExportedNames(pass.getExportedVariableNames());
            }

            @Override
            public void hotSwapScript(Node scriptRoot, Node originalRoot) {
              pass.hotSwapScript(scriptRoot, originalRoot);
            }
          };
        }

        @Override
        protected FeatureSet featureSet() {
          return ES_NEXT;
        }
      };

  /** Process AngularJS-specific annotations. */
  private final HotSwapPassFactory angularPass =
      new HotSwapPassFactory(PassNames.ANGULAR_PASS) {
        @Override
        protected HotSwapCompilerPass create(AbstractCompiler compiler) {
          return new AngularPass(compiler);
        }

        @Override
        public FeatureSet featureSet() {
          return ES_NEXT;
        }
      };

  /**
   * The default i18n pass. A lot of the options are not configurable, because ReplaceMessages has a
   * lot of legacy logic.
   */
  private final PassFactory replaceMessages =
      new PassFactory(PassNames.REPLACE_MESSAGES, true) {
        @Override
        protected CompilerPass create(final AbstractCompiler compiler) {
          return new ReplaceMessages(
              compiler,
              options.messageBundle,
              /* warn about message dupes */
              true,
              /* allow messages with goog.getMsg */
              JsMessage.Style.CLOSURE,
              /* if we can't find a translation, don't worry about it. */
              false);
        }

        @Override
        public FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  private final PassFactory replaceMessagesForChrome =
      new PassFactory(PassNames.REPLACE_MESSAGES, true) {
        @Override
        protected CompilerPass create(final AbstractCompiler compiler) {
          return new ReplaceMessagesForChrome(
              compiler,
              new GoogleJsMessageIdGenerator(options.tcProjectId),
              /* warn about message dupes */
              true,
              /* allow messages with goog.getMsg */
              JsMessage.Style.CLOSURE);
        }

        @Override
        public FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  /** Applies aliases and inlines goog.scope. */
  private final HotSwapPassFactory closureGoogScopeAliases =
      new HotSwapPassFactory("closureGoogScopeAliases") {
        @Override
        protected HotSwapCompilerPass create(AbstractCompiler compiler) {
          preprocessorSymbolTableFactory.maybeInitialize(compiler);
          return new ScopedAliases(
              compiler,
              preprocessorSymbolTableFactory.getInstanceOrNull(),
              options.getAliasTransformationHandler());
        }

        @Override
        protected FeatureSet featureSet() {
          return ES_NEXT;
        }
      };

  private final PassFactory injectRuntimeLibraries =
      new PassFactory("InjectRuntimeLibraries", true) {
        @Override
        protected CompilerPass create(final AbstractCompiler compiler) {
          return new InjectRuntimeLibraries(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES2018;
        }
      };

  /** Desugars ES6_TYPED features into ES6 code. */
  final HotSwapPassFactory convertEs6TypedToEs6 =
      new HotSwapPassFactory("convertEs6Typed") {
        @Override
        protected HotSwapCompilerPass create(final AbstractCompiler compiler) {
          return new Es6TypedToEs6Converter(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return TYPESCRIPT;
        }
      };

  private final PassFactory convertStaticInheritance =
      new PassFactory("Es6StaticInheritance", true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new Es6ToEs3ClassSideInheritance(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return TYPE_CHECK_SUPPORTED;
        }
      };

  private final PassFactory inlineTypeAliases =
      new PassFactory(PassNames.INLINE_TYPE_ALIASES, true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new InlineAliases(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES2018;
        }
      };

  /** Inlines type aliases if they are explicitly or effectively const. */
  private final PassFactory aggressiveInlineAliases =
      new PassFactory("aggressiveInlineAliases", true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new AggressiveInlineAliases(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  private final PassFactory removeWeakSources =
      new PassFactory("removeWeakSources", true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new RemoveWeakSources(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return FeatureSet.latest();
        }
      };

  private final PassFactory declaredGlobalExternsOnWindow =
      new PassFactory(PassNames.DECLARED_GLOBAL_EXTERNS_ON_WINDOW, true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new DeclaredGlobalExternsOnWindow(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES_NEXT;
        }
      };

  /** Rewrites goog.defineClass */
  private final HotSwapPassFactory closureRewriteClass =
      new HotSwapPassFactory(PassNames.CLOSURE_REWRITE_CLASS) {
        @Override
        protected HotSwapCompilerPass create(AbstractCompiler compiler) {
          return new ClosureRewriteClass(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES_NEXT;
        }
      };

  /** Checks of correct usage of goog.module */
  private final HotSwapPassFactory closureCheckModule =
      new HotSwapPassFactory("closureCheckModule") {
        @Override
        protected HotSwapCompilerPass create(AbstractCompiler compiler) {
          return new ClosureCheckModule(compiler, compiler.getModuleMetadataMap());
        }

        @Override
        protected FeatureSet featureSet() {
          return ES_NEXT;
        }
      };

  /** Rewrites goog.module */
  private final HotSwapPassFactory closureRewriteModule =
      new HotSwapPassFactory("closureRewriteModule") {
        @Override
        protected HotSwapCompilerPass create(AbstractCompiler compiler) {
          preprocessorSymbolTableFactory.maybeInitialize(compiler);
          maybeInitializeModuleRewriteState();
          return new ClosureRewriteModule(
              compiler, preprocessorSymbolTableFactory.getInstanceOrNull(), moduleRewriteState);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES_NEXT;
        }
      };

  /** Rewrite imports for Closure Library's goog.js file to global goog references. */
  private final HotSwapPassFactory rewriteGoogJsImports =
      new HotSwapPassFactory("rewriteGoogJsImports") {
        @Override
        protected HotSwapCompilerPass create(AbstractCompiler compiler) {
          return new RewriteGoogJsImports(compiler, RewriteGoogJsImports.Mode.LINT_AND_REWRITE);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES_NEXT;
        }
      };

  /** Checks that CSS class names are wrapped in goog.getCssName */
  private final PassFactory closureCheckGetCssName =
      new PassFactory("closureCheckGetCssName", true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new CheckMissingGetCssName(
              compiler,
              options.checkMissingGetCssNameLevel,
              options.checkMissingGetCssNameBlacklist);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES_NEXT;
        }
      };

  /**
   * Processes goog.getCssName. The cssRenamingMap is used to lookup replacement values for the
   * classnames. If null, the raw class names are inlined.
   */
  private final PassFactory closureReplaceGetCssName =
      new PassFactory("closureReplaceGetCssName", true) {
        @Override
        protected CompilerPass create(final AbstractCompiler compiler) {
          return new CompilerPass() {
            @Override
            public void process(Node externs, Node jsRoot) {
              Map<String, Integer> newCssNames = null;
              if (options.gatherCssNames) {
                newCssNames = new HashMap<String, Integer>();
              }
              ReplaceCssNames pass =
                  new ReplaceCssNames(compiler, newCssNames, options.cssRenamingWhitelist);
              pass.process(externs, jsRoot);
              compiler.setCssNames(newCssNames);
            }
          };
        }

        @Override
        protected FeatureSet featureSet() {
          return ES2018;
        }
      };

  /**
   * Creates synthetic blocks to prevent FoldConstants from moving code past markers in the source.
   */
  private final PassFactory createSyntheticBlocks =
      new PassFactory("createSyntheticBlocks", true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new CreateSyntheticBlocks(
              compiler, options.syntheticBlockStartMarker, options.syntheticBlockEndMarker);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES_NEXT;
        }
      };

  private final PassFactory earlyPeepholeOptimizations =
      new PassFactory("earlyPeepholeOptimizations", true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          List<AbstractPeepholeOptimization> peepholeOptimizations = new ArrayList<AbstractPeepholeOptimization>();
          peepholeOptimizations.add(new PeepholeRemoveDeadCode());
          if (compiler.getOptions().j2clPassMode.shouldAddJ2clPasses()) {
            peepholeOptimizations.add(new J2clEqualitySameRewriterPass());
          }
          return new PeepholeOptimizationsPass(compiler, getName(), peepholeOptimizations);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  private final PassFactory earlyInlineVariables =
      new PassFactory("earlyInlineVariables", true) {
    @Override
    protected CompilerPass create(AbstractCompiler compiler) {
      InlineVariables.Mode mode;
      if (options.inlineVariables) {
        mode = InlineVariables.Mode.ALL;
      } else if (options.inlineLocalVariables) {
        mode = InlineVariables.Mode.LOCALS_ONLY;
      } else {
        throw new IllegalStateException("No variable inlining option set.");
      }
      return new InlineVariables(compiler, mode, true);
    }

    @Override
    protected FeatureSet featureSet() {
      return ES8_MODULES;
    }
  };

  /** Various peephole optimizations. */
  private static CompilerPass createPeepholeOptimizationsPass(
      AbstractCompiler compiler, String passName) {
    final boolean late = false;
    final boolean useTypesForOptimization = compiler.getOptions().useTypesForLocalOptimization;
    List<AbstractPeepholeOptimization> optimizations = new ArrayList<AbstractPeepholeOptimization>();
    optimizations.add(new MinimizeExitPoints());
    optimizations.add(new PeepholeMinimizeConditions(late));
    optimizations.add(new PeepholeSubstituteAlternateSyntax(late));
    optimizations.add(new PeepholeReplaceKnownMethods(late, useTypesForOptimization));
    optimizations.add(new PeepholeRemoveDeadCode());
    if (compiler.getOptions().j2clPassMode.shouldAddJ2clPasses()) {
      optimizations.add(new J2clEqualitySameRewriterPass());
      optimizations.add(new J2clStringValueOfRewriterPass());
    }
    optimizations.add(new PeepholeFoldConstants(late, useTypesForOptimization));
    optimizations.add(new PeepholeCollectPropertyAssignments());
    return new PeepholeOptimizationsPass(compiler, passName, optimizations);
  }

  /** Various peephole optimizations. */
  private final PassFactory peepholeOptimizations =
      new PassFactory(PassNames.PEEPHOLE_OPTIMIZATIONS, false /* oneTimePass */) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return createPeepholeOptimizationsPass(compiler, getName());
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  /** Various peephole optimizations. */
  private final PassFactory peepholeOptimizationsOnce =
      new PassFactory(PassNames.PEEPHOLE_OPTIMIZATIONS, true /* oneTimePass */) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return createPeepholeOptimizationsPass(compiler, getName());
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  /** Same as peepholeOptimizations but aggressively merges code together */
  private final PassFactory latePeepholeOptimizations =
      new PassFactory("latePeepholeOptimizations", true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          final boolean late = true;
          final boolean useTypesForOptimization = options.useTypesForLocalOptimization;
          return new PeepholeOptimizationsPass(
              compiler,
              getName(),
              new StatementFusion(options.aggressiveFusion),
              new PeepholeRemoveDeadCode(),
              new PeepholeMinimizeConditions(late),
              new PeepholeSubstituteAlternateSyntax(late),
              new PeepholeReplaceKnownMethods(late, useTypesForOptimization),
              new PeepholeFoldConstants(late, useTypesForOptimization),
              new PeepholeReorderConstantExpression());
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  /** Checks that all variables are defined. */
  private final HotSwapPassFactory checkVars =
      new HotSwapPassFactory(PassNames.CHECK_VARS) {
        @Override
        protected HotSwapCompilerPass create(AbstractCompiler compiler) {
          return new VarCheck(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES_NEXT;
        }
      };

  /** Infers constants. */
  private final PassFactory inferConsts =
      new PassFactory(PassNames.INFER_CONSTS, true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new InferConsts(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES_NEXT;
        }
      };

  /** Checks for RegExp references. */
  private final PassFactory checkRegExp =
      new PassFactory(PassNames.CHECK_REG_EXP, true) {
        @Override
        protected CompilerPass create(final AbstractCompiler compiler) {
          final CheckRegExp pass = new CheckRegExp(compiler);

          return new CompilerPass() {
            @Override
            public void process(Node externs, Node root) {
              pass.process(externs, root);
              compiler.setHasRegExpGlobalReferences(pass.isGlobalRegExpPropertiesUsed());
            }
          };
        }

        @Override
        protected FeatureSet featureSet() {
          return ES_NEXT;
        }
      };

  /** Checks that references to variables look reasonable. */
  private final HotSwapPassFactory checkVariableReferencesForTranspileOnly =
      new HotSwapPassFactory(PassNames.CHECK_VARIABLE_REFERENCES) {
        @Override
        protected HotSwapCompilerPass create(AbstractCompiler compiler) {
          return new VariableReferenceCheck(compiler, true);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  /** Checks that references to variables look reasonable. */
  private final HotSwapPassFactory checkVariableReferences =
      new HotSwapPassFactory(PassNames.CHECK_VARIABLE_REFERENCES) {
        @Override
        protected HotSwapCompilerPass create(AbstractCompiler compiler) {
          return new VariableReferenceCheck(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES_NEXT;
        }
      };

  /** Checks that references to variables look reasonable. */
  private final HotSwapPassFactory checkSuper =
      new HotSwapPassFactory("checkSuper") {
        @Override
        protected HotSwapCompilerPass create(AbstractCompiler compiler) {
          return new CheckSuper(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES_NEXT;
        }
      };

  /** Pre-process goog.testing.ObjectPropertyString. */
  private final PassFactory objectPropertyStringPreprocess =
      new PassFactory("ObjectPropertyStringPreprocess", true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new ObjectPropertyStringPreprocess(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES_NEXT;
        }
      };

  /** Creates a typed scope and adds types to the type registry. */
  final HotSwapPassFactory resolveTypes =
      new HotSwapPassFactory(PassNames.RESOLVE_TYPES) {
        @Override
        protected HotSwapCompilerPass create(AbstractCompiler compiler) {
          return new GlobalTypeResolver(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return TYPE_CHECK_SUPPORTED;
        }
      };

  /** Clears the typed scope when we're done. */
  private final PassFactory clearTypedScopePass =
      new PassFactory("clearTypedScopePass", true) {
    @Override
    protected CompilerPass create(AbstractCompiler compiler) {
      return new ClearTypedScope();
    }

    @Override
    protected FeatureSet featureSet() {
      return FeatureSet.latest();
    }
  };

  /** Runs type inference. */
  final HotSwapPassFactory inferTypes =
      new HotSwapPassFactory(PassNames.INFER_TYPES) {
        @Override
        protected HotSwapCompilerPass create(final AbstractCompiler compiler) {
          return new HotSwapCompilerPass() {
            @Override
            public void process(Node externs, Node root) {
              checkNotNull(topScope);
              checkNotNull(getTypedScopeCreator());

              makeTypeInference(compiler).process(externs, root);
            }

            @Override
            public void hotSwapScript(Node scriptRoot, Node originalRoot) {
              makeTypeInference(compiler).inferAllScopes(scriptRoot);
            }
          };
        }

        @Override
        protected FeatureSet featureSet() {
          return TYPE_CHECK_SUPPORTED;
        }
      };

  private final HotSwapPassFactory inferJsDocInfo =
      new HotSwapPassFactory("inferJsDocInfo") {
        @Override
        protected HotSwapCompilerPass create(final AbstractCompiler compiler) {
          return new HotSwapCompilerPass() {
            @Override
            public void process(Node externs, Node root) {
              checkNotNull(topScope);
              checkNotNull(getTypedScopeCreator());

              makeInferJsDocInfo(compiler).process(externs, root);
            }

            @Override
            public void hotSwapScript(Node scriptRoot, Node originalRoot) {
              makeInferJsDocInfo(compiler).hotSwapScript(scriptRoot, originalRoot);
            }
          };
        }

        @Override
        protected FeatureSet featureSet() {
          return TYPE_CHECK_SUPPORTED;
        }
      };

  /** Checks type usage */
  private final HotSwapPassFactory checkTypes =
      new HotSwapPassFactory(PassNames.CHECK_TYPES) {
        @Override
        protected HotSwapCompilerPass create(final AbstractCompiler compiler) {
          return new HotSwapCompilerPass() {
            @Override
            public void process(Node externs, Node root) {
              checkNotNull(topScope);
              checkNotNull(getTypedScopeCreator());

              TypeCheck check = makeTypeCheck(compiler);
              check.process(externs, root);
              compiler.getErrorManager().setTypedPercent(check.getTypedPercent());
            }

            @Override
            public void hotSwapScript(Node scriptRoot, Node originalRoot) {
              makeTypeCheck(compiler).check(scriptRoot, false);
            }
          };
        }

        @Override
        protected FeatureSet featureSet() {
          return TYPE_CHECK_SUPPORTED;
        }
      };

  /**
   * Checks possible execution paths of the program for problems: missing return statements and dead
   * code.
   */
  private final HotSwapPassFactory checkControlFlow =
      new HotSwapPassFactory("checkControlFlow") {
        @Override
        protected HotSwapCompilerPass create(AbstractCompiler compiler) {
          List<Callback> callbacks = new ArrayList<Callback>();
          if (!options.disables(DiagnosticGroups.CHECK_USELESS_CODE)) {
            callbacks.add(new CheckUnreachableCode(compiler));
          }
          if (!options.disables(DiagnosticGroups.MISSING_RETURN)) {
            callbacks.add(new CheckMissingReturn(compiler));
          }
          return combineChecks(compiler, callbacks);
        }

        @Override
        public FeatureSet featureSet() {
          return ES2018;
        }
      };

  /** Checks access controls. Depends on type-inference. */
  /*
  private final HotSwapPassFactory checkAccessControls =
      new HotSwapPassFactory("checkAccessControls") {
    @Override
    protected HotSwapCompilerPass create(AbstractCompiler compiler) {
      return new CheckAccessControls(
          compiler, options.enforceAccessControlCodingConventions);
    }

    @Override
    protected FeatureSet featureSet() {
      return TYPE_CHECK_SUPPORTED;
    }
  };*/

  private final HotSwapPassFactory lintChecks =
      new HotSwapPassFactory(PassNames.LINT_CHECKS) {
        @Override
        protected HotSwapCompilerPass create(AbstractCompiler compiler) {
          ImmutableList.Builder<Callback> callbacks =
              ImmutableList.<Callback>builder()
                  .add(new CheckEmptyStatements(compiler))
                  .add(new CheckEnums(compiler))
                  .add(new CheckEs6ModuleFileStructure(compiler))
                  .add(new CheckEs6Modules(compiler))
                  .add(new CheckNoMutatedEs6Exports(compiler))
                  .add(new CheckInterfaces(compiler))
                  .add(new CheckJSDocStyle(compiler))
                  .add(new CheckMissingSemicolon(compiler))
                  .add(new CheckNullabilityModifiers(compiler))
                  .add(new CheckPrimitiveAsObject(compiler))
                  .add(new CheckPrototypeProperties(compiler))
                  .add(new CheckUnusedLabels(compiler))
                  .add(new CheckUselessBlocks(compiler));
          return combineChecks(compiler, callbacks.build());
        }

        @Override
        protected FeatureSet featureSet() {
          return ES_NEXT;
        }
      };

  private final HotSwapPassFactory analyzerChecks =
      new HotSwapPassFactory(PassNames.ANALYZER_CHECKS) {
        @Override
        protected HotSwapCompilerPass create(AbstractCompiler compiler) {
          ImmutableList.Builder<Callback> callbacks = ImmutableList.builder();
          if (options.enables(DiagnosticGroups.ANALYZER_CHECKS_INTERNAL)) {
            callbacks
                .add(new CheckNullableReturn(compiler))
                .add(new CheckArrayWithGoogObject(compiler))
                .add(new ImplicitNullabilityCheck(compiler));
          }
          // These are grouped together for better execution efficiency.
          if (options.enables(DiagnosticGroups.UNUSED_PRIVATE_PROPERTY)) {
            callbacks.add(new CheckUnusedPrivateProperties(compiler));
          }
          if (options.enables(DiagnosticGroups.MISSING_CONST_PROPERTY)) {
            callbacks.add(new CheckConstPrivateProperties(compiler));
          }
          return combineChecks(compiler, callbacks.build());
        }

        @Override
        protected FeatureSet featureSet() {
          return TYPE_CHECK_SUPPORTED;
        }
      };

  private final HotSwapPassFactory checkRequiresAndProvidesSorted =
      new HotSwapPassFactory("checkRequiresAndProvidesSorted") {
        @Override
        protected HotSwapCompilerPass create(AbstractCompiler compiler) {
          return new CheckRequiresAndProvidesSorted(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES_NEXT;
        }
      };

  /** Executes the given callbacks with a {@link CombinedCompilerPass}. */
  private static HotSwapCompilerPass combineChecks(AbstractCompiler compiler,
      List<Callback> callbacks) {
    checkArgument(!callbacks.isEmpty());
    return new CombinedCompilerPass(compiler, callbacks);
  }

  /** A compiler pass that resolves types in the global scope. */
  class GlobalTypeResolver implements HotSwapCompilerPass {
    private final AbstractCompiler compiler;

    GlobalTypeResolver(AbstractCompiler compiler) {
      this.compiler = compiler;
    }

    @Override
    public void process(Node externs, Node root) {
      this.compiler.setTypeCheckingHasRun(true);
      if (topScope == null) {
        regenerateGlobalTypedScope(compiler, root.getParent());
      } else {
        compiler.getTypeRegistry().resolveTypes();
      }
    }
    @Override
    public void hotSwapScript(Node scriptRoot, Node originalRoot) {
      patchGlobalTypedScope(compiler, scriptRoot);
    }
  }

  /** A compiler pass that clears the global scope. */
  class ClearTypedScope implements CompilerPass {
    @Override
    public void process(Node externs, Node root) {
      clearTypedScope();
    }
  }

  /** Checks global name usage. */
  private final PassFactory checkGlobalNames =
      new PassFactory("checkGlobalNames", true) {
    @Override
    protected CompilerPass create(final AbstractCompiler compiler) {
      return new CompilerPass() {
        @Override
        public void process(Node externs, Node jsRoot) {
          // Create a global namespace for analysis by check passes.
          // Note that this class does all heavy computation lazily,
          // so it's OK to create it here.
          namespaceForChecks = new GlobalNamespace(compiler, externs, jsRoot);
          new CheckGlobalNames(compiler, options.checkGlobalNamesLevel)
              .injectNamespace(namespaceForChecks).process(externs, jsRoot);
        }
      };
    }

    @Override
    protected FeatureSet featureSet() {
      return TYPE_CHECK_SUPPORTED;
    }
  };

  /** Checks that the code is ES5 strict compliant. */
  private final PassFactory checkStrictMode =
      new PassFactory("checkStrictMode", true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new StrictModeCheck(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES_NEXT;
        }
      };

  /** Process goog.tweak.getTweak() calls. */
  private final PassFactory processTweaks = new PassFactory("processTweaks", true) {
    @Override
    protected CompilerPass create(final AbstractCompiler compiler) {
      return new CompilerPass() {
        @Override
        public void process(Node externs, Node jsRoot) {
          new ProcessTweaks(compiler,
              options.getTweakProcessing().shouldStrip(),
              options.getTweakReplacements()).process(externs, jsRoot);
        }
      };
    }

    @Override
    protected FeatureSet featureSet() {
      return TYPE_CHECK_SUPPORTED;
    }
  };

  /** Override @define-annotated constants. */
  private final PassFactory processDefines =
      new PassFactory("processDefines", true) {
        @Override
        protected CompilerPass create(final AbstractCompiler compiler) {
          return new CompilerPass() {
            @Override
            public void process(Node externs, Node jsRoot) {
              HashMap<String, Node> replacements = new HashMap<String, Node>();
              replacements.putAll(compiler.getDefaultDefineValues());
              replacements.putAll(getAdditionalReplacements(options));
              replacements.putAll(options.getDefineReplacements());
              new ProcessDefines(compiler, ImmutableMap.copyOf(replacements), !options.checksOnly)
                  .injectNamespace(namespaceForChecks)
                  .process(externs, jsRoot);
            }
          };
        }

        @Override
        public FeatureSet featureSet() {
          return TYPE_CHECK_SUPPORTED;
        }
      };

  /**
   * Strips code for smaller compiled code. This is useful for removing debug
   * statements to prevent leaking them publicly.
   */
  private final PassFactory stripCode = new PassFactory("stripCode", true) {
    @Override
    protected CompilerPass create(final AbstractCompiler compiler) {
      return new CompilerPass() {
        @Override
        public void process(Node externs, Node jsRoot) {
          CompilerOptions options = compiler.getOptions();
          StripCode pass = new StripCode(compiler, options.stripTypes, options.stripNameSuffixes,
              options.stripTypePrefixes, options.stripNamePrefixes);
          if (options.getTweakProcessing().shouldStrip()) {
            pass.enableTweakStripping();
          }
          pass.process(externs, jsRoot);
        }
      };
    }

    @Override
    protected FeatureSet featureSet() {
      return ES8_MODULES;
    }
  };

  /** Release references to data that is only needed during checks. */
  final PassFactory garbageCollectChecks =
      new HotSwapPassFactory("garbageCollectChecks") {
    @Override
    protected HotSwapCompilerPass create(final AbstractCompiler compiler) {
      return new HotSwapCompilerPass() {
        @Override
        public void process(Node externs, Node jsRoot) {
          // Kill the global namespace so that it can be garbage collected
          // after all passes are through with it.
          namespaceForChecks = null;
        }

        @Override
        public void hotSwapScript(Node scriptRoot, Node originalRoot) {
          process(null, null);
        }
      };
    }

    @Override
    public FeatureSet featureSet() {
      return FeatureSet.latest();
    }
  };

  /** Checks that all constants are not modified */
  /*
  private final PassFactory checkConsts =
      new PassFactory("checkConsts", true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new ConstCheck(compiler);
        }

        @Override
        public FeatureSet featureSet() {
          return ES2018;
        }
      };*/

  /** Checks that the arguments are constants */
  private final PassFactory checkConstParams =
      new PassFactory(PassNames.CHECK_CONST_PARAMS, true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new ConstParamCheck(compiler);
        }

        @Override
        public FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  /** Computes the names of functions for later analysis. */
  private final PassFactory computeFunctionNames =
      new PassFactory("computeFunctionNames", true) {
        @Override
        protected CompilerPass create(final AbstractCompiler compiler) {
          return new CompilerPass() {
            @Override
            public void process(Node externs, Node root) {
              CollectFunctionNames pass = new CollectFunctionNames(compiler);
              pass.process(externs, root);
              compiler.setFunctionNames(pass.getFunctionNames());
            }
          };
        }

        @Override
        public FeatureSet featureSet() {
          return ES2018;
        }
      };

  /** Inserts run-time type assertions for debugging. */
  private final PassFactory runtimeTypeCheck =
      new PassFactory(PassNames.RUNTIME_TYPE_CHECK, true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new RuntimeTypeCheck(compiler, options.runtimeTypeCheckLogFunction);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES5;
        }
      };

  /** Generates unique ids. */
  private final PassFactory replaceIdGenerators =
      new PassFactory(PassNames.REPLACE_ID_GENERATORS, true) {
        @Override
        protected CompilerPass create(final AbstractCompiler compiler) {
          return new CompilerPass() {
            @Override
            public void process(Node externs, Node root) {
              ReplaceIdGenerators pass =
                  new ReplaceIdGenerators(
                      compiler,
                      options.idGenerators,
                      options.generatePseudoNames,
                      options.idGeneratorsMapSerialized,
                      options.xidHashFunction);
              pass.process(externs, root);
              compiler.setIdGeneratorMap(pass.getSerializedIdMappings());
            }
          };
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  /** Replace strings. */
  private final PassFactory replaceStrings =
      new PassFactory("replaceStrings", true) {
        @Override
        protected CompilerPass create(final AbstractCompiler compiler) {
          return new CompilerPass() {
            @Override
            public void process(Node externs, Node root) {
              ReplaceStrings pass =
                  new ReplaceStrings(
                      compiler,
                      options.replaceStringsPlaceholderToken,
                      options.replaceStringsFunctionDescriptions,
                      options.replaceStringsReservedStrings,
                      options.replaceStringsInputMap);
              pass.process(externs, root);
              compiler.setStringMap(pass.getStringMap());
            }
          };
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  /** Optimizes the "arguments" array. */
  private final PassFactory optimizeArgumentsArray =
      new PassFactory(PassNames.OPTIMIZE_ARGUMENTS_ARRAY, true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new OptimizeArgumentsArray(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  /** Remove variables set to goog.abstractMethod. */
  private final PassFactory closureCodeRemoval =
      new PassFactory("closureCodeRemoval", true) {
    @Override
    protected CompilerPass create(final AbstractCompiler compiler) {
      return new ClosureCodeRemoval(compiler, options.removeAbstractMethods,
          options.removeClosureAsserts);
    }

    @Override
    protected FeatureSet featureSet() {
      return ES8_MODULES;
    }
  };

  /** Special case optimizations for closure functions. */
  private final PassFactory closureOptimizePrimitives =
      new PassFactory("closureOptimizePrimitives", true) {
        @Override
        protected CompilerPass create(final AbstractCompiler compiler) {
          return new ClosureOptimizePrimitives(
              compiler,
              compiler.getOptions().propertyRenaming == PropertyRenamingPolicy.ALL_UNQUOTED,
              compiler.getOptions().getOutputFeatureSet().contains(ES6));
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  /** Puts global symbols into a single object. */
  private final PassFactory rescopeGlobalSymbols =
      new PassFactory("rescopeGlobalSymbols", true) {
    @Override
    protected CompilerPass create(AbstractCompiler compiler) {
      return new RescopeGlobalSymbols(
          compiler,
          options.renamePrefixNamespace,
          options.renamePrefixNamespaceAssumeCrossChunkNames);
    }

    @Override
    protected FeatureSet featureSet() {
      return ES8_MODULES;
    }
  };

  /** Collapses names in the global scope. */
  private final PassFactory collapseProperties =
      new PassFactory(PassNames.COLLAPSE_PROPERTIES, true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new CollapsePropertiesWithModuleSupport(compiler, options.getPropertyCollapseLevel(), sourceFileName, varRenameMapFile);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  /** Rewrite properties as variables. */
  private final PassFactory collapseObjectLiterals =
      new PassFactory(PassNames.COLLAPSE_OBJECT_LITERALS, false) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new InlineObjectLiterals(compiler, compiler.getUniqueNameIdSupplier());
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  /** Disambiguate property names based on the coding convention. */
  private final PassFactory disambiguatePrivateProperties =
      new PassFactory(PassNames.DISAMBIGUATE_PRIVATE_PROPERTIES, true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new DisambiguatePrivateProperties(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  /** Disambiguate property names based on type information. */
  private final PassFactory disambiguateProperties =
      new PassFactory(PassNames.DISAMBIGUATE_PROPERTIES, true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new DisambiguateProperties(compiler, options.propertyInvalidationErrors);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  /** Rewrite instance methods as static methods, to make them easier to inline. */
  private final PassFactory devirtualizePrototypeMethods =
      new PassFactory(PassNames.DEVIRTUALIZE_PROTOTYPE_METHODS, true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          OptimizeCalls passes = new OptimizeCalls(compiler);
          passes.addPass(new DevirtualizePrototypeMethods(compiler));
          return passes;
        }

        @Override
        protected FeatureSet featureSet() {
          return ES5;
        }
      };

  /**
   * Optimizes unused function arguments, unused return values, and inlines constant parameters.
   * Also runs RemoveUnusedCode.
   */
  private final PassFactory optimizeCalls =
      new PassFactory(PassNames.OPTIMIZE_CALLS, false) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          OptimizeCalls passes = new OptimizeCalls(compiler);
          // Remove unused return values.
          passes.addPass(new OptimizeReturns(compiler));
          // Remove all parameters that are constants or unused.
          passes.addPass(new OptimizeParameters(compiler));
          return passes;
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  /**
   * Look for function calls that are pure, and annotate them
   * that way.
   */
  private final PassFactory markPureFunctions =
      new PassFactory("markPureFunctions", true) {
    @Override
    protected CompilerPass create(AbstractCompiler compiler) {
      return new PureFunctionIdentifier.Driver(
          compiler, options.debugFunctionSideEffectsPath);
    }

    @Override
    protected FeatureSet featureSet() {
      return ES8_MODULES;
    }
  };

  /** Look for function calls that have no side effects, and annotate them that way. */
  private final PassFactory markNoSideEffectCalls =
      new PassFactory(PassNames.MARK_NO_SIDE_EFFECT_CALLS, true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new MarkNoSideEffectCalls(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES5;
        }
      };

  /** Inlines variables heuristically. */
  private final PassFactory inlineVariables =
      new PassFactory(PassNames.INLINE_VARIABLES, false) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          InlineVariables.Mode mode;
          if (options.inlineVariables) {
            mode = InlineVariables.Mode.ALL;
          } else if (options.inlineLocalVariables) {
            mode = InlineVariables.Mode.LOCALS_ONLY;
          } else {
            throw new IllegalStateException("No variable inlining option set.");
          }
          return new InlineVariables(compiler, mode, true);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  /** Inlines variables that are marked as constants. */
  private final PassFactory inlineConstants =
      new PassFactory("inlineConstants", false) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new InlineVariables(compiler, InlineVariables.Mode.CONSTANTS_ONLY, true);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  /** Use data flow analysis to remove dead branches. */
  private final PassFactory removeUnreachableCode =
      new PassFactory(PassNames.REMOVE_UNREACHABLE_CODE, false) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new UnreachableCodeElimination(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8;
        }
      };

  /**
   * Use data flow analysis to remove dead branches.
   */
  private final PassFactory removeUnusedPolyfills =
      new PassFactory("removeUnusedPolyfills", true) {
    @Override
    protected CompilerPass create(AbstractCompiler compiler) {
      return new RemoveUnusedPolyfills(compiler);
    }

    @Override
    protected FeatureSet featureSet() {
      return ES8_MODULES;
    }
  };

  /** Inlines simple methods, like getters */
  private final PassFactory inlineSimpleMethods =
      new PassFactory("inlineSimpleMethods", false) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new InlineSimpleMethods(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  /** Kills dead assignments. */
  private final PassFactory deadAssignmentsElimination =
      new PassFactory(PassNames.DEAD_ASSIGNMENT_ELIMINATION, false) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new DeadAssignmentsElimination(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  /** Kills dead property assignments. */
  private final PassFactory deadPropertyAssignmentElimination =
      new PassFactory("deadPropertyAssignmentElimination", false) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new DeadPropertyAssignmentElimination(compiler);
        }

        @Override
        public FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  /** Inlines function calls. */
  private final PassFactory inlineFunctions =
      new PassFactory(PassNames.INLINE_FUNCTIONS, false) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new InlineFunctions(
              compiler,
              compiler.getUniqueNameIdSupplier(),
              options.getInlineFunctionsLevel(),
              options.assumeStrictThis() || options.expectStrictModeInput(),
              options.assumeClosuresOnlyCaptureReferences,
              options.maxFunctionSizeAfterInlining);
        }

        @Override
        public FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  /** Inlines constant properties. */
  private final PassFactory inlineProperties =
      new PassFactory(PassNames.INLINE_PROPERTIES, false) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new InlineProperties(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES5;
        }
      };

  private final PassFactory removeUnusedCodeOnce = getRemoveUnusedCode(true /* isOneTimePass */);
  private final PassFactory removeUnusedCode = getRemoveUnusedCode(false /* isOneTimePass */);

  private PassFactory getRemoveUnusedCode(boolean isOneTimePass) {
    /** Removes variables that are never used. */
    return new PassFactory(PassNames.REMOVE_UNUSED_CODE, isOneTimePass) {
      @Override
      protected CompilerPass create(AbstractCompiler compiler) {
        boolean preserveAnonymousFunctionNames =
            options.anonymousFunctionNaming != AnonymousFunctionNamingPolicy.OFF;
        return new RemoveUnusedCode.Builder(compiler)
            .removeLocalVars(options.removeUnusedLocalVars)
            .removeGlobals(options.removeUnusedVars)
            .preserveFunctionExpressionNames(preserveAnonymousFunctionNames)
            .removeUnusedPrototypeProperties(options.removeUnusedPrototypeProperties)
            .allowRemovalOfExternProperties(options.removeUnusedPrototypePropertiesInExterns)
            .removeUnusedThisProperties(options.isRemoveUnusedClassProperties())
            .removeUnusedObjectDefinePropertiesDefinitions(options.isRemoveUnusedClassProperties())
            .removeUnusedConstructorProperties(options.isRemoveUnusedConstructorProperties())
            .build();
      }

      @Override
      public FeatureSet featureSet() {
        return ES8_MODULES;
      }
    };

  }

  /** Move global symbols to a deeper common module */
  private final PassFactory crossModuleCodeMotion =
      new PassFactory(PassNames.CROSS_CHUNK_CODE_MOTION, false) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new CrossChunkCodeMotion(
              compiler,
              compiler.getModuleGraph(),
              options.parentChunkCanSeeSymbolsDeclaredInChildren);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  /** Move methods to a deeper common module */
  private final PassFactory crossModuleMethodMotion =
      new PassFactory(PassNames.CROSS_CHUNK_METHOD_MOTION, false) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new CrossChunkMethodMotion(
              compiler,
              compiler.getCrossModuleIdGenerator(),
              // Only move properties in externs if we're not treating
              // them as exports.
              options.removeUnusedPrototypePropertiesInExterns,
              options.crossChunkCodeMotionNoStubMethods);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  /** A data-flow based variable inliner. */
  private final PassFactory flowSensitiveInlineVariables =
      new PassFactory(PassNames.FLOW_SENSITIVE_INLINE_VARIABLES, true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new FlowSensitiveInlineVariables(compiler);
        }

        @Override
        public FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  /** Uses register-allocation algorithms to use fewer variables. */
  private final PassFactory coalesceVariableNames =
      new PassFactory(PassNames.COALESCE_VARIABLE_NAMES, true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new CoalesceVariableNames(compiler, options.generatePseudoNames);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  /** Some simple, local collapses (e.g., {@code var x; var y;} becomes {@code var x,y;}. */
  private final PassFactory exploitAssign =
      new PassFactory(PassNames.EXPLOIT_ASSIGN, true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new PeepholeOptimizationsPass(compiler, getName(), new ExploitAssigns());
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  /** Some simple, local collapses (e.g., {@code var x; var y;} becomes {@code var x,y;}. */
  private final PassFactory collapseVariableDeclarations =
      new PassFactory(PassNames.COLLAPSE_VARIABLE_DECLARATIONS, true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new CollapseVariableDeclarations(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  /** Extracts common sub-expressions. */
  private final PassFactory extractPrototypeMemberDeclarations =
      new PassFactory(PassNames.EXTRACT_PROTOTYPE_MEMBER_DECLARATIONS, true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          Pattern pattern;
          switch (options.extractPrototypeMemberDeclarations) {
            case USE_GLOBAL_TEMP:
              pattern = Pattern.USE_GLOBAL_TEMP;
              break;
            case USE_IIFE:
              pattern = Pattern.USE_IIFE;
              break;
            default:
              throw new IllegalStateException("unexpected");
          }

          return new ExtractPrototypeMemberDeclarations(compiler, pattern);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8;
        }
      };

  /** Rewrites common function definitions to be more compact. */
  private final PassFactory rewriteFunctionExpressions =
      new PassFactory(PassNames.REWRITE_FUNCTION_EXPRESSIONS, true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new FunctionRewriter(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return FeatureSet.latest();
        }
      };

  /** Collapses functions to not use the VAR keyword. */
  private final PassFactory collapseAnonymousFunctions =
      new PassFactory(PassNames.COLLAPSE_ANONYMOUS_FUNCTIONS, true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new CollapseAnonymousFunctions(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  /** Moves function declarations to the top, to simulate actual hoisting. */
  private final PassFactory moveFunctionDeclarations =
      new PassFactory(PassNames.MOVE_FUNCTION_DECLARATIONS, true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new MoveFunctionDeclarations(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8;
        }
      };

  private final PassFactory nameUnmappedAnonymousFunctions =
      new PassFactory(PassNames.NAME_ANONYMOUS_FUNCTIONS, true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new NameAnonymousFunctions(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  private final PassFactory nameMappedAnonymousFunctions =
      new PassFactory(PassNames.NAME_ANONYMOUS_FUNCTIONS, true) {
        @Override
        protected CompilerPass create(final AbstractCompiler compiler) {
          return new CompilerPass() {
            @Override
            public void process(Node externs, Node root) {
              NameAnonymousFunctionsMapped naf =
                  new NameAnonymousFunctionsMapped(
                      compiler, options.inputAnonymousFunctionNamingMap);
              naf.process(externs, root);
              compiler.setAnonymousFunctionNameMap(naf.getFunctionMap());
            }
          };
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  /**
   * Alias string literals with global variables, to avoid creating lots of
   * transient objects.
   */
  private final PassFactory aliasStrings = new PassFactory("aliasStrings", true) {
    @Override
    protected CompilerPass create(AbstractCompiler compiler) {
      return new AliasStrings(
          compiler,
          compiler.getModuleGraph(),
          options.aliasAllStrings ? null : options.aliasableStrings,
          options.aliasStringsBlacklist,
          options.outputJsStringUsage);
    }

    @Override
    protected FeatureSet featureSet() {
      return ES8_MODULES;
    }
  };

  /** Handling for the ObjectPropertyString primitive. */
  private final PassFactory objectPropertyStringPostprocess =
      new PassFactory("ObjectPropertyStringPostprocess", true) {
    @Override
    protected CompilerPass create(AbstractCompiler compiler) {
      return new ObjectPropertyStringPostprocess(compiler);
    }

    @Override
    protected FeatureSet featureSet() {
      return ES5;
    }
  };

  /**
   * Renames properties so that the two properties that never appear on the same object get the same
   * name.
   */
  private final PassFactory ambiguateProperties =
      new PassFactory(PassNames.AMBIGUATE_PROPERTIES, true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new AmbiguateProperties(
              compiler,
              options.getPropertyReservedNamingFirstChars(),
              options.getPropertyReservedNamingNonFirstChars());
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  /** Mark the point at which the normalized AST assumptions no longer hold. */
  private final PassFactory markUnnormalized =
      new PassFactory("markUnnormalized", true) {
        @Override
        protected CompilerPass create(final AbstractCompiler compiler) {
          return new CompilerPass() {
            @Override
            public void process(Node externs, Node root) {
              compiler.setLifeCycleStage(LifeCycleStage.RAW);
            }
          };
        }

        @Override
        protected FeatureSet featureSet() {
          return FeatureSet.latest();
        }
      };

  private final PassFactory normalize =
      new PassFactory(PassNames.NORMALIZE, true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new Normalize(compiler, false);
        }

        @Override
        protected FeatureSet featureSet() {
          // TODO(johnlenz): Update this and gatherRawExports to latest()
          return ES8_MODULES;
        }
      };

  private final PassFactory externExports =
      new PassFactory(PassNames.EXTERN_EXPORTS, true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new ExternExportsPass(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES5;
        }
      };

  /** Denormalize the AST for code generation. */
  private final PassFactory denormalize = new PassFactory("denormalize", true) {
    @Override
    protected CompilerPass create(AbstractCompiler compiler) {
      return new Denormalize(compiler);
    }

    @Override
    protected FeatureSet featureSet() {
      return ES8_MODULES;
    }
  };

  /** Inverting name normalization. */
  private final PassFactory invertContextualRenaming =
      new PassFactory("invertContextualRenaming", true) {
    @Override
    protected CompilerPass create(AbstractCompiler compiler) {
      return MakeDeclaredNamesUnique.getContextualRenameInverter(compiler);
    }

    @Override
    protected FeatureSet featureSet() {
      return ES8_MODULES;
    }
  };

  /** Renames properties. */
  private final PassFactory renameProperties =
      new PassFactory("renameProperties", true) {
        @Override
        protected CompilerPass create(final AbstractCompiler compiler) {
          checkState(options.propertyRenaming == PropertyRenamingPolicy.ALL_UNQUOTED);
          final VariableMap prevPropertyMap = options.inputPropertyMap;
          return new CompilerPass() {
            @Override
            public void process(Node externs, Node root) {
              RenamePropertiesWithModuleSupport rprop =
                  new RenamePropertiesWithModuleSupport(
                      compiler,
                      options.generatePseudoNames,
                      prevPropertyMap,
                      options.getPropertyReservedNamingFirstChars(),
                      options.getPropertyReservedNamingNonFirstChars(),
                      options.nameGenerator,
                      propertyNamesToKeep);
              rprop.process(externs, root);
              compiler.setPropertyMap(rprop.getPropertyMap());
            }
          };
        }
        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  /** Renames variables. */
  private final PassFactory renameVars = new PassFactory("renameVars", true) {
    @Override
    protected CompilerPass create(final AbstractCompiler compiler) {
      final VariableMap prevVariableMap = options.inputVariableMap;
      return new CompilerPass() {
        @Override public void process(Node externs, Node root) {
          compiler.setVariableMap(runVariableRenaming(
              compiler, prevVariableMap, externs, root));
        }
      };
    }

    @Override
    protected FeatureSet featureSet() {
      return ES8_MODULES;
    }
  };

  private VariableMap runVariableRenaming(
      AbstractCompiler compiler, VariableMap prevVariableMap,
      Node externs, Node root) {
    char[] reservedChars =
        options.anonymousFunctionNaming.getReservedCharacters();
    boolean preserveAnonymousFunctionNames =
        options.anonymousFunctionNaming != AnonymousFunctionNamingPolicy.OFF;
    Set<String> reservedNames = new HashSet<String>();
    if (options.renamePrefixNamespace != null) {
      // don't use the prefix name as a global symbol.
      reservedNames.add(options.renamePrefixNamespace);
    }
    reservedNames.addAll(compiler.getExportedNames());
    reservedNames.addAll(ParserRunner.getReservedVars());
    RenameVarsWithModuleSupport rn = new RenameVarsWithModuleSupport(
        compiler,
        options.renamePrefix,
        options.variableRenaming == VariableRenamingPolicy.LOCAL,
        preserveAnonymousFunctionNames,
        options.generatePseudoNames,
        options.shadowVariables,
        options.preferStableNames,
        prevVariableMap,
        reservedChars,
        reservedNames,
        options.nameGenerator);
    rn.process(externs, root);
    return rn.getVariableMap();
  }

  /** Renames labels */
  private final PassFactory renameLabels =
      new PassFactory("renameLabels", true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new RenameLabels(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  /** Convert bracket access to dot access */
  private final PassFactory convertToDottedProperties =
      new PassFactory(PassNames.CONVERT_TO_DOTTED_PROPERTIES, true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new ConvertToDottedProperties(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  private final PassFactory checkAstValidity =
      new PassFactory("checkAstValidity", true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new AstValidator(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return FeatureSet.latest();
        }
      };

  /** Checks that all variables are defined. */
  private final PassFactory varCheckValidity =
      new PassFactory("varCheckValidity", true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new VarCheck(compiler, true);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  /** Adds instrumentations according to an instrumentation template. */
  private final PassFactory instrumentFunctions =
      new PassFactory("instrumentFunctions", true) {
    @Override
    protected CompilerPass create(final AbstractCompiler compiler) {
      return new InstrumentFunctions(
          compiler, compiler.getFunctionNames(),
          options.instrumentationTemplate, options.appNameStr);
    }

    @Override
    protected FeatureSet featureSet() {
      return ES5;
    }
  };

  private final PassFactory instrumentForCodeCoverage =
      new PassFactory("instrumentForCodeCoverage", true) {
        @Override
        protected CompilerPass create(final AbstractCompiler compiler) {
          // TODO(johnlenz): make global instrumentation an option
          if (options.instrumentBranchCoverage) {
            return new CoverageInstrumentationPass(
                compiler, CoverageReach.CONDITIONAL, InstrumentOption.BRANCH_ONLY);
          } else {
            return new CoverageInstrumentationPass(compiler, CoverageReach.CONDITIONAL);
          }
        }

        @Override
        protected FeatureSet featureSet() {
          return ES5;
        }
      };

  /** Extern property names gathering pass. */
  private final PassFactory gatherExternProperties =
      new PassFactory("gatherExternProperties", true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new GatherExternProperties(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
     };

  /**
   * Runs custom passes that are designated to run at a particular time.
   */
  private PassFactory getCustomPasses(
      final CustomPassExecutionTime executionTime) {
    return new PassFactory("runCustomPasses", true) {
      @Override
      protected CompilerPass create(final AbstractCompiler compiler) {
        return runInSerial(options.customPasses.get(executionTime));
      }

      @Override
      protected FeatureSet featureSet() {
        return ES5;
      }
    };
  }

  /** Create a compiler pass that runs the given passes in serial. */
  private static CompilerPass runInSerial(
      final Collection<CompilerPass> passes) {
    return new CompilerPass() {
      @Override public void process(Node externs, Node root) {
        for (CompilerPass pass : passes) {
          pass.process(externs, root);
        }
      }
    };
  }

  @VisibleForTesting
  static Map<String, Node> getAdditionalReplacements(CompilerOptions options) {
    Map<String, Node> additionalReplacements = new HashMap<String, Node>();

    if (options.markAsCompiled || options.closurePass) {
      additionalReplacements.put(COMPILED_CONSTANT_NAME, IR.trueNode());
    }

    if (options.closurePass && options.locale != null) {
      additionalReplacements.put(CLOSURE_LOCALE_CONSTANT_NAME,
          IR.string(options.locale));
    }

    return additionalReplacements;
  }

  /** Rewrites Polymer({}) */
  private final HotSwapPassFactory polymerPass =
      new HotSwapPassFactory("polymerPass") {
        @Override
        protected HotSwapCompilerPass create(AbstractCompiler compiler) {
          return new PolymerPass(
              compiler,
              compiler.getOptions().polymerVersion,
              compiler.getOptions().polymerExportPolicy,
              compiler.getOptions().propertyRenaming == PropertyRenamingPolicy.ALL_UNQUOTED);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES_NEXT;
        }
      };

  private final PassFactory chromePass = new PassFactory("chromePass", true) {
    @Override
    protected CompilerPass create(AbstractCompiler compiler) {
      return new ChromePass(compiler);
    }

    @Override
    protected FeatureSet featureSet() {
      return ES8_MODULES;
    }
  };

  /** Rewrites the super accessors calls to support Dart Dev Compiler output. */
  private final HotSwapPassFactory dartSuperAccessorsPass =
      new HotSwapPassFactory("dartSuperAccessorsPass") {
        @Override
        protected HotSwapCompilerPass create(AbstractCompiler compiler) {
          return new DartSuperAccessorsPass(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES_NEXT;
        }
      };

  /** Rewrites J2CL constructs to be more optimizable. */
  private final PassFactory j2clConstantHoisterPass =
      new PassFactory("j2clConstantHoisterPass", false) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new J2clConstantHoisterPass(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  /** Optimizes J2CL clinit methods. */
  private final PassFactory j2clClinitPass =
      new PassFactory("j2clClinitPass", false) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          List<Node> changedScopeNodes = compiler.getChangedScopeNodesForPass(getName());
          return new J2clClinitPrunerPass(compiler, changedScopeNodes);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  /** Rewrites J2CL constructs to be more optimizable. */
  private final PassFactory j2clPropertyInlinerPass =
      new PassFactory("j2clES6Pass", true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new J2clPropertyInlinerPass(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  /** Rewrites J2CL constructs to be more optimizable. */
  private final PassFactory j2clPass =
      new PassFactory("j2clPass", true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new J2clPass(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  /** Rewrites J2CL constructs to be more optimizable. */
  private final PassFactory j2clUtilGetDefineRewriterPass =
      new PassFactory("j2clUtilGetDefineRewriterPass", true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new J2clUtilGetDefineRewriterPass(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  private final PassFactory j2clAssertRemovalPass =
      new PassFactory("j2clAssertRemovalPass", true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new J2clAssertRemovalPass(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  private final PassFactory j2clSourceFileChecker =
      new PassFactory("j2clSourceFileChecker", true) {
        @Override
        protected CompilerPass create(final AbstractCompiler compiler) {
          return new J2clSourceFileChecker(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return FeatureSet.latest();
        }
      };

  private final PassFactory j2clChecksPass =
      new PassFactory("j2clChecksPass", true) {
        @Override
        protected CompilerPass create(final AbstractCompiler compiler) {
          return new J2clChecksPass(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES2018;
        }
      };

  private final PassFactory checkConformance =
      new PassFactory("checkConformance", true) {
        @Override
        protected CompilerPass create(final AbstractCompiler compiler) {
          return new CheckConformance(
              compiler, ImmutableList.copyOf(options.getConformanceConfigs()));
        }

        @Override
        protected FeatureSet featureSet() {
          return TYPE_CHECK_SUPPORTED;
        }
      };

  /** Optimizations that output ES6 features. */
  private final PassFactory optimizeToEs6 =
      new PassFactory("optimizeToEs6", true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new SubstituteEs6Syntax(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  /** Rewrites goog.module in whitespace only mode */
  private final HotSwapPassFactory whitespaceWrapGoogModules =
      new HotSwapPassFactory("whitespaceWrapGoogModules") {
        @Override
        protected HotSwapCompilerPass create(AbstractCompiler compiler) {
          return new WhitespaceWrapGoogModules(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES8_MODULES;
        }
      };

  private final PassFactory rewriteCommonJsModules =
      new PassFactory(PassNames.REWRITE_COMMON_JS_MODULES, true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new ProcessCommonJSModules(compiler);
        }

        @Override
        public FeatureSet featureSet() {
          return ES_NEXT;
        }
      };

  private final PassFactory rewriteScriptsToEs6Modules =
      new PassFactory(PassNames.REWRITE_SCRIPTS_TO_ES6_MODULES, true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new Es6RewriteScriptsToModules(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES_NEXT;
        }
      };

  private final HotSwapPassFactory gatherModuleMetadataPass =
      new HotSwapPassFactory(PassNames.GATHER_MODULE_METADATA) {
        @Override
        protected HotSwapCompilerPass create(AbstractCompiler compiler) {
          return new GatherModuleMetadata(
              compiler, options.processCommonJSModules, options.moduleResolutionMode);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES_NEXT;
        }
      };

  private final PassFactory gatherGettersAndSetters =
      new PassFactory(PassNames.GATHER_GETTERS_AND_SETTERS, /* isOneTimePass= */ true) {
        @Override
        protected CompilerPass create(AbstractCompiler compiler) {
          return new GatherGettersAndSetterProperties(compiler);
        }

        @Override
        protected FeatureSet featureSet() {
          return ES_NEXT;
        }
      };
}
