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

Fix incremental compilation with JDK16 using toolchains #16066

Merged
merged 14 commits into from Feb 11, 2021

Conversation

rieske
Copy link
Contributor

@rieske rieske commented Feb 8, 2021

#15538

  • add a test to compile java using toolchains with a range of JDKs
  • remove uses of private Java compiler APIs in incremental compiler plugin

@rieske rieske added from:member in:jvm-ecosystem @core Issue owned by GBT Core labels Feb 8, 2021
@rieske rieske self-assigned this Feb 8, 2021
@rieske rieske added this to the 7.0 RC1 milestone Feb 8, 2021
Copy link
Contributor

@bmuskalla bmuskalla left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. The one workaround with the --add-opens is fine but it would be good to look into my comment and see if we can continue without it

@@ -349,6 +353,10 @@ private DefaultJavaCompileSpec createBaseSpec() {
private void applyToolchain(ForkOptions forkOptions) {
final JavaInstallationMetadata metadata = getToolchain();
forkOptions.setJavaHome(metadata.getInstallationPath().getAsFile());
if (isToolchainCompatibleWithJava16()) {
// used by the incremental compiler plugin, see org.gradle.internal.compiler.java.ClassNameCollector
forkOptions.getJvmArgs().addAll(Arrays.asList("--add-opens", "jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED"));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might be worthing looking to actually fixing this without the add opens. I pushed a small WIP here that I played around with, we might not need this workaround for this. WDYT?

2fc4346

So that they are compatible with Java 8.
On Java 8, calling ((JavacTask) delegate).getElements() in the IncrementalCompileTask of the incremental compiler plugin, somehow
makes the the deprecation messages print the class names with their fully qualified names, in this case - com.example.Foo.
@@ -68,7 +68,7 @@ public void setLocale(Locale locale) {
@Override
public Boolean call() {
if (delegate instanceof JavacTask) {
ClassNameCollector collector = new ClassNameCollector(relativize);
ClassNameCollector collector = new ClassNameCollector(relativize, ((JavacTask) delegate).getElements());
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Calling javacTask.getElements() here has a rather weird side effect on deprecation messages in Java 8 - see this commit: b04b5ab
Not sure if there can be more implications here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the side effect is not too bad but would be good to capture in the tests instead of ignoring it. Initially, I thought they dropped the class name completely which is not great.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And would be nice to pull the cast out as we do the same cast in the next line. Time to switch to Java 14 with pattern matching :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder also if the instanceof-or-throw can be pulled out to the constructor so that the delegate field is always a JavacTask here. Let's see what CI thinks.

@rieske rieske marked this pull request as ready for review February 10, 2021 14:05
Copy link
Contributor

@bmuskalla bmuskalla left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor nits and some questions. Generally good to go. Let me know if I should review the remaining changes

if (symbol.endsWith("module-info")) {
symbol = "module-info";
} else if (typeElement.getNestingKind().isNested()) {
symbol = elements.getBinaryName(typeElement).toString();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice

@@ -68,7 +68,7 @@ public void setLocale(Locale locale) {
@Override
public Boolean call() {
if (delegate instanceof JavacTask) {
ClassNameCollector collector = new ClassNameCollector(relativize);
ClassNameCollector collector = new ClassNameCollector(relativize, ((JavacTask) delegate).getElements());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the side effect is not too bad but would be good to capture in the tests instead of ignoring it. Initially, I thought they dropped the class name completely which is not great.

@@ -68,7 +68,7 @@ public void setLocale(Locale locale) {
@Override
public Boolean call() {
if (delegate instanceof JavacTask) {
ClassNameCollector collector = new ClassNameCollector(relativize);
ClassNameCollector collector = new ClassNameCollector(relativize, ((JavacTask) delegate).getElements());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And would be nice to pull the cast out as we do the same cast in the next line. Time to switch to Java 14 with pattern matching :)


}

def "can compile Java using different JDKs"() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe use #javaVersion to see which iterations are skipped?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We get this information without explicitly embedding the variable in the test header (since Spock 2 I believe): https://ge.gradle.org/s/vhyeam6vqgtqi/tests
image

};
}
}
"""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to check for anonymous classes using method-level nested classes?

class Anonymous2 {
    SomeInterface getAnonymous() {
        class Foobar implements SomeInterface {
        }
        return new Foobar() {
            public int foo() {
                return 42;
            }
        };
    }
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, for our use case, do lambdas behave the same as anonymous classes for this use case?

@rieske rieske merged commit f8f9f6f into master Feb 11, 2021
@rieske rieske deleted the vv/jdk16/toolchains branch February 11, 2021 14:10
@dreis2211
Copy link
Contributor

Is this maybe possible to backport to 6.x?

@rieske rieske removed this from the 7.0 RC1 milestone Feb 12, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
@core Issue owned by GBT Core in:jvm-ecosystem
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants