bertramdev / asset-pipeline

The core implementation of the asset pipeline for the jvm
193 stars 92 forks source link

Compile asset-pipeline-core with Groovy 3 #350

Closed jamesfredley closed 2 months ago

jamesfredley commented 2 months ago

Compile asset-pipeline-core with Groovy 3 to avoid Groovy 4 incompatibility when Gradle runs it in asset-pipeline-gradle with Groovy 3

When compiled with Groovy 4, the compiler uses groovy.lang.IntRange(boolean, boolean, int, int), which does not exist in Groovy 3 and causes the NoSuchMethodError when Gradle runs the class with Groovy 3.0.22.

The specific line that gets transformed to use groovy.lang.IntRange(boolean, boolean, int, int) when compiled with Groovy 4, which does not exist in Groovy 3. https://docs.groovy-lang.org/3.0.22/html/api/groovy/lang/IntRange.html

https://github.com/bertramdev/asset-pipeline/blob/186b7bee2ae092aad88ecd6f19b45a0109e179cc/asset-pipeline-core/src/main/groovy/asset/pipeline/GenericAssetFile.groovy#L57

Compiled with Groovy 3:

return pathArgs.size() == 1 ? (String)ShortTypeHandling.castToString((Object)null) : DefaultGroovyMethods.join(DefaultGroovyMethods.getAt(pathArgs, new IntRange(true, 0, pathArgs.size() - 2)), "/");

Compiled with Groovy 4:

return pathArgs.size() == 1 ? null.cast((Object)null) : DefaultGroovyMethods.join(DefaultGroovyMethods.getAt(pathArgs, new IntRange(true, true, 0, pathArgs.size() - 2)), "/");

codeconsole commented 2 months ago

@jamesfredley what is it about Groovy 4 that is causing the NoSuchMethodError?

jamesfredley commented 2 months ago

@codeconsole The dependency (asset-pipeline-core) was compiled with Groovy 4. Groovy 4 has a new method groovy.lang.IntRange(boolean, boolean, int, int) which the compiler used in the generated class, which then failed when Gradle tried to runs it on Groovy 3.0.22 during the build because that method did not exist in Groovy 3.

The Gradle build is still executing using the included Groovy libraries, unfortunately.

jamesfredley commented 2 months ago

I think this is the root underlying issue Gradle is trying to warn user about with:

"Gradle plugins written in Groovy must use Groovy 3.x for compatibility with Gradle and Groovy DSL build scripts. https://docs.gradle.org/current/userguide/compatibility.html#groovy

codeconsole commented 2 months ago

@jamesfredley can we just tweak the method a bit so it runs on both?

jamesfredley commented 2 months ago

@codeconsole It would have to be refactored to not use a range, since that is what is triggering this.

codeconsole commented 2 months ago

@jamesfredley that should be re-written. It seems overly complicated as is.

Isn't

return (pathArgs[0..(pathArgs.size()-2)]).join("/") 

the same as

pathArgs[0..-2).join("/")

no need for return either

codeconsole commented 2 months ago
List<String> pathArgs = 'abc/def/ghi/jkl/mno'.tokenize('/')
assert pathArgs[0..pathArgs.size()-2] == pathArgs[0..-2]
davydotcom commented 2 months ago

thanks!