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()
+        '''
+    }
 }