// tools/hako_check/rules/rule_dead_static_box.hako — HC012: Dead Static Box // Detect static boxes that are never referenced from any code path. // Excludes Main box (entry point) and boxes referenced in calls. static box RuleDeadStaticBoxBox { // Local int_to_str helper (avoids using alias issues) _itoa(n) { local v = 0 + n if v == 0 { return "0" } local out = "" local digits = "0123456789" local tmp = "" loop (v > 0) { local d = v % 10 tmp = digits.substring(d, d+1) + tmp v = v / 10 } out = tmp return out } method apply_ir(ir, path, out) { local boxes = ir.get("boxes") if boxes == null { return 0 } local calls = ir.get("calls") if calls == null { return 0 } // Collect all box names that are referenced in calls local referenced_boxes = new MapBox() local ci = 0 while ci < calls.size() { local call = calls.get(ci) if call == null { ci = ci + 1; continue } local to = call.get("to") if to != null { // Extract box name from qualified call (e.g., "Box.method/0" -> "Box") local dot = to.indexOf(".") if dot > 0 { local box_name = to.substring(0, dot) referenced_boxes.set(box_name, "1") } } ci = ci + 1 } // Check each box local bi = 0 while bi < boxes.size() { local box_info = boxes.get(bi) if box_info == null { bi = bi + 1; continue } local name = box_info.get("name") if name == null { bi = bi + 1; continue } local is_static = box_info.get("is_static") // Skip Main box (entry point) if name == "Main" { bi = bi + 1; continue } // Only check static boxes if is_static == null || is_static == 0 { bi = bi + 1; continue } // Check if box is referenced - if not in map, it returns "[map/missing]" StringBox local ref_check = referenced_boxes.get(name) // If ref_check is null or doesn't equal "1", box is unreferenced if ref_check == null || ref_check != "1" { // Box is never referenced - report error // Line precision: prefer span_line from AST intake if present local line = box_info.get("span_line") if line == null { line = 1 } out.push("[HC012] dead static box (never referenced): " + name + " :: path:" + me._itoa(line)) } bi = bi + 1 } return out.size() } } static box RuleDeadStaticBoxMain { method main(args) { return 0 } }