Format additional predefined attribute infos

This commit is contained in:
ktkk 2026-07-05 00:25:25 +02:00
parent 9af766e495
commit f8b1f968e0
4 changed files with 273 additions and 19 deletions

View file

@ -259,7 +259,6 @@ pub const AttributeInfo = union(enum) {
w: *std.Io.Writer,
depth: usize,
indent: u8,
allocator: std.mem.Allocator,
constant_pool: []const ?ConstantPoolInfo,
) std.Io.Writer.Error!void {
switch (self.*) {
@ -325,7 +324,7 @@ pub const AttributeInfo = union(enum) {
try w.splatByteAll(' ', depth * attr_indent);
try w.print("{d}:\n", .{ i });
try a.indentedFormat(w, depth, attr_indent + 1, allocator, constant_pool);
try a.indentedFormat(w, depth, attr_indent + 1, constant_pool);
}
},
//.stack_map_table,
@ -333,12 +332,14 @@ pub const AttributeInfo = union(enum) {
try w.splatByteAll(' ', depth * indent);
_ = try w.write("exceptions:\n");
var exception_indent = indent;
for (attr.exception_index_table, 0..) |exception, i| {
for (attr.exception_index_table, 0..) |exception_index, i| {
exception_indent += 1;
defer exception_indent -= 1;
if (exception >= constant_pool.len) return error.WriteFailed;
const cp_info = constant_pool[exception - 1];
const index = exception_index - 1;
if (index >= constant_pool.len) return error.WriteFailed;
const cp_info = constant_pool[index];
if (cp_info == null or @as(ConstantPoolInfo.Tag, cp_info.?) != .class) return error.WriteFailed;
try w.splatByteAll(' ', depth * exception_indent);
@ -396,14 +397,102 @@ pub const AttributeInfo = union(enum) {
//.runtime_invisible_parameter_annotations,
//.annotation_default,
//.bootstrap_methods,
//.method_parameters,
.method_parameters => |attr| {
try w.splatByteAll(' ', depth * indent);
_ = try w.write("parameters:\n");
var parameter_indent = indent;
for (attr.parameters, 0..) |parameter, i| {
parameter_indent += 1;
defer parameter_indent -= 1;
try w.splatByteAll(' ', depth * parameter_indent);
try w.print("{d}:\n", .{ i });
try parameter.indentedFormat(w, depth, parameter_indent, constant_pool);
}
},
//.module,
//.module_packages,
//.module_main_class,
//.nest_host,
//.nest_members,
//.record,
//.permitted_subclasses,
.module_packages => |attr| {
try w.splatByteAll(' ', depth * indent);
_ = try w.write("packages:\n");
var package_indent = indent;
for (attr.package_indeces, 0..) |package_index, i| {
package_indent += 1;
defer package_indent -= 1;
const index = package_index - 1;
if (index >= constant_pool.len) return error.WriteFailed;
const cp_info = constant_pool[index];
if (cp_info == null or @as(ConstantPoolInfo.Tag, cp_info.?) != .package) return error.WriteFailed;
try w.splatByteAll(' ', depth * package_indent);
try w.print("{d}:\n", .{ i });
try cp_info.?.indentedFormat(w, depth, package_indent + 1, constant_pool);
}
},
.module_main_class => |attr| {
const main_class = attr.mainClass(constant_pool) catch return error.WriteFailed;
try w.splatByteAll(' ', depth * indent);
_ = try w.write("main_class:\n");
try main_class.indentedFormat(w, depth, indent + 1, constant_pool);
},
.nest_host => |attr| {
const host_class = attr.hostClass(constant_pool) catch return error.WriteFailed;
try w.splatByteAll(' ', depth * indent);
_ = try w.write("host_class:\n");
try host_class.indentedFormat(w, depth, indent + 1, constant_pool);
},
.nest_members => |attr| {
try w.splatByteAll(' ', depth * indent);
_ = try w.write("classes:\n");
var class_indent = indent;
for (attr.classes, 0..) |class_index, i| {
class_indent += 1;
defer class_indent -= 1;
const index = class_index - 1;
if (index >= constant_pool.len) return error.WriteFailed;
const cp_info = constant_pool[index];
if (cp_info == null or @as(ConstantPoolInfo.Tag, cp_info.?) != .class) return error.WriteFailed;
try w.splatByteAll(' ', depth * class_indent);
try w.print("{d}:\n", .{ i });
try cp_info.?.indentedFormat(w, depth, class_indent + 1, constant_pool);
}
},
.record => |attr| {
try w.splatByteAll(' ', depth * indent);
_ = try w.write("components:\n");
var component_indent = indent;
for (attr.components, 0..) |component, i| {
component_indent += 1;
defer component_indent -= 1;
try w.splatByteAll(' ', depth * component_indent);
try w.print("{d}:\n", .{ i });
try component.indentedFormat(w, depth, component_indent, constant_pool);
}
},
.permitted_subclasses => |attr| {
try w.splatByteAll(' ', depth * indent);
_ = try w.write("classes:\n");
var class_indent = indent;
for (attr.classes, 0..) |class_index, i| {
class_indent += 1;
defer class_indent -= 1;
const index = class_index - 1;
if (index >= constant_pool.len) return error.WriteFailed;
const cp_info = constant_pool[index];
if (cp_info == null or @as(ConstantPoolInfo.Tag, cp_info.?) != .class) return error.WriteFailed;
try w.splatByteAll(' ', depth * class_indent);
try w.print("{d}:\n", .{ i });
try cp_info.?.indentedFormat(w, depth, class_indent + 1, constant_pool);
}
},
else => {},
}
},
@ -1392,6 +1481,30 @@ pub const MethodParameters = struct {
};
pub const ParameterAccessFlags = EnumFlags(ParameterFlags);
pub fn indentedFormat(
self: *const Parameter,
w: *std.Io.Writer,
depth: usize,
indent: u8,
constant_pool: []const ?ConstantPoolInfo,
) std.Io.Writer.Error!void {
try w.splatByteAll(' ', depth * indent);
try w.print("flags: {f}\n", .{ self.access_flags });
const name_ = self.name(constant_pool) catch return error.WriteFailed;
try w.splatByteAll(' ', depth * indent);
_ = try w.write("name:\n");
try name_.indentedFormat(w, depth, indent + 1, constant_pool);
}
pub fn name(self: *const Parameter, constant_pool: []const ?ConstantPoolInfo) ResolveError!ConstantPoolInfo {
const name_index = self.name_index - 1;
if (name_index >= constant_pool.len) return ResolveError.InvalidConstantPoolIndex;
const cp_info = constant_pool[name_index];
if (cp_info == null or @as(ConstantPoolInfo.Tag, cp_info.?) != .utf8) return ResolveError.InvalidConstantType;
return cp_info.?;
}
};
pub fn parse(input: *std.Io.Reader, allocator: std.mem.Allocator) ParseError!Self {
@ -1448,6 +1561,14 @@ pub const ModuleMainClass = struct {
.main_class_index = try input.takeInt(u16, .big),
};
}
pub fn mainClass(self: *const ModuleMainClass, constant_pool: []const ?ConstantPoolInfo) ResolveError!ConstantPoolInfo {
const main_class_index = self.main_class_index - 1;
if (main_class_index >= constant_pool.len) return ResolveError.InvalidConstantPoolIndex;
const cp_info = constant_pool[main_class_index];
if (cp_info == null or @as(ConstantPoolInfo.Tag, cp_info.?) != .class) return ResolveError.InvalidConstantType;
return cp_info.?;
}
};
pub const NestHost = struct {
@ -1460,6 +1581,14 @@ pub const NestHost = struct {
.host_class_index = try input.takeInt(u16, .big),
};
}
pub fn hostClass(self: *const NestHost, constant_pool: []const ?ConstantPoolInfo) ResolveError!ConstantPoolInfo {
const host_class_index = self.host_class_index - 1;
if (host_class_index >= constant_pool.len) return ResolveError.InvalidConstantPoolIndex;
const cp_info = constant_pool[host_class_index];
if (cp_info == null or @as(ConstantPoolInfo.Tag, cp_info.?) != .class) return ResolveError.InvalidConstantType;
return cp_info.?;
}
};
pub const NestMembers = struct {
@ -1518,6 +1647,53 @@ pub const Record = struct {
}
allocator.free(self.attributes);
}
pub fn indentedFormat(
self: *const RecordComponentInfo,
w: *std.Io.Writer,
depth: usize,
indent: u8,
constant_pool: []const ?ConstantPoolInfo,
) std.Io.Writer.Error!void {
const name_ = self.name(constant_pool) catch return error.WriteFailed;
try w.splatByteAll(' ', depth * indent);
_ = try w.write("name:\n");
try name_.indentedFormat(w, depth, indent + 1, constant_pool);
const descriptor_ = self.descriptor(constant_pool) catch return error.WriteFailed;
try w.splatByteAll(' ', depth * indent);
_ = try w.write("descriptor:\n");
try descriptor_.indentedFormat(w, depth, indent + 1, constant_pool);
try w.splatByteAll(' ', depth * indent);
_ = try w.write("attributes:\n");
var attr_indent = indent;
for (self.attributes, 0..) |*attr, i| {
attr_indent += 1;
defer attr_indent -= 1;
try w.splatByteAll(' ', depth * attr_indent);
try w.print("{d}:\n", .{ i });
try attr.indentedFormat(w, depth, attr_indent + 1, constant_pool);
}
}
pub fn name(self: *const RecordComponentInfo, constant_pool: []const ?ConstantPoolInfo) ResolveError!ConstantPoolInfo {
const name_index = self.name_index - 1;
if (name_index >= constant_pool.len) return ResolveError.InvalidConstantPoolIndex;
const cp_info = constant_pool[name_index];
if (cp_info == null or @as(ConstantPoolInfo.Tag, cp_info.?) != .utf8) return ResolveError.InvalidConstantType;
return cp_info.?;
}
pub fn descriptor(self: *const RecordComponentInfo, constant_pool: []const ?ConstantPoolInfo) ResolveError!ConstantPoolInfo {
const descriptor_index = self.descriptor_index - 1;
if (descriptor_index >= constant_pool.len) return ResolveError.InvalidConstantPoolIndex;
const cp_info = constant_pool[descriptor_index];
if (cp_info == null or @as(ConstantPoolInfo.Tag, cp_info.?) != .utf8) return ResolveError.InvalidConstantType;
return cp_info.?;
}
};
pub fn parse(input: *std.Io.Reader, constant_pool: []const ?ConstantPoolInfo, allocator: std.mem.Allocator) (ParseError || ResolveError)!Self {