From 9eb29a8262ae857b613d575c88e6312cb79fda9d Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Mon, 8 Jun 2020 15:16:36 +0200 Subject: [PATCH] Fix class cast exception when release flag is not a string Fixes #13351 --- .../tasks/compile/JavaCompilerArgumentsBuilder.java | 9 +++++++-- .../compile/JavaCompilerArgumentsBuilderTest.groovy | 10 ++++++++++ .../compile/BasicJavaCompilerIntegrationSpec.groovy | 11 ++++++++++- .../gradle/api/plugins/internal/JvmPluginsHelper.java | 4 +++- 4 files changed, 30 insertions(+), 4 deletions(-) diff --git a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/JavaCompilerArgumentsBuilder.java b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/JavaCompilerArgumentsBuilder.java index 5ce0216b0bad..4a30b85e60d1 100644 --- a/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/JavaCompilerArgumentsBuilder.java +++ b/subprojects/language-java/src/main/java/org/gradle/api/internal/tasks/compile/JavaCompilerArgumentsBuilder.java @@ -17,10 +17,10 @@ package org.gradle.api.internal.tasks.compile; import com.google.common.base.Joiner; -import com.google.common.collect.Lists; import org.gradle.api.InvalidUserDataException; import org.gradle.api.JavaVersion; import org.gradle.api.tasks.compile.ForkOptions; +import org.gradle.internal.Cast; import org.gradle.util.GUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -29,6 +29,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.stream.Collectors; public class JavaCompilerArgumentsBuilder { public static final Logger LOGGER = LoggerFactory.getLogger(JavaCompilerArgumentsBuilder.class); @@ -77,7 +78,11 @@ public JavaCompilerArgumentsBuilder noEmptySourcePath() { public List build() { args = new ArrayList<>(); // Take a deep copy of the compilerArgs because the following methods mutate it. - List compArgs = Lists.newArrayList(spec.getCompileOptions().getCompilerArgs()); + List compilerArgs = Cast.uncheckedCast(spec.getCompileOptions().getCompilerArgs()); + List compArgs = compilerArgs + .stream() + .map(Object::toString) + .collect(Collectors.toList()); validateCompilerArgs(compArgs); diff --git a/subprojects/language-java/src/test/groovy/org/gradle/api/internal/tasks/compile/JavaCompilerArgumentsBuilderTest.groovy b/subprojects/language-java/src/test/groovy/org/gradle/api/internal/tasks/compile/JavaCompilerArgumentsBuilderTest.groovy index 457fa255431b..fdd4282625c4 100644 --- a/subprojects/language-java/src/test/groovy/org/gradle/api/internal/tasks/compile/JavaCompilerArgumentsBuilderTest.groovy +++ b/subprojects/language-java/src/test/groovy/org/gradle/api/internal/tasks/compile/JavaCompilerArgumentsBuilderTest.groovy @@ -93,6 +93,16 @@ class JavaCompilerArgumentsBuilderTest extends Specification { builder.build() == defaultOptions + ['--release', '7'] } + def "can use a GString for the value of the release flag"() { + when: + spec.compileOptions.compilerArgs += ['--release', "${ -> 7}"] + spec.sourceCompatibility = '1.7' + spec.targetCompatibility = '1.7' + + then: + builder.build() == defaultOptions + ['--release', '7'] + } + def "generates -d option"() { def file = new File("/project/build") spec.destinationDir = file diff --git a/subprojects/plugins/src/integTest/groovy/org/gradle/java/compile/BasicJavaCompilerIntegrationSpec.groovy b/subprojects/plugins/src/integTest/groovy/org/gradle/java/compile/BasicJavaCompilerIntegrationSpec.groovy index 4b3dc6858199..2ad79a52c4fd 100644 --- a/subprojects/plugins/src/integTest/groovy/org/gradle/java/compile/BasicJavaCompilerIntegrationSpec.groovy +++ b/subprojects/plugins/src/integTest/groovy/org/gradle/java/compile/BasicJavaCompilerIntegrationSpec.groovy @@ -23,6 +23,7 @@ import org.gradle.integtests.fixtures.ToBeFixedForInstantExecution import org.gradle.test.fixtures.file.ClassFile import org.gradle.util.Requires import org.gradle.util.TestPrecondition +import spock.lang.Unroll abstract class BasicJavaCompilerIntegrationSpec extends AbstractIntegrationSpec { def setup() { @@ -143,12 +144,13 @@ public class FxApp extends Application { } @Requires(TestPrecondition.JDK9_OR_LATER) + @Unroll def "compile with release option"() { given: goodCode() buildFile << """ java.targetCompatibility = JavaVersion.VERSION_1_7 -compileJava.options.compilerArgs.addAll(['--release', '8']) +compileJava.options.compilerArgs.addAll(['--release', $notation]) compileJava { doFirst { assert configurations.apiElements.attributes.getAttribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE) == 8 @@ -162,6 +164,13 @@ compileJava { expect: succeeds 'compileJava' bytecodeVersion() == 52 + + where: + notation << [ + "'8'", + '8', // Integer, see #13351 + '"${8}"' // GString, see #13351 + ] } @Requires(TestPrecondition.JDK9_OR_LATER) diff --git a/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/JvmPluginsHelper.java b/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/JvmPluginsHelper.java index 205cec8efe9a..1b17a17ab445 100644 --- a/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/JvmPluginsHelper.java +++ b/subprojects/plugins/src/main/java/org/gradle/api/plugins/internal/JvmPluginsHelper.java @@ -277,7 +277,9 @@ public static Action configureDefaultTargetPlatform(JavaP private static int getReleaseOption(List compilerArgs) { int flagIndex = compilerArgs.indexOf("--release"); if (flagIndex != -1 && flagIndex + 1 < compilerArgs.size()) { - return Integer.parseInt(compilerArgs.get(flagIndex + 1)); + // Using String.valueOf because despite the type signature being List + // a user can put anything in that list, including Groovy's GString + return Integer.parseInt(String.valueOf(compilerArgs.get(flagIndex + 1))); } return 0; }