Parse access flags

This commit is contained in:
ktkk 2026-06-19 11:35:45 +00:00
parent 1e6be5588a
commit 7d7df22df3
5 changed files with 147 additions and 14 deletions

10
Interface.java Normal file
View file

@ -0,0 +1,10 @@
public interface Interface {
String getName();
default void sayHello() {
System.out.println("Hello " + getName());
}
}

View file

@ -1,19 +1,27 @@
import java.util.concurrent.*;
import java.util.function.Supplier;
public class Main implements Runnable, Callable<Integer> {
private static final String message = "Hello, World";
public class Main implements Runnable, Supplier<Integer>, Interface {
private static final String name = "John";
private static final int number = 42;
private static final double funnyNumber = 6.9;
public static void main() {
System.out.println(message);
new Main().sayHello();
}
@Override
public void run() {
Main.main();
}
public Integer call() {
@Override
public Integer get() {
return number;
}
@Override
public String getName() {
return name;
}
}

View file

@ -17,6 +17,8 @@
nativeBuildInputs = with pkgs; [
zig
zls
javaPackages.compiler.openjdk25
jdt-language-server
];
buildInputs = with pkgs; [];

View file

@ -1,12 +1,14 @@
const std = @import("std");
const EnumFlags = @import("EnumFlags.zig").EnumFlags;
allocator: std.mem.Allocator,
magic: u32,
minor_version: u16,
major_version: u16,
constant_pool: []?CpInfo,
access_flags: u16,
access_flags: ClassAccessFlags,
this_class: u16,
super_class: u16,
interfaces: []u16,
@ -43,7 +45,7 @@ pub fn parse(input: *std.Io.Reader, allocator: std.mem.Allocator) ParseError!Sel
allocator.free(constant_pool);
}
const access_flags = try input.takeInt(u16, .big);
const access_flags: ClassAccessFlags = .{ .mask = try input.takeInt(u16, .big) };
const this_class = try input.takeInt(u16, .big);
const super_class = try input.takeInt(u16, .big);
@ -223,6 +225,8 @@ pub fn format(self: *const Self, w: *std.Io.Writer) std.Io.Writer.Error!void {
try w.print("version: {d}.{d}\n", .{ self.major_version, self.minor_version });
try w.print("flags: {f}\n", .{ self.access_flags });
const this_class = self.thisClass() catch return error.WriteFailed;
_ = try w.write("this class:\n");
try self.formatCpInfo(w, depth, indent + 1, &.{ .class = this_class });
@ -258,7 +262,7 @@ pub fn format(self: *const Self, w: *std.Io.Writer) std.Io.Writer.Error!void {
defer indent -= 1;
try w.splatByteAll(' ', depth * indent);
try w.print("flags: {d}\n", .{ field.access_flags });
try w.print("flags: {f}\n", .{ field.access_flags });
try w.splatByteAll(' ', depth * indent);
_ = try w.write("name:\n");
@ -294,6 +298,9 @@ pub fn format(self: *const Self, w: *std.Io.Writer) std.Io.Writer.Error!void {
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;
@ -478,6 +485,9 @@ fn formatCpInfo(self: *const Self, w: *std.Io.Writer, depth: usize, indent: u8,
try w.print("bytes: \"{s}\"\n", .{ utf8.bytes });
},
.method_handle => |method_handle| {
try w.splatByteAll(' ', depth * indent);
try w.print("kind: {t}\n", .{ method_handle.reference_kind });
try w.splatByteAll(' ', depth * indent);
_ = try w.write("reference:\n");
const reference = method_handle.reference(self.constant_pool) catch return error.WriteFailed;
@ -854,14 +864,27 @@ pub const CpInfo = union(CpInfo.Tag) {
}
};
pub const ClassFlags = enum(u16) {
public = 0x0001,
final = 0x0010,
super = 0x0020,
interface = 0x0200,
abstract = 0x0400,
synthetic = 0x1000,
annotation = 0x2000,
@"enum" = 0x4000,
};
pub const ClassAccessFlags = EnumFlags(ClassFlags);
pub const FieldInfo = struct {
access_flags: u16,
access_flags: FieldAccessFlags,
name_index: u16,
descriptor_index: u16,
attributes: []AttributeInfo,
pub fn parse(input: *std.Io.Reader, allocator: std.mem.Allocator) !FieldInfo {
const access_flags = try input.takeInt(u16, .big);
const access_flags: FieldAccessFlags = .{ .mask = try input.takeInt(u16, .big) };
const name_index = try input.takeInt(u16, .big);
const descriptor_index = try input.takeInt(u16, .big);
const attributes = try parseAttributes(input, allocator);
@ -897,14 +920,28 @@ pub const FieldInfo = struct {
}
};
pub const FieldFlags = enum(u16) {
public = 0x0001,
private = 0x0002,
protected = 0x0004,
static = 0x0008,
final = 0x0010,
@"volatile" = 0x0040,
transient = 0x0080,
synthetic = 0x1000,
@"enum" = 0x4000,
};
pub const FieldAccessFlags = EnumFlags(FieldFlags);
pub const MethodInfo = struct {
access_flags: u16,
access_flags: MethodAccessFlags,
name_index: u16,
descriptor_index: u16,
attributes: []AttributeInfo,
pub fn parse(input: *std.Io.Reader, allocator: std.mem.Allocator) !MethodInfo {
const access_flags = try input.takeInt(u16, .big);
const access_flags: MethodAccessFlags = .{ .mask = try input.takeInt(u16, .big) };
const name_index = try input.takeInt(u16, .big);
const descriptor_index = try input.takeInt(u16, .big);
const attributes = try parseAttributes(input, allocator);
@ -940,6 +977,23 @@ pub const MethodInfo = struct {
}
};
pub const MethodFlags = enum(u16) {
public = 0x0001,
private = 0x0002,
protected = 0x0004,
static = 0x0008,
final = 0x0010,
synchronized = 0x0020,
bridge = 0x0040,
varargs = 0x0080,
native = 0x0100,
abstract = 0x0400,
strict = 0x0800,
synthetic = 0x1000,
};
pub const MethodAccessFlags = EnumFlags(MethodFlags);
pub const AttributeInfo = struct {
attribute_name_index: u16,
info: []u8,
@ -1172,8 +1226,23 @@ pub const AttributeInfo = struct {
inner_class_info_index: u16,
outer_class_info_index: u16,
inner_name_index: u16,
inner_class_access_flags: u16,
inner_class_access_flags: InnerClassAccessFlags,
};
pub const InnerClassFlags = enum(u16) {
public = 0x0001,
private = 0x0002,
protected = 0x0004,
static = 0x0008,
final = 0x0010,
interface = 0x0200,
abstract = 0x0400,
synthetic = 0x1000,
annotation = 0x2000,
@"enum" = 0x4000,
};
pub const InnerClassAccessFlags = EnumFlags(InnerClassFlags);
};
pub const EnclosingMethod = struct {
@ -1534,7 +1603,7 @@ pub const AttributeInfo = struct {
.inner_class_info_index = try r.takeInt(u16, .big),
.outer_class_info_index = try r.takeInt(u16, .big),
.inner_name_index = try r.takeInt(u16, .big),
.inner_class_access_flags = try r.takeInt(u16, .big),
.inner_class_access_flags = .{ .mask = try r.takeInt(u16, .big) },
};
}

44
src/EnumFlags.zig Normal file
View file

@ -0,0 +1,44 @@
const std = @import("std");
pub fn EnumFlags(comptime E: type) type {
return packed struct {
const Self = @This();
const BackingInt = @typeInfo(E).@"enum".tag_type;
mask: BackingInt,
pub const empty: Self = .{ .data = 0 };
pub fn contains(self: Self, flag: E) bool {
return (self.mask & @intFromEnum(flag)) != 0;
}
pub fn insert(self: *Self, flag: E) void {
self.mask |= @intFromEnum(flag);
}
pub fn remove(self: *Self, flag: E) void {
self.mask &= ~@intFromEnum(flag);
}
pub fn toggle(self: *Self, flag: E) void {
self.mask ^= @intFromEnum(flag);
}
pub fn format(self: *const Self, w: *std.Io.Writer) std.Io.Writer.Error!void {
var index: usize = 0;
inline for (std.meta.fields(E)) |field| {
const key = @field(E, field.name);
if (self.contains(key)) {
if (index > 0) {
_ = try w.write(" | ");
}
try w.print("{s}", .{ field.name });
index += 1;
}
}
}
};
}