pub struct JavaAst {
pub const_fields: HashMap<String, JavaId>,
pub const_scalars: HashSet<String>,
pub noop_private_methods: HashMap<String, HashMap<usize, Vec<NoopCandidate>>>,
pub field_types: HashMap<String, JType>,
pub unit_shadows_lang: bool,
pub raw_generic_names: HashSet<String>,
pub final_fields: HashSet<String>,
pub inline_methods: HashMap<String, (Vec<String>, JavaId, String)>,
pub unit_string_identity: bool,
/* private fields */
}Expand description
Java AST arena。只追加不回收,JavaId 永不失效。
Fields§
§const_fields: HashMap<String, JavaId>类级常量字段(static final 且字面量/字面量数组初始化、无写、无同名局部) → 初始化节点。由 simplify_unit 填充(跨方法解密的字符串表)。
const_scalars: HashSet<String>可安全做 VarRef → 字面量传播的常量字段名(标量字面量且声明类型 与字面量种类精确匹配——过载解析/常量池身份不受影响)。 数组常量不进(只走下标折叠,整表引用不复制)。
noop_private_methods: HashMap<String, HashMap<usize, Vec<NoopCandidate>>>空私有方法(no-op 调用清理用):名字 → 元数 → 同名同元数全部 候选(参数类型表 + 是否 private 空体)。调用点做类型适用性消解 (唯一适用者且为 private 空体 → no-op)。同名任意方法含 varargs → 该名整体放弃(varargs 可吸收任意元数)。由 simplify_unit 填充 (–dead-code 门控)。
field_types: HashMap<String, JType>字段声明类型表(名字 → JType;同名二见移除)——调用点实参静态 类型解析用(VarRef 解析不到局部时查字段)。collect_unit_consts 填充。
unit_shadows_lang: bool本单元声明了名为 String/StringBuilder 的类型(遮蔽 java.lang——
new String(“x”) 折叠/字符串链折叠在该单元全部拒绝。探针 T4a/b
抓获:class String{…} 同文件时 new String 折叠产出不可编译或
静默错值)。collect_unit_consts 每轮重算。
raw_generic_names: HashSet<String>已知为泛型的类型简单名(单元内带 ty_params 的类型 + 常见 JDK 泛型库类)。raw 引用(无类型实参)这些名字时,接收位传播 改变成员解析(raw 擦除 vs 泛型形参——CAP#1 编译错)。
final_fields: HashSet<String>final 字段名集合(同名二见移除——保守)。static_exec 截断守卫 用:前缀字段写被 rest 再赋值时,仅 final 才放弃(非 final 的 材料化写是死写,语义恒等、可编译)。
inline_methods: HashMap<String, (Vec<String>, JavaId, String)>可内联的单 return 方法:名字 → (参数名表, 返回表达式节点, 声明 该方法的类的简单名)。owner 供 const_method_inline 的归属守卫: 限定调用的接收者类名必须与之一致——名字匹配不判归属会把 JDK 的 Integer.valueOf 当本类同名方法内联。由 simplify_unit 填充(解密 helper:d(0) → 方法体)。
unit_string_identity: bool单元级 String 身份比较存在标志(collect_unit_consts 每轮重算)。 new String(lit) 解包为池化字面量会翻转任何 == 观察点——字段 init 解包的观察点在其他方法里(InputNoWhitespaceAfterWithEmoji 抓获 合成证实:a == “hello” false→true),单根扫描看不见 → 单元级守卫。
Implementations§
Source§impl JavaAst
impl JavaAst
pub fn new() -> Self
Sourcepub fn clone_node(&mut self, id: JavaId, children: Vec<JavaId>) -> JavaId
pub fn clone_node(&mut self, id: JavaId, children: Vec<JavaId>) -> JavaId
以 node 的负载 + 指定 children 构造新节点(深拷贝/替换用)。
pub fn node(&self, id: JavaId) -> &Node
pub fn data(&self, id: JavaId) -> &NodeData
Sourcepub fn node_count(&self) -> usize
pub fn node_count(&self) -> usize
arena 节点总数(诊断/深度测量用)。
pub fn children(&self, id: JavaId) -> &[JavaId]
pub fn block(&mut self, stmts: Vec<JavaId>) -> JavaId
pub fn empty(&mut self) -> JavaId
pub fn expr_stmt(&mut self, e: JavaId) -> JavaId
pub fn var_decl( &mut self, name: &str, ty: JType, init: Option<JavaId>, ) -> JavaId
Sourcepub fn var_decl_final(
&mut self,
name: &str,
ty: JType,
init: Option<JavaId>,
final_mod: bool,
) -> JavaId
pub fn var_decl_final( &mut self, name: &str, ty: JType, init: Option<JavaId>, final_mod: bool, ) -> JavaId
final 局部声明(JLS 4.12.4:case 标签常量的必要条件——
final 局部删除曾致 case ARRAY_BOUND: 失去常量性不可编译,
LargeFile.java 抓获)。
pub fn assign(&mut self, target: JavaId, value: JavaId) -> JavaId
pub fn assign_op(&mut self, op: BinOp, target: JavaId, value: JavaId) -> JavaId
pub fn if_(&mut self, cond: JavaId, then: JavaId, els: Option<JavaId>) -> JavaId
pub fn while_(&mut self, cond: JavaId, body: JavaId) -> JavaId
pub fn do_while(&mut self, body: JavaId, cond: JavaId) -> JavaId
pub fn for_( &mut self, inits: Vec<JavaId>, cond: Option<JavaId>, steps: Vec<JavaId>, body: JavaId, ) -> JavaId
pub fn for_each( &mut self, name: &str, ty: JType, iterable: JavaId, body: JavaId, ) -> JavaId
pub fn yield_(&mut self, expr: JavaId) -> JavaId
pub fn ret(&mut self, value: Option<JavaId>) -> JavaId
pub fn break_(&mut self, label: Option<&str>) -> JavaId
pub fn continue_(&mut self, label: Option<&str>) -> JavaId
pub fn throw(&mut self, e: JavaId) -> JavaId
pub fn try_( &mut self, resources: Vec<JavaId>, try_block: JavaId, catches: Vec<JavaId>, finally: Option<JavaId>, ) -> JavaId
pub fn catch_(&mut self, ty_raw: &str, name: &str, block: JavaId) -> JavaId
pub fn synchronized(&mut self, lock: JavaId, block: JavaId) -> JavaId
pub fn switch_(&mut self, subject: JavaId, cases: Vec<JavaId>) -> JavaId
pub fn case_( &mut self, labels: Vec<JavaId>, is_default: bool, arrow: bool, stmts: Vec<JavaId>, ) -> JavaId
pub fn label(&mut self, name: &str, stmt: JavaId) -> JavaId
pub fn assert_(&mut self, cond: JavaId, msg: Option<JavaId>) -> JavaId
pub fn raw(&mut self, text: &str) -> JavaId
pub fn bin(&mut self, op: BinOp, l: JavaId, r: JavaId) -> JavaId
pub fn un(&mut self, op: UnOp, e: JavaId) -> JavaId
pub fn call(&mut self, callee: JavaId, args: Vec<JavaId>) -> JavaId
pub fn member(&mut self, obj: JavaId, name: &str) -> JavaId
pub fn index(&mut self, arr: JavaId, idx: JavaId) -> JavaId
pub fn cast(&mut self, ty: JType, e: JavaId) -> JavaId
pub fn paren(&mut self, e: JavaId) -> JavaId
pub fn ternary(&mut self, c: JavaId, a: JavaId, b: JavaId) -> JavaId
pub fn new_(&mut self, ty: JType, args: Vec<JavaId>) -> JavaId
pub fn new_anon( &mut self, ty: JType, args: Vec<JavaId>, body_raw: String, ) -> JavaId
pub fn new_array( &mut self, ty: JType, dims: u16, sized: u16, sizes: Vec<JavaId>, init: Option<JavaId>, ) -> JavaId
pub fn array_lit(&mut self, elems: Vec<JavaId>) -> JavaId
pub fn var(&mut self, name: &str) -> JavaId
pub fn lit(&mut self, l: Lit) -> JavaId
pub fn this(&mut self) -> JavaId
pub fn super_(&mut self) -> JavaId
pub fn instance_of( &mut self, e: JavaId, ty: JType, bind: Option<&str>, ) -> JavaId
pub fn lambda(&mut self, params_raw: &str, body: JavaId) -> JavaId
pub fn method_ref(&mut self, receiver: JavaId, name: &str) -> JavaId
Sourcepub fn method_call(
&mut self,
obj: JavaId,
name: &str,
args: Vec<JavaId>,
) -> JavaId
pub fn method_call( &mut self, obj: JavaId, name: &str, args: Vec<JavaId>, ) -> JavaId
obj.name(args…) 调用。
Sourcepub fn plain_call(&mut self, name: &str, args: Vec<JavaId>) -> JavaId
pub fn plain_call(&mut self, name: &str, args: Vec<JavaId>) -> JavaId
裸方法调用 name(args…)(隐式 this / static)。
Sourcepub fn any_string_identity(&self, roots: &[JavaId]) -> bool
pub fn any_string_identity(&self, roots: &[JavaId]) -> bool
root 子树内是否存在「两侧都可能为 String」的 ==/!=(引用比较)? 折叠守卫用:new String(lit)/常量链等产出池化字面量会改变 == 语义。 结果按 (root, prepare 代次) 缓存——prepare 每次改树后清空, 首次查询全扫一次,同轮内所有守卫调用复用。 多根扫描:任一根存在 String 身份比较。
pub fn has_string_identity_compare(&self, root: JavaId) -> bool
Sourcepub fn set_param_scope(&mut self, params: &[(String, JType)])
pub fn set_param_scope(&mut self, params: &[(String, JType)])
设置当前方法的参数类型表(作为根作用域参与解析)。
Sourcepub fn is_param_name(&self, name: &str) -> bool
pub fn is_param_name(&self, name: &str) -> bool
名字是否为当前方法参数(虚拟执行的字段写守卫——参数写不得 误记为字段写)。
Sourcepub fn name_of_key(&self, k: u32) -> Option<String>
pub fn name_of_key(&self, k: u32) -> Option<String>
名字键 → 名字反查(虚拟执行的字段写材料化)。
pub fn clear_param_scope(&mut self)
Trait Implementations§
Source§impl Lang for JavaAst
impl Lang for JavaAst
Source§fn prepare(&mut self, root: JavaId)
fn prepare(&mut self, root: JavaId)
重建缓存:
- 效果表——arena 按升序扫描(child index < parent index 不变量);
- 变量类型表——从 root 做作用域栈遍历。
Source§type NameKey = u32
type NameKey = u32
fn kind(&self, id: JavaId) -> NodeKind
fn children(&self, id: JavaId) -> &[JavaId]
Source§fn set_child(&mut self, parent: JavaId, index: usize, new: JavaId)
fn set_child(&mut self, parent: JavaId, index: usize, new: JavaId)
parent 的第 index 个孩子替换为 new。Source§fn remove_child(&mut self, parent: JavaId, index: usize)
fn remove_child(&mut self, parent: JavaId, index: usize)
parent 的第 index 个孩子。Source§fn splice(
&mut self,
node: JavaId,
index: usize,
remove: usize,
insert: Vec<JavaId>,
)
fn splice( &mut self, node: JavaId, index: usize, remove: usize, insert: Vec<JavaId>, )
node 的第 index 个孩子开始删 remove 个、插入 insert。fn build_return(&mut self, value: Option<JavaId>) -> JavaId
fn build_block(&mut self, stmts: Vec<JavaId>) -> JavaId
fn build_unary(&mut self, op: UnOp, operand: JavaId) -> JavaId
fn build_bool(&mut self, v: bool) -> JavaId
Source§fn build_int(&mut self, v: i64, long: bool) -> JavaId
fn build_int(&mut self, v: i64, long: bool) -> JavaId
long 为 true 时带 L 语义。Source§fn build_char(&mut self, c: char) -> JavaId
fn build_char(&mut self, c: char) -> JavaId
(char)('a'+1) → ‘b’)。Source§fn build_bin(&mut self, op: BinOp, l: JavaId, r: JavaId) -> JavaId
fn build_bin(&mut self, op: BinOp, l: JavaId, r: JavaId) -> JavaId
Source§fn build_ternary(&mut self, c: JavaId, a: JavaId, b: JavaId) -> JavaId
fn build_ternary(&mut self, c: JavaId, a: JavaId, b: JavaId) -> JavaId
c ? a : b(if→ternary 归并)。Source§fn build_assign(&mut self, target: JavaId, value: JavaId) -> JavaId
fn build_assign(&mut self, target: JavaId, value: JavaId) -> JavaId
target = value(if→三元赋值归并)。Source§fn fold_lit_bin(&mut self, op: BinOp, l: JavaId, r: JavaId) -> Option<JavaId>
fn fold_lit_bin(&mut self, op: BinOp, l: JavaId, r: JavaId) -> Option<JavaId>
+ - * / % << >> >>> & | ^)
与字符串拼接。操作数为字面量节点 id;返回折叠产物节点。Source§fn fold_lit_cmp(&mut self, op: BinOp, l: JavaId, r: JavaId) -> Option<bool>
fn fold_lit_cmp(&mut self, op: BinOp, l: JavaId, r: JavaId) -> Option<bool>
1 < 2)。可比较的字面量种类与字符串比较
语义(引用比较 vs 值比较)由语言侧决定;返回布尔结果。Source§fn fold_lit_neg(&mut self, v: i64, wide: bool) -> Option<i64>
fn fold_lit_neg(&mut self, v: i64, wide: bool) -> Option<i64>
-(-lit) 外层负消除)。宽度溢出时必须
返回 None 拒绝折叠(如 Java i32 的 -(-2147483648))。
默认实现按 i64 拒绝 i64::MIN 取反(防 debug panic / release 回绕)。Source§fn reassoc_delta(
&mut self,
op1: BinOp,
k1: i64,
op2: BinOp,
k2: i64,
wide: bool,
) -> Option<ReassocOutcome<JavaId>>
fn reassoc_delta( &mut self, op1: BinOp, k1: i64, op2: BinOp, k2: i64, wide: bool, ) -> Option<ReassocOutcome<JavaId>>
(x op1 K1) op2 K2 的常量合并结果。
语言侧负责宽度回绕(Java i32 的 K1+K2 溢出必须回绕,否则
产物是非法字面量)。Source§fn copy_subtree(&mut self, id: JavaId) -> JavaId
fn copy_subtree(&mut self, id: JavaId) -> JavaId
Source§fn invalidate_effect(&mut self, id: JavaId)
fn invalidate_effect(&mut self, id: JavaId)
id 的聚合效果缓存失效(若有)。引擎在同 pass 批量应用编辑后
沿祖先链调用——祖先的聚合效果含被改子树,必须失效,
后续 effect() 读取回退为按需重算(子缓存仍有效,代价 O(孩子数))。
默认空实现:无缓存的语言每次现算,天然正确。Source§fn debug_verify_events(&self, stmt: JavaId)
fn debug_verify_events(&self, stmt: JavaId)
id 子树的区域事件序列(使用索引,prepare 期间预计算)。
事件序必须等于 scan_region 原递归的遍历序;返回 None 表示该
节点无索引(未构建/已失效)——scan_region 回退为原递归遍历。
引擎在应用编辑后沿祖先链调用 invalidate_effect 使索引失效。
事件索引一致性自检(惰性重建 B3 调试):默认空实现。fn region_events(&self, id: JavaId) -> Option<&[RegionEvent<JavaId, u32>]>
Source§fn var_key(&self, id: JavaId) -> Option<u32>
fn var_key(&self, id: JavaId) -> Option<u32>
Source§fn node_index(&self, id: JavaId) -> usize
fn node_index(&self, id: JavaId) -> usize
Source§fn id_of_index(&self, idx: usize) -> JavaId
fn id_of_index(&self, idx: usize) -> JavaId
node_index 的逆映射(下标 → Id)。cure-tree 工具包的线性
扫描(效果表重建、名字键扩展)需要按 arena 下标遍历。Source§fn is_opaque(&self, id: JavaId) -> bool
fn is_opaque(&self, id: JavaId) -> bool
Source§fn own_effect(&self, id: JavaId) -> Effect
fn own_effect(&self, id: JavaId) -> Effect
Source§fn is_exact_int(&self, id: JavaId) -> bool
fn is_exact_int(&self, id: JavaId) -> bool
Source§fn is_local_var(&self, id: JavaId) -> bool
fn is_local_var(&self, id: JavaId) -> bool
Source§fn is_inferred_decl(&self, decl: JavaId) -> bool
fn is_inferred_decl(&self, decl: JavaId) -> bool
var)。推断声明剥除 init 后
变成 var x;——非法源码(obf_fuzz 差分抓获)。剥 init 类规则
必须拒绝。默认 false。Source§fn is_char_decl(&self, decl: JavaId) -> bool
fn is_char_decl(&self, decl: JavaId) -> bool
char c = 98; println(c) 打印 ‘b’,而内联成 println(98) 打印
98——静态类型可被 println / 字符串拼接观察。窄域规则(如
local_propagation)须拒绝非 Char 字面量值出字符声明。Source§fn has_pattern_bindings(&self, root: JavaId) -> bool
fn has_pattern_bindings(&self, root: JavaId) -> bool
Source§fn is_long_decl(&self, decl: JavaId) -> bool
fn is_long_decl(&self, decl: JavaId) -> bool
b += K ≡ b = (byte)(b + K))——把 delta 折回声明会产出
非法(超域常量)或变义(丢静态类型:char ch = 99 内联进
println 打数字而非字符)的字面量。默认 true(宽域语言)。fn is_wide_decl(&self, decl: JavaId) -> bool
Source§fn receiver_propagation_unsound(
&self,
decl: JavaId,
value: JavaId,
use_parent: Option<JavaId>,
use_at_head: bool,
) -> bool
fn receiver_propagation_unsound( &self, decl: JavaId, value: JavaId, use_parent: Option<JavaId>, use_at_head: bool, ) -> bool
List l = m(); l.add("x") 的 raw 擦除收 Object,内联成
m().add("x") 后按泛型收 CAP#1 → javac 硬错——mockito
ReturningDefaultValuesTest 抓获)。仅接收位敏感(实参位 raw↔
泛型双向兼容)。默认 false(无 raw 泛型的语言)。fn bin_op(&self, id: JavaId) -> Option<BinOp>
fn un_op(&self, id: JavaId) -> Option<UnOp>
fn literal(&self, id: JavaId) -> Option<LitRef<'_>>
Source§fn var_name(&self, id: JavaId) -> Option<&str>
fn var_name(&self, id: JavaId) -> Option<&str>
Source§fn member_name(&self, id: JavaId) -> Option<&str>
fn member_name(&self, id: JavaId) -> Option<&str>
Source§fn is_field_name(&self, name: &str) -> bool
fn is_field_name(&self, name: &str) -> bool
Source§fn payload_equal(&self, a: JavaId, b: JavaId) -> bool
fn payload_equal(&self, a: JavaId, b: JavaId) -> bool
cond ? new FairSync() : new NonfairSync()(参数相同、类型不同)判相等折叠:JDK 语料
90 处真实误折(ReentrantReadWriteLock 锁公平性、DirectByteBuffer
字节序、instanceof 守卫 cast → CCE,5 例运行时行为改变证实)。