From e6f1f6f9ea1104e0396a88b95a5989a44ef93f38 Mon Sep 17 00:00:00 2001 From: ktkk Date: Tue, 23 Jun 2026 15:04:17 +0000 Subject: [PATCH] Refactor field, method and attribute formatting --- src/Class.zig | 433 +++++++++++++++++++++++++------------------------- 1 file changed, 220 insertions(+), 213 deletions(-) diff --git a/src/Class.zig b/src/Class.zig index d4411c7..d5fb701 100644 --- a/src/Class.zig +++ b/src/Class.zig @@ -257,34 +257,7 @@ pub fn format(self: *const Self, w: *std.Io.Writer) std.Io.Writer.Error!void { try w.splatByteAll(' ', depth * indent); try w.print("{d}:\n", .{ i }); - - indent += 1; - defer indent -= 1; - - try w.splatByteAll(' ', depth * indent); - try w.print("flags: {f}\n", .{ field.access_flags }); - - try w.splatByteAll(' ', depth * indent); - _ = try w.write("name:\n"); - const field_name = field.name(self.constant_pool) catch return error.WriteFailed; - try field_name.format(w, depth, indent + 1, self.constant_pool); - - try w.splatByteAll(' ', depth * indent); - _ = try w.write("descriptor:\n"); - const field_descriptor = field.descriptor(self.constant_pool) catch return error.WriteFailed; - try field_descriptor.format(w, depth, indent + 1, self.constant_pool); - - try w.splatByteAll(' ', depth * indent); - _ = try w.write("attributes:\n"); - for (field.attributes, 0..) |*attribute, j| { - indent += 1; - defer indent -= 1; - - try w.splatByteAll(' ', depth * indent); - try w.print("{d}:\n", .{ j }); - - try self.formatAttribute(w, depth, indent + 1, attribute); - } + try field.format(w, depth, indent + 1, self.allocator, self.constant_pool); } _ = try w.write("methods:\n"); @@ -294,34 +267,7 @@ pub fn format(self: *const Self, w: *std.Io.Writer) std.Io.Writer.Error!void { try w.splatByteAll(' ', depth * indent); try w.print("{d}:\n", .{ i }); - - indent += 1; - defer indent -= 1; - - try w.splatByteAll(' ', depth * indent); - try w.print("flags: {f}\n", .{ method.access_flags }); - - try w.splatByteAll(' ', depth * indent); - _ = try w.write("name:\n"); - const method_name = method.name(self.constant_pool) catch return error.WriteFailed; - try method_name.format(w, depth, indent + 1, self.constant_pool); - - try w.splatByteAll(' ', depth * indent); - _ = try w.write("descriptor:\n"); - const method_descriptor = method.descriptor(self.constant_pool) catch return error.WriteFailed; - try method_descriptor.format(w, depth, indent + 1, self.constant_pool); - - try w.splatByteAll(' ', depth * indent); - _ = try w.write("attributes:\n"); - for (method.attributes, 0..) |*attribute, j| { - indent += 1; - defer indent -= 1; - - try w.splatByteAll(' ', depth * indent); - try w.print("{d}:\n", .{ j }); - - try self.formatAttribute(w, depth, indent + 1, attribute); - } + try method.format(w, depth, indent + 1, self.allocator, self.constant_pool); } _ = try w.write("attributes:\n"); @@ -331,163 +277,7 @@ pub fn format(self: *const Self, w: *std.Io.Writer) std.Io.Writer.Error!void { try w.splatByteAll(' ', depth * indent); try w.print("{d}:\n", .{ i }); - - try self.formatAttribute(w, depth, indent + 1, attribute); - } -} - -fn formatAttribute(self: *const Self, w: *std.Io.Writer, depth: usize, indent: u8, attribute: *const AttributeInfo) std.Io.Writer.Error!void { - try w.splatByteAll(' ', depth * indent); - _ = try w.write("name:\n"); - const attribute_name = attribute.attributeName(self.constant_pool) catch return error.WriteFailed; - try attribute_name.format(w, depth, indent + 1, self.constant_pool); - - var predefined = attribute.resolve(self.allocator, self.constant_pool) catch return error.WriteFailed; - if (predefined) |*p| { - defer p.deinit(self.allocator); - - try w.splatByteAll(' ', depth * indent); - _ = try w.write("predefined: yes\n"); - - try w.splatByteAll(' ', depth * indent); - try w.print("type: {s}\n", .{ @tagName(p.*) }); - - switch (p.*) { - .constant_value => |attr| { - const constant_value = attr.constantValue(self.constant_pool) catch return error.WriteFailed; - try constant_value.format(w, depth, indent + 1, self.constant_pool); - }, - .code => |attr| { - try w.splatByteAll(' ', depth * indent); - try w.print("max_stack: {d}\n", .{ attr.max_stack }); - - try w.splatByteAll(' ', depth * indent); - try w.print("max_locals: {d}\n", .{ attr.max_locals }); - - try w.splatByteAll(' ', depth * indent); - _ = try w.write("code:\n"); - var instr_indent = indent; - for (attr.code, 0..) |instr, i| { - instr_indent += 1; - defer instr_indent -= 1; - - try w.splatByteAll(' ', depth * instr_indent); - try w.print("{d}: 0x{x}\n", .{ i, instr }); - } - - //try w.splatByteAll(' ', depth * indent); - //_ = try w.write("exception_table:\n"); - //var exception_indent = indent; - //for (attr.exception_table, 0..) |*exception, i| { - // exception_indent += 1; - // defer exception_indent -= 1; - - // try w.splatByteAll(' ', depth * exception_indent); - // try w.print("{d}:\n", .{ i }); - - // try self.formatExceptionHandler(w, depth, exception_indent + 1, exception); - //} - - try w.splatByteAll(' ', depth * indent); - _ = try w.write("attributes:\n"); - var attr_indent = indent; - for (attr.attributes, 0..) |*a, i| { - attr_indent += 1; - defer attr_indent -= 1; - - try w.splatByteAll(' ', depth * attr_indent); - try w.print("{d}:\n", .{ i }); - - try self.formatAttribute(w, depth, attr_indent + 1, a); - } - }, - //.stack_map_table, - .exceptions => |attr| { - try w.splatByteAll(' ', depth * indent); - _ = try w.write("exceptions:\n"); - var attr_indent = indent; - for (attr.exception_index_table, 0..) |exception, i| { - attr_indent += 1; - defer attr_indent -= 1; - - if (exception >= self.constant_pool.len) return error.WriteFailed; - const cp_info = self.constant_pool[exception - 1]; - if (cp_info == null or @as(CpInfo.Tag, cp_info.?) != .class) return error.WriteFailed; - - try w.splatByteAll(' ', depth * attr_indent); - try w.print("{d}:\n", .{ i }); - try cp_info.?.format(w, depth, attr_indent + 1, self.constant_pool); - } - }, - .inner_classes => |attr| { - try w.splatByteAll(' ', depth * indent); - _ = try w.write("classes:\n"); - var inner_classes_indent = indent; - for (attr.classes) |*class| { - inner_classes_indent += 1; - defer inner_classes_indent -= 1; - - const inner_class = class.innerClass(self.constant_pool) catch return error.WriteFailed; - try w.splatByteAll(' ', depth * inner_classes_indent); - _ = try w.write("inner_class:\n"); - try inner_class.format(w, depth, inner_classes_indent + 1, self.constant_pool); - - const outer_class = class.outerClass(self.constant_pool) catch return error.WriteFailed; - if (outer_class) |oc| { - try w.splatByteAll(' ', depth * inner_classes_indent); - _ = try w.write("outer_class:\n"); - try oc.format(w, depth, inner_classes_indent + 1, self.constant_pool); - } - - const inner_name = class.innerName(self.constant_pool) catch return error.WriteFailed; - if (inner_name) |in| { - try w.splatByteAll(' ', depth * inner_classes_indent); - _ = try w.write("inner_name:\n"); - try in.format(w, depth, inner_classes_indent + 1, self.constant_pool); - } - - try w.splatByteAll(' ', depth * inner_classes_indent); - try w.print("flags: {f}\n", .{ class.inner_class_access_flags }); - } - }, - .enclosing_method => |attr| { - const class = attr.class(self.constant_pool) catch return error.WriteFailed; - try w.splatByteAll(' ', depth * indent); - _ = try w.write("class:\n"); - try class.format(w, depth, indent + 1, self.constant_pool); - - const method = attr.method(self.constant_pool) catch return error.WriteFailed; - if (method) |m| { - try w.splatByteAll(' ', depth * indent); - _ = try w.write("method:\n"); - try m.format(w, depth, indent + 1, self.constant_pool); - } - }, - .synthetic => {}, - .signature => |attr| { - const signature = attr.signature(self.constant_pool) catch return error.WriteFailed; - try signature.format(w, depth, indent + 1, self.constant_pool); - }, - .source_file => |attr| { - const source_file = attr.sourceFile(self.constant_pool) catch return error.WriteFailed; - try source_file.format(w, depth, indent + 1, self.constant_pool); - }, - //.source_debug_extension, - //.line_number_table, - //.local_variable_table, - //.local_variable_type_table, - .deprecated => {}, - //.runtime_visible_annotations, - //.runtime_invisible_annotations, - //.runtime_visible_parameter_annotations, - //.runtime_invisible_parameter_annotations, - //.annotation_default, - //.bootstrap_methods, - else => {}, - } - } else { - try w.splatByteAll(' ', depth * indent); - _ = try w.write("predefined: no\n"); + try attribute.format(w, depth, indent + 1, self.allocator, self.constant_pool); } } @@ -996,6 +786,34 @@ pub const FieldInfo = struct { allocator.free(self.attributes); } + pub fn format(self: *const FieldInfo, w: *std.Io.Writer, depth: usize, indent: u8, allocator: std.mem.Allocator, constant_pool: []const ?CpInfo) std.Io.Writer.Error!void { + try w.splatByteAll(' ', depth * indent); + try w.print("flags: {f}\n", .{ self.access_flags }); + + try w.splatByteAll(' ', depth * indent); + _ = try w.write("name:\n"); + const field_name = self.name(constant_pool) catch return error.WriteFailed; + try field_name.format(w, depth, indent + 1, constant_pool); + + try w.splatByteAll(' ', depth * indent); + _ = try w.write("descriptor:\n"); + const field_descriptor = self.descriptor(constant_pool) catch return error.WriteFailed; + try field_descriptor.format(w, depth, indent + 1, constant_pool); + + try w.splatByteAll(' ', depth * indent); + _ = try w.write("attributes:\n"); + var attr_indent = indent; + for (self.attributes, 0..) |*attribute, j| { + attr_indent += 1; + defer attr_indent -= 1; + + try w.splatByteAll(' ', depth * attr_indent); + try w.print("{d}:\n", .{ j }); + + try attribute.format(w, depth, attr_indent + 1, allocator, constant_pool); + } + } + pub fn name(self: *const FieldInfo, constant_pool: []const ?CpInfo) ResolveError!CpInfo { const name_index = self.name_index - 1; if (name_index >= constant_pool.len) return ResolveError.InvalidConstantPoolIndex; @@ -1053,6 +871,34 @@ pub const MethodInfo = struct { allocator.free(self.attributes); } + pub fn format(self: *const MethodInfo, w: *std.Io.Writer, depth: usize, indent: u8, allocator: std.mem.Allocator, constant_pool: []const ?CpInfo) std.Io.Writer.Error!void { + try w.splatByteAll(' ', depth * indent); + try w.print("flags: {f}\n", .{ self.access_flags }); + + try w.splatByteAll(' ', depth * indent); + _ = try w.write("name:\n"); + const method_name = self.name(constant_pool) catch return error.WriteFailed; + try method_name.format(w, depth, indent + 1, constant_pool); + + try w.splatByteAll(' ', depth * indent); + _ = try w.write("descriptor:\n"); + const method_descriptor = self.descriptor(constant_pool) catch return error.WriteFailed; + try method_descriptor.format(w, depth, indent + 1, constant_pool); + + try w.splatByteAll(' ', depth * indent); + _ = try w.write("attributes:\n"); + var attr_indent = indent; + for (self.attributes, 0..) |*attribute, j| { + attr_indent += 1; + defer attr_indent -= 1; + + try w.splatByteAll(' ', depth * attr_indent); + try w.print("{d}:\n", .{ j }); + + try attribute.format(w, depth, attr_indent + 1, allocator, constant_pool); + } + } + pub fn name(self: *const MethodInfo, constant_pool: []const ?CpInfo) ResolveError!CpInfo { const name_index = self.name_index - 1; if (name_index >= constant_pool.len) return ResolveError.InvalidConstantPoolIndex; @@ -1321,6 +1167,30 @@ pub const AttributeInfo = struct { inner_name_index: u16, inner_class_access_flags: InnerClassAccessFlags, + pub fn format(self: *const InnerClass, w: *std.Io.Writer, depth: usize, indent: u8, constant_pool: []const ?CpInfo) std.Io.Writer.Error!void { + try w.splatByteAll(' ', depth * indent); + try w.print("flags: {f}\n", .{ self.inner_class_access_flags }); + + const inner_class = self.innerClass(constant_pool) catch return error.WriteFailed; + try w.splatByteAll(' ', depth * indent); + _ = try w.write("inner_class:\n"); + try inner_class.format(w, depth, indent + 1, constant_pool); + + const outer_class = self.outerClass(constant_pool) catch return error.WriteFailed; + if (outer_class) |oc| { + try w.splatByteAll(' ', depth * indent); + _ = try w.write("outer_class:\n"); + try oc.format(w, depth, indent + 1, constant_pool); + } + + const inner_name = self.innerName(constant_pool) catch return error.WriteFailed; + if (inner_name) |in| { + try w.splatByteAll(' ', depth * indent); + _ = try w.write("inner_name:\n"); + try in.format(w, depth, indent + 1, constant_pool); + } + } + pub fn innerClass(self: *const InnerClass, constant_pool: []const ?CpInfo) ResolveError!CpInfo { const inner_class_info_index = self.inner_class_info_index - 1; if (inner_class_info_index >= constant_pool.len) return ResolveError.InvalidConstantPoolIndex; @@ -1650,6 +1520,143 @@ pub const AttributeInfo = struct { allocator.free(self.info); } + pub fn format(self: *const AttributeInfo, w: *std.Io.Writer, depth: usize, indent: u8, allocator: std.mem.Allocator, constant_pool: []const ?CpInfo) std.Io.Writer.Error!void { + try w.splatByteAll(' ', depth * indent); + _ = try w.write("name:\n"); + const attribute_name = self.attributeName(constant_pool) catch return error.WriteFailed; + try attribute_name.format(w, depth, indent + 1, constant_pool); + + var predefined = self.resolve(allocator, constant_pool) catch return error.WriteFailed; + if (predefined) |*p| { + defer p.deinit(allocator); + + try w.splatByteAll(' ', depth * indent); + _ = try w.write("predefined: yes\n"); + + try w.splatByteAll(' ', depth * indent); + try w.print("type: {s}\n", .{ @tagName(p.*) }); + + switch (p.*) { + .constant_value => |attr| { + const constant_value = attr.constantValue(constant_pool) catch return error.WriteFailed; + try constant_value.format(w, depth, indent + 1, constant_pool); + }, + .code => |attr| { + try w.splatByteAll(' ', depth * indent); + try w.print("max_stack: {d}\n", .{ attr.max_stack }); + + try w.splatByteAll(' ', depth * indent); + try w.print("max_locals: {d}\n", .{ attr.max_locals }); + + try w.splatByteAll(' ', depth * indent); + _ = try w.write("code:\n"); + var instr_indent = indent; + for (attr.code, 0..) |instr, i| { + instr_indent += 1; + defer instr_indent -= 1; + + try w.splatByteAll(' ', depth * instr_indent); + try w.print("{d}: 0x{x}\n", .{ i, instr }); + } + + //try w.splatByteAll(' ', depth * indent); + //_ = try w.write("exception_table:\n"); + //var exception_indent = indent; + //for (attr.exception_table, 0..) |*exception, i| { + // exception_indent += 1; + // defer exception_indent -= 1; + + // try w.splatByteAll(' ', depth * exception_indent); + // try w.print("{d}:\n", .{ i }); + + // try self.formatExceptionHandler(w, depth, exception_indent + 1, exception); + //} + + try w.splatByteAll(' ', depth * indent); + _ = try w.write("attributes:\n"); + var attr_indent = indent; + for (attr.attributes, 0..) |*a, i| { + attr_indent += 1; + defer attr_indent -= 1; + + try w.splatByteAll(' ', depth * attr_indent); + try w.print("{d}:\n", .{ i }); + + try a.format(w, depth, attr_indent + 1, allocator, constant_pool); + } + }, + //.stack_map_table, + .exceptions => |attr| { + try w.splatByteAll(' ', depth * indent); + _ = try w.write("exceptions:\n"); + var exception_indent = indent; + for (attr.exception_index_table, 0..) |exception, i| { + exception_indent += 1; + defer exception_indent -= 1; + + if (exception >= constant_pool.len) return error.WriteFailed; + const cp_info = constant_pool[exception - 1]; + if (cp_info == null or @as(CpInfo.Tag, cp_info.?) != .class) return error.WriteFailed; + + try w.splatByteAll(' ', depth * exception_indent); + try w.print("{d}:\n", .{ i }); + try cp_info.?.format(w, depth, exception_indent + 1, constant_pool); + } + }, + .inner_classes => |attr| { + try w.splatByteAll(' ', depth * indent); + _ = try w.write("classes:\n"); + var class_indent = indent; + for (attr.classes, 0..) |*class, i| { + class_indent += 1; + defer class_indent -= 1; + + try w.splatByteAll(' ', depth * class_indent); + try w.print("{d}:\n", .{ i }); + try class.format(w, depth, class_indent + 1, constant_pool); + } + }, + .enclosing_method => |attr| { + const class = attr.class(constant_pool) catch return error.WriteFailed; + try w.splatByteAll(' ', depth * indent); + _ = try w.write("class:\n"); + try class.format(w, depth, indent + 1, constant_pool); + + const method = attr.method(constant_pool) catch return error.WriteFailed; + if (method) |m| { + try w.splatByteAll(' ', depth * indent); + _ = try w.write("method:\n"); + try m.format(w, depth, indent + 1, constant_pool); + } + }, + .synthetic => {}, + .signature => |attr| { + const signature = attr.signature(constant_pool) catch return error.WriteFailed; + try signature.format(w, depth, indent + 1, constant_pool); + }, + .source_file => |attr| { + const source_file = attr.sourceFile(constant_pool) catch return error.WriteFailed; + try source_file.format(w, depth, indent + 1, constant_pool); + }, + //.source_debug_extension, + //.line_number_table, + //.local_variable_table, + //.local_variable_type_table, + .deprecated => {}, + //.runtime_visible_annotations, + //.runtime_invisible_annotations, + //.runtime_visible_parameter_annotations, + //.runtime_invisible_parameter_annotations, + //.annotation_default, + //.bootstrap_methods, + else => {}, + } + } else { + try w.splatByteAll(' ', depth * indent); + _ = try w.write("predefined: no\n"); + } + } + pub fn attributeName(self: *const AttributeInfo, constant_pool: []const ?CpInfo) ResolveError!CpInfo { const attribute_name_index = self.attribute_name_index - 1; if (attribute_name_index >= constant_pool.len) return ResolveError.InvalidConstantPoolIndex;