diff --git a/Interface.java b/Interface.java new file mode 100644 index 0000000..ebe4af3 --- /dev/null +++ b/Interface.java @@ -0,0 +1,10 @@ +public interface Interface { + + String getName(); + + default void sayHello() { + System.out.println("Hello " + getName()); + } + +} + diff --git a/Main.java b/Main.java index 4d7481b..1458098 100644 --- a/Main.java +++ b/Main.java @@ -1,19 +1,27 @@ -import java.util.concurrent.*; +import java.util.function.Supplier; -public class Main implements Runnable, Callable { - private static final String message = "Hello, World"; +public class Main implements Runnable, Supplier, 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; + } } + diff --git a/flake.nix b/flake.nix index d83cf0f..c48263a 100644 --- a/flake.nix +++ b/flake.nix @@ -17,6 +17,8 @@ nativeBuildInputs = with pkgs; [ zig zls + javaPackages.compiler.openjdk25 + jdt-language-server ]; buildInputs = with pkgs; []; diff --git a/src/Class.zig b/src/Class.zig index 3e6bacd..06a1287 100644 --- a/src/Class.zig +++ b/src/Class.zig @@ -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) }, }; } diff --git a/src/EnumFlags.zig b/src/EnumFlags.zig new file mode 100644 index 0000000..9b5da99 --- /dev/null +++ b/src/EnumFlags.zig @@ -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; + } + } + } + }; +} +