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

Internal groovy compiler error #258

Closed
AntonPanikov opened this issue Jan 24, 2017 · 7 comments
Closed

Internal groovy compiler error #258

AntonPanikov opened this issue Jan 24, 2017 · 7 comments

Comments

@AntonPanikov
Copy link

I have this error on almost all groovy classes on my work project since new year. Unfortunately I am unable to reproduce it on the separate simple test project. My work project is a Grails 3.x project, but I tried to use the same dependencies on the test project and I have no issue - everything working without any errors, so dependencies is not a problem. It looks like it is some strange coincidence. I tried to copy any class with internal error from my working project to a new one, but as soon as I do that it will start compiling without internal errors. Also tried to recreate project from the scratch - got internal errors on almost all groovy classes again. I will provide an error and stack trace for it. May be it will help. Please just take a look on this, may be it will give you some clue. I will try to continue to reproduce it on the separate test project, but so far - no luck. Feel free to ask me if you need more info.

I am using groovy-eclispe plugin of version: Groovy-Eclipse Feature 2.9.2.xx-201701232340-e46

No other changes was made to this project in term of dependencies, migration to new version or others and it was perfectly working in the past, until some groovy-eclipe update break it.

The error is:
Internal groovy compiler error.

Stack Trace:

BUG! exception in phase 'semantic analysis' in source unit '/***/***/****.groovy' Tried to overwrite existing meta data ConstantExpression[(\.\.\\)|(\.\./)].
	at org.codehaus.groovy.ast.ASTNode.setNodeMetaData(ASTNode.java:179)
	at org.codehaus.groovy.control.StaticImportVisitor.transformInlineConstants(StaticImportVisitor.java:247)
	at org.codehaus.groovy.control.StaticImportVisitor.transformVariableExpression(StaticImportVisitor.java:207)
	at org.codehaus.groovy.control.StaticImportVisitor.transform(StaticImportVisitor.java:104)
	at org.codehaus.groovy.ast.expr.Expression.transformExpressions(Expression.java:51)
	at org.codehaus.groovy.ast.expr.ListExpression.transformExpression(ListExpression.java:68)
	at org.codehaus.groovy.control.StaticImportVisitor.transform(StaticImportVisitor.java:149)
	at org.codehaus.groovy.ast.ClassCodeExpressionTransformer.visitAnnotations(ClassCodeExpressionTransformer.java:98)
	at org.codehaus.groovy.control.StaticImportVisitor.visitAnnotations(StaticImportVisitor.java:97)
	at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitConstructorOrMethod(ClassCodeVisitorSupport.java:158)
	at org.codehaus.groovy.ast.ClassCodeExpressionTransformer.visitConstructorOrMethod(ClassCodeExpressionTransformer.java:53)
	at org.codehaus.groovy.control.StaticImportVisitor.visitConstructorOrMethod(StaticImportVisitor.java:89)
	at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitMethod(ClassCodeVisitorSupport.java:170)
	at org.codehaus.groovy.ast.ClassNode.visitContents(ClassNode.java:1195)
	at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitClass(ClassCodeVisitorSupport.java:56)
	at org.codehaus.groovy.control.StaticImportVisitor.visitClass(StaticImportVisitor.java:83)
	at org.codehaus.groovy.control.CompilationUnit$2.call(CompilationUnit.java:740)
	at org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:1201)
	at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:665)
	at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:643)
	at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:620)
	at org.codehaus.jdt.groovy.internal.compiler.ast.GroovyCompilationUnitDeclaration.processToPhase(GroovyCompilationUnitDeclaration.java:214)
	at org.codehaus.jdt.groovy.internal.compiler.ast.GroovyCompilationUnitDeclaration.resolve(GroovyCompilationUnitDeclaration.java:618)
	at org.eclipse.jdt.internal.compiler.Compiler.process(Compiler.java:923)
	at org.eclipse.jdt.internal.compiler.ProcessTaskManager.run(ProcessTaskManager.java:141)
	at java.lang.Thread.run(Thread.java:745)
@eric-milles
Copy link
Member

eric-milles commented Jan 24, 2017

Somewhere in your code, you have a string literal "(\.\.\\)|(\.\./)". There is a bit of code in StaticImportVisitor that tries to save information on qualified type expressions. I think your regex is getting mistaken for a qualified type expression. You must be setting this string to a static final in some class and then referencing it somewhere else, this is where the constant gets inlined.

    private Expression transformInlineConstants(Expression exp) {
        if (exp instanceof PropertyExpression) {
            PropertyExpression pe = (PropertyExpression) exp;
            if (pe.getObjectExpression() instanceof ClassExpression) {
                ClassExpression ce = (ClassExpression) pe.getObjectExpression();
                ClassNode type = ce.getType();
                if (type.isEnum()) return exp;
                Expression constant = findConstant(getField(type, pe.getPropertyAsString()));
                // GRECLIPSE edit
                //if (constant != null) return constant;
                if (constant != null) {
                    String name = pe.getText().replace('$', '.');
                    Object alias = pe.getNodeMetaData("static.import.alias");
                    if (alias != null && !alias.equals(pe.getPropertyAsString())) {
                        name += " as " + alias;
                    }
                    // store the qualified name to facilitate organizing static imports
                    constant.setNodeMetaData("static.import", name);

                    return constant;
                }
                // GRECLIPSE end

It is the setNodeMetaData call where the exception is being thrown.

@eric-milles
Copy link
Member

I was able to recreate with this. Does this look familiar to what you have? Using the constant reference in an annotation seems to be the critical bit.

package a.b.c.d
interface E {
    String F = 'G.H'
}
import static a.b.c.d.E.F as X
import static a.b.c.d.E.F as Y
@SuppressWarnings([X, Y])
class C {
}

@AntonPanikov
Copy link
Author

Thanks for clarification. Yes, we are using such pattern as a constant for internal security check, directory traversal checks in particular.

I was able to reproduce that:

package test

interface TestStrings {
    public static final String ONE = 'one'
    public static final String TWO = 'two'
    public static final String THREE = 'three'
    public static final String DIRECTORY_TRAVERSAL = /(\.\.\\)|(\.\.\/)/
}
package test

@interface TestAnnotation {
    String[] value()
}

@interface TestAnnotation2 {
    String[] value()
}
package test

import static test.TestStrings.*

class Test {

    @TestAnnotation(value = [ONE, TWO, DIRECTORY_TRAVERSAL])
    @TestAnnotation2(value = [ONE, TWO, DIRECTORY_TRAVERSAL])
    static main(args) {
        println 'hello groovy'
    }

}

As soon as you comment out the second @TestAnnotation2, everything will works and looks fine, but I guess it is not.

@AntonPanikov
Copy link
Author

Thanks for the second replay, have not seen it. Please look onto my response above. I also was able to reproduce it without static alias. The trick is to use two annotations with constant that has pattern. This code I provided mimic our production code.

@eric-milles
Copy link
Member

Thanks. This simpler class, including the interface E above does the trick:

import static a.b.c.d.E.*
class Foo {
  @SuppressWarnings(F)
  def one() {}
  @SuppressWarnings(F)
  def two() {}
}

@eric-milles
Copy link
Member

Can you recheck? This should be resolved with the latest snapshot.

@AntonPanikov
Copy link
Author

I tested this one, it is working now, but exposed two other issues. I will file them separately. Thanks a lot!

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