/*
 * Copyright 2020 Google Inc.
 *
 * 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.template.soy.passes;

import static com.google.common.base.Preconditions.checkNotNull;

import com.google.common.collect.ImmutableSet;
import com.google.template.soy.base.internal.IdGenerator;
import com.google.template.soy.error.ErrorReporter;
import com.google.template.soy.soytree.SoyFileNode;

/**
 * A pass that ensures that experimental features are only used when enabled.
 *
 * <p>In general access to experimental features should be controlled by the passes that implement
 * their behavior, but if the new behavior is a change to syntax that might not be feasible, or if
 * the new behavior is a change scattered across the compiler then it might be impractical. In those
 * cases this pass is a reasonable place to put the enforcement code.
 */
final class EnforceExperimentalFeaturesPass implements CompilerFilePass {

  private final ImmutableSet<String> features;
  private final ErrorReporter reporter;

  EnforceExperimentalFeaturesPass(ImmutableSet<String> features, ErrorReporter reporter) {
    this.features = checkNotNull(features);
    this.reporter = checkNotNull(reporter);
  }

  @Override
  public void run(SoyFileNode file, IdGenerator nodeIdGen) {}
}

@@ -743,16 +743,107 @@
 bleSet;%0A
+import com.google.common.collect.Sets;%0Aimport com.google.template.soy.base.SourceLocation;%0A
 import c
@@ -892,16 +892,16 @@
 erator;%0A
-
 import c
@@ -944,16 +944,67 @@
 porter;%0A
+import com.google.template.soy.error.SoyErrorKind;%0A
 import c
@@ -1581,16 +1581,278 @@
 Pass %7B%0A%0A
+  private static final ImmutableSet%3CString%3E ALL_EXPERIMENTAL_FEATURES =%0A      ImmutableSet.of(%22testonly_throw_on_warnings%22);%0A%0A  private static final SoyErrorKind INVALID_EXPERIMENTAL_FEATURE =%0A      SoyErrorKind.of(%22Invalid Soy experimental feature(s): %7B0%7D.%22);%0A%0A
   privat
@@ -2127,16 +2127,16 @@
 verride%0A
-
   public
@@ -2187,12 +2187,243 @@
 IdGen) %7B
+%0A    if (!ALL_EXPERIMENTAL_FEATURES.containsAll(features)) %7B%0A      reporter.report(%0A          SourceLocation.UNKNOWN,%0A          INVALID_EXPERIMENTAL_FEATURE,%0A          Sets.difference(features, ALL_EXPERIMENTAL_FEATURES));%0A    %7D%0A  
 %7D%0A%7D%0A

Add an error message if an unknown experimental feature flag is used.