Details
-
Bug
-
Status: Closed
-
Major
-
Resolution: Fixed
-
2.4.10
-
None
Description
I have discovered a situation in which doing a static import of all members of a class causes a compilation error as the compiler incorrectly infers that the code is attempting to use a private static member on the imported class.
There appears to be a very specific combination of factors that causes this to occur. Specifically, the class that's doing the static import must be statically compiled using the @CompileStatic annotation, and both classes must share a logger variable with the same name from @Log (or @Slf4j, etc.). Furthermore, the classes cannot be compiled at the same time (for instance, the one could be in a jar or a sub-build in Gradle).
The following is a specific Gradle example that produces the issue.
First, the build structure:
import-static-issue src/main/groovy/test build.gradle settings.gradle Importer.groovy SameProjectImported.groovy subproject src/main/groovy/test/DifferentProjectImported.groovy
And the relevant files:
group 'test' version '1.0-SNAPSHOT' allprojects { apply plugin: 'groovy' apply plugin: 'java' sourceCompatibility = 1.8 repositories { mavenCentral() } dependencies { compile 'org.codehaus.groovy:groovy-all:2.4.10' } } dependencies { compile project(':subproject') }
include 'subproject'
package test import groovy.transform.CompileStatic import groovy.util.logging.Log //import static test.SameProjectImported.* //Using this one instead won't trigger the issue import static test.DifferentProjectImported.* @Log @CompileStatic class Importer { static void main(String[] args) { log.info 'This will cause a compilation failure' } }
package test import groovy.util.logging.Log @Log class SameProjectImported { }
package test import groovy.util.logging.Log @Log class DifferentProjectImported { // private static java.util.logging.Logger log // Using this instead of @Log will also cause the error }
Compiling this code via Gradle (e.g. "gradle compileGroovy") produces the following error:
/[...]/import-static-issue/src/main/groovy/test/Importer.groovy: -1: Access to test.DifferentProjectImported#log is forbidden @ line -1, column -1.
I have confirmed the issue in Groovy 2.4.10. I have also confirmed that this issue appears to have been present for the whole Groovy 2.x series.
It doesn't occur if you manually create the private static field in the importing class instead of using the @Log AST transformation. It will occur if you manually create the static "log" field in the statically imported class but use @Log in the importing class. It doesn't occur if the importing class doesn't use @CompileStatic. It doesn't occur if the importing class and the imported class are in the same Gradle project. The issue also occurs if you statically import just the "log" field and not "*" (though practically speaking, you should never actually try to do that).
I ran across this issue when I was migrating some code into a shared library and was statically importing a number of fields for a class that was being moved. Manually declaring the fields to be statically imported would work, but my IDE settings would fold it back into "*" if the imports are ever optimized for the class, so this isn't a workable solution for me (if nothing else, it would be supremely confusing for any developers down the road).
Edit: Upon further investigation, there is a different but related issue if the importing class is not annotated with @CompileStatic. If it's not statically compiled, rather than throwing a compilation failure, it will instead use the imported private log variable, not its own.
Attachments
Issue Links
- relates to
-
GROOVY-11180 Regression: STC loses track of package-scope constants
- Closed