All Downloads are FREE. Search and download functionalities are using the official Maven repository.

software.amazon.awssdk.codegen.poet.rules2.PrepareForCodegenVisitor Maven / Gradle / Ivy

/*
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file 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 software.amazon.awssdk.codegen.poet.rules2;

import java.util.List;
import software.amazon.awssdk.codegen.internal.Utils;
import software.amazon.awssdk.utils.internal.CodegenNamingUtils;

/**
 * Visitor that rewrites some expressions in preparation for codegen and also renaming locals assignments to use idiomatic java
 * names. This visitor in particular rewrites variable references to the equivalent to {@code getAttr(params, NAME)} or {@code
 * getAttr(locals, NAME)}, depending on whether the reference is an endpoint params variable or a locally assigned one.
 */
public final class PrepareForCodegenVisitor extends RewriteRuleExpressionVisitor {
    private final SymbolTable symbolTable;
    private final SymbolTable.Builder renames;

    public PrepareForCodegenVisitor(SymbolTable symbolTable) {
        this.symbolTable = symbolTable;
        this.renames = SymbolTable.builder();
    }

    public SymbolTable symbolTable() {
        String regionParamName = symbolTable.regionParamName();
        if (regionParamName != null) {
            renames.regionParamName(javaName(regionParamName));
        }
        return renames.build();
    }

    @Override
    public RuleExpression visitBooleanNotExpression(BooleanNotExpression e) {
        e = (BooleanNotExpression) super.visitBooleanNotExpression(e);
        RuleExpression arg = e.expression();
        if (arg instanceof FunctionCallExpression) {
            FunctionCallExpression functionCall = (FunctionCallExpression) arg;
            if ("isSet".equals(functionCall.name())) {
                return functionCall.toBuilder()
                                   .name("isNotSet")
                                   .build();
            }
        }
        return e;
    }

    @Override
    public RuleExpression visitFunctionCallExpression(FunctionCallExpression e) {
        e = (FunctionCallExpression) super.visitFunctionCallExpression(e);
        String fn = e.name();
        switch (fn) {
            case "booleanEquals":
                return simplifyBooleanEquals(e);
            case "stringEquals":
                return simplifyStringEquals(e);
            case "not":
                return simplifyNotExpression(e);
            default:
                return e;
        }
    }

    @Override
    public RuleExpression visitVariableReferenceExpression(VariableReferenceExpression e) {
        String name = e.variableName();
        if (symbolTable.isLocal(name)) {
            RuleType type = symbolTable.localType(name);
            String newName = javaName(name);
            renames.putLocal(newName, type);
            return MemberAccessExpression
                .builder()
                .type(e.type())
                .source(VariableReferenceExpression.builder().variableName("locals").build())
                .name(newName)
                .build();
        }
        if (symbolTable.isParam(name)) {
            RuleType type = symbolTable.paramType(name);
            String newName = javaName(name);
            renames.putParam(newName, type);
            return MemberAccessExpression
                .builder()
                .type(e.type())
                .source(VariableReferenceExpression.builder().variableName("params").build())
                .name(newName)
                .build();
        }
        return e;
    }

    @Override
    public RuleExpression visitIndexedAccessExpression(IndexedAccessExpression e) {
        e = (IndexedAccessExpression) super.visitIndexedAccessExpression(e);
        return FunctionCallExpression
            .builder()
            .name("listAccess")
            .type(e.type())
            .addArgument(e.source())
            .addArgument(new LiteralIntegerExpression(e.index()))
            .build();
    }

    @Override
    public RuleExpression visitLetExpression(LetExpression e) {
        LetExpression.Builder builder = LetExpression.builder();
        e.bindings().forEach((k, v) -> {
            String newName = javaName(k);
            RuleExpression value = v.accept(this);
            builder.putBinding(newName, value);
            renames.putLocal(newName, value.type());
        });
        return builder.build();
    }

    /**
     * Transforms the following expressions:
     * 
    *
  • {@code booleanEquals(left, TRUE)} transforms to {@code left}
  • *
  • {@code booleanEquals(TRUE, right)} transforms to {@code right}
  • *
  • {@code booleanEquals(left, FALSE)} transforms to {@code (not left)}
  • *
  • {@code booleanEquals(FALSE, right)} transforms to {@code (not right)}
  • *
*/ private RuleExpression simplifyBooleanEquals(FunctionCallExpression e) { List args = e.arguments(); RuleExpression left = args.get(0).accept(this); RuleExpression right = args.get(1).accept(this); if (left.kind() == RuleExpression.RuleExpressionKind.BOOLEAN_VALUE) { LiteralBooleanExpression leftAsBoolean = (LiteralBooleanExpression) left; if (leftAsBoolean.value()) { return right; } return BooleanNotExpression .builder() .expression(right) .build(); } if (right.kind() == RuleExpression.RuleExpressionKind.BOOLEAN_VALUE) { LiteralBooleanExpression rightAsBoolean = (LiteralBooleanExpression) right; if (rightAsBoolean.value()) { return left; } return BooleanNotExpression .builder() .expression(left) .build(); } return MethodCallExpression.builder() .name("equals") .source(left) .addArgument(right) .build(); } /** * Transforms the following expression *
    *
  • {@code stringEquals(left, right)} to {@code left.equals(right)} when left is a String constant
  • *
  • {@code stringEquals(left, right)} to {@code right.equals(left)} when right is a String constant
  • *
*/ private RuleExpression simplifyStringEquals(FunctionCallExpression e) { List args = e.arguments(); RuleExpression left = args.get(0).accept(this); RuleExpression right = args.get(1).accept(this); if (right.kind() == RuleExpression.RuleExpressionKind.STRING_VALUE) { return MethodCallExpression.builder() .name("equals") .source(right) .addArgument(left) .build(); } if (left.kind() == RuleExpression.RuleExpressionKind.STRING_VALUE) { return MethodCallExpression.builder() .name("equals") .source(left) .addArgument(right) .build(); } return e; } /** * Transforms the following expression *
    *
  • {@code not(isSet(getAttr(source, name)))} to {@code isNotSet(getAttr(source, name))} which can be later * transformed into {@code getAttr(source, name) == null}
  • *
*/ private RuleExpression simplifyNotExpression(FunctionCallExpression e) { RuleExpression arg = e.arguments().get(0); if (arg instanceof FunctionCallExpression) { FunctionCallExpression inner = (FunctionCallExpression) arg; if ("isSet".equals(inner.name())) { return inner.toBuilder() .name("isNotSet") .build(); } } return e; } private String javaName(String name) { return Utils.unCapitalize(CodegenNamingUtils.pascalCase(name)); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy