use cure_engine::Config;
use cure_java_parser::parse;
use cure_java_simplify::simplify_unit;
use cure_java_print::print_unit;
fn run_src(src: &str) -> String {
let mut out = parse(src);
simplify_unit(&mut out.ast, &mut out.unit, &Config::default());
print_unit(&out.ast, &out.unit)
}
#[test]
fn null_arg_keeps_typed_var_form() {
let out = run_src(
r#"
public class NullArg {
public static void main(String[] args) {
String s = null;
StringBuilder sb = new StringBuilder();
sb.append(s);
System.out.println(sb.length());
}
}
"#,
);
assert!(
out.contains("sb.append(s);"),
"null 单次使用位于重载族实参位:必须保持变量形态(声明类型 = 消歧依据)\n{out}"
);
assert!(
!out.contains("append(null)"),
"append(null) 不可编译(CharSequence/char[] 二义)\n{out}"
);
}
#[test]
fn null_return_position_still_propagates() {
let out = run_src(
r#"
public class NullRet {
static String f(int x) {
String s = null;
if (x > 0) {
s = "pos";
}
return s;
}
public static void main(String[] args) {
System.out.println(f(1) + f(-1));
}
}
"#,
);
assert!(out.contains("return"), "return 必然保留\n{out}");
}
#[test]
fn null_cast_position_still_propagates() {
let out = run_src(
r#"
public class NullCast {
public static void main(String[] args) {
String s = null;
String t = (String) s;
System.out.println(t == null);
}
}
"#,
);
assert!(
!out.contains(") s;") || out.contains("(String) null"),
"Cast 位应放行内联((String) null 合法)\n{out}"
);
}
#[test]
fn while_iterator_opaque_type_stays_while() {
let out = run_src(
r#"
import java.util.Iterator;
import java.util.NoSuchElementException;
public class OpaqueSeqLoop {
static class Seq {
private final String[] items;
Seq(String[] items) { this.items = items; }
Iterator<String> iterator() {
return new Iterator<String>() {
int i = 0;
public boolean hasNext() { return i < items.length; }
public String next() {
if (!hasNext()) { throw new NoSuchElementException(); }
return items[i++];
}
};
}
}
static String firstNonEmpty(Seq seq) {
Iterator<String> it = seq.iterator();
while (it.hasNext()) {
String s = it.next();
if (s.length() > 0) {
return s;
}
}
return "";
}
public static void main(String[] args) {
Seq seq = new Seq(new String[] {"", "hit", "x"});
System.out.println(firstNonEmpty(seq));
}
}
"#,
);
assert!(
out.contains("while (it.hasNext())"),
"不透明 Iterable(非白名单类型)必须保留 while 形态\n{out}"
);
assert!(
!out.contains("for (String s : seq)"),
"for-each 对非 Iterable 类型不可编译\n{out}"
);
}
#[test]
fn while_iterator_typed_list_still_recovers() {
let out = run_src(
r#"
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class TypedListLoop {
static int total(List<String> names) {
Iterator<String> it = names.iterator();
int n = 0;
while (it.hasNext()) {
String s = it.next();
n += s.length();
}
return n;
}
public static void main(String[] args) {
List<String> names = new ArrayList<>();
names.add("alpha");
names.add("beta");
System.out.println(total(names));
}
}
"#,
);
assert!(
out.contains("for (String s : names)"),
"List 白名单类型应还原 for-each\n{out}"
);
}
#[test]
fn const_method_inline_owner_guard() {
let out = run_src(
r#"
public class ValOf {
static java.lang.Integer TRUE_C = java.lang.Integer.valueOf(-1);
static java.lang.Boolean valueOf(boolean p) {
return !p ? Boolean.FALSE : Boolean.TRUE;
}
static Object bare() {
return valueOf(false);
}
static Object qualified() {
return ValOf.valueOf(true);
}
public static void main(String[] args) {
System.out.println(TRUE_C + "" + bare() + qualified());
}
}
"#,
);
assert!(
out.contains("Integer.valueOf(-1)"),
"Integer.valueOf 必须原样保留(归属不符)\n{out}"
);
assert!(!out.contains("!-1"), "撞名误内联的坏形态不得出现\n{out}");
assert!(
out.contains("return Boolean.TRUE;"),
"同类裸名 valueOf(false) 应内联并折叠\n{out}"
);
assert!(
out.contains("return Boolean.FALSE;"),
"同类限定 ValOf.valueOf(true) 应内联并折叠\n{out}"
);
}
#[test]
fn enum_constant_shadows_outer_const_field() {
let out = run_src(
r#"
public class Enc {
private static final java.lang.String b17 = "hm";
public static enum E {
a, b17;
private static final Enc.E[] c;
private E() {}
static {
c = new Enc.E[] {a, b17};
}
}
public static void main(String[] args) {
System.out.println(b17 + E.c[1]);
}
}
"#,
);
assert!(
out.contains("new Enc.E[] {a, b17}"),
"枚举常量 b17 不得被外层同名字段字面量替换\n{out}"
);
assert!(
!out.contains("{a, \"hm\"}"),
"坏形态(枚举常量→字符串字面量)不得出现\n{out}"
);
}
#[test]
fn typed_var_not_inlined_into_cast_position() {
let out = run_src(
r#"
public class CastPos {
static Object src() { return null; }
public static void main(String[] args) {
Object obj5 = src();
String s = (String) obj5;
boolean b = obj5 instanceof java.lang.String;
System.out.println(s + b);
}
}
"#,
);
assert!(
out.contains("(String) obj5"),
"cast 操作数位的 Object 中转变量必须保持变量形态\n{out}"
);
assert!(
out.contains("obj5 instanceof"),
"instanceof 被测式位同理保持变量形态\n{out}"
);
}
#[test]
fn while_iterator_no_post_loop_reference() {
let out = run_src(
r#"
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class PostUse {
static java.util.List<String> saved;
static int consume(List<String> src) {
Iterator<String> it = src.iterator();
int n = 0;
while (it.hasNext()) {
n += it.next().length();
}
// 循环后引用 it(状态机保存块的形状)
String marker = (it == null) ? "x" : "y";
return n + marker.length();
}
public static void main(String[] args) {
List<String> src = new ArrayList<>();
src.add("alpha");
System.out.println(consume(src));
}
}
"#,
);
assert!(
out.contains("while (it.hasNext())"),
"循环后仍引用迭代器 → 不得还原 for-each(声明会被消费)\n{out}"
);
}
#[test]
fn ctor_delegation_hoist_with_inline() {
let out = run_src(
r#"
public class Hoist {
Hoist(long p1, long p2) {}
Hoist(long p1, long p2, int p3, Object marker) {
long v5;
long v6 = 0L;
v5 = (p3 & 1) == 0 ? p1 : 0L;
v6 = (p3 & 2) == 0 ? p2 : 9223372036854775807L;
this(v5, v6);
Object[] box = new Object[] { Long.valueOf(v5), Long.valueOf(v6) };
System.out.println(box.length);
}
public static void main(String[] args) {
new Hoist(1L, 2L);
}
}
"#,
);
assert!(
out.contains("this((p3 & 1) == 0 ? p1 : 0L, (p3 & 2) == 0 ? p2 : 9223372036854775807L);"),
"委托须在首位且实参内联三元\n{out}"
);
}
#[test]
fn ctor_delegation_hoist_rejects_impure_pre() {
let out = run_src(
r#"
public class NoHoist {
NoHoist(int a) {}
NoHoist(int p, Object m) {
side(p);
this(p);
}
static int side(int x) { return x + 1; }
public static void main(String[] args) { new NoHoist(1); }
}
"#,
);
let side_pos = out.find("side(p);").unwrap_or(usize::MAX);
let this_pos = out.find("this(p);").unwrap_or(usize::MAX);
assert!(
side_pos < this_pos,
"不纯前置(裸调用)不得被跨过提升\n{out}"
);
}
#[test]
fn ctor_delegation_hoist_recursive_arg() {
let out = run_src(
r#"
public class RecHoist {
RecHoist(int a, int b) {}
RecHoist(int p1, Object m) {
int v6 = 0;
v6 = p1 + 1;
this(p1, v6);
System.out.println(v6);
}
public static void main(String[] args) { new RecHoist(7); }
}
"#,
);
assert!(
out.contains("this(p1, p1 + 1);"),
"实参内联:this(p1, p1 + 1)\n{out}"
);
}