Skip to content

scip-java: generated Gradle init script is unparseable on Windows — unescaped backslashes in interpolated paths #992

Description

@carheart

scip-java: generated Gradle init script is unparseable on Windows — unescaped backslashes in interpolated paths

Repo: scip-code/scip-java
Affected: v0.12.3 (Scala) and v0.13.1 (Kotlin rewrite) — verified in both
Platform: Windows (any); reproduced on Windows 11 Pro 10.0.26200, x64
Severity: blocks scip-java index --build-tool gradle entirely on Windows


Summary

GradleBuildTool.initScript() builds a Groovy init script by string-interpolating absolute
filesystem paths. On Windows those paths contain backslashes, which Groovy parses as escape
sequences inside a double-quoted string. A temp path such as
C:\Users\<name>\AppData\Local\Temp\scip-java-…\gradle-plugin.jar contains \U, which is not a
valid Groovy escape, so the generated script fails to compile and the build never starts.

Unlike the Maven wrapper issue, GradleBuildTool does invoke the correct wrapper on Windows — so
this failure occurs one layer deeper and is reached only after wrapper selection succeeds.

Reproduction

git clone https://github.com/spring-projects/spring-petclinic
cd spring-petclinic
scip-java index --build-tool gradle

The correct command is constructed and launched:

$ C:\…\spring-petclinic\gradlew.bat --no-daemon --init-script C:\Users\…\Temp\scip-java-…\init-script.gradle clean scipPrintDependencies scipCompileAll

then:

init-script.gradle: 3: Unexpected character: '"' @ line 3, column 26.
       classpath(files("C:\Users\carhe\AppData\Local\Temp\scip-java-…\gradle-plugin.jar"))
                       ^

Source

scip-java/src/main/kotlin/org/scip_code/scip_java/buildtools/GradleBuildTool.kt (v0.13.1,
L101-128):

val script =
    """
     initscript {
         dependencies{ 
             classpath(files("${gradlePluginPath}"))
         }
     }

     import org.scip_code.scip_java.gradle.ScipGradlePlugin

     allprojects {
       project.ext["scipTarget"] = "${targetroot()}"
       project.ext["javacPluginJar"] = "$pluginpath"
       project.ext["dependenciesOut"] = "$dependenciesPath"
       project.ext["scipKotlincJar"] = "$scipKotlincPath"
       apply plugin: ScipGradlePlugin
     }
    """
        .trimIndent()

Five interpolated paths are affected, not just the one that reports the error:
gradlePluginPath, targetroot(), pluginpath, dependenciesPath, scipKotlincPath. The parse
fails at the first, so the others are latent — fixing only line 3 would surface the next one.

Whether a given path breaks depends on the character following each backslash: \U (from
\Users) and \A (\AppData) are invalid escapes and hard-error, while e.g. \b/\n/\t would
silently corrupt the path instead. Both outcomes are wrong; only one is loud.

Suggested fix

Groovy accepts forward slashes in paths on Windows, so normalising at interpolation is sufficient
and needs no escaping logic:

fun Path.forGroovy(): String = toString().replace('\\', '/')

then "${gradlePluginPath.forGroovy()}", "${targetroot().forGroovy()}", and the same for the
other three.

Alternative: emit single-quoted Groovy strings (no escape processing), but that only shifts the
problem to any path containing a quote. Forward-slash normalisation is simpler and platform-safe.

Impact

Combined with the Maven wrapper issue, scip-java index has no working code path on Windows in
either 0.12.3 or 0.13.1:

  • default / --build-tool mavenCreateProcess error=193 spawning mvnw
  • --build-tool gradle → this parse error

No environment workaround exists. In particular, forcing a forward-slash temp directory via
-Djava.io.tmpdir=C:/some/path does not help — the JVM canonicalises java.io.tmpdir back to
backslashes before GradleBuildTool reads it. Verified experimentally.

That both defects survived the full Scala→Kotlin rewrite suggests there is no Windows coverage in
CI. A single smoke test — scip-java index on a wrapper-based fixture on a windows-latest
runner — would catch both.

Environment

  • Windows 11 Pro 10.0.26200 (x64), 24 cores
  • Eclipse Temurin JDK 17.0.20 and 21.0.12 both present
  • Gradle 9.5.1 via gradlew.bat
  • scip-java 0.12.3 launched via Coursier (cs launch com.sourcegraph:scip-java_2.13:0.12.3);
    source re-verified against the v0.13.1 tag
  • Fixture: spring-petclinic

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions