Add runtime visible/invisible type annotations attributes
This commit is contained in:
parent
89e548c8cc
commit
5d58edb068
1 changed files with 314 additions and 45 deletions
|
|
@ -28,8 +28,8 @@ pub const AttributeInfo = union(enum) {
|
||||||
runtime_invisible_annotations: RuntimeInvisibleAnnotations,
|
runtime_invisible_annotations: RuntimeInvisibleAnnotations,
|
||||||
runtime_visible_parameter_annotations: RuntimeVisibleParameterAnnotations,
|
runtime_visible_parameter_annotations: RuntimeVisibleParameterAnnotations,
|
||||||
runtime_invisible_parameter_annotations: RuntimeInvisibleParameterAnnotations,
|
runtime_invisible_parameter_annotations: RuntimeInvisibleParameterAnnotations,
|
||||||
// runtime_visible_type_annotations: RuntimeVisibleTypeAnnotations,
|
runtime_visible_type_annotations: RuntimeVisibleTypeAnnotations,
|
||||||
// runtime_invisible_type_annotations: RuntimeInvisibleTypeAnnotations,
|
runtime_invisible_type_annotations: RuntimeInvisibleTypeAnnotations,
|
||||||
annotation_default: AnnotationDefault,
|
annotation_default: AnnotationDefault,
|
||||||
bootstrap_methods: BootstrapMethods,
|
bootstrap_methods: BootstrapMethods,
|
||||||
method_parameters: MethodParameters,
|
method_parameters: MethodParameters,
|
||||||
|
|
@ -163,6 +163,18 @@ pub const AttributeInfo = union(enum) {
|
||||||
.runtime_invisible_parameter_annotations = try RuntimeInvisibleParameterAnnotations.parse(limited, allocator),
|
.runtime_invisible_parameter_annotations = try RuntimeInvisibleParameterAnnotations.parse(limited, allocator),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
} else if (std.mem.eql(u8, name, "RuntimeInvisibleTypeAnnotations")) {
|
||||||
|
return .{
|
||||||
|
.predefined = .{
|
||||||
|
.runtime_invisible_type_annotations = try RuntimeInvisibleTypeAnnotations.parse(limited, allocator),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
} else if (std.mem.eql(u8, name, "RuntimeInvisibleTypeAnnotations")) {
|
||||||
|
return .{
|
||||||
|
.predefined = .{
|
||||||
|
.runtime_invisible_type_annotations = try RuntimeInvisibleTypeAnnotations.parse(limited, allocator),
|
||||||
|
},
|
||||||
|
};
|
||||||
} else if (std.mem.eql(u8, name, "AnnotationDefault")) {
|
} else if (std.mem.eql(u8, name, "AnnotationDefault")) {
|
||||||
return .{
|
return .{
|
||||||
.predefined = .{
|
.predefined = .{
|
||||||
|
|
@ -1857,50 +1869,307 @@ pub const RuntimeInvisibleParameterAnnotations = struct {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: TypeAnnotation structure
|
pub const TypeAnnotation = struct {
|
||||||
// pub const TypeAnnotation = struct {
|
target_type: TargetType,
|
||||||
// target_info: union(TargetType) {
|
target_info: TargetInfo,
|
||||||
// type_parameter_target: TypeParameterTarget,
|
target_path: TypePath,
|
||||||
// supertype_target: SupertypeTarget,
|
type_index: u16,
|
||||||
// type_parameter_bound_target: TypeParameterBoundTarget,
|
element_value_pairs: []ElementValuePair,
|
||||||
// emtpy_target: EmptyTarget,
|
|
||||||
// formal_parameter_target: FormalParameterTarget,
|
|
||||||
// throws_target: ThrowsTarget,
|
|
||||||
// localvar_target: LocalvarTarget,
|
|
||||||
// catch_target: CatchTarget,
|
|
||||||
// offset_target: OffsetTarget,
|
|
||||||
// type_argument_target: TypeArgumentTarget,
|
|
||||||
// },
|
|
||||||
// target_path: TypePath,
|
|
||||||
// type_index: u16,
|
|
||||||
// element_value_pairs: []ElementValuePair,
|
|
||||||
//
|
|
||||||
// pub const TargetType = enum(u8) {
|
|
||||||
// type_parameter_target = 0x00,
|
|
||||||
// type
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// pub const TypePath = struct {
|
|
||||||
// path: []Path,
|
|
||||||
//
|
|
||||||
// pub const Path = struct {
|
|
||||||
// type_path_kind: u8,
|
|
||||||
// type_argument_index: u8,
|
|
||||||
// };
|
|
||||||
// };
|
|
||||||
// };
|
|
||||||
|
|
||||||
// pub const RuntimeVisibleTypeAnnotations = struct {
|
const Self = @This();
|
||||||
// type_annotations: []TypeAnnotation,
|
|
||||||
//
|
pub const TargetType = enum(u8) {
|
||||||
// const Self = @This();
|
/// type parameter declaration of generic class or interface
|
||||||
// };
|
type_parameter_generic_class_interface = 0x00,
|
||||||
//
|
/// type parameter declaration of generic method or constructor
|
||||||
// pub const RuntimeInvisibleTypeAnnotations = struct {
|
type_parameter_generic_method_constructor = 0x01,
|
||||||
// type_annotations: []TypeAnnotation,
|
/// type in extends or implements clause of class declaration
|
||||||
//
|
/// (including the direct superclass or direct superinterface of an anonymous class declaration),
|
||||||
// const Self = @This();
|
/// or in extends clause of interface declaration
|
||||||
// };
|
type_in_extends_implements = 0x10,
|
||||||
|
/// type in bound of type parameter declaration of generic class or interface
|
||||||
|
type_in_bound_generic_class_interface = 0x11,
|
||||||
|
/// type in bound of type parameter declaration of generic method or constructor
|
||||||
|
type_in_bound_generic_method_constructor = 0x12,
|
||||||
|
/// type in field or record component declaration
|
||||||
|
type_in_field_record_component = 0x13,
|
||||||
|
/// return type of method, or type of newly constructed object
|
||||||
|
return_type_method_newly_constructed_object = 0x14,
|
||||||
|
/// receiver type of method or constructor
|
||||||
|
receiver_type_method_constructor = 0x15,
|
||||||
|
/// type in formal parameter declaration of method, constructor, or lambda expression
|
||||||
|
type_in_formal_parameter_declaration_method_constructor_lambda = 0x16,
|
||||||
|
/// type in throws clause of method or constructor
|
||||||
|
type_in_throws_method_constructor = 0x17,
|
||||||
|
/// type in local variable declaration
|
||||||
|
type_in_local_variable = 0x40,
|
||||||
|
/// type in resource variable declaration
|
||||||
|
type_in_resource_variable = 0x41,
|
||||||
|
/// type in exception parameter declaration
|
||||||
|
type_in_exception_parameter = 0x42,
|
||||||
|
/// type in instanceof expression
|
||||||
|
type_in_instanceof = 0x43,
|
||||||
|
/// type in new expression
|
||||||
|
type_in_new = 0x44,
|
||||||
|
/// type in method reference expression using ::new
|
||||||
|
type_in_method_reference_new = 0x45,
|
||||||
|
/// type in method reference expression using ::Identifier
|
||||||
|
type_in_method_reference_identifier = 0x46,
|
||||||
|
/// type in cast expression
|
||||||
|
type_in_cast = 0x47,
|
||||||
|
/// type argument for generic constructor in new expression or explicit constructor invocation statement
|
||||||
|
type_generic_constructor_new_explicit = 0x48,
|
||||||
|
/// type argument for generic method in method invocation expression
|
||||||
|
type_generic_method_invocation = 0x49,
|
||||||
|
/// type argument for generic constructor in method reference expression using ::new
|
||||||
|
type_generic_constructor_method_reference_new = 0x4a,
|
||||||
|
/// type argument for generic method in method reference expression using ::Identifier
|
||||||
|
type_generic_method_method_reference_identifier = 0x4b,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const TargetInfo = union {
|
||||||
|
type_parameter: TypeParameter,
|
||||||
|
supertype: SuperType,
|
||||||
|
type_parameter_bound: TypeParameterBound,
|
||||||
|
empty: Empty,
|
||||||
|
formal_parameter: FormalParameter,
|
||||||
|
throws: Throws,
|
||||||
|
localvar: Localvar,
|
||||||
|
@"catch": Catch,
|
||||||
|
offset: Offset,
|
||||||
|
type_argument: TypeArgument,
|
||||||
|
|
||||||
|
pub const TypeParameter = struct {
|
||||||
|
type_parameter_index: u8,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const SuperType = struct {
|
||||||
|
supertype_index: u16,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const TypeParameterBound = struct {
|
||||||
|
type_parameter_index: u8,
|
||||||
|
bound_index: u8,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Empty = struct { };
|
||||||
|
|
||||||
|
pub const FormalParameter = struct {
|
||||||
|
formal_parameter_index: u8,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Throws = struct {
|
||||||
|
throws_type_index: u16,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Localvar = struct {
|
||||||
|
table: []Entry,
|
||||||
|
|
||||||
|
pub const Entry = struct {
|
||||||
|
start_pc: u16,
|
||||||
|
length: u16,
|
||||||
|
index: u16,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Catch = struct {
|
||||||
|
exception_table_index: u16,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Offset = struct {
|
||||||
|
offset: u16,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const TypeArgument = struct {
|
||||||
|
offset: u16,
|
||||||
|
type_argument_index: u8,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const TypePath = struct {
|
||||||
|
paths: []Path,
|
||||||
|
|
||||||
|
pub const Path = struct {
|
||||||
|
type_path_kind: u8,
|
||||||
|
type_argument_index: u8,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn parse(input: *std.Io.Reader, allocator: std.mem.Allocator) ParseError!TypePath {
|
||||||
|
const length = try input.takeByte();
|
||||||
|
const paths = try allocator.alloc(Path, length);
|
||||||
|
errdefer allocator.free(paths);
|
||||||
|
for (paths) |*path| {
|
||||||
|
path.* = .{
|
||||||
|
.type_path_kind = try input.takeByte(),
|
||||||
|
.type_argument_index = try input.takeByte(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return .{
|
||||||
|
.paths = paths,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *TypePath, allocator: std.mem.Allocator) void {
|
||||||
|
allocator.free(self.paths);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn parse(input: *std.Io.Reader, allocator: std.mem.Allocator) ParseError!Self {
|
||||||
|
const target_type: TargetType = @enumFromInt(try input.takeInt(u8, .big));
|
||||||
|
const target_info: TargetInfo = switch (target_type) {
|
||||||
|
.type_parameter_generic_class_interface, .type_parameter_generic_method_constructor => .{
|
||||||
|
.type_parameter = .{
|
||||||
|
.type_parameter_index = try input.takeByte(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.type_in_extends_implements => .{
|
||||||
|
.supertype = .{
|
||||||
|
.supertype_index = try input.takeInt(u16, .big),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.type_in_bound_generic_class_interface, .type_in_bound_generic_method_constructor => .{
|
||||||
|
.type_parameter_bound = .{
|
||||||
|
.type_parameter_index = try input.takeByte(),
|
||||||
|
.bound_index = try input.takeByte(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.type_in_field_record_component, .return_type_method_newly_constructed_object, .receiver_type_method_constructor => .{
|
||||||
|
.empty = .{},
|
||||||
|
},
|
||||||
|
.type_in_formal_parameter_declaration_method_constructor_lambda => .{
|
||||||
|
.formal_parameter = .{
|
||||||
|
.formal_parameter_index = try input.takeByte(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.type_in_throws_method_constructor => .{
|
||||||
|
.throws = .{
|
||||||
|
.throws_type_index = try input.takeInt(u16, .big),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.type_in_local_variable, .type_in_resource_variable => blk: {
|
||||||
|
const table_length = try input.takeInt(u16, .big);
|
||||||
|
const table = try allocator.alloc(TargetInfo.Localvar.Entry, table_length);
|
||||||
|
errdefer allocator.free(table);
|
||||||
|
for (table) |*entry| {
|
||||||
|
entry.* = .{
|
||||||
|
.start_pc = try input.takeInt(u16, .big),
|
||||||
|
.length = try input.takeInt(u16, .big),
|
||||||
|
.index = try input.takeInt(u16, .big),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
break :blk .{
|
||||||
|
.localvar = .{
|
||||||
|
.table = table,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
.type_in_exception_parameter => .{
|
||||||
|
.@"catch" = . {
|
||||||
|
.exception_table_index = try input.takeInt(u16, .big),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.type_in_instanceof, .type_in_new, .type_in_method_reference_new, .type_in_method_reference_identifier => .{
|
||||||
|
.offset = .{
|
||||||
|
.offset = try input.takeInt(u16, .big),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.type_in_cast, .type_generic_constructor_new_explicit, .type_generic_method_invocation, .type_generic_constructor_method_reference_new, .type_generic_method_method_reference_identifier => .{
|
||||||
|
.type_argument = .{
|
||||||
|
.offset = try input.takeInt(u16, .big),
|
||||||
|
.type_argument_index = try input.takeByte(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
var target_path: TypePath = try .parse(input, allocator);
|
||||||
|
errdefer target_path.deinit(allocator);
|
||||||
|
|
||||||
|
const type_index = try input.takeInt(u16, .big);
|
||||||
|
|
||||||
|
const num_element_value_pairs = try input.takeInt(u16, .big);
|
||||||
|
const element_value_pairs = try allocator.alloc(ElementValuePair, num_element_value_pairs);
|
||||||
|
errdefer allocator.free(element_value_pairs);
|
||||||
|
for (element_value_pairs) |*element_value_pair| {
|
||||||
|
element_value_pair.* = .{
|
||||||
|
.element_name_index = try input.takeInt(u16, .big),
|
||||||
|
.value = try .parse(input, allocator),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return .{
|
||||||
|
.target_type = target_type,
|
||||||
|
.target_info = target_info,
|
||||||
|
.target_path = target_path,
|
||||||
|
.type_index = type_index,
|
||||||
|
.element_value_pairs = element_value_pairs,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *Self, allocator: std.mem.Allocator) void {
|
||||||
|
switch (self.target_info) {
|
||||||
|
.localvar => |localvar| allocator.free(localvar.table),
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
for (self.element_value_pairs) |*element_value_pair| {
|
||||||
|
element_value_pair.value.deinit(allocator);
|
||||||
|
}
|
||||||
|
allocator.free(self.element_value_pairs);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const RuntimeVisibleTypeAnnotations = struct {
|
||||||
|
type_annotations: []TypeAnnotation,
|
||||||
|
|
||||||
|
const Self = @This();
|
||||||
|
|
||||||
|
pub fn parse(input: *std.Io.Reader, allocator: std.mem.Allocator) ParseError!Self {
|
||||||
|
const num_annotations = try input.takeInt(u16, .big);
|
||||||
|
const type_annotations = try allocator.alloc(TypeAnnotation, num_annotations);
|
||||||
|
errdefer allocator.free(type_annotations);
|
||||||
|
for (type_annotations) |*type_annotation| {
|
||||||
|
type_annotation.* = try .parse(input, allocator);
|
||||||
|
}
|
||||||
|
|
||||||
|
return .{
|
||||||
|
.type_annotations = type_annotations,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *Self, allocator: std.mem.Allocator) void {
|
||||||
|
for (self.type_annotations) |*type_annotation| {
|
||||||
|
type_annotation.deinit(allocator);
|
||||||
|
}
|
||||||
|
allocator.free(self.type_annotations);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const RuntimeInvisibleTypeAnnotations = struct {
|
||||||
|
type_annotations: []TypeAnnotation,
|
||||||
|
|
||||||
|
const Self = @This();
|
||||||
|
|
||||||
|
pub fn parse(input: *std.Io.Reader, allocator: std.mem.Allocator) ParseError!Self {
|
||||||
|
const num_annotations = try input.takeInt(u16, .big);
|
||||||
|
const type_annotations = try allocator.alloc(TypeAnnotation, num_annotations);
|
||||||
|
errdefer allocator.free(type_annotations);
|
||||||
|
for (type_annotations) |*type_annotation| {
|
||||||
|
type_annotation.* = try .parse(input, allocator);
|
||||||
|
}
|
||||||
|
|
||||||
|
return .{
|
||||||
|
.type_annotations = type_annotations,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *Self, allocator: std.mem.Allocator) void {
|
||||||
|
for (self.type_annotations) |*type_annotation| {
|
||||||
|
type_annotation.deinit(allocator);
|
||||||
|
}
|
||||||
|
allocator.free(self.type_annotations);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
pub const AnnotationDefault = struct {
|
pub const AnnotationDefault = struct {
|
||||||
default_value: ElementValue,
|
default_value: ElementValue,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue