ffi #jni_main: emit name: Type; body members as private Java fields
`#jni_class` body items of the form `name: Type;` were parsed into `ForeignFieldDecl` but dropped by jni_java_emit. They now render as private Java fields between the static init block and the @Override delegates, using the same primitive / `*Foo` → fully-qualified-name type mapping as method parameters. Needed for the chess-on-Pixel `SxApp` Activity to hold its `SurfaceView` reference: `view: SurfaceView;` → `private android.view.SurfaceView view;`.
This commit is contained in:
@@ -269,6 +269,45 @@ test "lib_name renders System.loadLibrary static init block" {
|
||||
try std.testing.expect(std.mem.indexOf(u8, out2, "System.loadLibrary") == null);
|
||||
}
|
||||
|
||||
test "field declarations render as private Java fields" {
|
||||
const a = std.testing.allocator;
|
||||
var arena = std.heap.ArenaAllocator.init(a);
|
||||
defer arena.deinit();
|
||||
const aa = arena.allocator();
|
||||
|
||||
const surface_view_ty = try makePointer(aa, try makeTypeExpr(aa, "SurfaceView"));
|
||||
const int_ty = try makeTypeExpr(aa, "s32");
|
||||
const self_ty = try makePointer(aa, try makeTypeExpr(aa, "Self"));
|
||||
const body = try makeBodyMarker(aa);
|
||||
|
||||
const view_field: ast.ForeignClassMember = .{ .field = .{ .name = "view", .field_type = surface_view_ty } };
|
||||
const w_field: ast.ForeignClassMember = .{ .field = .{ .name = "viewport_w", .field_type = int_ty } };
|
||||
const method: ast.ForeignClassMember = .{ .method = .{
|
||||
.name = "onCreate",
|
||||
.params = &.{self_ty},
|
||||
.param_names = &.{"self"},
|
||||
.return_type = null,
|
||||
.body = body,
|
||||
} };
|
||||
|
||||
var registry = std.StringHashMap([]const u8).init(a);
|
||||
defer registry.deinit();
|
||||
try registry.put("SurfaceView", "android/view/SurfaceView");
|
||||
|
||||
const fcd: ast.ForeignClassDecl = .{
|
||||
.name = "SxApp",
|
||||
.foreign_path = "co/example/SxApp",
|
||||
.runtime = .jni_class,
|
||||
.is_main = true,
|
||||
.members = &.{ view_field, w_field, method },
|
||||
};
|
||||
const out = try emit.emitJavaSource(a, &fcd, .{ .classes = ®istry });
|
||||
defer a.free(out);
|
||||
|
||||
try std.testing.expect(std.mem.indexOf(u8, out, "private android.view.SurfaceView view;") != null);
|
||||
try std.testing.expect(std.mem.indexOf(u8, out, "private int viewport_w;") != null);
|
||||
}
|
||||
|
||||
test "#implements clauses on the class header" {
|
||||
const a = std.testing.allocator;
|
||||
var arena = std.heap.ArenaAllocator.init(a);
|
||||
|
||||
@@ -125,6 +125,20 @@ pub fn emitJavaSource(
|
||||
try buf.appendSlice(allocator, "\"); }\n");
|
||||
}
|
||||
|
||||
// Fields. `name: Type;` body items render as private Java fields —
|
||||
// primitive types pass through, pointer types resolve to fully
|
||||
// qualified Java class names via the class registry.
|
||||
for (fcd.members) |m| switch (m) {
|
||||
.field => |fd| {
|
||||
try buf.appendSlice(allocator, " private ");
|
||||
try emitJavaType(allocator, &buf, fd.field_type, opts);
|
||||
try buf.append(allocator, ' ');
|
||||
try buf.appendSlice(allocator, fd.name);
|
||||
try buf.appendSlice(allocator, ";\n");
|
||||
},
|
||||
else => {},
|
||||
};
|
||||
|
||||
// Two passes: @Override stubs + native delegate; then the native
|
||||
// declarations.
|
||||
for (fcd.members) |m| switch (m) {
|
||||
|
||||
Reference in New Issue
Block a user