เจนกินส์ตีความการประกาศวัตถุหลายรายการในหนึ่งบรรทัด


9

นี่ไม่ใช่คำถาม แต่เป็นคำเตือน: ฉันพยายามประหยัดพื้นที่และประกาศตัวแปรของฉันใน Jenkins Declarative Pipeline เช่น:

int a, b, c

จากนั้นฉันเริ่มต้นพวกเขาเป็น:

a = b = c = 0

ในรหัสของฉันฉันใช้จำนวนเต็มเหล่านี้เป็นตัวนับใน for-loop สคริปต์ของฉันยังคงล้มเหลวซ้ำไปซ้ำมามีข้อยกเว้นบางอย่างเกิดขึ้น:

java.lang.NullPointerException: Cannot invoke method next() on null object

และฉันรู้แน่นอนว่ารายการของฉันถูกต้องเพราะมันเป็นรหัสยาก ดังนั้นฉันเริ่มสงสัยว่าเกิดอะไรขึ้นกับเคาน์เตอร์เหล่านี้และเมื่อฉันโทรหา getClass () กับพวกเขาเจนกินส์บอกฉันอย่างมีความสุขว่าพวกเขาไม่ใช่จำนวนเต็ม แต่ค่อนข้าง

org.codehaus.groovy.runtime.NullObject

หลังจากเปลี่ยนรหัสเป็น

int a = 0
int b = 0
int c = 0

ทุกอย่างทำงานเหมือนมีเสน่ห์ แค่อยากจะแบ่งปันสิ่งนี้ บางทีมันอาจช่วยให้ใครบางคนประหยัดความหงุดหงิด

คำตอบ:


12

Jenkins pipelines รันโค้ด Groovy ในรูปแบบการส่งต่อโดยใช้ล่ามgroovy-cps นี่ไม่ใช่วานิลลา Groovy คุณสามารถดำเนินการโดยตรงใน IDE หรือใน Groovy Shell

Groovy CPS แปลงรหัสของคุณเพื่อสนับสนุนรูปแบบการส่งต่อและนิพจน์ Groovy ที่ถูกต้องเช่น:

a = b = c = 0

ได้รับการเปลี่ยนเป็นสิ่งที่ดูเหมือน:

eval(
  var("a"), 
  assign(
    eval(
      var("b"), 
      assign(
        eval(
          var("c"), 
          assign(0)
        )
      )
    )
  )
)

ปัญหาเกี่ยวกับการแสดงออกในล่าม CPS ที่เป็นที่ได้รับมอบหมายไม่ได้กลับค่าใด ๆ และทำให้nullค่าที่ได้รับมอบหมายให้ตัวแปรและสิ่งเดียวกันที่เกิดขึ้นให้กับตัวแปรba

หากคุณต้องการขุดลึกลงไปในบล็อกการเรียกใช้ 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 จะแปลงการมอบหมายบรรทัดเดียวของคุณเมื่อรวบรวมรหัสเป็น bytecode หากคุณรวบรวมสคริปต์ Groovy ง่ายๆเช่น:

int a, b, c
a = b = c = 0

println "$a $b $c"

จากนั้นคุณเปิดไฟล์คลาสใน IDE เพื่อคอมไพล์โค้ดไบต์ให้เทียบเท่าจาวาคุณจะเห็นดังนี้:

//
// 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[]{"", " ", " ", ""}));
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.