Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ codecov:

comment:
layout: "reach, diff, flags, files"
after_n_builds: 24
after_n_builds: 29
13 changes: 13 additions & 0 deletions .github/workflows/branches-and-prs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ jobs:
- '3.0'
- '4.0'
- '5.0'
- '6.0'
java:
- '8'
- '11'
Expand All @@ -78,6 +79,12 @@ jobs:
- variant: '5.0'
java: '8'
os: 'ubuntu-latest'
- variant: '6.0'
java: '8'
os: 'ubuntu-latest'
- variant: '6.0'
java: '11'
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Are the java versions from the different os types intentional?
Why Linux 8 and 11 and Windows + Mac 17?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Groovy 6 requires Java 17, so those Linux builds get excluded. And win+mac are include, i.e., adding executions.

os: 'ubuntu-latest'
include:
- variant: '2.5'
java: '8'
Expand All @@ -91,6 +98,9 @@ jobs:
- variant: '5.0'
java: '11'
os: 'windows-latest'
- variant: '6.0'
java: '17'
os: 'windows-latest'
- variant: '2.5'
java: '8'
os: 'macos-latest'
Expand All @@ -103,6 +113,9 @@ jobs:
- variant: '5.0'
java: '11'
os: 'macos-latest'
- variant: '6.0'
java: '17'
os: 'macos-latest'
steps:
- id: 'step-0'
name: 'Checkout Repository'
Expand Down
24 changes: 17 additions & 7 deletions .github/workflows/common.main.kts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ data class Matrix(
data class Axes(
val javaVersions: List<String>,
val additionalJavaTestVersions: List<String>,
val variants: List<String>
val variants: List<String>,
val additionalVariants: List<String>
)

data class Element(
Expand Down Expand Up @@ -137,19 +138,27 @@ fun WorkflowBuilder.job(
val Matrix.Companion.full
get() = Matrix(
operatingSystems = listOf("ubuntu-latest"),
variants = axes.variants,
variants = axes.variants + axes.additionalVariants,
javaVersions = axes.javaVersions + axes.additionalJavaTestVersions,
exclude = {
((variant == "2.5") && (javaVersion!!.toInt() >= 17)) ||
((variant == "5.0") && (javaVersion!!.toInt() < 11))
when (variant) {
"2.5" -> javaVersion!!.toInt() >= 17
"5.0" -> javaVersion!!.toInt() < 11
"6.0" -> javaVersion!!.toInt() < 17
else -> false
}
},
includes = listOf("windows-latest", "macos-latest")
.map { Matrix.Element(operatingSystem = it) }
.flatMap { element ->
axes.variants.map {
(axes.variants + axes.additionalVariants).map {
element.copy(
variant = it,
javaVersion = if (it == "5.0") "11" else axes.javaVersions.first()
javaVersion = when (it) {
"5.0" -> "11"
"6.0" -> "17"
else -> axes.javaVersions.first()
}
)
}
}
Expand All @@ -166,7 +175,8 @@ val Matrix.Companion.axes by lazy {
Matrix.Axes(
properties.getList("javaVersionsList"),
properties.getList("additionalJavaTestVersionsList"),
properties.getList("variantsList")
properties.getList("variantsList"),
properties.getList("additionalVariantsList")
)
}
}
Expand Down
13 changes: 13 additions & 0 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ jobs:
- '3.0'
- '4.0'
- '5.0'
- '6.0'
java:
- '8'
- '11'
Expand All @@ -58,6 +59,12 @@ jobs:
- variant: '5.0'
java: '8'
os: 'ubuntu-latest'
- variant: '6.0'
java: '8'
os: 'ubuntu-latest'
- variant: '6.0'
java: '11'
os: 'ubuntu-latest'
include:
- variant: '2.5'
java: '8'
Expand All @@ -71,6 +78,9 @@ jobs:
- variant: '5.0'
java: '11'
os: 'windows-latest'
- variant: '6.0'
java: '17'
os: 'windows-latest'
- variant: '2.5'
java: '8'
os: 'macos-latest'
Expand All @@ -83,6 +93,9 @@ jobs:
- variant: '5.0'
java: '11'
os: 'macos-latest'
- variant: '6.0'
java: '17'
os: 'macos-latest'
steps:
- id: 'step-0'
name: 'Checkout Repository'
Expand Down
2 changes: 1 addition & 1 deletion allVariants
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/sh
for var in 2.5 3.0 4.0 5.0; do
for var in 2.5 3.0 4.0 5.0 6.0; do
./gradlew -Dvariant="$var" "$@"
done
2 changes: 1 addition & 1 deletion allVariants.bat
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@echo off
for %%v in (2.5 3.0 4.0 5.0) do (
for %%v in (2.5 3.0 4.0 5.0 6.0) do (
gradlew.bat -Dvariant=%%v %*
)
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import java.time.Duration
class SpockBasePlugin implements Plugin<Project> {

@VisibleForTesting
public static final JavaLanguageVersion COMPILER_VERSION = JavaLanguageVersion.of(11)
public static final JavaLanguageVersion COMPILER_VERSION = JavaLanguageVersion.of(17)
public static final int COMPILER_RELEASE_VERSION = 8

void apply(Project project) {
Expand Down
15 changes: 13 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,17 @@ ext {
}
javaVersion = 11
}
} else if (variant == 6.0) {
groovyGroup = "org.apache.groovy"
groovyVersion = libs.versions.groovy6.get()
minGroovyVersion = "6.0.0"
maxGroovyVersion = "6.9.99"
if (javaVersion < 17) {
if (System.getProperty("javaVersion") != null) {
throw new InvalidUserDataException("Groovy $variant is not compatible with Java $javaVersion")
}
javaVersion = 17
}
} else {
throw new InvalidUserDataException("Unknown variant: $variant. Choose one of: $variants")
}
Expand Down Expand Up @@ -238,8 +249,8 @@ if (gradle.startParameter.taskNames == ["ghActionsPublish"] || gradle.startParam
}

if (originalStartParameterTaskNames == ["ghActionsPublish"]) {
if ((javaVersion != javaVersions.min()) && ((variant != 5.0) || (javaVersion != 11))) {
throw new IllegalArgumentException("ghActionsPublish can only be run on Java ${javaVersions.min()} (or 11 for variant 5.0) but was run on $javaVersion")
if ((javaVersion != javaVersions.min()) && ((variant != 5.0) || (javaVersion != 11)) && ((variant != 6.0) || (javaVersion != 17))) {
throw new IllegalArgumentException("ghActionsPublish can only be run on Java ${javaVersions.min()} (or 11 for variant 5.0, 17 for variant 6.0) but was run on $javaVersion")
}
/*
We want to release only snapshots directly from master, final releases will be tagged and then published from that tag.
Expand Down
1 change: 1 addition & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ org.gradle.caching=true
javaVersionsList=8, 11, 17, 21, 25
additionalJavaTestVersionsList=
variantsList=2.5, 3.0, 4.0, 5.0
additionalVariantsList=6.0
kotlin.code.style=official
2 changes: 2 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ groovy2 = '2.5.23'
groovy3 = '3.0.25'
groovy4 = '4.0.32'
groovy5 = '5.0.6'
groovy6 = '6.0.0-alpha-1'
jacoco = '0.8.14'
junit5 = '5.14.4'
junit6 = '6.1.0'
Expand Down Expand Up @@ -50,3 +51,4 @@ groovy-v2 = { module = "org.codehaus.groovy:groovy", version.ref="groovy2" }
groovy-v3 = { module = "org.codehaus.groovy:groovy", version.ref="groovy3" }
groovy-v4 = { module = "org.apache.groovy:groovy", version.ref="groovy4" }
groovy-v5 = { module = "org.apache.groovy:groovy", version.ref="groovy5" }
groovy-v6 = { module = "org.apache.groovy:groovy", version.ref="groovy6" }
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright 2026 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* https://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package org.spockframework.compiler;

import org.codehaus.groovy.ast.ClassHelper;
import org.codehaus.groovy.classgen.BytecodeExpression;

import groovyjarjarasm.asm.MethodVisitor;
import groovyjarjarasm.asm.Opcodes;

/**
* A direct, delegate-independent reference to the closure that is currently being executed.
*
* <p>For implicit-{@code this} <em>method</em> conditions inside {@code with} / {@code verifyAll} /
* {@code verifyEach} closures, {@link org.spockframework.runtime.SpockRuntime#verifyMethodCondition}
* must be handed the closure itself as the {@code target}, so that method resolution routes through
* the closure's delegate (with fallback to the owner/spec).
*
* <p>Groovy has no source-level keyword for "the closure I am currently in": inside a closure body a
* value-context {@code this} compiles to {@code getThisObject()} (the enclosing spec), not the closure.
* Earlier Spock versions worked around this by emitting {@code this.find()} (and before that
* {@code this.each(Closure.IDENTITY)}), relying on a no-arg DGM resolving against the closure object.
* Groovy 6 (GROOVY-11858) resolves in-closure implicit-{@code this} calls against the delegate first,
* which broke that trick.
*
* <p>A closure's {@code doCall} method is always an instance method of the generated {@code Closure}
* subclass, so local variable 0 is the closure instance. Emitting {@code ALOAD 0} therefore yields the
* current closure directly, without depending on the meta-object protocol at all.
*/
class CurrentClosureExpression extends BytecodeExpression {

CurrentClosureExpression() {
super(ClassHelper.CLOSURE_TYPE);
}

@Override
public void visit(MethodVisitor mv) {
// load "this" of the enclosing doCall method, i.e. the closure instance itself
mv.visitVarInsn(Opcodes.ALOAD, 0);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@

import java.util.List;

import static org.codehaus.groovy.ast.expr.MethodCallExpression.NO_ARGUMENTS;
import static org.spockframework.compiler.condition.ImplicitConditionsUtils.checkIsValidImplicitCondition;
import static org.spockframework.compiler.condition.ImplicitConditionsUtils.isImplicitCondition;

Expand Down Expand Up @@ -242,16 +241,7 @@ private void replaceObjectExpressionWithCurrentClosure(ExpressionStatement stat)
MethodCallExpression methodCall = AstUtil.getExpression(stat, MethodCallExpression.class);
if (methodCall == null) return;

MethodCallExpression target = referenceToCurrentClosure();
methodCall.setObjectExpression(target);
}

private MethodCallExpression referenceToCurrentClosure() {
return new MethodCallExpression(
new VariableExpression("this"),
new ConstantExpression("find"),
NO_ARGUMENTS
);
methodCall.setObjectExpression(new CurrentClosureExpression());
}

private boolean handleMockCall(MethodCallExpression expr) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package org.spockframework.smoke

import org.spockframework.runtime.GroovyRuntimeUtil
import org.spockframework.runtime.SpockAssertionError
import spock.lang.*

Expand Down Expand Up @@ -131,6 +132,11 @@ class WithBlocks extends Specification {
}

@Issue('https://github.com/spockframework/spock/issues/886')
// The 'with' target (delegate) here is the static nested class 'Person', and 'checkCondition()' is an
// instance method of the spec (the closure owner). On Groovy 6, resolving an owner instance method via a
// static-nested-class delegate throws IllegalArgumentException instead of falling through to the owner.
// This is an upstream Groovy regression (see GROOVY-12045), unrelated to Spock's condition rewriting.
@IgnoreIf(value = { GroovyRuntimeUtil.MAJOR_VERSION >= 6 }, reason = "GROOVY-12045: static-nested-class delegate breaks owner method resolution")
def "with works with void methods"() {
given:
Person person = new Person()
Expand Down
Loading