Os pipelines Jenkins executam o código Groovy no estilo de passagem de continuação usando groovy-cps interpretador . Isso não é o Groovy de baunilha, você pode executar diretamente no IDE ou no Groovy Shell.
O Groovy CPS transforma seu código para oferecer suporte ao estilo de passagem de continuação e à expressão correta do Groovy, como:
a = b = c = 0
é transformado em algo que se parece mais com:
eval(
var("a"),
assign(
eval(
var("b"),
assign(
eval(
var("c"),
assign(0)
)
)
)
)
)
O problema com essa expressão no intérprete do CPS é que a atribuição não retorna nenhum valor e, portanto, o null
valor é atribuído à variável b
, e o mesmo ocorre com a variável a
.
Se você quiser se aprofundar no bloco de invocações do CPS, poderá clonar o projeto groovy-cps e escrever um caso de teste simples na com.cloudbees.groovy.cps.CpsTransformerTest
classe.
@Test
void testMultiVariablesInlineCPS() {
def cps = parseCps('''
int a, b, c
a = b = c = 0
''')
println cps
}
Em seguida, você pode colocar um ponto de interrupção no println cps
e executar o depurador. Ao abrir a janela de inspeção, você verá a imagem semelhante a esta:
Como uma observação lateral, lembre-se de que o compilador Groovy também transforma suas atribuições de linha única ao compilar o código no bytecode. Se você compilar um script Groovy simples como:
int a, b, c
a = b = c = 0
println "$a $b $c"
e, em seguida, você abre o arquivo de classe no IDE para descompilar o bytecode para o equivalente em Java. Você verá algo assim:
//
// 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[]{"", " ", " ", ""}));
}
}