Le pipeline Jenkins eseguono il codice Groovy nello stile di passaggio di continuazione usando l' interprete groovy-cps . Questo non è vaniglia Groovy che puoi eseguire direttamente nell'IDE o in Groovy Shell.
Groovy CPS trasforma il tuo codice per supportare lo stile di passaggio di continuazione e l'espressione Groovy corretta come:
a = b = c = 0
si trasforma in qualcosa che assomiglia di più:
eval(
var("a"),
assign(
eval(
var("b"),
assign(
eval(
var("c"),
assign(0)
)
)
)
)
)
Il problema con questa espressione nell'interprete CPS è che l'assegnazione non restituisce alcun valore e quindi il null
valore viene assegnato alla variabile b
e la stessa cosa accade alla variabile a
.
Se vuoi scavare più a fondo nel blocco delle invocazioni CPS, puoi clonare il progetto groovy-cps e scrivere un semplice test case nella com.cloudbees.groovy.cps.CpsTransformerTest
classe.
@Test
void testMultiVariablesInlineCPS() {
def cps = parseCps('''
int a, b, c
a = b = c = 0
''')
println cps
}
Quindi puoi mettere un breakpoint in corrispondenza di println cps
ed eseguire il debugger. Quando apri la finestra di ispezione, vedrai l'immagine simile a questa:
Come nota a margine, tieni presente che il compilatore Groovy trasforma anche le assegnazioni a riga singola quando compili il codice in bytecode. Se compili un semplice script Groovy come:
int a, b, c
a = b = c = 0
println "$a $b $c"
e quindi apri il suo file di classe nell'IDE per decompilare il bytecode nell'equivalente Java, vedrai qualcosa del genere:
//
// 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[]{"", " ", " ", ""}));
}
}