Jenkins-Pipelines führen Groovy-Code im Continuation-Passing-Stil mit dem Groovy-CPS- Interpreter aus. Dies ist kein Vanilla Groovy, den Sie direkt in der IDE oder in der Groovy Shell ausführen können.
Groovy CPS transformiert Ihren Code, um den Continuation-Passing-Stil und den korrekten Groovy-Ausdruck wie folgt zu unterstützen:
a = b = c = 0
verwandelt sich in etwas, das eher so aussieht:
eval(
var("a"),
assign(
eval(
var("b"),
assign(
eval(
var("c"),
assign(0)
)
)
)
)
)
Das Problem mit diesem Ausdruck im CPS-Interpreter besteht darin, dass die Zuweisung keinen null
Wert zurückgibt und der Wert daher der Variablen zugewiesen wird b
, und dasselbe passiert mit der Variablen a
.
Wenn Sie tiefer in den CPS-Aufrufblock eintauchen möchten, können Sie das groovy-cps-Projekt klonen und einen einfachen Testfall in die com.cloudbees.groovy.cps.CpsTransformerTest
Klasse schreiben .
@Test
void testMultiVariablesInlineCPS() {
def cps = parseCps('''
int a, b, c
a = b = c = 0
''')
println cps
}
Dann können Sie einen Haltepunkt am setzen println cps
und den Debugger ausführen. Wenn Sie das Inspektionsfenster öffnen, sehen Sie ein Bild ähnlich dem folgenden:
Beachten Sie als Randnotiz, dass der Groovy-Compiler auch Ihre einzeiligen Zuweisungen transformiert, wenn Sie den Code in den Bytecode kompilieren. Wenn Sie ein einfaches Groovy-Skript wie folgt kompilieren:
int a, b, c
a = b = c = 0
println "$a $b $c"
Wenn Sie dann die Klassendatei in der IDE öffnen, um den Bytecode in das Java-Äquivalent zu dekompilieren, wird Folgendes angezeigt:
//
// 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[]{"", " ", " ", ""}));
}
}