Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.shapesecurity.shift.es2018.template.ReduceStructured Maven / Gradle / Ivy
// Generated by template-structured-reducer.js
/**
* Copyright 2018 Shape Security, 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.shapesecurity.shift.es2018.template;
import com.shapesecurity.functional.F;
import com.shapesecurity.functional.Pair;
import com.shapesecurity.functional.data.ConcatList;
import com.shapesecurity.functional.data.ImmutableList;
import com.shapesecurity.functional.data.Maybe;
import com.shapesecurity.functional.data.NonEmptyImmutableList;
import com.shapesecurity.shift.es2018.ast.*;
import com.shapesecurity.shift.es2018.reducer.ThunkedReducer;
import javax.annotation.Nonnull;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static com.shapesecurity.shift.es2018.reducer.LazyReconstructingReducer.listMaybeRefEquals;
import static com.shapesecurity.shift.es2018.reducer.LazyReconstructingReducer.listRefEquals;
import static com.shapesecurity.shift.es2018.reducer.LazyReconstructingReducer.maybeRefEquals;
public class ReduceStructured implements ThunkedReducer {
public static abstract class Label {}
public static class Bare extends Label {
final String name;
public Bare(String name) {
this.name = name;
}
}
public static class If extends Label {
final boolean inverted;
final String condition;
public If(boolean inverted, String condition) {
this.inverted = inverted;
this.condition = condition;
}
}
public static class Loop extends Label {
final String variable;
final String values;
public Loop(String variable, String values) {
this.variable = variable;
this.values = values;
}
}
public static class TemplateValues { // TODO relocate to Template
public final Map conditions;
public final Map> lists;
public final Map> replacers;
public TemplateValues(Map conditions, Map> lists, Map> replacers) {
this.conditions = conditions;
this.lists = lists;
this.replacers = replacers;
}
public TemplateValues merge(TemplateValues other, String namespace) {
// non-destructive
TemplateValues merged = new TemplateValues(new HashMap<>(this.conditions), new HashMap<>(this.lists), new HashMap<>(this.replacers));
for (Map.Entry entry : other.conditions.entrySet()) {
String namespaced = namespace + "::" + entry.getKey();
if (merged.conditions.containsKey(namespaced)) {
throw new RuntimeException("Name " + namespaced + " already exists");
}
merged.conditions.put(namespaced, entry.getValue());
}
for (Map.Entry> entry : other.lists.entrySet()) {
String namespaced = namespace + "::" + entry.getKey();
if (merged.lists.containsKey(namespaced)) {
throw new RuntimeException("Name " + namespaced + " already exists");
}
merged.lists.put(namespaced, entry.getValue());
}
for (Map.Entry> entry : other.replacers.entrySet()) {
String namespaced = namespace + "::" + entry.getKey();
if (merged.replacers.containsKey(namespaced)) {
throw new RuntimeException("Name " + namespaced + " already exists");
}
merged.replacers.put(namespaced, entry.getValue());
}
return merged;
}
}
IdentityHashMap> nodeToLabels;
TemplateValues values;
boolean currentNodeMayHaveStructuredLabel;
public ReduceStructured(IdentityHashMap> nodeToLabels, TemplateValues values) {
this.nodeToLabels = nodeToLabels;
this.values = values;
this.currentNodeMayHaveStructuredLabel = false;
}
void enforceNoStrayStructuralLabels(Node node) {
List labels = this.nodeToLabels.get(node);
if (!this.currentNodeMayHaveStructuredLabel && labels != null && labels.stream().anyMatch(l -> !(l instanceof Bare))) {
Label label = labels.stream().filter(l -> !(l instanceof Bare)).findFirst().get();
if (label instanceof If) {
throw new RuntimeException("Node of type " + node.getClass().getSimpleName() + " with condition " + ((If) label).condition + " is not in an omittable position");
} else if (label instanceof Loop) {
throw new RuntimeException("Node of type " + node.getClass().getSimpleName() + " iterating over " + ((Loop) label).values + " is not in a loopable position");
} else {
throw new RuntimeException("unreachable");
}
}
this.currentNodeMayHaveStructuredLabel = false;
}
Node applyReplacer(List labels, Node transformed) {
if (labels == null || labels.isEmpty()) {
return transformed;
}
List bareLabels = labels.stream().flatMap(l -> l instanceof Bare ? Stream.of((Bare) l) : Stream.empty()).collect(Collectors.toList());
if (bareLabels.size() > 1) {
throw new RuntimeException("Node has multiple labels: " + bareLabels.get(0).name + ", " + bareLabels.get(1).name);
}
if (bareLabels.isEmpty()) {
return transformed;
}
F replacer = this.values.replacers.get(bareLabels.get(0).name);
if (replacer == null) {
throw new RuntimeException("Replacer " + bareLabels.get(0).name + " not found");
}
return replacer.apply(transformed);
}
ImmutableList applyListLabels(ImmutableList originalChildren, ImmutableList> childThunks) {
return originalChildren.zipWith(Pair::of, childThunks).flatMap(p -> {
List childLabels = this.nodeToLabels.get(p.left);
if (childLabels == null || childLabels.isEmpty()) {
return ImmutableList.of(p.right.get());
}
return this.applyLabels(p.right, ImmutableList.from(childLabels).filter(l -> !(l instanceof Bare))).toList();
}).map(n -> (T) n);
}
Maybe applyMaybeLabels(Maybe originalChild, Maybe> childThunk) {
if (originalChild.isNothing()) {
return Maybe.empty();
}
List childLabels = this.nodeToLabels.get(originalChild.fromJust());
if (childLabels == null || childLabels.isEmpty()) {
return Maybe.of((T) childThunk.fromJust().get());
}
ImmutableList result = this.applyLabels(childThunk.fromJust(), ImmutableList.from(childLabels).filter(l -> !(l instanceof Bare))).toList();
if (result.isEmpty()) {
return Maybe.empty();
}
NonEmptyImmutableList nonEmptyResult = (NonEmptyImmutableList) result;
if (nonEmptyResult.tail.isNotEmpty()) {
throw new RuntimeException("unreachable");
}
return Maybe.of((T) nonEmptyResult.head);
}
ImmutableList> applyListMaybeLabels(ImmutableList> originalChildren, ImmutableList>> childThunks) {
return originalChildren.zipWith(Pair::of, childThunks).flatMap(p -> {
if (p.left.isNothing()) {
return ImmutableList.of(Maybe.empty());
}
List childLabels = this.nodeToLabels.get(p.left.fromJust());
if (childLabels == null || childLabels.isEmpty()) {
return ImmutableList.of(Maybe.of(p.right.fromJust().get()));
}
return this.applyLabels(p.right.fromJust(), ImmutableList.from(childLabels).filter(l -> !(l instanceof Bare))).toList().map(Maybe::of);
}).map(m -> m.map(n -> (T) n));
}
ConcatList applyLabels(Supplier childThunk, ImmutableList remainingLabels) {
if (remainingLabels.isEmpty()) {
this.currentNodeMayHaveStructuredLabel = true;
return ConcatList.of(childThunk.get());
}
NonEmptyImmutableList nonEmptyLabels = (NonEmptyImmutableList) remainingLabels;
Label head = nonEmptyLabels.head;
ImmutableList tail = nonEmptyLabels.tail;
if (head instanceof If) {
If label = (If) head;
Boolean condition = this.values.conditions.get(label.condition);
if (condition == null) {
throw new RuntimeException("Condition " + label.condition + " not found");
}
if (label.inverted == condition) {
return ConcatList.empty();
}
return applyLabels(childThunk, tail);
}
if (head instanceof Loop) {
Loop label = (Loop) head;
List list = this.values.lists.get(label.values);
if (list == null) {
throw new RuntimeException("Loop values " + label.values + " not found");
}
TemplateValues oldValues = this.values;
ConcatList out = ConcatList.empty();
for (TemplateValues perIterationTemplateValues : list) {
this.values = oldValues.merge(perIterationTemplateValues, label.variable);
out = out.append(applyLabels(childThunk, tail));
}
this.values = oldValues;
return out;
}
throw new RuntimeException("unreachable");
}
@Override
@Nonnull
public Node reduceArrayAssignmentTarget(
@Nonnull ArrayAssignmentTarget node,
@Nonnull ImmutableList>> elementsThunk,
@Nonnull Maybe> restThunk
) {
enforceNoStrayStructuralLabels(node);
ImmutableList> elements = applyListMaybeLabels(node.elements, elementsThunk);
Maybe rest = applyMaybeLabels(node.rest, restThunk);
Node newNode = listMaybeRefEquals(node.elements, elements) && maybeRefEquals(node.rest, rest)
? node
: new ArrayAssignmentTarget(elements, rest);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceArrayBinding(
@Nonnull ArrayBinding node,
@Nonnull ImmutableList>> elementsThunk,
@Nonnull Maybe> restThunk
) {
enforceNoStrayStructuralLabels(node);
ImmutableList> elements = applyListMaybeLabels(node.elements, elementsThunk);
Maybe rest = applyMaybeLabels(node.rest, restThunk);
Node newNode = listMaybeRefEquals(node.elements, elements) && maybeRefEquals(node.rest, rest)
? node
: new ArrayBinding(elements, rest);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceArrayExpression(
@Nonnull ArrayExpression node,
@Nonnull ImmutableList>> elementsThunk
) {
enforceNoStrayStructuralLabels(node);
ImmutableList> elements = applyListMaybeLabels(node.elements, elementsThunk);
Node newNode = listMaybeRefEquals(node.elements, elements)
? node
: new ArrayExpression(elements);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceArrowExpression(
@Nonnull ArrowExpression node,
@Nonnull Supplier paramsThunk,
@Nonnull Supplier bodyThunk
) {
enforceNoStrayStructuralLabels(node);
FormalParameters params = (FormalParameters) paramsThunk.get();
FunctionBodyExpression body = (FunctionBodyExpression) bodyThunk.get();
Node newNode = node.params == params && node.body == body
? node
: new ArrowExpression(node.isAsync, params, body);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceAssignmentExpression(
@Nonnull AssignmentExpression node,
@Nonnull Supplier bindingThunk,
@Nonnull Supplier expressionThunk
) {
enforceNoStrayStructuralLabels(node);
AssignmentTarget binding = (AssignmentTarget) bindingThunk.get();
Expression expression = (Expression) expressionThunk.get();
Node newNode = node.binding == binding && node.expression == expression
? node
: new AssignmentExpression(binding, expression);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceAssignmentTargetIdentifier(
@Nonnull AssignmentTargetIdentifier node
) {
enforceNoStrayStructuralLabels(node);
return applyReplacer(this.nodeToLabels.get(node), node);
}
@Override
@Nonnull
public Node reduceAssignmentTargetPropertyIdentifier(
@Nonnull AssignmentTargetPropertyIdentifier node,
@Nonnull Supplier bindingThunk,
@Nonnull Maybe> initThunk
) {
enforceNoStrayStructuralLabels(node);
AssignmentTargetIdentifier binding = (AssignmentTargetIdentifier) bindingThunk.get();
Maybe init = applyMaybeLabels(node.init, initThunk);
Node newNode = node.binding == binding && maybeRefEquals(node.init, init)
? node
: new AssignmentTargetPropertyIdentifier(binding, init);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceAssignmentTargetPropertyProperty(
@Nonnull AssignmentTargetPropertyProperty node,
@Nonnull Supplier nameThunk,
@Nonnull Supplier bindingThunk
) {
enforceNoStrayStructuralLabels(node);
PropertyName name = (PropertyName) nameThunk.get();
AssignmentTargetAssignmentTargetWithDefault binding = (AssignmentTargetAssignmentTargetWithDefault) bindingThunk.get();
Node newNode = node.name == name && node.binding == binding
? node
: new AssignmentTargetPropertyProperty(name, binding);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceAssignmentTargetWithDefault(
@Nonnull AssignmentTargetWithDefault node,
@Nonnull Supplier bindingThunk,
@Nonnull Supplier initThunk
) {
enforceNoStrayStructuralLabels(node);
AssignmentTarget binding = (AssignmentTarget) bindingThunk.get();
Expression init = (Expression) initThunk.get();
Node newNode = node.binding == binding && node.init == init
? node
: new AssignmentTargetWithDefault(binding, init);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceAwaitExpression(
@Nonnull AwaitExpression node,
@Nonnull Supplier expressionThunk
) {
enforceNoStrayStructuralLabels(node);
Expression expression = (Expression) expressionThunk.get();
Node newNode = node.expression == expression
? node
: new AwaitExpression(expression);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceBinaryExpression(
@Nonnull BinaryExpression node,
@Nonnull Supplier leftThunk,
@Nonnull Supplier rightThunk
) {
enforceNoStrayStructuralLabels(node);
Expression left = (Expression) leftThunk.get();
Expression right = (Expression) rightThunk.get();
Node newNode = node.left == left && node.right == right
? node
: new BinaryExpression(left, node.operator, right);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceBindingIdentifier(
@Nonnull BindingIdentifier node
) {
enforceNoStrayStructuralLabels(node);
return applyReplacer(this.nodeToLabels.get(node), node);
}
@Override
@Nonnull
public Node reduceBindingPropertyIdentifier(
@Nonnull BindingPropertyIdentifier node,
@Nonnull Supplier bindingThunk,
@Nonnull Maybe> initThunk
) {
enforceNoStrayStructuralLabels(node);
BindingIdentifier binding = (BindingIdentifier) bindingThunk.get();
Maybe init = applyMaybeLabels(node.init, initThunk);
Node newNode = node.binding == binding && maybeRefEquals(node.init, init)
? node
: new BindingPropertyIdentifier(binding, init);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceBindingPropertyProperty(
@Nonnull BindingPropertyProperty node,
@Nonnull Supplier nameThunk,
@Nonnull Supplier bindingThunk
) {
enforceNoStrayStructuralLabels(node);
PropertyName name = (PropertyName) nameThunk.get();
BindingBindingWithDefault binding = (BindingBindingWithDefault) bindingThunk.get();
Node newNode = node.name == name && node.binding == binding
? node
: new BindingPropertyProperty(name, binding);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceBindingWithDefault(
@Nonnull BindingWithDefault node,
@Nonnull Supplier bindingThunk,
@Nonnull Supplier initThunk
) {
enforceNoStrayStructuralLabels(node);
Binding binding = (Binding) bindingThunk.get();
Expression init = (Expression) initThunk.get();
Node newNode = node.binding == binding && node.init == init
? node
: new BindingWithDefault(binding, init);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceBlock(
@Nonnull Block node,
@Nonnull ImmutableList> statementsThunk
) {
enforceNoStrayStructuralLabels(node);
ImmutableList statements = applyListLabels(node.statements, statementsThunk);
Node newNode = listRefEquals(node.statements, statements)
? node
: new Block(statements);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceBlockStatement(
@Nonnull BlockStatement node,
@Nonnull Supplier blockThunk
) {
enforceNoStrayStructuralLabels(node);
Block block = (Block) blockThunk.get();
Node newNode = node.block == block
? node
: new BlockStatement(block);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceBreakStatement(
@Nonnull BreakStatement node
) {
enforceNoStrayStructuralLabels(node);
return applyReplacer(this.nodeToLabels.get(node), node);
}
@Override
@Nonnull
public Node reduceCallExpression(
@Nonnull CallExpression node,
@Nonnull Supplier calleeThunk,
@Nonnull ImmutableList> argumentsThunk
) {
enforceNoStrayStructuralLabels(node);
ExpressionSuper callee = (ExpressionSuper) calleeThunk.get();
ImmutableList arguments = applyListLabels(node.arguments, argumentsThunk);
Node newNode = node.callee == callee && listRefEquals(node.arguments, arguments)
? node
: new CallExpression(callee, arguments);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceCatchClause(
@Nonnull CatchClause node,
@Nonnull Supplier bindingThunk,
@Nonnull Supplier bodyThunk
) {
enforceNoStrayStructuralLabels(node);
Binding binding = (Binding) bindingThunk.get();
Block body = (Block) bodyThunk.get();
Node newNode = node.binding == binding && node.body == body
? node
: new CatchClause(binding, body);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceClassDeclaration(
@Nonnull ClassDeclaration node,
@Nonnull Supplier nameThunk,
@Nonnull Maybe> _superThunk,
@Nonnull ImmutableList> elementsThunk
) {
enforceNoStrayStructuralLabels(node);
BindingIdentifier name = (BindingIdentifier) nameThunk.get();
Maybe _super = applyMaybeLabels(node._super, _superThunk);
ImmutableList elements = applyListLabels(node.elements, elementsThunk);
Node newNode = node.name == name && maybeRefEquals(node._super, _super) && listRefEquals(node.elements, elements)
? node
: new ClassDeclaration(name, _super, elements);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceClassElement(
@Nonnull ClassElement node,
@Nonnull Supplier methodThunk
) {
enforceNoStrayStructuralLabels(node);
MethodDefinition method = (MethodDefinition) methodThunk.get();
Node newNode = node.method == method
? node
: new ClassElement(node.isStatic, method);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceClassExpression(
@Nonnull ClassExpression node,
@Nonnull Maybe> nameThunk,
@Nonnull Maybe> _superThunk,
@Nonnull ImmutableList> elementsThunk
) {
enforceNoStrayStructuralLabels(node);
Maybe name = applyMaybeLabels(node.name, nameThunk);
Maybe _super = applyMaybeLabels(node._super, _superThunk);
ImmutableList elements = applyListLabels(node.elements, elementsThunk);
Node newNode = maybeRefEquals(node.name, name) && maybeRefEquals(node._super, _super) && listRefEquals(node.elements, elements)
? node
: new ClassExpression(name, _super, elements);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceCompoundAssignmentExpression(
@Nonnull CompoundAssignmentExpression node,
@Nonnull Supplier bindingThunk,
@Nonnull Supplier expressionThunk
) {
enforceNoStrayStructuralLabels(node);
SimpleAssignmentTarget binding = (SimpleAssignmentTarget) bindingThunk.get();
Expression expression = (Expression) expressionThunk.get();
Node newNode = node.binding == binding && node.expression == expression
? node
: new CompoundAssignmentExpression(binding, node.operator, expression);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceComputedMemberAssignmentTarget(
@Nonnull ComputedMemberAssignmentTarget node,
@Nonnull Supplier objectThunk,
@Nonnull Supplier expressionThunk
) {
enforceNoStrayStructuralLabels(node);
ExpressionSuper object = (ExpressionSuper) objectThunk.get();
Expression expression = (Expression) expressionThunk.get();
Node newNode = node.object == object && node.expression == expression
? node
: new ComputedMemberAssignmentTarget(object, expression);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceComputedMemberExpression(
@Nonnull ComputedMemberExpression node,
@Nonnull Supplier objectThunk,
@Nonnull Supplier expressionThunk
) {
enforceNoStrayStructuralLabels(node);
ExpressionSuper object = (ExpressionSuper) objectThunk.get();
Expression expression = (Expression) expressionThunk.get();
Node newNode = node.object == object && node.expression == expression
? node
: new ComputedMemberExpression(object, expression);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceComputedPropertyName(
@Nonnull ComputedPropertyName node,
@Nonnull Supplier expressionThunk
) {
enforceNoStrayStructuralLabels(node);
Expression expression = (Expression) expressionThunk.get();
Node newNode = node.expression == expression
? node
: new ComputedPropertyName(expression);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceConditionalExpression(
@Nonnull ConditionalExpression node,
@Nonnull Supplier testThunk,
@Nonnull Supplier consequentThunk,
@Nonnull Supplier alternateThunk
) {
enforceNoStrayStructuralLabels(node);
Expression test = (Expression) testThunk.get();
Expression consequent = (Expression) consequentThunk.get();
Expression alternate = (Expression) alternateThunk.get();
Node newNode = node.test == test && node.consequent == consequent && node.alternate == alternate
? node
: new ConditionalExpression(test, consequent, alternate);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceContinueStatement(
@Nonnull ContinueStatement node
) {
enforceNoStrayStructuralLabels(node);
return applyReplacer(this.nodeToLabels.get(node), node);
}
@Override
@Nonnull
public Node reduceDataProperty(
@Nonnull DataProperty node,
@Nonnull Supplier nameThunk,
@Nonnull Supplier expressionThunk
) {
enforceNoStrayStructuralLabels(node);
PropertyName name = (PropertyName) nameThunk.get();
Expression expression = (Expression) expressionThunk.get();
Node newNode = node.name == name && node.expression == expression
? node
: new DataProperty(name, expression);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceDebuggerStatement(
@Nonnull DebuggerStatement node
) {
enforceNoStrayStructuralLabels(node);
return applyReplacer(this.nodeToLabels.get(node), node);
}
@Override
@Nonnull
public Node reduceDirective(
@Nonnull Directive node
) {
enforceNoStrayStructuralLabels(node);
return applyReplacer(this.nodeToLabels.get(node), node);
}
@Override
@Nonnull
public Node reduceDoWhileStatement(
@Nonnull DoWhileStatement node,
@Nonnull Supplier bodyThunk,
@Nonnull Supplier testThunk
) {
enforceNoStrayStructuralLabels(node);
Statement body = (Statement) bodyThunk.get();
Expression test = (Expression) testThunk.get();
Node newNode = node.body == body && node.test == test
? node
: new DoWhileStatement(body, test);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceEmptyStatement(
@Nonnull EmptyStatement node
) {
enforceNoStrayStructuralLabels(node);
return applyReplacer(this.nodeToLabels.get(node), node);
}
@Override
@Nonnull
public Node reduceExport(
@Nonnull Export node,
@Nonnull Supplier declarationThunk
) {
enforceNoStrayStructuralLabels(node);
FunctionDeclarationClassDeclarationVariableDeclaration declaration = (FunctionDeclarationClassDeclarationVariableDeclaration) declarationThunk.get();
Node newNode = node.declaration == declaration
? node
: new Export(declaration);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceExportAllFrom(
@Nonnull ExportAllFrom node
) {
enforceNoStrayStructuralLabels(node);
return applyReplacer(this.nodeToLabels.get(node), node);
}
@Override
@Nonnull
public Node reduceExportDefault(
@Nonnull ExportDefault node,
@Nonnull Supplier bodyThunk
) {
enforceNoStrayStructuralLabels(node);
FunctionDeclarationClassDeclarationExpression body = (FunctionDeclarationClassDeclarationExpression) bodyThunk.get();
Node newNode = node.body == body
? node
: new ExportDefault(body);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceExportFrom(
@Nonnull ExportFrom node,
@Nonnull ImmutableList> namedExportsThunk
) {
enforceNoStrayStructuralLabels(node);
ImmutableList namedExports = applyListLabels(node.namedExports, namedExportsThunk);
Node newNode = listRefEquals(node.namedExports, namedExports)
? node
: new ExportFrom(namedExports, node.moduleSpecifier);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceExportFromSpecifier(
@Nonnull ExportFromSpecifier node
) {
enforceNoStrayStructuralLabels(node);
return applyReplacer(this.nodeToLabels.get(node), node);
}
@Override
@Nonnull
public Node reduceExportLocalSpecifier(
@Nonnull ExportLocalSpecifier node,
@Nonnull Supplier nameThunk
) {
enforceNoStrayStructuralLabels(node);
IdentifierExpression name = (IdentifierExpression) nameThunk.get();
Node newNode = node.name == name
? node
: new ExportLocalSpecifier(name, node.exportedName);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceExportLocals(
@Nonnull ExportLocals node,
@Nonnull ImmutableList> namedExportsThunk
) {
enforceNoStrayStructuralLabels(node);
ImmutableList namedExports = applyListLabels(node.namedExports, namedExportsThunk);
Node newNode = listRefEquals(node.namedExports, namedExports)
? node
: new ExportLocals(namedExports);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceExpressionStatement(
@Nonnull ExpressionStatement node,
@Nonnull Supplier expressionThunk
) {
enforceNoStrayStructuralLabels(node);
Expression expression = (Expression) expressionThunk.get();
Node newNode = node.expression == expression
? node
: new ExpressionStatement(expression);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceForAwaitStatement(
@Nonnull ForAwaitStatement node,
@Nonnull Supplier leftThunk,
@Nonnull Supplier rightThunk,
@Nonnull Supplier bodyThunk
) {
enforceNoStrayStructuralLabels(node);
VariableDeclarationAssignmentTarget left = (VariableDeclarationAssignmentTarget) leftThunk.get();
Expression right = (Expression) rightThunk.get();
Statement body = (Statement) bodyThunk.get();
Node newNode = node.left == left && node.right == right && node.body == body
? node
: new ForAwaitStatement(left, right, body);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceForInStatement(
@Nonnull ForInStatement node,
@Nonnull Supplier leftThunk,
@Nonnull Supplier rightThunk,
@Nonnull Supplier bodyThunk
) {
enforceNoStrayStructuralLabels(node);
VariableDeclarationAssignmentTarget left = (VariableDeclarationAssignmentTarget) leftThunk.get();
Expression right = (Expression) rightThunk.get();
Statement body = (Statement) bodyThunk.get();
Node newNode = node.left == left && node.right == right && node.body == body
? node
: new ForInStatement(left, right, body);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceForOfStatement(
@Nonnull ForOfStatement node,
@Nonnull Supplier leftThunk,
@Nonnull Supplier rightThunk,
@Nonnull Supplier bodyThunk
) {
enforceNoStrayStructuralLabels(node);
VariableDeclarationAssignmentTarget left = (VariableDeclarationAssignmentTarget) leftThunk.get();
Expression right = (Expression) rightThunk.get();
Statement body = (Statement) bodyThunk.get();
Node newNode = node.left == left && node.right == right && node.body == body
? node
: new ForOfStatement(left, right, body);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceForStatement(
@Nonnull ForStatement node,
@Nonnull Maybe> initThunk,
@Nonnull Maybe> testThunk,
@Nonnull Maybe> updateThunk,
@Nonnull Supplier bodyThunk
) {
enforceNoStrayStructuralLabels(node);
Maybe init = applyMaybeLabels(node.init, initThunk);
Maybe test = applyMaybeLabels(node.test, testThunk);
Maybe update = applyMaybeLabels(node.update, updateThunk);
Statement body = (Statement) bodyThunk.get();
Node newNode = maybeRefEquals(node.init, init) && maybeRefEquals(node.test, test) && maybeRefEquals(node.update, update) && node.body == body
? node
: new ForStatement(init, test, update, body);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceFormalParameters(
@Nonnull FormalParameters node,
@Nonnull ImmutableList> itemsThunk,
@Nonnull Maybe> restThunk
) {
enforceNoStrayStructuralLabels(node);
ImmutableList items = applyListLabels(node.items, itemsThunk);
Maybe rest = applyMaybeLabels(node.rest, restThunk);
Node newNode = listRefEquals(node.items, items) && maybeRefEquals(node.rest, rest)
? node
: new FormalParameters(items, rest);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceFunctionBody(
@Nonnull FunctionBody node,
@Nonnull ImmutableList> directivesThunk,
@Nonnull ImmutableList> statementsThunk
) {
enforceNoStrayStructuralLabels(node);
ImmutableList directives = applyListLabels(node.directives, directivesThunk);
ImmutableList statements = applyListLabels(node.statements, statementsThunk);
Node newNode = listRefEquals(node.directives, directives) && listRefEquals(node.statements, statements)
? node
: new FunctionBody(directives, statements);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceFunctionDeclaration(
@Nonnull FunctionDeclaration node,
@Nonnull Supplier nameThunk,
@Nonnull Supplier paramsThunk,
@Nonnull Supplier bodyThunk
) {
enforceNoStrayStructuralLabels(node);
BindingIdentifier name = (BindingIdentifier) nameThunk.get();
FormalParameters params = (FormalParameters) paramsThunk.get();
FunctionBody body = (FunctionBody) bodyThunk.get();
Node newNode = node.name == name && node.params == params && node.body == body
? node
: new FunctionDeclaration(node.isAsync, node.isGenerator, name, params, body);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceFunctionExpression(
@Nonnull FunctionExpression node,
@Nonnull Maybe> nameThunk,
@Nonnull Supplier paramsThunk,
@Nonnull Supplier bodyThunk
) {
enforceNoStrayStructuralLabels(node);
Maybe name = applyMaybeLabels(node.name, nameThunk);
FormalParameters params = (FormalParameters) paramsThunk.get();
FunctionBody body = (FunctionBody) bodyThunk.get();
Node newNode = maybeRefEquals(node.name, name) && node.params == params && node.body == body
? node
: new FunctionExpression(node.isAsync, node.isGenerator, name, params, body);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceGetter(
@Nonnull Getter node,
@Nonnull Supplier nameThunk,
@Nonnull Supplier bodyThunk
) {
enforceNoStrayStructuralLabels(node);
PropertyName name = (PropertyName) nameThunk.get();
FunctionBody body = (FunctionBody) bodyThunk.get();
Node newNode = node.name == name && node.body == body
? node
: new Getter(name, body);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceIdentifierExpression(
@Nonnull IdentifierExpression node
) {
enforceNoStrayStructuralLabels(node);
return applyReplacer(this.nodeToLabels.get(node), node);
}
@Override
@Nonnull
public Node reduceIfStatement(
@Nonnull IfStatement node,
@Nonnull Supplier testThunk,
@Nonnull Supplier consequentThunk,
@Nonnull Maybe> alternateThunk
) {
enforceNoStrayStructuralLabels(node);
Expression test = (Expression) testThunk.get();
Statement consequent = (Statement) consequentThunk.get();
Maybe alternate = applyMaybeLabels(node.alternate, alternateThunk);
Node newNode = node.test == test && node.consequent == consequent && maybeRefEquals(node.alternate, alternate)
? node
: new IfStatement(test, consequent, alternate);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceImport(
@Nonnull Import node,
@Nonnull Maybe> defaultBindingThunk,
@Nonnull ImmutableList> namedImportsThunk
) {
enforceNoStrayStructuralLabels(node);
Maybe defaultBinding = applyMaybeLabels(node.defaultBinding, defaultBindingThunk);
ImmutableList namedImports = applyListLabels(node.namedImports, namedImportsThunk);
Node newNode = maybeRefEquals(node.defaultBinding, defaultBinding) && listRefEquals(node.namedImports, namedImports)
? node
: new Import(defaultBinding, namedImports, node.moduleSpecifier);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceImportNamespace(
@Nonnull ImportNamespace node,
@Nonnull Maybe> defaultBindingThunk,
@Nonnull Supplier namespaceBindingThunk
) {
enforceNoStrayStructuralLabels(node);
Maybe defaultBinding = applyMaybeLabels(node.defaultBinding, defaultBindingThunk);
BindingIdentifier namespaceBinding = (BindingIdentifier) namespaceBindingThunk.get();
Node newNode = maybeRefEquals(node.defaultBinding, defaultBinding) && node.namespaceBinding == namespaceBinding
? node
: new ImportNamespace(defaultBinding, namespaceBinding, node.moduleSpecifier);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceImportSpecifier(
@Nonnull ImportSpecifier node,
@Nonnull Supplier bindingThunk
) {
enforceNoStrayStructuralLabels(node);
BindingIdentifier binding = (BindingIdentifier) bindingThunk.get();
Node newNode = node.binding == binding
? node
: new ImportSpecifier(node.name, binding);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceLabeledStatement(
@Nonnull LabeledStatement node,
@Nonnull Supplier bodyThunk
) {
enforceNoStrayStructuralLabels(node);
Statement body = (Statement) bodyThunk.get();
Node newNode = node.body == body
? node
: new LabeledStatement(node.label, body);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceLiteralBooleanExpression(
@Nonnull LiteralBooleanExpression node
) {
enforceNoStrayStructuralLabels(node);
return applyReplacer(this.nodeToLabels.get(node), node);
}
@Override
@Nonnull
public Node reduceLiteralInfinityExpression(
@Nonnull LiteralInfinityExpression node
) {
enforceNoStrayStructuralLabels(node);
return applyReplacer(this.nodeToLabels.get(node), node);
}
@Override
@Nonnull
public Node reduceLiteralNullExpression(
@Nonnull LiteralNullExpression node
) {
enforceNoStrayStructuralLabels(node);
return applyReplacer(this.nodeToLabels.get(node), node);
}
@Override
@Nonnull
public Node reduceLiteralNumericExpression(
@Nonnull LiteralNumericExpression node
) {
enforceNoStrayStructuralLabels(node);
return applyReplacer(this.nodeToLabels.get(node), node);
}
@Override
@Nonnull
public Node reduceLiteralRegExpExpression(
@Nonnull LiteralRegExpExpression node
) {
enforceNoStrayStructuralLabels(node);
return applyReplacer(this.nodeToLabels.get(node), node);
}
@Override
@Nonnull
public Node reduceLiteralStringExpression(
@Nonnull LiteralStringExpression node
) {
enforceNoStrayStructuralLabels(node);
return applyReplacer(this.nodeToLabels.get(node), node);
}
@Override
@Nonnull
public Node reduceMethod(
@Nonnull Method node,
@Nonnull Supplier nameThunk,
@Nonnull Supplier paramsThunk,
@Nonnull Supplier bodyThunk
) {
enforceNoStrayStructuralLabels(node);
PropertyName name = (PropertyName) nameThunk.get();
FormalParameters params = (FormalParameters) paramsThunk.get();
FunctionBody body = (FunctionBody) bodyThunk.get();
Node newNode = node.name == name && node.params == params && node.body == body
? node
: new Method(node.isAsync, node.isGenerator, name, params, body);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceModule(
@Nonnull Module node,
@Nonnull ImmutableList> directivesThunk,
@Nonnull ImmutableList> itemsThunk
) {
enforceNoStrayStructuralLabels(node);
ImmutableList directives = applyListLabels(node.directives, directivesThunk);
ImmutableList items = applyListLabels(node.items, itemsThunk);
Node newNode = listRefEquals(node.directives, directives) && listRefEquals(node.items, items)
? node
: new Module(directives, items);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceNewExpression(
@Nonnull NewExpression node,
@Nonnull Supplier calleeThunk,
@Nonnull ImmutableList> argumentsThunk
) {
enforceNoStrayStructuralLabels(node);
Expression callee = (Expression) calleeThunk.get();
ImmutableList arguments = applyListLabels(node.arguments, argumentsThunk);
Node newNode = node.callee == callee && listRefEquals(node.arguments, arguments)
? node
: new NewExpression(callee, arguments);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceNewTargetExpression(
@Nonnull NewTargetExpression node
) {
enforceNoStrayStructuralLabels(node);
return applyReplacer(this.nodeToLabels.get(node), node);
}
@Override
@Nonnull
public Node reduceObjectAssignmentTarget(
@Nonnull ObjectAssignmentTarget node,
@Nonnull ImmutableList> propertiesThunk,
@Nonnull Maybe> restThunk
) {
enforceNoStrayStructuralLabels(node);
ImmutableList properties = applyListLabels(node.properties, propertiesThunk);
Maybe rest = applyMaybeLabels(node.rest, restThunk);
Node newNode = listRefEquals(node.properties, properties) && maybeRefEquals(node.rest, rest)
? node
: new ObjectAssignmentTarget(properties, rest);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceObjectBinding(
@Nonnull ObjectBinding node,
@Nonnull ImmutableList> propertiesThunk,
@Nonnull Maybe> restThunk
) {
enforceNoStrayStructuralLabels(node);
ImmutableList properties = applyListLabels(node.properties, propertiesThunk);
Maybe rest = applyMaybeLabels(node.rest, restThunk);
Node newNode = listRefEquals(node.properties, properties) && maybeRefEquals(node.rest, rest)
? node
: new ObjectBinding(properties, rest);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceObjectExpression(
@Nonnull ObjectExpression node,
@Nonnull ImmutableList> propertiesThunk
) {
enforceNoStrayStructuralLabels(node);
ImmutableList properties = applyListLabels(node.properties, propertiesThunk);
Node newNode = listRefEquals(node.properties, properties)
? node
: new ObjectExpression(properties);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceReturnStatement(
@Nonnull ReturnStatement node,
@Nonnull Maybe> expressionThunk
) {
enforceNoStrayStructuralLabels(node);
Maybe expression = applyMaybeLabels(node.expression, expressionThunk);
Node newNode = maybeRefEquals(node.expression, expression)
? node
: new ReturnStatement(expression);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceScript(
@Nonnull Script node,
@Nonnull ImmutableList> directivesThunk,
@Nonnull ImmutableList> statementsThunk
) {
enforceNoStrayStructuralLabels(node);
ImmutableList directives = applyListLabels(node.directives, directivesThunk);
ImmutableList statements = applyListLabels(node.statements, statementsThunk);
Node newNode = listRefEquals(node.directives, directives) && listRefEquals(node.statements, statements)
? node
: new Script(directives, statements);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceSetter(
@Nonnull Setter node,
@Nonnull Supplier nameThunk,
@Nonnull Supplier paramThunk,
@Nonnull Supplier bodyThunk
) {
enforceNoStrayStructuralLabels(node);
PropertyName name = (PropertyName) nameThunk.get();
Parameter param = (Parameter) paramThunk.get();
FunctionBody body = (FunctionBody) bodyThunk.get();
Node newNode = node.name == name && node.param == param && node.body == body
? node
: new Setter(name, param, body);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceShorthandProperty(
@Nonnull ShorthandProperty node,
@Nonnull Supplier nameThunk
) {
enforceNoStrayStructuralLabels(node);
IdentifierExpression name = (IdentifierExpression) nameThunk.get();
Node newNode = node.name == name
? node
: new ShorthandProperty(name);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceSpreadElement(
@Nonnull SpreadElement node,
@Nonnull Supplier expressionThunk
) {
enforceNoStrayStructuralLabels(node);
Expression expression = (Expression) expressionThunk.get();
Node newNode = node.expression == expression
? node
: new SpreadElement(expression);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceSpreadProperty(
@Nonnull SpreadProperty node,
@Nonnull Supplier expressionThunk
) {
enforceNoStrayStructuralLabels(node);
Expression expression = (Expression) expressionThunk.get();
Node newNode = node.expression == expression
? node
: new SpreadProperty(expression);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceStaticMemberAssignmentTarget(
@Nonnull StaticMemberAssignmentTarget node,
@Nonnull Supplier objectThunk
) {
enforceNoStrayStructuralLabels(node);
ExpressionSuper object = (ExpressionSuper) objectThunk.get();
Node newNode = node.object == object
? node
: new StaticMemberAssignmentTarget(object, node.property);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceStaticMemberExpression(
@Nonnull StaticMemberExpression node,
@Nonnull Supplier objectThunk
) {
enforceNoStrayStructuralLabels(node);
ExpressionSuper object = (ExpressionSuper) objectThunk.get();
Node newNode = node.object == object
? node
: new StaticMemberExpression(object, node.property);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceStaticPropertyName(
@Nonnull StaticPropertyName node
) {
enforceNoStrayStructuralLabels(node);
return applyReplacer(this.nodeToLabels.get(node), node);
}
@Override
@Nonnull
public Node reduceSuper(
@Nonnull Super node
) {
enforceNoStrayStructuralLabels(node);
return applyReplacer(this.nodeToLabels.get(node), node);
}
@Override
@Nonnull
public Node reduceSwitchCase(
@Nonnull SwitchCase node,
@Nonnull Supplier testThunk,
@Nonnull ImmutableList> consequentThunk
) {
enforceNoStrayStructuralLabels(node);
Expression test = (Expression) testThunk.get();
ImmutableList consequent = applyListLabels(node.consequent, consequentThunk);
Node newNode = node.test == test && listRefEquals(node.consequent, consequent)
? node
: new SwitchCase(test, consequent);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceSwitchDefault(
@Nonnull SwitchDefault node,
@Nonnull ImmutableList> consequentThunk
) {
enforceNoStrayStructuralLabels(node);
ImmutableList consequent = applyListLabels(node.consequent, consequentThunk);
Node newNode = listRefEquals(node.consequent, consequent)
? node
: new SwitchDefault(consequent);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceSwitchStatement(
@Nonnull SwitchStatement node,
@Nonnull Supplier discriminantThunk,
@Nonnull ImmutableList> casesThunk
) {
enforceNoStrayStructuralLabels(node);
Expression discriminant = (Expression) discriminantThunk.get();
ImmutableList cases = applyListLabels(node.cases, casesThunk);
Node newNode = node.discriminant == discriminant && listRefEquals(node.cases, cases)
? node
: new SwitchStatement(discriminant, cases);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceSwitchStatementWithDefault(
@Nonnull SwitchStatementWithDefault node,
@Nonnull Supplier discriminantThunk,
@Nonnull ImmutableList> preDefaultCasesThunk,
@Nonnull Supplier defaultCaseThunk,
@Nonnull ImmutableList> postDefaultCasesThunk
) {
enforceNoStrayStructuralLabels(node);
Expression discriminant = (Expression) discriminantThunk.get();
ImmutableList preDefaultCases = applyListLabels(node.preDefaultCases, preDefaultCasesThunk);
SwitchDefault defaultCase = (SwitchDefault) defaultCaseThunk.get();
ImmutableList postDefaultCases = applyListLabels(node.postDefaultCases, postDefaultCasesThunk);
Node newNode = node.discriminant == discriminant && listRefEquals(node.preDefaultCases, preDefaultCases) && node.defaultCase == defaultCase && listRefEquals(node.postDefaultCases, postDefaultCases)
? node
: new SwitchStatementWithDefault(discriminant, preDefaultCases, defaultCase, postDefaultCases);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceTemplateElement(
@Nonnull TemplateElement node
) {
enforceNoStrayStructuralLabels(node);
return applyReplacer(this.nodeToLabels.get(node), node);
}
@Override
@Nonnull
public Node reduceTemplateExpression(
@Nonnull TemplateExpression node,
@Nonnull Maybe> tagThunk,
@Nonnull ImmutableList> elementsThunk
) {
enforceNoStrayStructuralLabels(node);
Maybe tag = applyMaybeLabels(node.tag, tagThunk);
ImmutableList elements = applyListLabels(node.elements, elementsThunk);
Node newNode = maybeRefEquals(node.tag, tag) && listRefEquals(node.elements, elements)
? node
: new TemplateExpression(tag, elements);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceThisExpression(
@Nonnull ThisExpression node
) {
enforceNoStrayStructuralLabels(node);
return applyReplacer(this.nodeToLabels.get(node), node);
}
@Override
@Nonnull
public Node reduceThrowStatement(
@Nonnull ThrowStatement node,
@Nonnull Supplier expressionThunk
) {
enforceNoStrayStructuralLabels(node);
Expression expression = (Expression) expressionThunk.get();
Node newNode = node.expression == expression
? node
: new ThrowStatement(expression);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceTryCatchStatement(
@Nonnull TryCatchStatement node,
@Nonnull Supplier bodyThunk,
@Nonnull Supplier catchClauseThunk
) {
enforceNoStrayStructuralLabels(node);
Block body = (Block) bodyThunk.get();
CatchClause catchClause = (CatchClause) catchClauseThunk.get();
Node newNode = node.body == body && node.catchClause == catchClause
? node
: new TryCatchStatement(body, catchClause);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceTryFinallyStatement(
@Nonnull TryFinallyStatement node,
@Nonnull Supplier bodyThunk,
@Nonnull Maybe> catchClauseThunk,
@Nonnull Supplier finalizerThunk
) {
enforceNoStrayStructuralLabels(node);
Block body = (Block) bodyThunk.get();
Maybe catchClause = applyMaybeLabels(node.catchClause, catchClauseThunk);
Block finalizer = (Block) finalizerThunk.get();
Node newNode = node.body == body && maybeRefEquals(node.catchClause, catchClause) && node.finalizer == finalizer
? node
: new TryFinallyStatement(body, catchClause, finalizer);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceUnaryExpression(
@Nonnull UnaryExpression node,
@Nonnull Supplier operandThunk
) {
enforceNoStrayStructuralLabels(node);
Expression operand = (Expression) operandThunk.get();
Node newNode = node.operand == operand
? node
: new UnaryExpression(node.operator, operand);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceUpdateExpression(
@Nonnull UpdateExpression node,
@Nonnull Supplier operandThunk
) {
enforceNoStrayStructuralLabels(node);
SimpleAssignmentTarget operand = (SimpleAssignmentTarget) operandThunk.get();
Node newNode = node.operand == operand
? node
: new UpdateExpression(node.isPrefix, node.operator, operand);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceVariableDeclaration(
@Nonnull VariableDeclaration node,
@Nonnull ImmutableList> declaratorsThunk
) {
enforceNoStrayStructuralLabels(node);
ImmutableList declarators = applyListLabels(node.declarators, declaratorsThunk);
Node newNode = listRefEquals(node.declarators, declarators)
? node
: new VariableDeclaration(node.kind, declarators);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceVariableDeclarationStatement(
@Nonnull VariableDeclarationStatement node,
@Nonnull Supplier declarationThunk
) {
enforceNoStrayStructuralLabels(node);
VariableDeclaration declaration = (VariableDeclaration) declarationThunk.get();
Node newNode = node.declaration == declaration
? node
: new VariableDeclarationStatement(declaration);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceVariableDeclarator(
@Nonnull VariableDeclarator node,
@Nonnull Supplier bindingThunk,
@Nonnull Maybe> initThunk
) {
enforceNoStrayStructuralLabels(node);
Binding binding = (Binding) bindingThunk.get();
Maybe init = applyMaybeLabels(node.init, initThunk);
Node newNode = node.binding == binding && maybeRefEquals(node.init, init)
? node
: new VariableDeclarator(binding, init);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceWhileStatement(
@Nonnull WhileStatement node,
@Nonnull Supplier testThunk,
@Nonnull Supplier bodyThunk
) {
enforceNoStrayStructuralLabels(node);
Expression test = (Expression) testThunk.get();
Statement body = (Statement) bodyThunk.get();
Node newNode = node.test == test && node.body == body
? node
: new WhileStatement(test, body);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceWithStatement(
@Nonnull WithStatement node,
@Nonnull Supplier objectThunk,
@Nonnull Supplier bodyThunk
) {
enforceNoStrayStructuralLabels(node);
Expression object = (Expression) objectThunk.get();
Statement body = (Statement) bodyThunk.get();
Node newNode = node.object == object && node.body == body
? node
: new WithStatement(object, body);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceYieldExpression(
@Nonnull YieldExpression node,
@Nonnull Maybe> expressionThunk
) {
enforceNoStrayStructuralLabels(node);
Maybe expression = applyMaybeLabels(node.expression, expressionThunk);
Node newNode = maybeRefEquals(node.expression, expression)
? node
: new YieldExpression(expression);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
@Override
@Nonnull
public Node reduceYieldGeneratorExpression(
@Nonnull YieldGeneratorExpression node,
@Nonnull Supplier expressionThunk
) {
enforceNoStrayStructuralLabels(node);
Expression expression = (Expression) expressionThunk.get();
Node newNode = node.expression == expression
? node
: new YieldGeneratorExpression(expression);
return applyReplacer(this.nodeToLabels.get(node), newNode);
}
}