/**
   * Runs middleend passes on the given Soy tree.
   *
   * @param soyTree The Soy tree to run middleend passes on.
   * @param doEnforceSyntaxVersionV2 Whether to enforce SyntaxVersion.V2.
   * @throws SoySyntaxException If a syntax error is found.
   * @throws SoyAutoescapeException If there is a problem determining the context for an {@code
   *     autoescape="contextual"} template or one of its callers.
   */
  private void runMiddleendPasses(SoyFileSetNode soyTree, boolean doEnforceSyntaxVersionV2)
      throws SoySyntaxException {

    // If diallowing external calls, perform the check.
    if (generalOptions.allowExternalCalls() == Boolean.FALSE) {
      (new AssertNoExternalCallsVisitor()).exec(soyTree);
    }

    // Handle CSS commands (if not backend-specific) and substitute compile-time globals.
    (new HandleCssCommandVisitor(generalOptions.getCssHandlingScheme())).exec(soyTree);
    if (generalOptions.getCompileTimeGlobals() != null) {
      (new SubstituteGlobalsVisitor(generalOptions.getCompileTimeGlobals(), false)).exec(soyTree);
    }

    // Soy version 1 allowed calling functions that are not backed by any SoyFunction definition.
    checkFunctionCallsVisitor.setAllowExternallyDefinedFunctions(!doEnforceSyntaxVersionV2);
    checkFunctionCallsVisitor.exec(soyTree);

    // Run contextual escaping after CSS has been done, but before the autoescape visitor adds
    // |escapeHtml directives.  The contextual directive filterHtmlIdent serves the same purpose
    // in some places, but with runtime guarantees.
    doContextualEscaping(soyTree);
    performAutoescapeVisitor.exec(soyTree);

    // Attempt to simplify the tree.
    (new ChangeCallsToPassAllDataVisitor()).exec(soyTree);
    simplifyVisitor.exec(soyTree);
  }
  /**
   * @param baseTofuFactory Factory for creating an instance of BaseTofu.
   * @param jsSrcMainProvider Provider for getting an instance of JsSrcMain.
   * @param javaSrcMainProvider Provider for getting an instance of JavaSrcMain.
   * @param performAutoescapeVisitor The instance of PerformAutoescapeVisitor to use.
   * @param contextualAutoescaper The instance of ContextualAutoescaper to use.
   * @param simplifyVisitor The instance of SimplifyVisitor to use.
   * @param soyFileSuppliers The suppliers for the input Soy files.
   * @param generalOptions The general compiler options.
   */
  @Inject
  SoyFileSet(
      BaseTofuFactory baseTofuFactory,
      Provider<JsSrcMain> jsSrcMainProvider,
      Provider<JavaSrcMain> javaSrcMainProvider,
      Provider<GoSrcMain> goSrcMainProvider,
      PerformAutoescapeVisitor performAutoescapeVisitor,
      ContextualAutoescaper contextualAutoescaper,
      SimplifyVisitor simplifyVisitor,
      CheckFunctionCallsVisitor checkFunctionCallsVisitor,
      @Assisted List<SoyFileSupplier> soyFileSuppliers,
      @Assisted SoyGeneralOptions generalOptions) {

    // Default value is optionally replaced using method injection.
    this.msgBundleHandlerProvider = DEFAULT_SOY_MSG_BUNDLE_HANDLER_PROVIDER;

    this.baseTofuFactory = baseTofuFactory;
    this.jsSrcMainProvider = jsSrcMainProvider;
    this.javaSrcMainProvider = javaSrcMainProvider;
    this.goSrcMainProvider = goSrcMainProvider;
    this.performAutoescapeVisitor = performAutoescapeVisitor;
    this.contextualAutoescaper = contextualAutoescaper;
    this.simplifyVisitor = simplifyVisitor;
    this.checkFunctionCallsVisitor = checkFunctionCallsVisitor;

    Preconditions.checkArgument(
        soyFileSuppliers.size() > 0, "Must have non-zero number of input Soy files.");
    this.soyFileSuppliers = soyFileSuppliers;
    this.generalOptions = generalOptions.clone();
  }
  private List<Pair<String, String>> compileFileSetToGoSrc(
      SoyFileSetNode soyTree, SoyGoSrcOptions goSrcOptions, SoyMsgBundle msgBundle) {

    // Note: Globals should have been substituted already. The pass below is just a check.
    (new SubstituteGlobalsVisitor(generalOptions.getCompileTimeGlobals(), true)).exec(soyTree);

    return goSrcMainProvider.get().genGoSrc(soyTree, goSrcOptions, msgBundle);
  }
    /**
     * Constructs a builder with a specified {@link SoyGeneralOptions} object.
     *
     * @param generalOptions The {@code SoyGeneralOptions} object to use.
     */
    public Builder(SoyGeneralOptions generalOptions) {

      this.listBuilder = ImmutableList.builder();
      this.generalOptions = generalOptions.clone();

      // Bootstrap Guice for Soy API users that don't use Guice. This is done by statically
      // injecting an instance of SoyFileSetFactory into this Builder class. Everything derived
      // from this SoyFileSetFactory will be Guice-enabled.
      GuiceInitializer.initializeIfNecessary();
    }
  /**
   * Compiles this Soy file set into a Java object (type {@code SoyTofu}) capable of rendering the
   * compiled templates.
   *
   * @param tofuOptions The compilation options for the Tofu backend.
   * @return The resulting {@code SoyTofu} object.
   * @throws SoySyntaxException If a syntax error is found.
   */
  public SoyTofu compileToTofu(SoyTofuOptions tofuOptions) throws SoySyntaxException {

    // Defensive copy of options. (Doesn't matter now, but might forget later when it matters.)
    tofuOptions = tofuOptions.clone();

    // TODO: Allow binding a SoyTofu instance to volatile inputs.
    SoyFileSetNode soyTree = (new SoyFileSetParser(soyFileSuppliers)).parse();
    runMiddleendPasses(soyTree, true);

    // If allowExternalCalls is not explicitly set, then disallow by default for Tofu backend.
    if (generalOptions.allowExternalCalls() == null) {
      // TODO: Enable this check when all Google internal projects are compliant.
      // (new AssertNoExternalCallsVisitor()).exec(soyTree);
    }

    // Note: Globals should have been substituted already. The pass below is just a check.
    (new SubstituteGlobalsVisitor(generalOptions.getCompileTimeGlobals(), true)).exec(soyTree);

    // Clear the SoyDoc strings because they use unnecessary memory.
    (new ClearSoyDocStringsVisitor()).exec(soyTree);

    return baseTofuFactory.create(soyTree, tofuOptions.useCaching());
  }