-
Notifications
You must be signed in to change notification settings - Fork 5.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support Groovy $Trait$FieldHelper classes in new class file reader
Preface: for Groovy traits with fields which are extended by classes, the Groovy compiler generates synthetic "$Trait$FieldHelper" classes which posed several problems to our class file reader, caused by the fact the contents of the InnerClasses attribute broke some assumptions about how names on the JVM are formed. For a trait named `A`, the Groovy compiler will additionally generate a synthetic class file `A$Trait$FieldHelper` with the following in the InnerClasses attribute: InnerClasses: public static #15= #2 of #14; //FieldHelper=class A$Trait$FieldHelper of class A i.e. the simple name of the class is `FieldHelper`, the name of its outer class is `A`, but the full internal name is `A$Trait$FieldHelper`, which is surprising considering that the names are usually obtained by separating the outer and inner names via the dollar sign. Another detail is that in some usages of this synthetic class, the InnerClasses attribute was missing at all. For example, if an empty class `B` extends `A`, then there's no InnerClasses attribute in `B`'s class file, which is surprising because we might decode the same name differently depending on the class file we encounter it in. In this change, we attempt to treat these synthetic classes as top-level by refusing to read "invalid" InnerClasses attribute values (they are not technically invalid because they still conform to JVMS), fixing the problem of "unresolved supertypes" error which occrurred when these classes were used as supertypes in a class file in a dependency. 1) In ClassifierResolutionContext.mapInternalNameToClassId, do not use the ad-hoc logic (copy-pasted from intellij-core) to determine class id heuristically from the internal name. For $Trait$FieldHelper classes this logic attempted to replace all dollar signs with dots, which was semantically incorrect: dollars there were used as synthetic characters, not as a separator between outer and inner classes. 2) In isNotTopLevelClass (Other.kt), only consider "valid" InnerClasses attribute values, where the full name of the class is obtained by separating the outer name and the inner name with a dollar character. This way, we'll be able to treat class files with invalid attribute values as top-level and avoid breaking any other assumptions in the class file loader. 3) In BinaryJavaClass.visitInnerClass, record all valid InnerClasses attribute values present in the class file, not just those related to the class in question itself. This is needed now because previously, the removed heuristics (see p.1) transformed mentioned inner class names to class ids correctly >99% of the time. Now that the heuristics are gone, we'll use the information present in the class file to map names correctly and predictably. According to JVMS, this attribute should contain information about all inner classes mentioned in the class file, and this is true at least for class files produced by javac. #KT-18592 Fixed
- Loading branch information
Showing
11 changed files
with
95 additions
and
54 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6 changes: 6 additions & 0 deletions
6
compiler/testData/loadJava/compiledJava/TopLevel$Class.fast.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package test | ||
|
||
public open class `TopLevel$Class` { | ||
public constructor `TopLevel$Class`() | ||
public open fun foo(/*0*/ p0: test.`TopLevel$Class`!): kotlin.Unit | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
34 changes: 34 additions & 0 deletions
34
...ugin-integration-tests/src/test/resources/testProject/groovyTraitsWithFields/build.gradle
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
buildscript { | ||
repositories { | ||
mavenLocal() | ||
mavenCentral() | ||
} | ||
dependencies { | ||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" | ||
} | ||
} | ||
|
||
apply plugin: "kotlin" | ||
apply plugin: "groovy" | ||
apply plugin: "java" | ||
|
||
repositories { | ||
mavenLocal() | ||
mavenCentral() | ||
} | ||
|
||
dependencies { | ||
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" | ||
compile 'org.codehaus.groovy:groovy-all:2.5.3' | ||
} | ||
|
||
compileGroovy.dependsOn = compileGroovy.taskDependencies.values - 'compileJava' | ||
|
||
compileKotlin { | ||
dependsOn compileGroovy | ||
classpath += files(compileGroovy.destinationDir) | ||
} | ||
|
||
compileKotlin { | ||
kotlinOptions.jvmTarget = "1.8" | ||
} |
11 changes: 11 additions & 0 deletions
11
...ests/src/test/resources/testProject/groovyTraitsWithFields/src/main/groovy/MyTrait.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import groovy.transform.CompileStatic | ||
|
||
@CompileStatic | ||
trait MyTrait { | ||
private transient boolean somePrivateField = false | ||
List<String> someField | ||
|
||
def foo() { | ||
return 1 | ||
} | ||
} |
3 changes: 3 additions & 0 deletions
3
.../test/resources/testProject/groovyTraitsWithFields/src/main/groovy/MyTraitAccessor.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
class MyTraitAccessor implements MyTrait { | ||
def myField = 1 | ||
} |
3 changes: 3 additions & 0 deletions
3
...ts/src/test/resources/testProject/groovyTraitsWithFields/src/main/kotlin/MyKotlinClass.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
fun main(args: Array<String>) { | ||
System.out.println(MyTraitAccessor().myField) | ||
} |