diff --git a/scip-gradle-plugin/src/main/java/org/scip_code/scip_java/gradle/ScipGradlePlugin.java b/scip-gradle-plugin/src/main/java/org/scip_code/scip_java/gradle/ScipGradlePlugin.java index 310dc217..d57413c6 100644 --- a/scip-gradle-plugin/src/main/java/org/scip_code/scip_java/gradle/ScipGradlePlugin.java +++ b/scip-gradle-plugin/src/main/java/org/scip_code/scip_java/gradle/ScipGradlePlugin.java @@ -51,25 +51,34 @@ private void configureProject(Project project) { task.getOptions().setIncremental(false); if (pluginAdded) { - List args = task.getOptions().getCompilerArgs(); + // Groovy build scripts can append interpolated strings + // (GString) to compilerArgs, so despite the List + // signature the list may hold non-String elements. Iterate + // through a wildcard reference so elements are not implicitly + // cast to String, which throws ClassCastException (issue + // #801). + List args = task.getOptions().getCompilerArgs(); // It's important we don't add the plugin configuration more // than once, as javac considers that an error. boolean alreadyAdded = - args.stream().anyMatch(arg -> arg.startsWith("-Xplugin:scip")); + args.stream() + .anyMatch(arg -> String.valueOf(arg).startsWith("-Xplugin:scip")); if (!alreadyAdded) { // The random timestamp ensures the sources are _always_ // recompiled, so Gradle doesn't cache any state. // TODO: before this plugin is published to Maven Central, we // will need to revert this change - as it can have // detrimental effect on people's builds. - args.add( - "-Xplugin:scip -targetroot:" - + targetRoot - + " -sourceroot:" - + sourceRoot - + " -randomtimestamp=" - + System.nanoTime()); + task.getOptions() + .getCompilerArgs() + .add( + "-Xplugin:scip -targetroot:" + + targetRoot + + " -sourceroot:" + + sourceRoot + + " -randomtimestamp=" + + System.nanoTime()); } } }); diff --git a/scip-java/src/test/kotlin/tests/GradleBuildToolTest.kt b/scip-java/src/test/kotlin/tests/GradleBuildToolTest.kt index a1b3b933..a643b77f 100644 --- a/scip-java/src/test/kotlin/tests/GradleBuildToolTest.kt +++ b/scip-java/src/test/kotlin/tests/GradleBuildToolTest.kt @@ -71,6 +71,17 @@ class GradleBuildToolTest : BuildToolHarness() { add( checkGradleBuild("build-with-Werror", "gradle/build-with-Werror", expectedScipFiles = 2) ) + // Regression test: Groovy string interpolation puts GString elements + // (not java.lang.String) into compilerArgs, which used to crash the + // plugin with a ClassCastException. + // https://github.com/scip-code/scip-java/issues/801 + add( + checkGradleBuild( + "gstring-compiler-args", + "gradle/gstring-compiler-args", + expectedScipFiles = 1, + ) + ) add( checkGradleBuild( "publishing", diff --git a/scip-java/src/test/resources/fixtures/gradle/gstring-compiler-args/build.gradle b/scip-java/src/test/resources/fixtures/gradle/gstring-compiler-args/build.gradle new file mode 100644 index 00000000..865301c7 --- /dev/null +++ b/scip-java/src/test/resources/fixtures/gradle/gstring-compiler-args/build.gradle @@ -0,0 +1,14 @@ +plugins { + id 'java' +} +repositories { + mavenCentral() +} +// Groovy string interpolation produces GString elements, not java.lang.String, +// so compilerArgs may hold non-String values despite its List +// signature. Regression test for +// https://github.com/scip-code/scip-java/issues/801 +def maxErrors = 500 +compileJava { + options.compilerArgs << "-Xmaxerrs" << "${maxErrors}" +} diff --git a/scip-java/src/test/resources/fixtures/gradle/gstring-compiler-args/src/main/java/example/Example.java b/scip-java/src/test/resources/fixtures/gradle/gstring-compiler-args/src/main/java/example/Example.java new file mode 100644 index 00000000..c7fa8bb6 --- /dev/null +++ b/scip-java/src/test/resources/fixtures/gradle/gstring-compiler-args/src/main/java/example/Example.java @@ -0,0 +1,7 @@ +package example; + +public class Example { + public String greet(String name) { + return "Hello, " + name + "!"; + } +}