diff --git a/src/main/java/com/google/api/generator/engine/ast/AssignmentOperationExpr.java b/src/main/java/com/google/api/generator/engine/ast/AssignmentOperationExpr.java new file mode 100644 index 0000000000..8802465f98 --- /dev/null +++ b/src/main/java/com/google/api/generator/engine/ast/AssignmentOperationExpr.java @@ -0,0 +1,138 @@ +// Copyright 2020 Google LLC +// +// 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.api.generator.engine.ast; + +import com.google.auto.value.AutoValue; +import com.google.common.base.Preconditions; + +@AutoValue +public abstract class AssignmentOperationExpr implements OperationExpr { + public abstract VariableExpr variableExpr(); + + public abstract Expr valueExpr(); + + public abstract OperatorKind operatorKind(); + + @Override + public TypeNode type() { + return variableExpr().type(); + } + + @Override + public void accept(AstNodeVisitor visitor) { + visitor.visit(this); + } + + public static AssignmentOperationExpr xorAssignmentWithExprs( + VariableExpr variableExpr, Expr valueExpr) { + return builder() + .setVariableExpr(variableExpr) + .setValueExpr(valueExpr) + .setOperatorKind(OperatorKind.ASSIGNMENT_XOR) + .build(); + } + + public static AssignmentOperationExpr multiplyAssignmentWithExprs( + VariableExpr variableExpr, Expr valueExpr) { + return builder() + .setVariableExpr(variableExpr) + .setValueExpr(valueExpr) + .setOperatorKind(OperatorKind.ASSIGNMENT_MULTIPLY) + .build(); + } + + private static Builder builder() { + return new AutoValue_AssignmentOperationExpr.Builder(); + } + + @AutoValue.Builder + abstract static class Builder { + // Private setter. + abstract Builder setVariableExpr(VariableExpr variableExpr); + + // Private setter. + abstract Builder setValueExpr(Expr valueExpr); + + // Private setter. + abstract Builder setOperatorKind(OperatorKind operator); + + abstract AssignmentOperationExpr autoBuild(); + + private AssignmentOperationExpr build() { + AssignmentOperationExpr assignmentOperationExpr = autoBuild(); + TypeNode lhsType = assignmentOperationExpr.variableExpr().variable().type(); + TypeNode rhsType = assignmentOperationExpr.valueExpr().type(); + OperatorKind operator = assignmentOperationExpr.operatorKind(); + + // Check if the variable exprs have been declared, if yes, throw error. + Preconditions.checkState( + !assignmentOperationExpr.variableExpr().isDecl(), + String.format( + "Variable `%s` should not be declaration in the variable expression.", + assignmentOperationExpr.variableExpr().variable().name())); + + // errorMsg is type checking error message for operators. + final String errorMsg = + String.format( + "Assignment operator %s can not be applied to %s, %s.", + operator, lhsType.toString(), rhsType.toString()); + + // Check type for multiply and assignment operator (*=). + if (operator.equals(OperatorKind.ASSIGNMENT_MULTIPLY)) { + Preconditions.checkState(isValidMultiplyAssignmentType(lhsType, rhsType), errorMsg); + } + + // Check type for XOR and assignment operator (^=). + // TODO(summerji): Complete the type-checking for ^= and unit test. + if (operator.equals(OperatorKind.ASSIGNMENT_XOR)) { + Preconditions.checkState(isValidXORAssignmentType(lhsType, rhsType), errorMsg); + } + return assignmentOperationExpr; + } + + // isValidMultiplyAssignmentType validates the types for LHS variable expr and RHS expr. + // *= can be only applied on Primitive numeric type. + private boolean isValidMultiplyAssignmentType(TypeNode variableType, TypeNode valueType) { + // LHS is numeric type, RHS should be any numeric type or any numeric boxed type. + if (TypeNode.isNumericType(variableType) && !TypeNode.isBoxedType(variableType)) { + return TypeNode.isNumericType(valueType); + } + // LHS is integer boxed type, RHS should be any numeric type except long, float, double. + if (variableType.equals(TypeNode.INT)) { + return TypeNode.isNumericType(valueType) + && !(valueType.equals(TypeNode.LONG) || TypeNode.isFloatingPointType(valueType)); + } + // LHS is long boxed type, RHS should be any numeric type except float, double. + if (variableType.equals(TypeNode.LONG)) { + return TypeNode.isNumericType(valueType) && !TypeNode.isFloatingPointType(valueType); + } + // LHS is integer boxed type, RHS should be any numeric type except double. + if (variableType.equals(TypeNode.FLOAT)) { + return TypeNode.isNumericType(valueType) && !valueType.equals(TypeNode.DOUBLE); + } + // LHS is integer boxed type, RHS should be any numeric type or any numeric boxed type. + if (variableType.equals(TypeNode.DOUBLE)) { + return TypeNode.isNumericType(valueType); + } + // *= operator does not support boxed Short, Character, Byte, null, reference, void type. + return false; + } + + // TODO(summerji): Complete the type-checking for ^= and unit test. + private boolean isValidXORAssignmentType(TypeNode variableType, TypeNode valueType) { + return true; + } + } +} diff --git a/src/main/java/com/google/api/generator/engine/ast/AstNodeVisitor.java b/src/main/java/com/google/api/generator/engine/ast/AstNodeVisitor.java index 193ac553c2..32b0642619 100644 --- a/src/main/java/com/google/api/generator/engine/ast/AstNodeVisitor.java +++ b/src/main/java/com/google/api/generator/engine/ast/AstNodeVisitor.java @@ -59,6 +59,8 @@ public interface AstNodeVisitor { public void visit(LogicalOperationExpr logicalOperationExpr); + public void visit(AssignmentOperationExpr assignmentOperationExpr); + /** =============================== COMMENT =============================== */ public void visit(LineComment lineComment); diff --git a/src/main/java/com/google/api/generator/engine/ast/OperatorKind.java b/src/main/java/com/google/api/generator/engine/ast/OperatorKind.java index a895b7d991..1c11a77fc3 100644 --- a/src/main/java/com/google/api/generator/engine/ast/OperatorKind.java +++ b/src/main/java/com/google/api/generator/engine/ast/OperatorKind.java @@ -20,6 +20,8 @@ public enum OperatorKind { ARITHMETIC_ADDITION, LOGICAL_AND, LOGICAL_OR, + ASSIGNMENT_XOR, + ASSIGNMENT_MULTIPLY, RELATIONAL_EQUAL_TO, RELATIONAL_NOT_EQUAL_TO, RELATIONAL_LESS_THAN, diff --git a/src/main/java/com/google/api/generator/engine/ast/TypeNode.java b/src/main/java/com/google/api/generator/engine/ast/TypeNode.java index e85263ef2d..9505cbb8cc 100644 --- a/src/main/java/com/google/api/generator/engine/ast/TypeNode.java +++ b/src/main/java/com/google/api/generator/engine/ast/TypeNode.java @@ -174,6 +174,10 @@ public static boolean isNumericType(TypeNode type) { || type.equals(TypeNode.BYTE); } + public static boolean isFloatingPointType(TypeNode type) { + return type.equals(TypeNode.DOUBLE) || type.equals(TypeNode.FLOAT); + } + public static boolean isBoxedType(TypeNode type) { return isReferenceType(type) && BOXED_TYPE_MAP.containsValue(type); } diff --git a/src/main/java/com/google/api/generator/engine/writer/ImportWriterVisitor.java b/src/main/java/com/google/api/generator/engine/writer/ImportWriterVisitor.java index e59067ec0c..94af63747e 100644 --- a/src/main/java/com/google/api/generator/engine/writer/ImportWriterVisitor.java +++ b/src/main/java/com/google/api/generator/engine/writer/ImportWriterVisitor.java @@ -18,6 +18,7 @@ import com.google.api.generator.engine.ast.AnonymousClassExpr; import com.google.api.generator.engine.ast.ArithmeticOperationExpr; import com.google.api.generator.engine.ast.AssignmentExpr; +import com.google.api.generator.engine.ast.AssignmentOperationExpr; import com.google.api.generator.engine.ast.AstNodeVisitor; import com.google.api.generator.engine.ast.BlockComment; import com.google.api.generator.engine.ast.BlockStatement; @@ -240,6 +241,12 @@ public void visit(LogicalOperationExpr logicalOperationExpr) { logicalOperationExpr.rhsExpr().accept(this); } + @Override + public void visit(AssignmentOperationExpr assignmentOperationExpr) { + assignmentOperationExpr.variableExpr().accept(this); + assignmentOperationExpr.valueExpr().accept(this); + } + /** =============================== STATEMENTS =============================== */ @Override public void visit(ExprStatement exprStatement) { diff --git a/src/main/java/com/google/api/generator/engine/writer/JavaWriterVisitor.java b/src/main/java/com/google/api/generator/engine/writer/JavaWriterVisitor.java index b770de98bc..6112275b3c 100644 --- a/src/main/java/com/google/api/generator/engine/writer/JavaWriterVisitor.java +++ b/src/main/java/com/google/api/generator/engine/writer/JavaWriterVisitor.java @@ -18,6 +18,7 @@ import com.google.api.generator.engine.ast.AnonymousClassExpr; import com.google.api.generator.engine.ast.ArithmeticOperationExpr; import com.google.api.generator.engine.ast.AssignmentExpr; +import com.google.api.generator.engine.ast.AssignmentOperationExpr; import com.google.api.generator.engine.ast.AstNodeVisitor; import com.google.api.generator.engine.ast.BlockComment; import com.google.api.generator.engine.ast.BlockStatement; @@ -115,6 +116,8 @@ public class JavaWriterVisitor implements AstNodeVisitor { private static final String OPERATOR_LOGICAL_NOT = "!"; private static final String OPERATOR_LOGICAL_AND = "&&"; private static final String OPERATOR_LOGICAL_OR = "||"; + private static final String OPERATOR_XOR = "^="; + private static final String OPERATOR_MULTIPLE_AND_ASSIGNMENT = "*="; private final StringBuffer buffer = new StringBuffer(); private final ImportWriterVisitor importWriterVisitor = new ImportWriterVisitor(); @@ -430,6 +433,15 @@ public void visit(LogicalOperationExpr logicalOperationExpr) { logicalOperationExpr.rhsExpr().accept(this); } + @Override + public void visit(AssignmentOperationExpr assignmentOperationExpr) { + assignmentOperationExpr.variableExpr().accept(this); + space(); + operator(assignmentOperationExpr.operatorKind()); + space(); + assignmentOperationExpr.valueExpr().accept(this); + } + /** =============================== STATEMENTS =============================== */ @Override public void visit(ExprStatement exprStatement) { @@ -913,6 +925,15 @@ private void semicolon() { private void operator(OperatorKind kind) { switch (kind) { + case ARITHMETIC_ADDITION: + buffer.append(OPERATOR_ADDITION); + break; + case ASSIGNMENT_XOR: + buffer.append(OPERATOR_XOR); + break; + case ASSIGNMENT_MULTIPLY: + buffer.append(OPERATOR_MULTIPLE_AND_ASSIGNMENT); + break; case RELATIONAL_EQUAL_TO: buffer.append(OPERATOR_EQUAL_TO); break; @@ -928,9 +949,6 @@ private void operator(OperatorKind kind) { case UNARY_LOGICAL_NOT: buffer.append(OPERATOR_LOGICAL_NOT); break; - case ARITHMETIC_ADDITION: - buffer.append(OPERATOR_ADDITION); - break; case LOGICAL_AND: buffer.append(OPERATOR_LOGICAL_AND); break; diff --git a/src/test/java/com/google/api/generator/engine/ast/AssignmentOperationExprTest.java b/src/test/java/com/google/api/generator/engine/ast/AssignmentOperationExprTest.java new file mode 100644 index 0000000000..4ca573ce4d --- /dev/null +++ b/src/test/java/com/google/api/generator/engine/ast/AssignmentOperationExprTest.java @@ -0,0 +1,662 @@ +// Copyright 2020 Google LLC +// +// 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.api.generator.engine.ast; + +import static org.junit.Assert.assertThrows; + +import org.junit.Test; + +public class AssignmentOperationExprTest { + /** ========= Multiply And Assignment Operators: VariableExpr is numeric types ============== */ + @Test + public void validMultiplyAndAssignmentOperationExpr_numericMatched() { + // No need swap test case. + VariableExpr lhsExpr = createVariableExpr(TypeNode.INT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.INT, "y"); + AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void validMultiplyAndAssignmentOperationExpr_numericUnmatched() { + // No need swap test case. + VariableExpr lhsExpr = createVariableExpr(TypeNode.INT, "x"); + ValueExpr rhsExpr = createValueExpr(TypeNode.INT, "5"); + AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void validMultiplyAndAssignmentOperationExpr_numericMatchedBoxedType() { + // Swap test case in "validMultiplyAndAssignmentOperationExpr_integerMatchedBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.INT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.INT_OBJECT, "y"); + AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void validMultiplyAndAssignmentOperationExpr_numericUnmatchedBoxedType() { + // Swap test case in "validMultiplyAndAssignmentOperationExpr_integerBoxedWithShortType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.INT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.FLOAT_OBJECT, "y"); + AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void validMultiplyAndAssignmentOperationExpr_numericWithFloatType() { + // Swap test case in "validMultiplyAndAssignmentOperationExpr_integerBoxedWithFloatType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.FLOAT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.INT_OBJECT, "y"); + AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void validMultiplyAndAssignmentOperationExpr_doubleWithIntegerBoxedType() { + // Swap test case in "validMultiplyAndAssignmentOperationExpr_integerBoxedWithDoubleType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.DOUBLE, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.INT_OBJECT, "y"); + AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void validMultiplyAndAssignmentOperationExpr_doubleWithLongBoxedType() { + // Swap test case in "invalidMultiplyAndAssignmentOperationExpr_longBoxedWithDoubleType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.DOUBLE, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.LONG_OBJECT, "y"); + AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void validMultiplyAndAssignmentOperationExpr_longWithIntegerBoxedType() { + // Swap test case in "invalidMultiplyAndAssignmentOperationExpr_integerBoxedWithLongType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.LONG, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.INT_OBJECT, "y"); + AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void validMultiplyAndAssignmentOperationExpr_integerWithFloatBoxedType() { + // Swap test case in "validMultiplyAndAssignmentOperationExpr_floatBoxedWithIntegerType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.INT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.FLOAT_OBJECT, "y"); + AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void validMultiplyAndAssignmentOperationExpr_validFloatWithLongBoxedType() { + // Swap test case in "invalidMultiplyAndAssignmentOperationExpr_longBoxedWithFloatType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.FLOAT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.LONG_OBJECT, "y"); + AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void invalidMultiplyAndAssignmentOperationExpr_numericWithBooleanBoxedType() { + // Swap test case in "invalidMultiplyAndAssignmentOperationExpr_booleanBoxedWithNumericType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.INT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.BOOLEAN_OBJECT, "y"); + assertThrows( + IllegalStateException.class, + () -> AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void invalidMultiplyAndAssignmentOperationExpr_numericWithBooleanType() { + // Swap test case in "invalidMultiplyAndAssignmentOperationExpr_numericWithBooleanType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.INT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.BOOLEAN, "y"); + assertThrows( + IllegalStateException.class, + () -> AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void invalidMultiplyAndAssignmentOperationExpr_numericWithReferenceType() { + // Swap test case in "invalidMultiplyAndAssignmentOperationExpr_feferencedWithNumericType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.INT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.STRING, "y"); + assertThrows( + IllegalStateException.class, + () -> AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void invalidMultiplyAndAssignmentOperationExpr_NumericWithNewObject() { + // No Need swap case. + VariableExpr lhsExpr = createVariableExpr(TypeNode.INT, "x"); + NewObjectExpr rhsExpr = NewObjectExpr.withType(TypeNode.OBJECT); + assertThrows( + IllegalStateException.class, + () -> AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr)); + } + + /** ==== Multiply And Assignment Operators: LHS data type is boolean and its boxed type ===== */ + @Test + public void invalidMultiplyAndAssignmentOperationExpr_booleanWithNumericType() { + // Swap test case in "invalidMultiplyAndAssignmentOperationExpr_numericWithBooleanType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.BOOLEAN, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.INT, "y"); + assertThrows( + IllegalStateException.class, + () -> AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void invalidMultiplyAndAssignmentOperationExpr_booleanBoxedWithNumericType() { + // Swap test case in "invalidMultiplyAndAssignmentOperationExpr_numericWithBooleanBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.BOOLEAN_OBJECT, "x"); + ValueExpr rhsExpr = createValueExpr(TypeNode.INT, "5"); + assertThrows( + IllegalStateException.class, + () -> AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr)); + } + + /** ======== Multiply And Assignment Operators: LHS data type is Integer Box Type ============ */ + // RHS should be int, char, short, byte or these types' boxed types. + @Test + public void validMultiplyAndAssignmentOperationExpr_integerMatchedBoxedType() { + // Swap test case in "validMultiplyAndAssignmentOperationExpr_numericMatchedBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.INT_OBJECT, "x"); + ValueExpr rhsExpr = createValueExpr(TypeNode.INT, "5"); + AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void validMultiplyAndAssignmentOperationExpr_integerBoxedWithShortType() { + // Swap test case in "validMultiplyAndAssignmentOperationExpr_numericUnmatchedBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.INT_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.SHORT, "y"); + AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void validMultiplyAndAssignmentOperationExpr_integerBoxedWithShortBoxedType() { + // Swap test case in "validMultiplyAndAssignmentOperationExpr_shortBoxedWithIntegerBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.INT_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.SHORT_OBJECT, "y"); + AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void validMultiplyAndAssignmentOperationExpr_integerBoxedWithCharacterBoxedType() { + // Swap test case in "validMultiplyAndAssignmentOperationExpr_shortBoxedWithIntegerBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.INT_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.CHAR_OBJECT, "y"); + AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void validMultiplyAndAssignmentOperationExpr_integerBoxedWithByteBoxedType() { + // Swap test case in "validMultiplyAndAssignmentOperationExpr_byteBoxedWithIntegerBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.INT_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.BYTE_OBJECT, "y"); + AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void invalidMultiplyAndAssignmentOperationExpr_integerBoxedWithFloatType() { + // Swap test case in "validMultiplyAndAssignmentOperationExpr_numericWithFloatType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.INT_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.FLOAT, "y"); + assertThrows( + IllegalStateException.class, + () -> AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void invalidMultiplyAndAssignmentOperationExpr_integerBoxedWithFloatBoxedType() { + // Swap test case in "validMultiplyAndAssignmentOperationExpr_floatBoxedWithIntegerBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.INT_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.FLOAT_OBJECT, "y"); + assertThrows( + IllegalStateException.class, + () -> AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void invalidMultiplyAndAssignmentOperationExpr_integerBoxedWithDoubleType() { + // Swap test case in "validMultiplyAndAssignmentOperationExpr_doubleWithIntegerBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.INT_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.DOUBLE, "y"); + assertThrows( + IllegalStateException.class, + () -> AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void invalidMultiplyAndAssignmentOperationExpr_integerBoxedWithDoubleBoxedType() { + // Swap test case in "validMultiplyAndAssignmentOperationExpr_doubleBoxedWithIntegerBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.INT_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.DOUBLE_OBJECT, "y"); + assertThrows( + IllegalStateException.class, + () -> AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void invalidMultiplyAndAssignmentOperationExpr_integerBoxedWithLongType() { + // Swap test case in "validMultiplyAndAssignmentOperationExpr_longWithIntegerBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.INT_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.LONG, "y"); + assertThrows( + IllegalStateException.class, + () -> AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void invalidMultiplyAndAssignmentOperationExpr_integerBoxedWithLongBoxedType() { + // Swap test case in "validMultiplyAndAssignmentOperationExpr_longBoxedWithIntegerBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.INT_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.LONG_OBJECT, "y"); + assertThrows( + IllegalStateException.class, + () -> AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr)); + } + + /** ==== Multiply And Assignment Operators: LHS data type is Float boxed type ====== */ + // RHS could be numeric or numeric boxed type, beside double and its boxed type. + @Test + public void validMultiplyAndAssignmentOperationExpr_floatBoxedWithIntegerType() { + // Swap test case in "validMultiplyAndAssignmentOperationExpr_integerWithFloatBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.FLOAT_OBJECT, "x"); + ValueExpr rhsExpr = createValueExpr(TypeNode.INT, "5"); + AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void validMultiplyAndAssignmentOperationExpr_floatBoxedWithIntegerBoxedType() { + // Swap test case in "invalidMultiplyAndAssignmentOperationExpr_integerBoxedWithFloatBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.FLOAT_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.INT_OBJECT, "y"); + AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void validMultiplyAndAssignmentOperationExpr_floatBoxedWithCharBoxedType() { + // Swap test case in "invalidMultiplyAndAssignmentOperationExpr_charBoxedWithFloatBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.FLOAT_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.CHAR_OBJECT, "y"); + AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void validMultiplyAndAssignmentOperationExpr_floatBoxedWithByteBoxedType() { + // Swap test case in "invalidMultiplyAndAssignmentOperationExpr_byteBoxedWithFloatBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.FLOAT_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.BYTE_OBJECT, "y"); + AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void validMultiplyAndAssignmentOperationExpr_floatBoxedWithLongBoxedType() { + // Swap test case in "invalidMultiplyAndAssignmentOperationExpr_longBoxedWithFloatBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.FLOAT_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.LONG_OBJECT, "y"); + AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void validMultiplyAndAssignmentOperationExpr_floatBoxedWithDoubleBoxedType() { + // Swap test case in "validMultiplyAndAssignmentOperationExpr_doubleBoxedWithFloatBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.FLOAT_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.DOUBLE_OBJECT, "y"); + assertThrows( + IllegalStateException.class, + () -> AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void invalidMultiplyAndAssignmentOperationExpr_floatBoxedWithObjectType() { + // No need swap case. + VariableExpr lhsExpr = createVariableExpr(TypeNode.FLOAT_OBJECT, "x"); + NewObjectExpr rhsExpr = NewObjectExpr.withType(TypeNode.OBJECT); + assertThrows( + IllegalStateException.class, + () -> AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void invalidMultiplyAndAssignmentOperationExpr_floatBoxedWithNullType() { + // No need swap case. + VariableExpr lhsExpr = createVariableExpr(TypeNode.FLOAT_OBJECT, "x"); + ValueExpr rhsExpr = ValueExpr.withValue(NullObjectValue.create()); + assertThrows( + IllegalStateException.class, + () -> AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void invalidMultiplyAndAssignmentOperationExpr_floatBoxedWithReferenceType() { + // Swap test case in "invalidMultiplyAndAssignmentOperationExpr_referenceWithFloatBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.FLOAT_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.STRING, "y"); + assertThrows( + IllegalStateException.class, + () -> AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr)); + } + + /** ==== Multiply And Assignment Operators: LHS data type is Short/Char/Byte Boxed Type ====== */ + // RHS has no valid type. + @Test + public void invalidMultiplyAndAssignmentOperationExpr_byteBoxedWithIntegerBoxedType() { + // Swap test case in "validMultiplyAndAssignmentOperationExpr_integerBoxedWithByteBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.BYTE_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.INT_OBJECT, "y"); + assertThrows( + IllegalStateException.class, + () -> AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void invalidMultiplyAndAssignmentOperationExpr_shortBoxedWithIntegerBoxedType() { + // Swap test case in + // "validMultiplyAndAssignmentOperationExpr_validCharacterBoxedWithIntegerBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.SHORT_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.INT_OBJECT, "y"); + assertThrows( + IllegalStateException.class, + () -> AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void validMultiplyAndAssignmentOperationExpr_characterBoxedWithIntegerBoxedType() { + // Swap test case in + // "validMultiplyAndAssignmentOperationExpr_integerBoxedWithCharacterBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.CHAR_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.INT_OBJECT, "y"); + assertThrows( + IllegalStateException.class, + () -> AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void invalidMultiplyAndAssignmentOperationExpr_charBoxedWithFloatBoxedType() { + // Swap test case in "invalidMultiplyAndAssignmentOperationExpr_integerBoxedWithFloatBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.CHAR_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.FLOAT_OBJECT, "y"); + assertThrows( + IllegalStateException.class, + () -> AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void invalidMultiplyAndAssignmentOperationExpr_byteBoxedWithFloatBoxedType() { + // Swap test case in "validMultiplyAndAssignmentOperationExpr_floatBoxedWithByteBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.BYTE_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.FLOAT_OBJECT, "y"); + assertThrows( + IllegalStateException.class, + () -> AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr)); + } + + /** ======== Multiply And Assignment Operators: LHS data type is Double Boxed Type ============ */ + // RHS could be any numeric type or numeric boxed type. + @Test + public void validMultiplyAndAssignmentOperationExpr_doubleBoxedWithIntegerBoxedType() { + // Swap test case in + // "invalidMultiplyAndAssignmentOperationExpr_integerBoxedWithDoubleBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.DOUBLE_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.INT_OBJECT, "y"); + AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void validMultiplyAndAssignmentOperationExpr_doubleBoxedWithFloatBoxedType() { + // Swap test case in "invalidMultiplyAndAssignmentOperationExpr_floatBoxedWithDoubleBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.DOUBLE_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.FLOAT_OBJECT, "y"); + AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void validMultiplyAndAssignmentOperationExpr_doubleBoxedWithLongBoxedType() { + // Swap test case in "invalidMultiplyAndAssignmentOperationExpr_longBoxedWithDoubleBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.DOUBLE_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.LONG_OBJECT, "y"); + AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void invalidMultiplyAndAssignmentOperationExpr_doubleBoxedWithReferenceType() { + // Swap test case in "invalidMultiplyAndAssignmentOperationExpr_referenceWithDoubleBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.DOUBLE_OBJECT, "x"); + ValueExpr valueExpr = ValueExpr.withValue(StringObjectValue.withValue("abc")); + assertThrows( + IllegalStateException.class, + () -> AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, valueExpr)); + } + + @Test + public void invalidMultiplyAndAssignmentOperationExpr_doubleBoxedWithNullType() { + // No need swap case. + VariableExpr lhsExpr = createVariableExpr(TypeNode.DOUBLE_OBJECT, "x"); + ValueExpr valueExprExpr = ValueExpr.withValue(NullObjectValue.create()); + assertThrows( + IllegalStateException.class, + () -> AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, valueExprExpr)); + } + + @Test + public void invalidMultiplyAndAssignmentOperationExpr_doubleBoxedWithOjectType() { + // No need swap test. + VariableExpr lhsExpr = createVariableExpr(TypeNode.DOUBLE_OBJECT, "x"); + NewObjectExpr rhsExpr = NewObjectExpr.withType(TypeNode.OBJECT); + assertThrows( + IllegalStateException.class, + () -> AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr)); + } + + /** ======== Multiply And Assignment Operators: LHS data type is Long boxed type ============ */ + @Test + public void validMultiplyAndAssignmentOperationExpr_longBoxedWithIntegerBoxedType() { + // Swap test case in "invalidMultiplyAndAssignmentOperationExpr_integerBoxedWithLongBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.LONG_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.INT_OBJECT, "y"); + AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void invalidMultiplyAndAssignmentOperationExpr_longBoxedWithFloatBoxedType() { + // Swap test case in "validMultiplyAndAssignmentOperationExpr_floatBoxedWithLongBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.LONG_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.FLOAT_OBJECT, "y"); + assertThrows( + IllegalStateException.class, + () -> AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void invalidMultiplyAndAssignmentOperationExpr_longBoxedWithFloatType() { + // Swap test case in "validMultiplyAndAssignmentOperationExpr_floatWithLongBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.LONG_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.FLOAT, "y"); + assertThrows( + IllegalStateException.class, + () -> AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void invalidMultiplyAndAssignmentOperationExpr_longBoxedWithDoubleBoxedType() { + // Swap test case in "validMultiplyAndAssignmentOperationExpr_doubleBoxedWithLongBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.LONG_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.DOUBLE_OBJECT, "y"); + assertThrows( + IllegalStateException.class, + () -> AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void invalidMultiplyAndAssignmentOperationExpr_longBoxedWithDoubleType() { + // Swap test case in "validMultiplyAndAssignmentOperationExpr_doubleWithLongBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.LONG_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.DOUBLE, "y"); + assertThrows( + IllegalStateException.class, + () -> AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void invalidMultiplyAndAssignmentOperationExpr_longBoxedWithNullType() { + // Swap test case in "invalidMultiplyAndAssignmentOperationExpr_nullWithLongBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.LONG_OBJECT, "x"); + ValueExpr rhsExpr = ValueExpr.withValue(NullObjectValue.create()); + assertThrows( + IllegalStateException.class, + () -> AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void invalidMultiplyAndAssignmentOperationExpr_longBoxedWithObjectType() { + // No need swap case. + VariableExpr lhsExpr = createVariableExpr(TypeNode.LONG_OBJECT, "x"); + NewObjectExpr rhsExpr = NewObjectExpr.withType(TypeNode.OBJECT); + assertThrows( + IllegalStateException.class, + () -> AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void invalidMultiplyAndAssignmentOperationExpr_longBoxedWithReferenceType() { + // Swap test case in "invalidMultiplyAndAssignmentOperationExpr_referenceWithLongBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.LONG_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.STRING, "y"); + assertThrows( + IllegalStateException.class, + () -> AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr)); + } + + /** ======== Multiply And Assignment Operators: LHS data type is Reference Type ============ */ + @Test + public void invalidMultiplyAndAssignmentOperationExpr_referencedWithNumericType() { + // Swap test case in "invalidMultiplyAndAssignmentOperationExpr_numericWithReferenceType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.STRING, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.DOUBLE, "y"); + assertThrows( + IllegalStateException.class, + () -> AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void invalidMultiplyAndAssignmentOperationExpr_referenceWithFloatBoxedType() { + // Swap test case in "invalidMultiplyAndAssignmentOperationExpr_floatBoxedWithReferenceType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.STRING, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.FLOAT_OBJECT, "y"); + assertThrows( + IllegalStateException.class, + () -> AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void invalidMultiplyAndAssignmentOperationExpr_referenceWithLongBoxedType() { + // Swap test case in "invalidMultiplyAndAssignmentOperationExpr_longBoxedWithReferenceType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.STRING, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.LONG_OBJECT, "y"); + assertThrows( + IllegalStateException.class, + () -> AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void invalidMultiplyAndAssignmentOperationExpr_referenceWithDoubleBoxedType() { + // Swap test case in "invalidMultiplyAndAssignmentOperationExpr_doubleBoxedWithReferenceType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.STRING, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.DOUBLE_OBJECT, "y"); + assertThrows( + IllegalStateException.class, + () -> AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr)); + } + + /** =========== Multiply And Assignment Operators: Variable is declaration ================ */ + @Test + public void invalidMultiplyAndAssignmentOperationExpr_variableExprIsDecl() { + Variable variable = Variable.builder().setName("x").setType(TypeNode.INT).build(); + VariableExpr lhsExpr = VariableExpr.builder().setVariable(variable).setIsDecl(true).build(); + VariableExpr rhsExpr = createVariableExpr(TypeNode.INT, "y"); + assertThrows( + IllegalStateException.class, + () -> AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void invalidMultiplyAndAssignmentOperationExpr_valueExprIsDecl() { + VariableExpr lhsExpr = createVariableExpr(TypeNode.INT, "x"); + Variable variable = Variable.builder().setName("x").setType(TypeNode.INT).build(); + VariableExpr rhsExpr = VariableExpr.builder().setVariable(variable).setIsDecl(true).build(); + assertThrows( + IllegalStateException.class, + () -> AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void invalidMultiplyAndAssignmentOperationExpr_variableExprAndValueExprIsDecl() { + Variable lVariable = Variable.builder().setName("x").setType(TypeNode.INT).build(); + VariableExpr lhsExpr = VariableExpr.builder().setVariable(lVariable).setIsDecl(true).build(); + Variable rVariable = Variable.builder().setName("y").setType(TypeNode.INT).build(); + VariableExpr rhsExpr = VariableExpr.builder().setVariable(rVariable).setIsDecl(true).build(); + assertThrows( + IllegalStateException.class, + () -> AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr)); + } + + /** ======================= Multiply And Assignment Operators: Void type ===================== */ + @Test + public void invalidMultiplyAndAssignmentOperationExpr_voidType() { + // No need swap case. + VariableExpr lhsExprExpr = createVariableExpr(TypeNode.FLOAT_OBJECT, "x"); + MethodInvocationExpr rhsExpr = + MethodInvocationExpr.builder().setMethodName("x").setReturnType(TypeNode.VOID).build(); + assertThrows( + IllegalStateException.class, + () -> AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExprExpr, rhsExpr)); + } + + // TODO(summerji): Complete the type-checking for ^= and unit test. + /** ================== Bitwise Exclusive Or And Assignment Operators: ======================== */ + // createVariableExpr is help function to create a variable expr. + private VariableExpr createVariableExpr(TypeNode type, String name) { + Variable variable = Variable.builder().setName(name).setType(type).build(); + VariableExpr lhsExpr = VariableExpr.withVariable(variable); + return lhsExpr; + } + + // createValueExpr is help function to create a value expr. + private ValueExpr createValueExpr(TypeNode type, String value) { + PrimitiveValue primitiveValue = PrimitiveValue.builder().setType(type).setValue(value).build(); + ValueExpr valueExpr = ValueExpr.withValue(primitiveValue); + return valueExpr; + } +} diff --git a/src/test/java/com/google/api/generator/engine/ast/BUILD.bazel b/src/test/java/com/google/api/generator/engine/ast/BUILD.bazel index 323b5e1dc1..dda0ab0ac3 100644 --- a/src/test/java/com/google/api/generator/engine/ast/BUILD.bazel +++ b/src/test/java/com/google/api/generator/engine/ast/BUILD.bazel @@ -38,6 +38,7 @@ TESTS = [ "UnaryOperationExprTest", "RelationalOperationExprTest", "LogicalOperationExprTest", + "AssignmentOperationExprTest", ] filegroup( diff --git a/src/test/java/com/google/api/generator/engine/writer/JavaWriterVisitorTest.java b/src/test/java/com/google/api/generator/engine/writer/JavaWriterVisitorTest.java index 30632ea40c..5745b8e01f 100644 --- a/src/test/java/com/google/api/generator/engine/writer/JavaWriterVisitorTest.java +++ b/src/test/java/com/google/api/generator/engine/writer/JavaWriterVisitorTest.java @@ -21,6 +21,7 @@ import com.google.api.generator.engine.ast.AnonymousClassExpr; import com.google.api.generator.engine.ast.ArithmeticOperationExpr; import com.google.api.generator.engine.ast.AssignmentExpr; +import com.google.api.generator.engine.ast.AssignmentOperationExpr; import com.google.api.generator.engine.ast.BlockComment; import com.google.api.generator.engine.ast.BlockStatement; import com.google.api.generator.engine.ast.CastExpr; @@ -2145,6 +2146,39 @@ public void writeLogicalOperationExpr_logicalOr() { assertThat(writerVisitor.write()).isEqualTo("isGood || isValid()"); } + @Test + public void writeAssignmentOperationExpr_multiplyAssignment() { + VariableExpr lhsExpr = createVariableExpr("h", TypeNode.INT); + ValueExpr rhsExpr = + ValueExpr.withValue( + PrimitiveValue.builder().setType(TypeNode.INT).setValue("1000003").build()); + AssignmentOperationExpr assignmentOperationExpr = + AssignmentOperationExpr.multiplyAssignmentWithExprs(lhsExpr, rhsExpr); + assignmentOperationExpr.accept(writerVisitor); + assertThat(writerVisitor.write()).isEqualTo("h *= 1000003"); + } + + @Test + public void writeAssignmentOperationExpr_xorAssignment() { + VariableExpr lhsExpr = createVariableExpr("h", TypeNode.INT); + TypeNode objectType = + TypeNode.withReference( + VaporReference.builder().setName("Objects").setPakkage("java.lang.Object").build()); + MethodInvocationExpr rhsExpr = + MethodInvocationExpr.builder() + .setReturnType(TypeNode.INT) + .setMethodName("hashCode") + .setStaticReferenceType(objectType) + .setArguments( + Arrays.asList( + VariableExpr.withVariable(createVariable("fixedValue", TypeNode.OBJECT)))) + .build(); + AssignmentOperationExpr assignmentOperationExpr = + AssignmentOperationExpr.xorAssignmentWithExprs(lhsExpr, rhsExpr); + assignmentOperationExpr.accept(writerVisitor); + assertThat(writerVisitor.write()).isEqualTo("h ^= Objects.hashCode(fixedValue)"); + } + private static String createLines(int numLines) { return new String(new char[numLines]).replace("\0", "%s"); }