Jenkins pipelines execute Groovy code in the continuation-passing style using groovy-cps interpreter. This is not vanilla Groovy you can execute directly in the IDE or in Groovy Shell.
Groovy CPS transforms your code to support the continuation-passing style and the correct Groovy expression like:
a = b = c = 0
gets transformed to something that looks more like:
eval(
var("a"),
assign(
eval(
var("b"),
assign(
eval(
var("c"),
assign(0)
)
)
)
)
)
The problem with this expression in the CPS interpreter is that the assignment does not return any value, and thus the null
value gets assigned to the variable b
, and the same thing happens to the variable a
.
If you want to dig deeper in the CPS invocations block, you can clone groovy-cps project and write a simple test case in the com.cloudbees.groovy.cps.CpsTransformerTest
class.
@Test
void testMultiVariablesInlineCPS() {
def cps = parseCps('''
int a, b, c
a = b = c = 0
''')
println cps
}
Then you can put a breakpoint at the println cps
and run the debugger. When you open the inspection window, you will see the picture similar to this one:

As a side note, keep in mind that the Groovy compiler also transforms your single line assignments when compiled the code to the bytecode. If you compile a simple Groovy script like:
int a, b, c
a = b = c = 0
println "$a $b $c"
and then you open its class file in the IDE to decompile the bytecode to the Java equivalent, you will see something like this:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
import groovy.lang.Binding;
import groovy.lang.Script;
import org.codehaus.groovy.runtime.GStringImpl;
import org.codehaus.groovy.runtime.InvokerHelper;
import org.codehaus.groovy.runtime.callsite.CallSite;
public class test extends Script {
public test() {
CallSite[] var1 = $getCallSiteArray();
}
public test(Binding context) {
CallSite[] var2 = $getCallSiteArray();
super(context);
}
public static void main(String... args) {
CallSite[] var1 = $getCallSiteArray();
var1[0].call(InvokerHelper.class, test.class, args);
}
public Object run() {
CallSite[] var1 = $getCallSiteArray();
int a = 0;
int b = 0;
int c = 0;
byte var5 = 0;
return var1[1].callCurrent(this, new GStringImpl(new Object[]{Integer.valueOf(var5), Integer.valueOf(var5), Integer.valueOf(var5)}, new String[]{"", " ", " ", ""}));
}
}