/*
* Copyright 2008 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 com.google.common.base.Preconditions;
import com.google.template.soy.basetree.Node;
import com.google.template.soy.basetree.NodeVisitor;
import com.google.template.soy.basetree.SyntaxVersion;
import com.google.template.soy.basetree.SyntaxVersionUpperBound;
import com.google.template.soy.error.ErrorReporter;
import com.google.template.soy.error.SoyErrorKind;
import com.google.template.soy.exprtree.FunctionNode;
import com.google.template.soy.shared.internal.BuiltinFunction;
import com.google.template.soy.soytree.SoyFileNode;
import com.google.template.soy.soytree.SoyTreeUtils;
import com.google.template.soy.soytree.TemplateNode;
/**
* Reports syntax version errors for unparsed expressions and {@link SyntaxVersionUpperBound}s that
* aren't compatible with a required version.
*
*/
final class ReportSyntaxVersionErrors {
private static final SoyErrorKind SYNTAX_VERSION_OUT_OF_BOUNDS = SoyErrorKind.of("{0}: {1}");
private final SyntaxVersion requiredSyntaxVersion;
private final ErrorReporter errorReporter;
private final String errorPreamble;
/**
* @param requiredSyntaxVersion The required minimum syntax version to check for.
* @param isDeclared True if the required syntax version that we're checking for is user-declared.
* False if it is inferred.
* @param errorReporter For reporting errors.
*/
ReportSyntaxVersionErrors(
SyntaxVersion requiredSyntaxVersion, boolean isDeclared, ErrorReporter errorReporter) {
this.errorReporter = errorReporter;
this.requiredSyntaxVersion = requiredSyntaxVersion;
this.errorPreamble =
(requiredSyntaxVersion == SyntaxVersion.V1_0)
? "incorrect v1 syntax"
: ((isDeclared ? "declared" : "inferred")
+ " syntax version "
+ requiredSyntaxVersion
+ " not satisfied");
}
public void report(SoyFileNode node) {
for (final TemplateNode template : node.getChildren()) {
SoyTreeUtils.visitAllNodes(
template,
new NodeVisitor<Node, Boolean>() {
@Override
public Boolean exec(Node node) {
visitNode(template, node);
return true; // keep visiting
}
});
}
}
private void visitNode(TemplateNode template, Node node) {
if (!node.couldHaveSyntaxVersionAtLeast(requiredSyntaxVersion)) {
SyntaxVersionUpperBound syntaxVersionBound = node.getSyntaxVersionUpperBound();
Preconditions.checkNotNull(syntaxVersionBound);
errorReporter.report(
node.getSourceLocation(),
SYNTAX_VERSION_OUT_OF_BOUNDS,
errorPreamble,
syntaxVersionBound.reasonStr);
}
if (node instanceof FunctionNode) {
String functionName = ((FunctionNode) node).getFunctionName();
if (functionName.equals(BuiltinFunction.V1_EXPRESSION.getName())
&& template.couldHaveSyntaxVersionAtLeast(SyntaxVersion.V2_0)) {
errorReporter.report(
node.getSourceLocation(),
SYNTAX_VERSION_OUT_OF_BOUNDS,
errorPreamble,
"The v1Expression function can only be used in templates marked with the "
+ "deprecatedV1=\"true\" attribute");
}
}
}
}