Add runtime visible/invisible type annotations attributes
This commit is contained in:
parent
89e548c8cc
commit
a47405e903
1 changed files with 316 additions and 45 deletions
|
|
@ -28,8 +28,8 @@ pub const AttributeInfo = union(enum) {
|
|||
runtime_invisible_annotations: RuntimeInvisibleAnnotations,
|
||||
runtime_visible_parameter_annotations: RuntimeVisibleParameterAnnotations,
|
||||
runtime_invisible_parameter_annotations: RuntimeInvisibleParameterAnnotations,
|
||||
// runtime_visible_type_annotations: RuntimeVisibleTypeAnnotations,
|
||||
// runtime_invisible_type_annotations: RuntimeInvisibleTypeAnnotations,
|
||||
runtime_visible_type_annotations: RuntimeVisibleTypeAnnotations,
|
||||
runtime_invisible_type_annotations: RuntimeInvisibleTypeAnnotations,
|
||||
annotation_default: AnnotationDefault,
|
||||
bootstrap_methods: BootstrapMethods,
|
||||
method_parameters: MethodParameters,
|
||||
|
|
@ -163,6 +163,18 @@ pub const AttributeInfo = union(enum) {
|
|||
.runtime_invisible_parameter_annotations = try RuntimeInvisibleParameterAnnotations.parse(limited, allocator),
|
||||
},
|
||||
};
|
||||
} else if (std.mem.eql(u8, name, "RuntimeVisibleTypeAnnotations")) {
|
||||
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")) {
|
||||
return .{
|
||||
.predefined = .{
|
||||
|
|
@ -246,6 +258,8 @@ pub const AttributeInfo = union(enum) {
|
|||
.runtime_invisible_annotations => |*runtime_invisible_annotations| runtime_invisible_annotations.deinit(allocator),
|
||||
.runtime_visible_parameter_annotations => |*runtime_visible_parameter_annotations| runtime_visible_parameter_annotations.deinit(allocator),
|
||||
.runtime_invisible_parameter_annotations => |*runtime_invisible_parameter_annotations| runtime_invisible_parameter_annotations.deinit(allocator),
|
||||
.runtime_visible_type_annotations => |*runtime_visible_type_annotations| runtime_visible_type_annotations.deinit(allocator),
|
||||
.runtime_invisible_type_annotations => |*runtime_invisible_type_annotations| runtime_invisible_type_annotations.deinit(allocator),
|
||||
.annotation_default => |*annotation_default| annotation_default.deinit(allocator),
|
||||
.bootstrap_methods => |*bootstrap_methods| bootstrap_methods.deinit(allocator),
|
||||
.method_parameters => |*method_parameters| method_parameters.deinit(allocator),
|
||||
|
|
@ -1857,50 +1871,307 @@ pub const RuntimeInvisibleParameterAnnotations = struct {
|
|||
}
|
||||
};
|
||||
|
||||
// TODO: TypeAnnotation structure
|
||||
// pub const TypeAnnotation = struct {
|
||||
// target_info: union(TargetType) {
|
||||
// type_parameter_target: TypeParameterTarget,
|
||||
// supertype_target: SupertypeTarget,
|
||||
// type_parameter_bound_target: TypeParameterBoundTarget,
|
||||
// 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 TypeAnnotation = struct {
|
||||
target_type: TargetType,
|
||||
target_info: TargetInfo,
|
||||
target_path: TypePath,
|
||||
type_index: u16,
|
||||
element_value_pairs: []ElementValuePair,
|
||||
|
||||
// pub const RuntimeVisibleTypeAnnotations = struct {
|
||||
// type_annotations: []TypeAnnotation,
|
||||
//
|
||||
// const Self = @This();
|
||||
// };
|
||||
//
|
||||
// pub const RuntimeInvisibleTypeAnnotations = struct {
|
||||
// type_annotations: []TypeAnnotation,
|
||||
//
|
||||
// const Self = @This();
|
||||
// };
|
||||
const Self = @This();
|
||||
|
||||
pub const TargetType = enum(u8) {
|
||||
/// type parameter declaration of generic class or interface
|
||||
type_parameter_generic_class_interface = 0x00,
|
||||
/// type parameter declaration of generic method or constructor
|
||||
type_parameter_generic_method_constructor = 0x01,
|
||||
/// type in extends or implements clause of class declaration
|
||||
/// (including the direct superclass or direct superinterface of an anonymous class declaration),
|
||||
/// 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(enum) {
|
||||
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 {
|
||||
default_value: ElementValue,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue