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);
|
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" {
|
test "#implements clauses on the class header" {
|
||||||
const a = std.testing.allocator;
|
const a = std.testing.allocator;
|
||||||
var arena = std.heap.ArenaAllocator.init(a);
|
var arena = std.heap.ArenaAllocator.init(a);
|
||||||
|
|||||||
@@ -125,6 +125,20 @@ pub fn emitJavaSource(
|
|||||||
try buf.appendSlice(allocator, "\"); }\n");
|
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
|
// Two passes: @Override stubs + native delegate; then the native
|
||||||
// declarations.
|
// declarations.
|
||||||
for (fcd.members) |m| switch (m) {
|
for (fcd.members) |m| switch (m) {
|
||||||
|
|||||||
Reference in New Issue
Block a user