Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Static type checking errors on maven compile. #344

Closed
dsaita opened this issue Sep 27, 2017 · 8 comments
Closed

Static type checking errors on maven compile. #344

dsaita opened this issue Sep 27, 2017 · 8 comments
Assignees

Comments

@dsaita
Copy link

dsaita commented Sep 27, 2017

Hello.
I have a java 7 project that I want to use Groovy in.
I am migrating some classes that I believe should compile but I get errors.
Here is an example:

@CompileStatic
class StaticCompileTest {

    private Number value


    public BigDecimal compiles() {
        return this.value == null || value instanceof BigDecimal ? (BigDecimal) value : new BigDecimal(this.value.toString())
    }

    private BigDecimal doesNotCompile() {
        return this.value == null || value instanceof BigDecimal ? value : new BigDecimal(this.value.toString())
    }

    void doesNotCompileToo(Integer other) {
        if (other.compareTo(0) == 0) {
            //
        }
    }

}

[ERROR] return this.value == null || value instanceof BigDecimal ? value : new BigDecimal(this.value.toString())
[ERROR] ^
[ERROR] Groovy:[Static type checking] - Cannot return value of type java.lang.Number on method returning type java.math.BigDecimal
[ERROR]
[ERROR] if (other.compareTo(0) == 0) {
[ERROR] ^^^^^^^^^^^^^^^^^^^
[ERROR] Groovy:[Static type checking] - Reference to method is ambiguous. Cannot choose between [int java.lang.Integer#compareTo(java.lang.Integer), int java.lang.Integer#compareTo(java.lang.Object)]
[ERROR]

@eric-milles eric-milles self-assigned this Sep 30, 2017
@eric-milles
Copy link
Member

The code snippet below from StaticTypeCheckingVisitor determines the type of the ternary expression (and hence the return statement). Near the end, typeOfTrue is Number and typeOfFlase is BigDecimal. This is why the error is shown.

I'm not sure why this passes for Groovyc and Groovy Console. If I could find where flow-typing for the instanceof check is implemented, I may be able to understand the difference. The variable expression for the field (the true expression) did not have an inferred type set in its metadata, so the field type was used directly. If that type metadata was set, it would be used.

    public void visitTernaryExpression(final TernaryExpression expression) {
        Map<VariableExpression, List<ClassNode>> oldTracker = pushAssignmentTracking();
        // create a new temporary element in the if-then-else type info
        typeCheckingContext.pushTemporaryTypeInfo();
        expression.getBooleanExpression().visit(this);
        Expression trueExpression = expression.getTrueExpression();
        Expression falseExpression = expression.getFalseExpression();
        trueExpression.visit(this);
        // pop if-then-else temporary type info
        typeCheckingContext.popTemporaryTypeInfo();
        falseExpression.visit(this);
        ClassNode resultType;
        if (isNullConstant(trueExpression) || isNullConstant(falseExpression)) {
            BinaryExpression enclosingBinaryExpression = typeCheckingContext.getEnclosingBinaryExpression();
            if (enclosingBinaryExpression != null && enclosingBinaryExpression.getRightExpression()==expression) {
                resultType = getType(enclosingBinaryExpression.getLeftExpression());
            } else if (isNullConstant(trueExpression) && isNullConstant(falseExpression)) {
                resultType = OBJECT_TYPE;
            } else if (isNullConstant(trueExpression)) {
                resultType = wrapTypeIfNecessary(getType(falseExpression));
            } else {
                resultType = wrapTypeIfNecessary(getType(trueExpression));
            }
        } else {
            // store type information
            final ClassNode typeOfTrue = getType(trueExpression);
            final ClassNode typeOfFalse = getType(falseExpression);
            resultType = lowestUpperBound(typeOfTrue, typeOfFalse);
        }
        storeType(expression, resultType);
        popAssignmentTracking(oldTracker);
    }

@eric-milles
Copy link
Member

This should be fixed in the deployed plug-ins. It will take me some time to create and publish a new batch compiler artifact.

FYI, I posted an issue to Groovy for the instanceof check because I think there is an improvement opportunity in StaticTypeCheckingVisitor: https://issues.apache.org/jira/browse/GROOVY-8337

@dsaita
Copy link
Author

dsaita commented Oct 2, 2017

I can't seem to find the newer artifacts on the maven repository. Do I have to use bintray?

@eric-milles
Copy link
Member

eric-milles commented Oct 2, 2017 via email

@dsaita
Copy link
Author

dsaita commented Oct 2, 2017

I use it as a maven plugin to use Groovy with Java, like:

<plugin> 
                <artifactId>maven-compiler-plugin</artifactId> 
                <!-- 2.8.0-01 and later require maven-compiler-plugin 3.1 or higher --> 
                <version>3.6.1</version> 
                <configuration> 
                    <compilerId>groovy-eclipse-compiler</compilerId> 
                </configuration> 
                <dependencies> 
                    <dependency> 
                        <groupId>org.codehaus.groovy</groupId> 
                        <artifactId>groovy-eclipse-compiler</artifactId> 
                        <version>2.9.2-01</version> 
                    </dependency> 
                    <!-- for 2.8.0-01 and later you must have an explicit dependency on groovy-eclipse-batch --> 
                    <dependency> 
                        <groupId>org.codehaus.groovy</groupId> 
                        <artifactId>groovy-eclipse-batch</artifactId> 
                        <version>2.4.3-01</version> 
                    </dependency> 
                </dependencies> 
            </plugin> 

Is there a release calendar I can follow? Also, thank you very much for your help. Really appreciate it.

@eric-milles
Copy link
Member

You can link to the latest compiler from bintray like this:

  <pluginRepositories>
    <pluginRepository>
      <id>groovy-bintray</id>
      <name>Groovy Bintray</name>
      <url>https://dl.bintray.com/groovy/maven</url>
    </pluginRepository>
  </pluginRepositories>

  <build>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.6.1</version>
        <configuration>
          <compilerId>groovy-eclipse-compiler</compilerId>
        </configuration>
        <dependencies>
          <dependency>
            <groupId>org.codehaus.groovy</groupId>
            <artifactId>groovy-eclipse-compiler</artifactId>
            <version>2.9.2-03</version>
          </dependency>
          <dependency>
            <groupId>org.codehaus.groovy</groupId>
            <artifactId>groovy-eclipse-batch</artifactId>
            <version>2.4.12-03</version>
          </dependency>
        </dependencies>
      </plugin>
    </plugins>
  </build>

Here are the latest versions available:
groovy-eclipse-compiler: Download

groovy-eclipse-batch: Download

@dsaita
Copy link
Author

dsaita commented Oct 4, 2017

Will it be available on Maven?
My company has a mirror and it does not contain bintray.
I could ask them to mirror it, but if these artifacts are eventually going to Maven Central, I could wait.

@eric-milles
Copy link
Member

eric-milles commented Oct 4, 2017 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants