/*
* Copyright 2011 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.soytree;
import com.google.common.collect.ImmutableList;
import com.google.template.soy.base.SourceLocation;
import com.google.template.soy.basetree.CopyState;
import com.google.template.soy.error.ErrorReporter;
import com.google.template.soy.error.ErrorReporter.Checkpoint;
import com.google.template.soy.error.SoyErrorKind;
import com.google.template.soy.exprtree.ExprRootNode;
import com.google.template.soy.exprtree.IntegerNode;
import com.google.template.soy.soytree.SoyNode.ExprHolderNode;
/**
* Node representing a 'let' statement with a value expression.
*
* <p>Important: Do not use outside of Soy code (treat as superpackage-private).
*
*/
public final class LetValueNode extends LetNode implements ExprHolderNode {
public static final SoyErrorKind SELF_ENDING_WITHOUT_VALUE =
SoyErrorKind.of(
"A ''let'' tag should be self-ending (with a trailing ''/'') if and only if "
+ "it also contains a value (invalid tag is '{'let {0} /'}').");
private static final SoyErrorKind KIND_ATTRIBUTE_NOT_ALLOWED_WITH_VALUE =
SoyErrorKind.of(
"The ''kind'' attribute is not allowed on self-ending ''let'' tags that "
+ "contain a value (invalid tag is '{'let {0} /'}').");
/** The value expression that the variable is set to. */
private final ExprRootNode valueExpr;
private LetValueNode(
int id,
SourceLocation sourceLocation,
String localVarName,
String commandText,
ExprRootNode valueExpr) {
super(id, sourceLocation, localVarName, commandText);
this.valueExpr = valueExpr;
}
/**
* Copy constructor.
*
* @param orig The node to copy.
*/
private LetValueNode(LetValueNode orig, CopyState copyState) {
super(orig, copyState);
this.valueExpr = orig.valueExpr.copy(copyState);
}
@Override
public Kind getKind() {
return Kind.LET_VALUE_NODE;
}
/** Return The local variable name (without preceding '$'). */
@Override
public final String getVarName() {
return var.name();
}
/** Returns the value expression that the variable is set to. */
public ExprRootNode getValueExpr() {
return valueExpr;
}
@Override
public ImmutableList<ExprRootNode> getExprList() {
return ImmutableList.of(valueExpr);
}
@Override
public LetValueNode copy(CopyState copyState) {
return new LetValueNode(this, copyState);
}
@Override
public String getTagString() {
return this.buildTagStringHelper(true);
}
/** Builder for {@link LetValueNode}. */
public static final class Builder {
private static LetValueNode error() {
return new LetValueNode(
-1,
SourceLocation.UNKNOWN,
"$error",
"$error: 1",
new ExprRootNode(new IntegerNode(1, SourceLocation.UNKNOWN)));
}
private final int id;
private final CommandTextParseResult parseResult;
private final SourceLocation sourceLocation;
/**
* @param id The node's id.
* @param commandText The node's command text.
* @param sourceLocation The node's source location.
*/
public Builder(int id, CommandTextParseResult parseResult, SourceLocation sourceLocation) {
this.id = id;
this.parseResult = parseResult;
this.sourceLocation = sourceLocation;
}
/**
* Returns a new {@link LetValueNode} built from the builder's state. If the builder's state is
* invalid, errors are reported to the {@code errorManager} and {Builder#error} is returned.
*/
public LetValueNode build(Checkpoint checkpoint, ErrorReporter errorReporter) {
if (parseResult.valueExpr == null) {
errorReporter.report(
sourceLocation, SELF_ENDING_WITHOUT_VALUE, parseResult.originalCommandText);
}
if (parseResult.contentKind != null) {
errorReporter.report(
sourceLocation, KIND_ATTRIBUTE_NOT_ALLOWED_WITH_VALUE, parseResult.originalCommandText);
}
if (errorReporter.errorsSince(checkpoint)) {
return error();
}
return new LetValueNode(
id,
sourceLocation,
parseResult.localVarName,
parseResult.originalCommandText,
parseResult.valueExpr);
}
}
}