neo-decompiler 0.10.1

Neo N3 NEF decompiler: parse, disassemble, lift bytecode to high-level pseudocode and C# skeletons, with a CLI, JSON reports, and optional WebAssembly bindings.
Documentation
use super::super::*;

#[test]
fn eliminate_fallthrough_gotos_strips_goto_followed_by_label() {
    let mut statements = vec![
        "let x = 1;".to_string(),
        "goto label_0x0010;".to_string(),
        "label_0x0010:".to_string(),
        "return x;".to_string(),
    ];

    HighLevelEmitter::eliminate_fallthrough_gotos(&mut statements);

    assert!(
        statements[1].is_empty(),
        "fallthrough goto should be cleared: {statements:?}"
    );
    // The label remains; remove_orphaned_labels (a separate pass) is what
    // strips it once it has no remaining references.
    assert_eq!(statements[2], "label_0x0010:");
}

#[test]
fn eliminate_fallthrough_gotos_strips_leave_followed_by_label() {
    // `leave` is the high-level encoding of an ENDTRY transfer. When the
    // resume target sits immediately after the `leave`, the transfer is a
    // visual no-op the C# / Rust backends would emit identical control
    // flow for, so it should be stripped just like the `goto` form.
    let mut statements = vec![
        "try {".to_string(),
        "    leave label_0x0008;".to_string(),
        "    label_0x0008:".to_string(),
        "}".to_string(),
        "finally {".to_string(),
        "}".to_string(),
    ];

    HighLevelEmitter::eliminate_fallthrough_gotos(&mut statements);

    assert!(
        statements[1].is_empty(),
        "fallthrough leave should be cleared: {statements:?}"
    );
}

#[test]
fn eliminate_fallthrough_gotos_strips_leave_through_close_braces() {
    // The leave is the last statement of a catch body; the label sits
    // immediately after the `}`. Walking past the close-brace finds the
    // label, so the transfer is dead — control reaches the label by
    // structural fall-out anyway.
    let mut statements = vec![
        "try {".to_string(),
        "}".to_string(),
        "catch {".to_string(),
        "    leave label_0x0009;".to_string(),
        "}".to_string(),
        "label_0x0009:".to_string(),
        "return;".to_string(),
    ];

    HighLevelEmitter::eliminate_fallthrough_gotos(&mut statements);

    assert!(
        statements[3].is_empty(),
        "leave at end of catch body should be cleared when label sits past `}}`: {statements:?}"
    );
}

#[test]
fn eliminate_fallthrough_gotos_keeps_leave_when_intervening_code_present() {
    // Same shape but with executable code between the closing brace and
    // the label — eliminating the leave would now skip that code,
    // changing semantics. The transfer must stay.
    let mut statements = vec![
        "catch {".to_string(),
        "    leave label_0x0010;".to_string(),
        "}".to_string(),
        "let x = 1;".to_string(),
        "label_0x0010:".to_string(),
        "return;".to_string(),
    ];

    HighLevelEmitter::eliminate_fallthrough_gotos(&mut statements);

    assert_eq!(
        statements[1].trim(),
        "leave label_0x0010;",
        "leave with intervening code must be preserved: {statements:?}"
    );
}

#[test]
fn eliminate_fallthrough_gotos_keeps_leave_when_target_is_distant() {
    let mut statements = vec![
        "leave label_0x0010;".to_string(),
        "let unreachable = 1;".to_string(),
        "label_0x0010:".to_string(),
        "return;".to_string(),
    ];

    HighLevelEmitter::eliminate_fallthrough_gotos(&mut statements);

    assert_eq!(
        statements[0], "leave label_0x0010;",
        "non-fallthrough leave must be preserved: {statements:?}"
    );
}