diff --git a/buildSrc/src/main/java/io/github/jwharm/javagi/generator/Builder.java b/buildSrc/src/main/java/io/github/jwharm/javagi/generator/Builder.java index 51de21d3..4224fda8 100644 --- a/buildSrc/src/main/java/io/github/jwharm/javagi/generator/Builder.java +++ b/buildSrc/src/main/java/io/github/jwharm/javagi/generator/Builder.java @@ -94,7 +94,7 @@ public static void generateBuilder(SourceWriter writer, io.github.jwharm.javagi. writer.write("\n"); writer.write("/**\n"); writer.write(" * Finish building the {@code " + c.javaName + "} object. This will call \n"); - writer.write(" * {@link org.gnome.gobject.GObject#newWithProperties} to create a new \n"); + writer.write(" * {@link org.gnome.gobject.GObject#withProperties} to create a new \n"); writer.write(" * GObject instance, which is then cast to {@code " + c.javaName + "}.\n"); writer.write(" * @return A new instance of {@code " + c.javaName + "} with the properties \n"); writer.write(" * that were set in the Builder object.\n"); @@ -107,7 +107,7 @@ public static void generateBuilder(SourceWriter writer, io.github.jwharm.javagi. writer.write("try {\n"); writer.increaseIndent(); c.generatePlatformCheck(writer); - writer.write("return (" + c.qualifiedName + ") org.gnome.gobject.GObject.newWithProperties(\n"); + writer.write("return (" + c.qualifiedName + ") org.gnome.gobject.GObject.withProperties(\n"); writer.write(" " + c.qualifiedName + ".getType(), getNames(), getValues()\n"); writer.write(");\n"); writer.decreaseIndent(); diff --git a/buildSrc/src/main/java/io/github/jwharm/javagi/generator/Conversions.java b/buildSrc/src/main/java/io/github/jwharm/javagi/generator/Conversions.java index a2e3d8d7..a991dfc3 100644 --- a/buildSrc/src/main/java/io/github/jwharm/javagi/generator/Conversions.java +++ b/buildSrc/src/main/java/io/github/jwharm/javagi/generator/Conversions.java @@ -145,7 +145,7 @@ private static String replaceKeywords(String name) { "protected", "throw", "byte", "else", "import", "public", "throws", "case", "enum", "instanceof", "return", "transient", "catch", "extends", "int", "short", "try", "char", "final", "interface", "static", "void", "class", "finally", "long", "strictfp", "volatile", - "const", "float", "native", "super", "while", "wait", "finalize" + "const", "float", "native", "super", "while", "wait", "finalize", "null" }; return Arrays.stream(keywords).anyMatch(kw -> kw.equalsIgnoreCase(name)) ? name + "_" : name; } diff --git a/buildSrc/src/main/java/io/github/jwharm/javagi/generator/Javadoc.java b/buildSrc/src/main/java/io/github/jwharm/javagi/generator/Javadoc.java index d07365bd..492881c0 100644 --- a/buildSrc/src/main/java/io/github/jwharm/javagi/generator/Javadoc.java +++ b/buildSrc/src/main/java/io/github/jwharm/javagi/generator/Javadoc.java @@ -227,7 +227,7 @@ private String convertLink(String link, String type, String path, if ("new".equals(part2)) { return checkLink(part1) + part1 + "#" + part1 + "}"; } else { - return checkLink(part1, part2) + part1 + formatMethod(part2) + "}"; + return checkLink(part1, part2) + part1 + formatMethod(stripNewPrefix(part2)) + "}"; } } else { Namespace ns = getNamespace(part1); @@ -235,7 +235,7 @@ private String convertLink(String link, String type, String path, if ("new".equals(part3)) { return checkLink(part1, part2) + formatNS(part1) + className + "#" + className + "}"; } else { - return checkLink(part1, part2, part3) + formatNS(part1) + className + formatMethod(part3) + "}"; + return checkLink(part1, part2, part3) + formatNS(part1) + className + formatMethod(stripNewPrefix(part3)) + "}"; } } case "method": @@ -403,6 +403,11 @@ private String formatMethod(String name) { return "#" + Conversions.toLowerCaseJavaName(name); } + // Strip "new_" prefix from named constructors + private String stripNewPrefix(String name) { + return name.startsWith("new_") ? name.substring(4) : name; + } + // Format the type as a Java type (with org.package.Class#methodName syntax) private String girElementToString(GirElement girElement, boolean uppercase) { if (girElement == null) { diff --git a/buildSrc/src/main/java/io/github/jwharm/javagi/model/Constructor.java b/buildSrc/src/main/java/io/github/jwharm/javagi/model/Constructor.java index 0b03a3c0..8ca4ca00 100644 --- a/buildSrc/src/main/java/io/github/jwharm/javagi/model/Constructor.java +++ b/buildSrc/src/main/java/io/github/jwharm/javagi/model/Constructor.java @@ -30,6 +30,11 @@ public Constructor(GirElement parent, String name, String cIdentifier, String de super(parent, name, cIdentifier, deprecated, throws_, null, null, null); // constructor helper method has private visibility visibility = "private"; + + // Strip the "new" prefix from named constructors + if (name.startsWith("new_")) { + this.name = name.substring(4); + } } public void generate(SourceWriter writer) throws IOException { diff --git a/buildSrc/src/main/java/io/github/jwharm/javagi/model/Method.java b/buildSrc/src/main/java/io/github/jwharm/javagi/model/Method.java index 82e31c24..ccd6bbdb 100644 --- a/buildSrc/src/main/java/io/github/jwharm/javagi/model/Method.java +++ b/buildSrc/src/main/java/io/github/jwharm/javagi/model/Method.java @@ -173,7 +173,7 @@ public void generate(SourceWriter writer) throws IOException { // Documentation if (this instanceof Constructor) { writer.write("/**\n"); - writer.write(" * Helper function for the {@code " + name + "} constructor\n"); + writer.write(" * Helper function for the {@code " + cIdentifier + "} constructor\n"); writer.write(" */\n"); } else if (doc != null) { doc.generate(writer, false); diff --git a/buildSrc/src/main/java/io/github/jwharm/javagi/patches/GLibPatch.java b/buildSrc/src/main/java/io/github/jwharm/javagi/patches/GLibPatch.java index 8145a475..4b4d5a8a 100644 --- a/buildSrc/src/main/java/io/github/jwharm/javagi/patches/GLibPatch.java +++ b/buildSrc/src/main/java/io/github/jwharm/javagi/patches/GLibPatch.java @@ -21,34 +21,34 @@ public void patch(Repository repo) { pid.isPrimitive = true; // These calls return floating references - setReturnFloating(findConstructor(repo, "Variant", "new_array")); - setReturnFloating(findConstructor(repo, "Variant", "new_boolean")); - setReturnFloating(findConstructor(repo, "Variant", "new_byte")); - setReturnFloating(findConstructor(repo, "Variant", "new_bytestring")); - setReturnFloating(findConstructor(repo, "Variant", "new_bytestring_array")); - setReturnFloating(findConstructor(repo, "Variant", "new_dict_entry")); - setReturnFloating(findConstructor(repo, "Variant", "new_double")); - setReturnFloating(findConstructor(repo, "Variant", "new_fixed_array")); - setReturnFloating(findConstructor(repo, "Variant", "new_from_bytes")); - setReturnFloating(findConstructor(repo, "Variant", "new_handle")); - setReturnFloating(findConstructor(repo, "Variant", "new_int16")); - setReturnFloating(findConstructor(repo, "Variant", "new_int32")); - setReturnFloating(findConstructor(repo, "Variant", "new_int64")); - setReturnFloating(findConstructor(repo, "Variant", "new_maybe")); - setReturnFloating(findConstructor(repo, "Variant", "new_object_path")); - setReturnFloating(findConstructor(repo, "Variant", "new_objv")); - setReturnFloating(findConstructor(repo, "Variant", "new_parsed")); - setReturnFloating(findConstructor(repo, "Variant", "new_parsed_va")); - setReturnFloating(findConstructor(repo, "Variant", "new_printf")); - setReturnFloating(findConstructor(repo, "Variant", "new_signature")); - setReturnFloating(findConstructor(repo, "Variant", "new_string")); - setReturnFloating(findConstructor(repo, "Variant", "new_strv")); - setReturnFloating(findConstructor(repo, "Variant", "new_take_string")); - setReturnFloating(findConstructor(repo, "Variant", "new_tuple")); - setReturnFloating(findConstructor(repo, "Variant", "new_uint16")); - setReturnFloating(findConstructor(repo, "Variant", "new_uint32")); - setReturnFloating(findConstructor(repo, "Variant", "new_uint64")); - setReturnFloating(findConstructor(repo, "Variant", "new_va")); - setReturnFloating(findConstructor(repo, "Variant", "new_variant")); + setReturnFloating(findConstructor(repo, "Variant", "array")); + setReturnFloating(findConstructor(repo, "Variant", "boolean")); + setReturnFloating(findConstructor(repo, "Variant", "byte")); + setReturnFloating(findConstructor(repo, "Variant", "bytestring")); + setReturnFloating(findConstructor(repo, "Variant", "bytestring_array")); + setReturnFloating(findConstructor(repo, "Variant", "dict_entry")); + setReturnFloating(findConstructor(repo, "Variant", "double")); + setReturnFloating(findConstructor(repo, "Variant", "fixed_array")); + setReturnFloating(findConstructor(repo, "Variant", "from_bytes")); + setReturnFloating(findConstructor(repo, "Variant", "handle")); + setReturnFloating(findConstructor(repo, "Variant", "int16")); + setReturnFloating(findConstructor(repo, "Variant", "int32")); + setReturnFloating(findConstructor(repo, "Variant", "int64")); + setReturnFloating(findConstructor(repo, "Variant", "maybe")); + setReturnFloating(findConstructor(repo, "Variant", "object_path")); + setReturnFloating(findConstructor(repo, "Variant", "objv")); + setReturnFloating(findConstructor(repo, "Variant", "parsed")); + setReturnFloating(findConstructor(repo, "Variant", "parsed_va")); + setReturnFloating(findConstructor(repo, "Variant", "printf")); + setReturnFloating(findConstructor(repo, "Variant", "signature")); + setReturnFloating(findConstructor(repo, "Variant", "string")); + setReturnFloating(findConstructor(repo, "Variant", "strv")); + setReturnFloating(findConstructor(repo, "Variant", "take_string")); + setReturnFloating(findConstructor(repo, "Variant", "tuple")); + setReturnFloating(findConstructor(repo, "Variant", "uint16")); + setReturnFloating(findConstructor(repo, "Variant", "uint32")); + setReturnFloating(findConstructor(repo, "Variant", "uint64")); + setReturnFloating(findConstructor(repo, "Variant", "va")); + setReturnFloating(findConstructor(repo, "Variant", "variant")); } } diff --git a/modules/gio/src/test/java/io/github/jwharm/javagi/test/gio/ValueTest.java b/modules/gio/src/test/java/io/github/jwharm/javagi/test/gio/ValueTest.java index f247d6dd..e3cac376 100644 --- a/modules/gio/src/test/java/io/github/jwharm/javagi/test/gio/ValueTest.java +++ b/modules/gio/src/test/java/io/github/jwharm/javagi/test/gio/ValueTest.java @@ -97,7 +97,7 @@ public void objectValue() { @Test public void boxedValue() { // compare a boxed value with its duplicate - Date date = Date.newDmy(new DateDay((byte) 3), DateMonth.JUNE, new DateYear((short) 2023)); + Date date = Date.dmy(new DateDay((byte) 3), DateMonth.JUNE, new DateYear((short) 2023)); Value boxedValue = Value.allocate(Arena.ofAuto()).init(Date.getType()); boxedValue.setBoxed(date.handle()); var copy = boxedValue.dupBoxed(); diff --git a/modules/gobject/src/main/java/io/github/jwharm/javagi/gobject/JavaClosure.java b/modules/gobject/src/main/java/io/github/jwharm/javagi/gobject/JavaClosure.java index 1d2e635b..59f68f8f 100644 --- a/modules/gobject/src/main/java/io/github/jwharm/javagi/gobject/JavaClosure.java +++ b/modules/gobject/src/main/java/io/github/jwharm/javagi/gobject/JavaClosure.java @@ -19,7 +19,6 @@ package io.github.jwharm.javagi.gobject; -import java.lang.foreign.MemorySegment; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -28,7 +27,6 @@ import org.gnome.glib.GLib; import org.gnome.glib.LogLevelFlags; import org.gnome.gobject.Closure; -import org.gnome.gobject.ClosureMarshal; import org.gnome.gobject.Value; import static io.github.jwharm.javagi.Constants.LOG_DOMAIN; @@ -45,8 +43,8 @@ public class JavaClosure extends Closure { * @param callback a callback with signature {@code void run()} */ public JavaClosure(Runnable callback) { - super(Closure.newSimple((int) Closure.getMemoryLayout().byteSize(), null).handle()); - setMarshal((closure, returnValue, args, hint, marshalData) -> callback.run()); + super(Closure.simple((int) Closure.getMemoryLayout().byteSize(), null).handle()); + setMarshal((closure, returnValue, paramValues, hint, data) -> callback.run()); } /** @@ -54,8 +52,11 @@ public JavaClosure(Runnable callback) { * @param callback a callback with signature {@code boolean run()} */ public JavaClosure(BooleanSupplier callback) { - super(Closure.newSimple((int) Closure.getMemoryLayout().byteSize(), null).handle()); - setMarshal((closure, returnValue, args, hint, marshalData) -> returnValue.setBoolean(callback.getAsBoolean())); + super(Closure.simple((int) Closure.getMemoryLayout().byteSize(), null).handle()); + setMarshal((closure, returnValue, paramValues, hint, data) -> { + if (returnValue != null) + returnValue.setBoolean(callback.getAsBoolean()); + }); } /** @@ -112,45 +113,43 @@ public static Method getSingleMethod(Class functionalInterfaceClass) throws I * @param method the method to invoke. See {@link Method#invoke(Object, Object...)} */ public JavaClosure(Object instance, Method method) { - super(Closure.newSimple((int) Closure.getMemoryLayout().byteSize(), null).handle()); - setMarshal(new ClosureMarshal() { - public void run(Closure closure, Value returnValue, Value[] paramValues, MemorySegment invocationHint, MemorySegment marshalData) { - try { - Object[] parameterObjects; - if (paramValues == null || paramValues.length == 0) { - parameterObjects = new Object[0]; - } else { - // Convert the parameter Values into Java Objects - parameterObjects = new Object[paramValues.length - 1]; - for (int v = 1; v < paramValues.length; v++) { - parameterObjects[v - 1] = ValueUtil.valueToObject(paramValues[v]); - } + super(Closure.simple((int) Closure.getMemoryLayout().byteSize(), null).handle()); + setMarshal((closure, returnValue, paramValues, hint, data) -> { + try { + Object[] parameterObjects; + if (paramValues == null || paramValues.length == 0) { + parameterObjects = new Object[0]; + } else { + // Convert the parameter Values into Java Objects + parameterObjects = new Object[paramValues.length - 1]; + for (int v = 1; v < paramValues.length; v++) { + parameterObjects[v - 1] = ValueUtil.valueToObject(paramValues[v]); } - // Invoke the method - method.setAccessible(true); - Object result = method.invoke(instance, parameterObjects); - - // Convert the returned Object to a GValue - ValueUtil.objectToValue(result, returnValue); - } catch (InvocationTargetException e) { - GLib.log( - LOG_DOMAIN, - LogLevelFlags.LEVEL_CRITICAL, - "JavaClosure: Exception in method %s in class %s: %s\n", - method.getName(), - instance == null ? "null" : instance.getClass().getName(), - e.getCause().toString() - ); - } catch (Exception e) { - GLib.log( - LOG_DOMAIN, - LogLevelFlags.LEVEL_CRITICAL, - "JavaClosure: Cannot invoke method %s in class %s: %s\n", - method == null ? "null" : method.getName(), - instance == null ? "null" : instance.getClass().getName(), - e.toString() - ); } + // Invoke the method + method.setAccessible(true); + Object result = method.invoke(instance, parameterObjects); + + // Convert the returned Object to a GValue + ValueUtil.objectToValue(result, returnValue); + } catch (InvocationTargetException e) { + GLib.log( + LOG_DOMAIN, + LogLevelFlags.LEVEL_CRITICAL, + "JavaClosure: Exception in method %s in class %s: %s\n", + method.getName(), + instance == null ? "null" : instance.getClass().getName(), + e.getCause().toString() + ); + } catch (Exception e) { + GLib.log( + LOG_DOMAIN, + LogLevelFlags.LEVEL_CRITICAL, + "JavaClosure: Cannot invoke method %s in class %s: %s\n", + method == null ? "null" : method.getName(), + instance == null ? "null" : instance.getClass().getName(), + e.toString() + ); } }); } diff --git a/modules/gobject/src/main/java/io/github/jwharm/javagi/gobject/types/Properties.java b/modules/gobject/src/main/java/io/github/jwharm/javagi/gobject/types/Properties.java index 60a74dde..22567d50 100644 --- a/modules/gobject/src/main/java/io/github/jwharm/javagi/gobject/types/Properties.java +++ b/modules/gobject/src/main/java/io/github/jwharm/javagi/gobject/types/Properties.java @@ -145,7 +145,7 @@ public static T newGObjectWithProperties(Type objectType, Ob // Create and return the GObject with the property names and values // The cast to T is safe: it will always return the expected GObject-derived objectType @SuppressWarnings("unchecked") - T gobject = (T) GObject.newWithProperties(objectType, names.toArray(new String[0]), values.toArray(new Value[0])); + T gobject = (T) GObject.withProperties(objectType, names.toArray(new String[0]), values.toArray(new Value[0])); return gobject; } finally { typeClass.unref();