You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2019/11/22 02:41:14 UTC
[groovy] branch master updated: STC: isLHSOfEnclosingAssignment
returns true for ++/-- on variable expr
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/master by this push:
new 8c0c5b0 STC: isLHSOfEnclosingAssignment returns true for ++/-- on variable expr
8c0c5b0 is described below
commit 8c0c5b018805fcab7217f5cdc784fc88354cfb15
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Mon Nov 18 10:17:13 2019 -0600
STC: isLHSOfEnclosingAssignment returns true for ++/-- on variable expr
PV_FIELDS_MUTATION is recorded instead of PV_FIELDS_ACCESS
This is a first step towards fixing:
@NotYetImplemented // GROOVY-7304
void testShouldGoThroughPrivateBridgeAccessorWithWriteAccess() {
['++i', 'i++', 'i+=1', 'i=i+1'].each {
assertScript """
class Foo {
private int i = 1
def m() { new String().with { $it } }
}
assert new Foo().m() == 2
class Bar extends Foo {}
assert new Bar().m() == 2
"""
}
}
---
.../java/org/codehaus/groovy/syntax/TokenUtil.java | 77 +++++++++-------------
.../transform/stc/StaticTypeCheckingVisitor.java | 63 ++++++++++--------
2 files changed, 67 insertions(+), 73 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/syntax/TokenUtil.java b/src/main/java/org/codehaus/groovy/syntax/TokenUtil.java
index b03b6c7..884ab2d 100644
--- a/src/main/java/org/codehaus/groovy/syntax/TokenUtil.java
+++ b/src/main/java/org/codehaus/groovy/syntax/TokenUtil.java
@@ -18,45 +18,30 @@
*/
package org.codehaus.groovy.syntax;
-import static org.codehaus.groovy.syntax.Types.BITWISE_AND;
-import static org.codehaus.groovy.syntax.Types.BITWISE_AND_EQUAL;
-import static org.codehaus.groovy.syntax.Types.BITWISE_OR;
-import static org.codehaus.groovy.syntax.Types.BITWISE_OR_EQUAL;
-import static org.codehaus.groovy.syntax.Types.BITWISE_XOR;
-import static org.codehaus.groovy.syntax.Types.BITWISE_XOR_EQUAL;
-import static org.codehaus.groovy.syntax.Types.DIVIDE;
-import static org.codehaus.groovy.syntax.Types.DIVIDE_EQUAL;
-import static org.codehaus.groovy.syntax.Types.INTDIV;
-import static org.codehaus.groovy.syntax.Types.INTDIV_EQUAL;
-import static org.codehaus.groovy.syntax.Types.LEFT_SHIFT;
-import static org.codehaus.groovy.syntax.Types.LEFT_SHIFT_EQUAL;
-import static org.codehaus.groovy.syntax.Types.LOGICAL_AND;
-import static org.codehaus.groovy.syntax.Types.LOGICAL_AND_EQUAL;
-import static org.codehaus.groovy.syntax.Types.LOGICAL_OR;
-import static org.codehaus.groovy.syntax.Types.LOGICAL_OR_EQUAL;
-import static org.codehaus.groovy.syntax.Types.MINUS;
-import static org.codehaus.groovy.syntax.Types.MINUS_EQUAL;
-import static org.codehaus.groovy.syntax.Types.MOD;
-import static org.codehaus.groovy.syntax.Types.MOD_EQUAL;
-import static org.codehaus.groovy.syntax.Types.MULTIPLY;
-import static org.codehaus.groovy.syntax.Types.MULTIPLY_EQUAL;
-import static org.codehaus.groovy.syntax.Types.PLUS;
-import static org.codehaus.groovy.syntax.Types.PLUS_EQUAL;
-import static org.codehaus.groovy.syntax.Types.POWER;
-import static org.codehaus.groovy.syntax.Types.POWER_EQUAL;
-import static org.codehaus.groovy.syntax.Types.RIGHT_SHIFT;
-import static org.codehaus.groovy.syntax.Types.RIGHT_SHIFT_EQUAL;
-import static org.codehaus.groovy.syntax.Types.RIGHT_SHIFT_UNSIGNED;
-import static org.codehaus.groovy.syntax.Types.RIGHT_SHIFT_UNSIGNED_EQUAL;
+import java.util.Optional;
/**
* Utility methods for working with Tokens.
- *
*/
public class TokenUtil {
+
private TokenUtil() {
}
+ public static Optional<Token> asAssignment(int op) {
+ switch (op) {
+ case Types.PLUS_PLUS:
+ case Types.PREFIX_PLUS_PLUS:
+ case Types.POSTFIX_PLUS_PLUS:
+ return Optional.of(Token.newSymbol(Types.PLUS_EQUAL, -1, -1));
+ case Types.MINUS_MINUS:
+ case Types.PREFIX_MINUS_MINUS:
+ case Types.POSTFIX_MINUS_MINUS:
+ return Optional.of(Token.newSymbol(Types.MINUS_EQUAL, -1, -1));
+ }
+ return Optional.empty();
+ }
+
/**
* Removes the assignment portion of a given token. If the given token
* is not an operator with assignment, the given token is returned.
@@ -67,21 +52,21 @@ public class TokenUtil {
*/
public static int removeAssignment(int op) {
switch (op) {
- case PLUS_EQUAL: return PLUS;
- case MINUS_EQUAL: return MINUS;
- case MULTIPLY_EQUAL: return MULTIPLY;
- case LEFT_SHIFT_EQUAL: return LEFT_SHIFT;
- case RIGHT_SHIFT_EQUAL: return RIGHT_SHIFT;
- case RIGHT_SHIFT_UNSIGNED_EQUAL: return RIGHT_SHIFT_UNSIGNED;
- case LOGICAL_OR_EQUAL: return LOGICAL_OR;
- case LOGICAL_AND_EQUAL: return LOGICAL_AND;
- case MOD_EQUAL: return MOD;
- case DIVIDE_EQUAL: return DIVIDE;
- case INTDIV_EQUAL: return INTDIV;
- case POWER_EQUAL: return POWER;
- case BITWISE_OR_EQUAL: return BITWISE_OR;
- case BITWISE_AND_EQUAL: return BITWISE_AND;
- case BITWISE_XOR_EQUAL: return BITWISE_XOR;
+ case Types.PLUS_EQUAL: return Types.PLUS;
+ case Types.MINUS_EQUAL: return Types.MINUS;
+ case Types.MULTIPLY_EQUAL: return Types.MULTIPLY;
+ case Types.LEFT_SHIFT_EQUAL: return Types.LEFT_SHIFT;
+ case Types.RIGHT_SHIFT_EQUAL: return Types.RIGHT_SHIFT;
+ case Types.RIGHT_SHIFT_UNSIGNED_EQUAL: return Types.RIGHT_SHIFT_UNSIGNED;
+ case Types.LOGICAL_OR_EQUAL: return Types.LOGICAL_OR;
+ case Types.LOGICAL_AND_EQUAL: return Types.LOGICAL_AND;
+ case Types.MOD_EQUAL: return Types.MOD;
+ case Types.DIVIDE_EQUAL: return Types.DIVIDE;
+ case Types.INTDIV_EQUAL: return Types.INTDIV;
+ case Types.POWER_EQUAL: return Types.POWER;
+ case Types.BITWISE_OR_EQUAL: return Types.BITWISE_OR;
+ case Types.BITWISE_AND_EQUAL: return Types.BITWISE_AND;
+ case Types.BITWISE_XOR_EQUAL: return Types.BITWISE_XOR;
default: return op;
}
}
diff --git a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
index 79132b3..bc36c28 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -187,6 +187,7 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.binX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.block;
import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.castX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.constX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.isOrImplements;
import static org.codehaus.groovy.ast.tools.GeneralUtils.localVarX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.thisPropX;
@@ -2044,7 +2045,6 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
@Override
public void visitPostfixExpression(final PostfixExpression expression) {
- super.visitPostfixExpression(expression);
Expression operand = expression.getExpression();
int operator = expression.getOperation().getType();
visitPrefixOrPostifExpression(expression, operand, operator);
@@ -2052,46 +2052,55 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
@Override
public void visitPrefixExpression(final PrefixExpression expression) {
- super.visitPrefixExpression(expression);
Expression operand = expression.getExpression();
int operator = expression.getOperation().getType();
visitPrefixOrPostifExpression(expression, operand, operator);
}
private void visitPrefixOrPostifExpression(final Expression origin, final Expression operand, final int operator) {
- boolean isPostfix = origin instanceof PostfixExpression;
- ClassNode exprType = getType(operand);
- String name = operator == PLUS_PLUS ? "next" : operator == MINUS_MINUS ? "previous" : null;
-
- if (name != null && isNumberType(exprType)) {
- if (!isPrimitiveType(exprType)) {
- MethodNode node = findMethodOrFail(varX("_dummy_", exprType), exprType, name);
+ Optional<Token> token = TokenUtil.asAssignment(operator);
+ if (token.isPresent()) { // push "operand += 1" or "operand -= 1" onto stack for LHS checks
+ typeCheckingContext.pushEnclosingBinaryExpression(binX(operand, token.get(), constX(1)));
+ }
+ try {
+ operand.visit(this);
+ ClassNode operandType = getType(operand);
+ boolean isPostfix = (origin instanceof PostfixExpression);
+ String name = (operator == PLUS_PLUS ? "next" : operator == MINUS_MINUS ? "previous" : null);
+
+ if (name != null && isNumberType(operandType)) {
+ if (!isPrimitiveType(operandType)) {
+ MethodNode node = findMethodOrFail(varX("_dummy_", operandType), operandType, name);
+ if (node != null) {
+ storeTargetMethod(origin, node);
+ storeType(origin, isPostfix ? operandType : getMathWideningClassNode(operandType));
+ return;
+ }
+ }
+ storeType(origin, operandType);
+ return;
+ }
+ if (name != null && operandType.isDerivedFrom(Number_TYPE)) {
+ // special case for numbers, improve type checking as we can expect ++ and -- to return the same type
+ MethodNode node = findMethodOrFail(operand, operandType, name);
if (node != null) {
storeTargetMethod(origin, node);
- storeType(origin, isPostfix ? exprType : getMathWideningClassNode(exprType));
+ storeType(origin, getMathWideningClassNode(operandType));
return;
}
}
- storeType(origin, exprType);
- return;
- }
- if (name != null && exprType.isDerivedFrom(Number_TYPE)) {
- // special case for numbers, improve type checking as we can expect ++ and -- to return the same type
- MethodNode node = findMethodOrFail(operand, exprType, name);
+ if (name == null) {
+ addUnsupportedPreOrPostfixExpressionError(origin);
+ return;
+ }
+
+ MethodNode node = findMethodOrFail(operand, operandType, name);
if (node != null) {
storeTargetMethod(origin, node);
- storeType(origin, getMathWideningClassNode(exprType));
- return;
+ storeType(origin, isPostfix ? operandType : inferReturnTypeGenerics(operandType, node, ArgumentListExpression.EMPTY_ARGUMENTS));
}
- }
- if (name == null) {
- addUnsupportedPreOrPostfixExpressionError(origin);
- return;
- }
- MethodNode node = findMethodOrFail(operand, exprType, name);
- if (node != null) {
- storeTargetMethod(origin, node);
- storeType(origin, isPostfix ? exprType : inferReturnTypeGenerics(exprType, node, ArgumentListExpression.EMPTY_ARGUMENTS));
+ } finally {
+ if (token.isPresent()) typeCheckingContext.popEnclosingBinaryExpression();
}
}