Jenkinsパイプラインは、groovy-cpsインタープリターを使用して、継続渡しスタイルでGroovyコードを実行します。これは、IDEまたはGroovy Shellで直接実行できる単純なGroovyではありません。
Groovy CPSはコードを変換して、継続渡しスタイルと次のような正しいGroovy式をサポートします。
a = b = c = 0
より似たものに変換されます:
eval(
var("a"),
assign(
eval(
var("b"),
assign(
eval(
var("c"),
assign(0)
)
)
)
)
)
CPSインタープリターでのこの式の問題は、割り当てが値を返さないため、null
値が変数b
に割り当てられ、同じことが変数にも発生することですa
。
CPS呼び出しブロックをさらに掘り下げたい場合は、groovy-cpsプロジェクトのクローンを作成し、com.cloudbees.groovy.cps.CpsTransformerTest
クラスに簡単なテストケースを記述できます。
@Test
void testMultiVariablesInlineCPS() {
def cps = parseCps('''
int a, b, c
a = b = c = 0
''')
println cps
}
次に、ブレークポイントをに置いprintln cps
てデバッガを実行できます。検査ウィンドウを開くと、次のような画像が表示されます。
ちなみに、Groovyコンパイラーは、コードをバイトコードにコンパイルするときに単一行の割り当ても変換することに注意してください。次のような単純なGroovyスクリプトをコンパイルすると、
int a, b, c
a = b = c = 0
println "$a $b $c"
次に、そのクラスファイルをIDEで開いて、バイトコードをJavaの同等のものに逆コンパイルすると、次のようになります。
//
// 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[]{"", " ", " ", ""}));
}
}