You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2017/11/19 07:14:35 UTC
[1/4] groovy git commit: Remove deprecated
StringGroovyMethods.capitalize call
Repository: groovy
Updated Branches:
refs/heads/GROOVY_2_6_X d446f55a8 -> 7a0052208
Remove deprecated StringGroovyMethods.capitalize call
I also noticed that propName was being capitalized three times in the
createComparatorFor() method, so I only call it once at the beginning.
I followed the same style of passing in the CharSequence like it was
defined in the deprecated method:
```groovy
@Deprecated
public static String capitalize(String self) {
return capitalize((CharSequence) self);
}
````
If you would rather have something like the following, or something else
let me know:
```groovy
CharSequence propName = property.getName();
String capitalizedPropName = StringGroovyMethods.capitalize(propName);
```
Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/7aa7071a
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/7aa7071a
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/7aa7071a
Branch: refs/heads/GROOVY_2_6_X
Commit: 7aa7071a412003c341007303c704869406a6a9a5
Parents: d446f55
Author: Russell Sanborn <ru...@gmail.com>
Authored: Fri Nov 17 10:02:19 2017 -0600
Committer: paulk <pa...@asert.com.au>
Committed: Sun Nov 19 17:14:18 2017 +1000
----------------------------------------------------------------------
.../codehaus/groovy/transform/SortableASTTransformation.java | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/groovy/blob/7aa7071a/src/main/org/codehaus/groovy/transform/SortableASTTransformation.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/transform/SortableASTTransformation.java b/src/main/org/codehaus/groovy/transform/SortableASTTransformation.java
index 643feaa..5da9a6d 100644
--- a/src/main/org/codehaus/groovy/transform/SortableASTTransformation.java
+++ b/src/main/org/codehaus/groovy/transform/SortableASTTransformation.java
@@ -161,8 +161,8 @@ public class SortableASTTransformation extends AbstractASTTransformation {
}
private static void createComparatorFor(ClassNode classNode, PropertyNode property, boolean reversed) {
- String propName = property.getName();
- String className = classNode.getName() + "$" + StringGroovyMethods.capitalize(propName) + "Comparator";
+ String propName = StringGroovyMethods.capitalize((CharSequence) property.getName());
+ String className = classNode.getName() + "$" + propName + "Comparator";
ClassNode superClass = makeClassSafeWithGenerics(AbstractComparator.class, classNode);
InnerClassNode cmpClass = new InnerClassNode(classNode, className, ACC_PRIVATE | ACC_STATIC, superClass);
classNode.getModule().addClass(cmpClass);
@@ -176,7 +176,7 @@ public class SortableASTTransformation extends AbstractASTTransformation {
createCompareMethodBody(property, reversed)
));
- String fieldName = "this$" + StringGroovyMethods.capitalize(propName) + "Comparator";
+ String fieldName = "this$" + propName + "Comparator";
// private final Comparator this$<property>Comparator = new <type>$<property>Comparator();
FieldNode cmpField = classNode.addField(
fieldName,
@@ -185,7 +185,7 @@ public class SortableASTTransformation extends AbstractASTTransformation {
ctorX(cmpClass));
classNode.addMethod(new MethodNode(
- "comparatorBy" + StringGroovyMethods.capitalize(propName),
+ "comparatorBy" + propName,
ACC_PUBLIC | ACC_STATIC,
COMPARATOR_TYPE,
Parameter.EMPTY_ARRAY,
[3/4] groovy git commit: GROOVY-8383: OptimizerVisitor#setConstField
not @CS friendly (closes #640)
Posted by pa...@apache.org.
GROOVY-8383: OptimizerVisitor#setConstField not @CS friendly (closes #640)
Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/83bd385d
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/83bd385d
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/83bd385d
Branch: refs/heads/GROOVY_2_6_X
Commit: 83bd385de3b1d32b3e4bd836daa71a6734b0c289
Parents: b5b5271
Author: paulk <pa...@asert.com.au>
Authored: Sun Nov 19 14:49:31 2017 +1000
Committer: paulk <pa...@asert.com.au>
Committed: Sun Nov 19 17:14:19 2017 +1000
----------------------------------------------------------------------
.../groovy/control/OptimizerVisitor.java | 57 +++++++++++---------
src/test/groovy/bugs/Groovy8383Bug.groovy | 51 ++++++++++++++++++
2 files changed, 84 insertions(+), 24 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/groovy/blob/83bd385d/src/main/org/codehaus/groovy/control/OptimizerVisitor.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/control/OptimizerVisitor.java b/src/main/org/codehaus/groovy/control/OptimizerVisitor.java
index f32651c..6bb343b 100644
--- a/src/main/org/codehaus/groovy/control/OptimizerVisitor.java
+++ b/src/main/org/codehaus/groovy/control/OptimizerVisitor.java
@@ -33,18 +33,23 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import static org.codehaus.groovy.ast.ClassHelper.isPrimitiveType;
+
/**
* Visitor to produce several optimizations:
* <ul>
- * <li>to replace numbered constants with references to static fields</li>
- * <li>remove superfluous references to GroovyObject interface</li>
+ * <li>to replace numbered constants with references to static fields</li>
+ * <li>remove superfluous references to GroovyObject interface</li>
* </ul>
*/
public class OptimizerVisitor extends ClassCodeExpressionTransformer {
private ClassNode currentClass;
private SourceUnit source;
- private final Map const2Var = new HashMap();
+ // TODO make @CS lookup smarter so that we don't need both these maps
+ private final Map<Object, FieldNode> const2Objects = new HashMap<Object, FieldNode>();
+ private final Map<Object, FieldNode> const2Prims = new HashMap<Object, FieldNode>();
+ private int index;
private final List<FieldNode> missingFields = new LinkedList<FieldNode>();
public OptimizerVisitor(CompilationUnit cu) {
@@ -53,8 +58,10 @@ public class OptimizerVisitor extends ClassCodeExpressionTransformer {
public void visitClass(ClassNode node, SourceUnit source) {
this.currentClass = node;
this.source = source;
- const2Var.clear();
+ const2Objects.clear();
+ const2Prims.clear();
missingFields.clear();
+ index = 0;
super.visitClass(node);
addMissingFields();
pruneUnneededGroovyObjectInterface(node);
@@ -85,8 +92,7 @@ public class OptimizerVisitor extends ClassCodeExpressionTransformer {
}
private void addMissingFields() {
- for (Object missingField : missingFields) {
- FieldNode f = (FieldNode) missingField;
+ for (FieldNode f : missingFields) {
currentClass.addField(f);
}
}
@@ -95,35 +101,38 @@ public class OptimizerVisitor extends ClassCodeExpressionTransformer {
final Object n = constantExpression.getValue();
if (!(n instanceof Number)) return;
if (n instanceof Integer || n instanceof Double) return;
- if (n instanceof Long && (0L== (Long) n || 1L==(Long) n )) return; // LCONST_0, LCONST_1
+ if (n instanceof Long && (0L == (Long) n || 1L == (Long) n)) return; // LCONST_0, LCONST_1
- FieldNode field = (FieldNode) const2Var.get(n);
- if (field!=null) {
+ boolean isPrimitive = isPrimitiveType(constantExpression.getType());
+ FieldNode field = isPrimitive ? const2Prims.get(n) : const2Objects.get(n);
+ if (field != null) {
constantExpression.setConstantName(field.getName());
return;
}
- final String name = "$const$" + const2Var.size();
- //TODO: this part here needs a bit of rethinking. If it can happen that the field is defined already,
- // then is this code still valid?
- field = currentClass.getDeclaredField(name);
- if (field==null) {
- field = new FieldNode(name,
- Opcodes.ACC_PRIVATE|Opcodes.ACC_STATIC|Opcodes.ACC_SYNTHETIC| Opcodes.ACC_FINAL,
- constantExpression.getType(),
- currentClass,
- constantExpression
- );
- field.setSynthetic(true);
- missingFields.add(field);
+ String name;
+ while (true) {
+ name = "$const$" + index++;
+ if (currentClass.getDeclaredField(name) == null) break;
}
+ field = new FieldNode(name,
+ Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_FINAL,
+ constantExpression.getType(),
+ currentClass,
+ constantExpression);
+ field.setSynthetic(true);
+ missingFields.add(field);
constantExpression.setConstantName(field.getName());
- const2Var.put(n, field);
+ if (isPrimitive) {
+ const2Prims.put(n, field);
+ } else {
+ const2Objects.put(n, field);
+ }
}
public Expression transform(Expression exp) {
if (exp == null) return null;
if (!currentClass.isInterface() && exp.getClass() == ConstantExpression.class) {
- setConstField((ConstantExpression)exp);
+ setConstField((ConstantExpression) exp);
}
return exp.transformExpression(this);
}
http://git-wip-us.apache.org/repos/asf/groovy/blob/83bd385d/src/test/groovy/bugs/Groovy8383Bug.groovy
----------------------------------------------------------------------
diff --git a/src/test/groovy/bugs/Groovy8383Bug.groovy b/src/test/groovy/bugs/Groovy8383Bug.groovy
new file mode 100644
index 0000000..1091260
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy8383Bug.groovy
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 groovy.bugs
+
+class Groovy8383Bug extends GroovyTestCase {
+ void testCompileStaticWithOptimizedConstants() {
+ assertScript '''
+ @groovy.transform.CompileStatic
+ class Foo {
+ private static String $const$0 = 'xyzzy'
+
+ def method() {
+ Long wrapper1 = 8L
+ long prim1 = 8L
+ long prim2 = 8L
+ long prim3 = 9L
+ Long wrapper2 = 9L
+ wrapper1 + prim1 + prim2 + prim3 + wrapper2
+ }
+ }
+ assert new Foo().method() == 42
+
+ class Bar {
+ private static long $const$0 = 9
+ private static long $const$2 = 10
+ def method2() {
+ long prim4 = 11L
+ long prim5 = 12L
+ prim4 + prim5 + $const$0 + $const$2
+ }
+ }
+ assert new Bar().method2() == 42
+ '''
+ }
+}
[2/4] groovy git commit: trivial refactor (closes #638)
Posted by pa...@apache.org.
trivial refactor (closes #638)
Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/b5b5271f
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/b5b5271f
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/b5b5271f
Branch: refs/heads/GROOVY_2_6_X
Commit: b5b5271f2614a9d6a4f431d2f1cf806521f648f1
Parents: 7aa7071
Author: paulk <pa...@asert.com.au>
Authored: Sun Nov 19 14:57:38 2017 +1000
Committer: paulk <pa...@asert.com.au>
Committed: Sun Nov 19 17:14:19 2017 +1000
----------------------------------------------------------------------
.../org/codehaus/groovy/transform/SortableASTTransformation.java | 3 ---
1 file changed, 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/groovy/blob/b5b5271f/src/main/org/codehaus/groovy/transform/SortableASTTransformation.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/transform/SortableASTTransformation.java b/src/main/org/codehaus/groovy/transform/SortableASTTransformation.java
index 5da9a6d..5db6961 100644
--- a/src/main/org/codehaus/groovy/transform/SortableASTTransformation.java
+++ b/src/main/org/codehaus/groovy/transform/SortableASTTransformation.java
@@ -53,9 +53,6 @@ import static org.codehaus.groovy.ast.tools.GenericsUtils.newClass;
/**
* Injects a set of Comparators and sort methods.
- *
- * @author Andres Almiray
- * @author Paul King
*/
@GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION)
[4/4] groovy git commit: GROOVY-8384 - Regression in 2.4.13 snapshot
with STC and intdiv plus some cleanup (closes #639)
Posted by pa...@apache.org.
GROOVY-8384 - Regression in 2.4.13 snapshot with STC and intdiv plus some cleanup (closes #639)
Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/7a005220
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/7a005220
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/7a005220
Branch: refs/heads/GROOVY_2_6_X
Commit: 7a0052208daee3ad453d5460b74a08867ffb615f
Parents: 83bd385
Author: paulk <pa...@asert.com.au>
Authored: Sun Nov 19 00:29:08 2017 +1000
Committer: paulk <pa...@asert.com.au>
Committed: Sun Nov 19 17:14:20 2017 +1000
----------------------------------------------------------------------
.../groovy/classgen/asm/CallSiteWriter.java | 7 --
.../NumberMathModificationInfo.java | 10 ++-
.../stc/StaticTypeCheckingSupport.java | 23 +++++-
.../stc/StaticTypeCheckingVisitor.java | 83 ++++++++++++--------
.../groovy/transform/stc/MiscSTCTest.groovy | 19 +++++
5 files changed, 97 insertions(+), 45 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/groovy/blob/7a005220/src/main/org/codehaus/groovy/classgen/asm/CallSiteWriter.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/classgen/asm/CallSiteWriter.java b/src/main/org/codehaus/groovy/classgen/asm/CallSiteWriter.java
index 0309138..4983b4b 100644
--- a/src/main/org/codehaus/groovy/classgen/asm/CallSiteWriter.java
+++ b/src/main/org/codehaus/groovy/classgen/asm/CallSiteWriter.java
@@ -34,16 +34,9 @@ import static org.objectweb.asm.Opcodes.*;
/**
* This class represents non public API used by AsmClassGenerator. Don't
* use this class in your code
- * @author Jochen Theodorou
*/
public class CallSiteWriter {
- private static final Set<String> NAMES = new HashSet<String>();
- private static final Set<String> BASIC = new HashSet<String>();
- static {
- Collections.addAll(NAMES, "plus", "minus", "multiply", "div", "compareTo", "or", "and", "xor", "intdiv", "mod", "leftShift", "rightShift", "rightShiftUnsigned");
- Collections.addAll(BASIC, "plus", "minus", "multiply", "div");
- }
private static String [] sig = new String [255];
private static String getCreateArraySignature(int numberOfArguments) {
if (sig[numberOfArguments] == null) {
http://git-wip-us.apache.org/repos/asf/groovy/blob/7a005220/src/main/org/codehaus/groovy/runtime/typehandling/NumberMathModificationInfo.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/runtime/typehandling/NumberMathModificationInfo.java b/src/main/org/codehaus/groovy/runtime/typehandling/NumberMathModificationInfo.java
index 4525c06..65dbf41 100644
--- a/src/main/org/codehaus/groovy/runtime/typehandling/NumberMathModificationInfo.java
+++ b/src/main/org/codehaus/groovy/runtime/typehandling/NumberMathModificationInfo.java
@@ -29,12 +29,14 @@ public class NumberMathModificationInfo {
public static final NumberMathModificationInfo instance = new NumberMathModificationInfo();
- private final HashSet<String> names = new HashSet<String>();
+ private static final HashSet<String> NAMES = new HashSet<String>();
- private NumberMathModificationInfo() {
- Collections.addAll(names, "plus", "minus", "multiply", "div", "compareTo", "or", "and", "xor", "intdiv", "mod", "leftShift", "rightShift", "rightShiftUnsigned");
+ static {
+ Collections.addAll(NAMES, "plus", "minus", "multiply", "div", "compareTo", "or", "and", "xor", "intdiv", "mod", "leftShift", "rightShift", "rightShiftUnsigned");
}
+ private NumberMathModificationInfo() { }
+
public void checkIfStdMethod(MetaMethod method) {
if (method.getClass() != NewInstanceMetaMethod.class) {
String name = method.getName();
@@ -45,7 +47,7 @@ public class NumberMathModificationInfo {
if (!method.getParameterTypes()[0].isNumber && method.getParameterTypes()[0].getTheClass() != Object.class)
return;
- if (!names.contains(name))
+ if (!NAMES.contains(name))
return;
checkNumberOps(name, method.getDeclaringClass().getTheClass());
http://git-wip-us.apache.org/repos/asf/groovy/blob/7a005220/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java b/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
index 30584a9..9f9fc5f 100644
--- a/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
+++ b/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
@@ -76,6 +76,22 @@ public abstract class StaticTypeCheckingSupport {
put(Double_TYPE, 5);
}});
+ protected static final Map<String, Integer> NUMBER_OPS = Collections.unmodifiableMap(
+ new HashMap<String, Integer>() {{
+ put("plus", PLUS);
+ put("minus", MINUS);
+ put("multiply", MULTIPLY);
+ put("div", DIVIDE);
+ put("or", BITWISE_OR);
+ put("and", BITWISE_AND);
+ put("xor", BITWISE_XOR);
+ put("mod", MOD);
+ put("intdiv", INTDIV);
+ put("leftShift", LEFT_SHIFT);
+ put("rightShift", RIGHT_SHIFT);
+ put("rightShiftUnsigned", RIGHT_SHIFT_UNSIGNED);
+ }});
+
protected static final ClassNode GSTRING_STRING_CLASSNODE = WideningCategories.lowestUpperBound(
STRING_TYPE,
GSTRING_TYPE
@@ -373,7 +389,7 @@ public abstract class StaticTypeCheckingSupport {
}
static boolean isBoolIntrinsicOp(int op) {
- return op == LOGICAL_AND || op == LOGICAL_OR ||
+ return op == LOGICAL_AND || op == LOGICAL_OR || op == COMPARE_NOT_IDENTICAL || op == COMPARE_IDENTICAL ||
op == MATCH_REGEX || op == KEYWORD_INSTANCEOF || op == COMPARE_NOT_INSTANCEOF;
}
@@ -660,7 +676,12 @@ public abstract class StaticTypeCheckingSupport {
return node.getCompileUnit() != null;
}
+ @Deprecated
static boolean checkPossibleLooseOfPrecision(ClassNode left, ClassNode right, Expression rightExpr) {
+ return checkPossibleLossOfPrecision(left, right, rightExpr);
+ }
+
+ static boolean checkPossibleLossOfPrecision(ClassNode left, ClassNode right, Expression rightExpr) {
if (left == right || left.equals(right)) return false; // identical types
int leftIndex = NUMBER_TYPES.get(left);
int rightIndex = NUMBER_TYPES.get(right);
http://git-wip-us.apache.org/repos/asf/groovy/blob/7a005220/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
index 10021c1..285036a 100644
--- a/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -110,9 +110,7 @@ import static org.codehaus.groovy.ast.tools.WideningCategories.lowestUpperBound;
import static org.codehaus.groovy.syntax.Types.ASSIGN;
import static org.codehaus.groovy.syntax.Types.ASSIGNMENT_OPERATOR;
import static org.codehaus.groovy.syntax.Types.COMPARE_EQUAL;
-import static org.codehaus.groovy.syntax.Types.COMPARE_IDENTICAL;
import static org.codehaus.groovy.syntax.Types.COMPARE_NOT_EQUAL;
-import static org.codehaus.groovy.syntax.Types.COMPARE_NOT_IDENTICAL;
import static org.codehaus.groovy.syntax.Types.COMPARE_NOT_IN;
//import static org.codehaus.groovy.syntax.Types.COMPARE_NOT_INSTANCEOF;
import static org.codehaus.groovy.syntax.Types.COMPARE_TO;
@@ -121,6 +119,8 @@ import static org.codehaus.groovy.syntax.Types.DIVIDE_EQUAL;
import static org.codehaus.groovy.syntax.Types.ELVIS_EQUAL;
import static org.codehaus.groovy.syntax.Types.EQUAL;
import static org.codehaus.groovy.syntax.Types.FIND_REGEX;
+import static org.codehaus.groovy.syntax.Types.INTDIV;
+import static org.codehaus.groovy.syntax.Types.INTDIV_EQUAL;
import static org.codehaus.groovy.syntax.Types.KEYWORD_IN;
import static org.codehaus.groovy.syntax.Types.KEYWORD_INSTANCEOF;
import static org.codehaus.groovy.syntax.Types.LEFT_SQUARE_BRACKET;
@@ -930,7 +930,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
private void addPrecisionErrors(ClassNode leftRedirect, ClassNode lhsType, ClassNode inferredrhsType, Expression rightExpression) {
if (isNumberType(leftRedirect) && isNumberType(inferredrhsType)) {
- if (checkPossibleLooseOfPrecision(leftRedirect, inferredrhsType, rightExpression)) {
+ if (checkPossibleLossOfPrecision(leftRedirect, inferredrhsType, rightExpression)) {
addStaticTypeError("Possible loss of precision from " + inferredrhsType + " to " + leftRedirect, rightExpression);
return;
}
@@ -3098,6 +3098,16 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
}
}
}
+ // adjust typing for explicit math methods which have special handling - operator variants handled elsewhere
+ if (NUMBER_OPS.containsKey(name) && isNumberType(receiver) && argumentList.getExpressions().size() == 1
+ && isNumberType(getType(argumentList.getExpression(0)))) {
+ ClassNode right = getType(argumentList.getExpression(0));
+ ClassNode resultType = getMathResultType(NUMBER_OPS.get(name), receiver, right, name);
+ if (resultType != null) {
+ storeType(call, resultType);
+ }
+ }
+
// now that a method has been chosen, we are allowed to visit the closures
if (!callArgsVisited) {
MethodNode mn = (MethodNode) call.getNodeMetaData(StaticTypesMarker.DIRECT_METHOD_CALL_TARGET);
@@ -3132,8 +3142,9 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
*
* @param directMethodCallCandidate a method selected by the type checker
* @param receiver the receiver of the method call
- *@param args the arguments of the method call
- * @param returnType the original return type, as inferred by the type checker @return fixed return type if the selected method is {@link org.codehaus.groovy.runtime.DefaultGroovyMethods#withTraits(Object, Class[]) withTraits}
+ * @param args the arguments of the method call
+ * @param returnType the original return type, as inferred by the type checker
+ * @return fixed return type if the selected method is {@link org.codehaus.groovy.runtime.DefaultGroovyMethods#withTraits(Object, Class[]) withTraits}
*/
private static ClassNode adjustWithTraits(final MethodNode directMethodCallCandidate, final ClassNode receiver, final ClassNode[] args, final ClassNode returnType) {
if (directMethodCallCandidate instanceof ExtensionMethodNode) {
@@ -3593,10 +3604,6 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
ClassNode leftRedirect = left.redirect();
ClassNode rightRedirect = right.redirect();
- if (op == COMPARE_NOT_IDENTICAL || op == COMPARE_IDENTICAL) {
- return boolean_TYPE;
- }
-
Expression leftExpression = expr.getLeftExpression();
Expression rightExpression = expr.getRightExpression();
if (op == ASSIGN || op == ASSIGNMENT_OPERATOR || op == ELVIS_EQUAL) {
@@ -3638,9 +3645,11 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
}
}
return right;
- } else if (isBoolIntrinsicOp(op)) {
+ }
+ if (isBoolIntrinsicOp(op)) {
return boolean_TYPE;
- } else if (isArrayOp(op)) {
+ }
+ if (isArrayOp(op)) {
// using getPNR() to ignore generics at this point
// and a different binary expression not to pollute the AST
BinaryExpression newExpr = binX(expr.getLeftExpression(), expr.getOperation(), rightExpression);
@@ -3650,13 +3659,40 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
return inferReturnTypeGenerics(left, method, rightExpression);
}
return method!=null?inferComponentType(left, right):null;
- } else if (op == FIND_REGEX) {
+ }
+ if (op == FIND_REGEX) {
// this case always succeeds the result is a Matcher
return Matcher_TYPE;
}
// the left operand is determining the result of the operation
// for primitives and their wrapper we use a fixed table here
- else if (isNumberType(leftRedirect) && isNumberType(rightRedirect)) {
+ String operationName = getOperationName(op);
+ ClassNode mathResultType = getMathResultType(op, leftRedirect, rightRedirect, operationName);
+ if (mathResultType != null) {
+ return mathResultType;
+ }
+
+ // GROOVY-5890
+ // do not mix Class<Foo> with Foo
+ if (leftExpression instanceof ClassExpression) {
+ left = CLASS_Type.getPlainNodeReference();
+ }
+
+ MethodNode method = findMethodOrFail(expr, left, operationName, right);
+ if (method != null) {
+ storeTargetMethod(expr, method);
+ typeCheckMethodsWithGenericsOrFail(left, new ClassNode[]{right}, method, expr);
+ if (isAssignment(op)) return left;
+ if (isCompareToBoolean(op)) return boolean_TYPE;
+ if (op == COMPARE_TO) return int_TYPE;
+ return inferReturnTypeGenerics(left, method, args(rightExpression));
+ }
+ //TODO: other cases
+ return null;
+ }
+
+ private ClassNode getMathResultType(int op, ClassNode leftRedirect, ClassNode rightRedirect, String operationName) {
+ if (isNumberType(leftRedirect) && isNumberType(rightRedirect)) {
if (isOperationInGroup(op)) {
if (isIntCategory(leftRedirect) && isIntCategory(rightRedirect)) return int_TYPE;
if (isLongCategory(leftRedirect) && isLongCategory(rightRedirect)) return long_TYPE;
@@ -3664,7 +3700,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
if (isDouble(leftRedirect) && isDouble(rightRedirect)) return double_TYPE;
} else if (isPowerOperator(op)) {
return Number_TYPE;
- } else if (isBitOperator(op)) {
+ } else if (isBitOperator(op) || op == INTDIV || op == INTDIV_EQUAL) {
if (isIntCategory(getUnwrapper(leftRedirect)) && isIntCategory(getUnwrapper(rightRedirect))) return int_TYPE;
if (isLongCategory(getUnwrapper(leftRedirect)) && isLongCategory(getUnwrapper(rightRedirect))) return long_TYPE;
if (isBigIntCategory(getUnwrapper(leftRedirect)) && isBigIntCategory(getUnwrapper(rightRedirect))) return BigInteger_TYPE;
@@ -3677,9 +3713,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
}
}
-
// try to find a method for the operation
- String operationName = getOperationName(op);
if (isShiftOperation(operationName) && isNumberCategory(leftRedirect) && (isIntCategory(rightRedirect) || isLongCategory(rightRedirect))) {
return leftRedirect;
}
@@ -3704,23 +3738,6 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
if (isNumberCategory(getWrapper(rightRedirect)) && isNumberCategory(getWrapper(leftRedirect)) && (MOD == op || MOD_EQUAL == op)) {
return leftRedirect;
}
-
- // GROOVY-5890
- // do not mix Class<Foo> with Foo
- if (leftExpression instanceof ClassExpression) {
- left = CLASS_Type.getPlainNodeReference();
- }
-
- MethodNode method = findMethodOrFail(expr, left, operationName, right);
- if (method != null) {
- storeTargetMethod(expr, method);
- typeCheckMethodsWithGenericsOrFail(left, new ClassNode[]{right}, method, expr);
- if (isAssignment(op)) return left;
- if (isCompareToBoolean(op)) return boolean_TYPE;
- if (op == COMPARE_TO) return int_TYPE;
- return inferReturnTypeGenerics(left, method, args(rightExpression));
- }
- //TODO: other cases
return null;
}
http://git-wip-us.apache.org/repos/asf/groovy/blob/7a005220/src/test/groovy/transform/stc/MiscSTCTest.groovy
----------------------------------------------------------------------
diff --git a/src/test/groovy/transform/stc/MiscSTCTest.groovy b/src/test/groovy/transform/stc/MiscSTCTest.groovy
index 0b786d8..94be0de 100644
--- a/src/test/groovy/transform/stc/MiscSTCTest.groovy
+++ b/src/test/groovy/transform/stc/MiscSTCTest.groovy
@@ -409,4 +409,23 @@ class MiscSTCTest extends StaticTypeCheckingTestCase {
method()
'''
}
+
+ // GROOVY-8384
+ void testIntdiv() {
+ assertScript '''
+ def method() {
+ assert new Long(7L.multiply(3)) == 21
+ assert new Long(7L.plus(3)) == 10
+ assert new Long(7L.leftShift(3)) == 56
+ assert new Long(7L.rightShift(1)) == 3
+ assert new Long(7L.mod(3)) == 1
+ assert new Long(7L.intdiv(3)) == 2
+ assert new Integer((-8).intdiv(-4)) == 2
+ Integer x = 9
+ Integer y = 5
+ assert new Integer(x.intdiv(y)) == 1
+ }
+ method()
+ '''
+ }
}