Format runtime visible/invisible type annotations attributes

This commit is contained in:
ktkk 2026-07-08 22:22:17 +02:00
parent 76c436714f
commit 5ff7a358f9
3 changed files with 211 additions and 5 deletions

View file

@ -295,11 +295,13 @@ pub const AttributeInfo = union(enum) {
_ = try w.write("predefined: yes\n");
try w.splatByteAll(' ', depth * indent);
try w.print("type: {s}\n", .{ @tagName(predefined) });
try w.print("type: {t}\n", .{ predefined });
switch (predefined) {
.constant_value => |attr| {
const constant_value = attr.constantValue(constant_pool) catch return error.WriteFailed;
try w.splatByteAll(' ', depth * indent);
_ = try w.write("constant_value:\n");
try constant_value.indentedFormat(w, depth, indent + 1, constant_pool);
},
.code => |attr| {
@ -513,9 +515,37 @@ pub const AttributeInfo = union(enum) {
try parameter_annotation.indentedFormat(w, depth, parameter_annotation_indent + 1, constant_pool);
}
},
//.runtime_visible_type_annotations,
//.runtime_invisible_type_annotations,
//.annotation_default,
.runtime_visible_type_annotations => |attr| {
try w.splatByteAll(' ', depth * indent);
_ = try w.write("type_annotations:\n");
var type_annotation_indent = indent;
for (attr.type_annotations, 0..) |type_annotation, i| {
type_annotation_indent += 1;
defer type_annotation_indent -= 1;
try w.splatByteAll(' ', depth * type_annotation_indent);
try w.print("{d}:\n", .{ i });
try type_annotation.indentedFormat(w, depth, type_annotation_indent + 1, constant_pool);
}
},
.runtime_invisible_type_annotations => |attr| {
try w.splatByteAll(' ', depth * indent);
_ = try w.write("type_annotations:\n");
var type_annotation_indent = indent;
for (attr.type_annotations, 0..) |type_annotation, i| {
type_annotation_indent += 1;
defer type_annotation_indent -= 1;
try w.splatByteAll(' ', depth * type_annotation_indent);
try w.print("{d}:\n", .{ i });
try type_annotation.indentedFormat(w, depth, type_annotation_indent + 1, constant_pool);
}
},
.annotation_default => |attr| {
try w.splatByteAll(' ', depth * indent);
_ = try w.write("default_value:\n");
try attr.default_value.indentedFormat(w, depth, indent + 1, constant_pool);
},
.bootstrap_methods => |attr| {
try w.splatByteAll(' ', depth * indent);
_ = try w.write("bootstrap_methods:\n");
@ -613,7 +643,6 @@ pub const AttributeInfo = union(enum) {
try info.indentedFormat(w, depth, class_indent + 1, constant_pool);
}
},
else => {},
}
},
}
@ -1971,6 +2000,22 @@ pub const TypeAnnotation = struct {
start_pc: u16,
length: u16,
index: u16,
pub fn indentedFormat(
self: *const Entry,
w: *std.Io.Writer,
depth: usize,
indent: u8,
) std.Io.Writer.Error!void {
try w.splatByteAll(' ', depth * indent);
try w.print("start_pc: {d}\n", .{ self.start_pc });
try w.splatByteAll(' ', depth * indent);
try w.print("length: {d}\n", .{ self.length });
try w.splatByteAll(' ', depth * indent);
try w.print("start_pc: {d}\n", .{ self.index });
}
};
};
@ -1986,6 +2031,72 @@ pub const TypeAnnotation = struct {
offset: u16,
type_argument_index: u8,
};
pub fn indentedFormat(
self: *const TargetInfo,
w: *std.Io.Writer,
depth: usize,
indent: u8,
) std.Io.Writer.Error!void {
try w.splatByteAll(' ', depth * indent);
try w.print("target_info_type: {t}\n", .{ self.* });
switch (self.*) {
.type_parameter => |*type_parameter| {
try w.splatByteAll(' ', depth * indent);
try w.print("type_parameter_index: {d}\n", .{ type_parameter.type_parameter_index });
},
.supertype => |*supertype| {
try w.splatByteAll(' ', depth * indent);
try w.print("supertype_index: {d}\n", .{ supertype.supertype_index });
},
.type_parameter_bound => |*type_parameter_bound| {
try w.splatByteAll(' ', depth * indent);
try w.print("type_parameter_index: {d}\n", .{ type_parameter_bound.type_parameter_index });
try w.splatByteAll(' ', depth * indent);
try w.print("bound_index: {d}\n", .{ type_parameter_bound.bound_index });
},
.formal_parameter => |*formal_parameter| {
try w.splatByteAll(' ', depth * indent);
try w.print("formal_parameter_index: {d}\n", .{ formal_parameter.formal_parameter_index });
},
.throws => |*throws| {
try w.splatByteAll(' ', depth * indent);
try w.print("throws_type_index: {d}\n", .{ throws.throws_type_index });
},
.localvar => |*localvar| {
try w.splatByteAll(' ', depth * indent);
_ = try w.write("table:\n");
var entry_indent = indent;
for (localvar.table, 0..) |*entry, i| {
entry_indent += 1;
defer entry_indent -= 1;
try w.splatByteAll(' ', depth * entry_indent);
try w.print("{d}:\n", .{ i });
try entry.indentedFormat(w, depth, indent);
}
},
.@"catch" => |*@"catch"| {
try w.splatByteAll(' ', depth * indent);
try w.print("exception_table_index: {d}\n", .{ @"catch".exception_table_index });
},
.offset => |*offset| {
try w.splatByteAll(' ', depth * indent);
try w.print("offset: {d}\n", .{ offset.offset });
},
.type_argument => |*type_argument| {
try w.splatByteAll(' ', depth * indent);
try w.print("offset: {d}\n", .{ type_argument.offset });
try w.splatByteAll(' ', depth * indent);
try w.print("type_argument_index: {d}\n", .{ type_argument.type_argument_index });
},
else => {},
}
}
};
pub const TypePath = struct {
@ -1994,6 +2105,19 @@ pub const TypeAnnotation = struct {
pub const Path = struct {
type_path_kind: u8,
type_argument_index: u8,
pub fn indentedFormat(
self: *const Path,
w: *std.Io.Writer,
depth: usize,
indent: u8,
) std.Io.Writer.Error!void {
try w.splatByteAll(' ', depth * indent);
try w.print("type_path_kind: {d}\n", .{ self.type_path_kind });
try w.splatByteAll(' ', depth * indent);
try w.print("type_argument_index: {d}\n", .{ self.type_argument_index });
}
};
pub fn parse(input: *std.Io.Reader, allocator: std.mem.Allocator) ParseError!TypePath {
@ -2015,6 +2139,25 @@ pub const TypeAnnotation = struct {
pub fn deinit(self: *TypePath, allocator: std.mem.Allocator) void {
allocator.free(self.paths);
}
pub fn indentedFormat(
self: *const TypePath,
w: *std.Io.Writer,
depth: usize,
indent: u8,
) std.Io.Writer.Error!void {
try w.splatByteAll(' ', depth * indent);
_ = try w.write("paths:\n");
var path_indent = indent;
for (self.paths, 0..) |path, i| {
path_indent += 1;
defer path_indent -= 1;
try w.splatByteAll(' ', depth * path_indent);
try w.print("{d}:\n", .{ i });
try path.indentedFormat(w, depth, path_indent + 1);
}
}
};
pub fn parse(input: *std.Io.Reader, allocator: std.mem.Allocator) ParseError!Self {
@ -2119,6 +2262,46 @@ pub const TypeAnnotation = struct {
}
allocator.free(self.element_value_pairs);
}
pub fn indentedFormat(
self: *const Self,
w: *std.Io.Writer,
depth: usize,
indent: u8,
constant_pool: ConstantPool,
) std.Io.Writer.Error!void {
try w.splatByteAll(' ', depth * indent);
try w.print("target_type: {t}\n", .{ self.target_type });
try w.splatByteAll(' ', depth * indent);
_ = try w.write("target_info:\n");
try self.target_info.indentedFormat(w, depth + 1, indent);
try w.splatByteAll(' ', depth * indent);
_ = try w.write("target_path:\n");
try self.target_path.indentedFormat(w, depth + 1, indent);
const type_ = self.@"type"(constant_pool) catch return error.WriteFailed;
try w.splatByteAll(' ', depth * indent);
_ = try w.write("type:\n");
try type_.indentedFormat(w, depth, indent + 1, constant_pool);
try w.splatByteAll(' ', depth * indent);
_ = try w.write("element_value_pairs:\n");
var element_value_pair_indent = indent;
for (self.element_value_pairs, 0..) |element_value_pair, i| {
element_value_pair_indent += 1;
defer element_value_pair_indent -= 1;
try w.splatByteAll(' ', depth * element_value_pair_indent);
try w.print("{d}:\n", .{ i });
try element_value_pair.indentedFormat(w, depth, element_value_pair_indent + 1, constant_pool);
}
}
pub fn @"type"(self: *const Self, constant_pool: ConstantPool) ResolveError!ConstantPool.Info {
return constant_pool.getTag(self.type_index, .utf8);
}
};
pub const RuntimeVisibleTypeAnnotations = struct {

View file

@ -0,0 +1,9 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE_PARAMETER)
public @interface CustomTypeAnnotation {
}

View file

@ -0,0 +1,14 @@
import java.util.function.Supplier;
public class GenericClass<@CustomTypeAnnotation T> {
public <T> Supplier<T> getSupplier(T value) {
return new Supplier<T>() {
@Override
public T get() {
return value;
}
};
}
}