From c2ba63528fc9ee75ca3fd07d7e7c490435ac4542 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Fri, 6 Aug 2021 17:09:55 +0000 Subject: [PATCH] Mark function arguments and return values Nullable if relevant Fixes #35. --- bindingstypes.py | 2 ++ genbindings.py | 30 ++++++++++++++++++++++++++++++ java_strings.py | 7 +++++++ 3 files changed, 39 insertions(+) diff --git a/bindingstypes.py b/bindingstypes.py index 2ca6c0de..edb19565 100644 --- a/bindingstypes.py +++ b/bindingstypes.py @@ -65,6 +65,8 @@ class ConvInfo: self.to_hu_conv = to_hu_conv self.to_hu_conv_name = to_hu_conv_name self.from_hu_conv = from_hu_conv + # This is set based on docstrings in various contexts: + self.nullable = False class TraitMethInfo: def __init__(self, fn_name, self_is_const, ret_ty_info, args_ty, docs): diff --git a/genbindings.py b/genbindings.py index 5e8071ec..e8cde683 100755 --- a/genbindings.py +++ b/genbindings.py @@ -70,6 +70,21 @@ def camel_to_snake(s): lastund = True return (ret + lastchar.lower()).strip("_") +def doc_to_params_ret_nullable(doc): + if doc is None: + return (set(), False) + params = set() + ret_null = False + for line in doc.splitlines(): + if "may be NULL or all-0s to represent None" not in line: + continue + if "Note that the return value" in line: + ret_null = True + elif "Note that " in line: + param = line.split("Note that ")[1].split(" ")[0] + params.add(param) + return (params, ret_null) + unitary_enums = set() complex_enums = set() opaque_structs = set() @@ -418,6 +433,10 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: return_type_info = type_mapping_generator.map_type(method_return_type.strip() + " ret", True, ret_arr_len, False, False) + (params_nullable, ret_nullable) = doc_to_params_ret_nullable(doc_comment) + if ret_nullable: + return_type_info.nullable = True + argument_types = [] default_constructor_args = {} takes_self = False @@ -430,7 +449,10 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: takes_self = True if argument_conversion_info.ty_info.is_ptr: takes_self_ptr = True + elif argument_conversion_info.arg_name in params_nullable: + argument_conversion_info.nullable = True if argument_conversion_info.arg_conv is not None and "Warning" in argument_conversion_info.arg_conv: + assert not argument_conversion_info.arg_name in params_nullable if argument_conversion_info.rust_obj in constructor_fns: assert not is_free for explode_arg in constructor_fns[argument_conversion_info.rust_obj].split(','): @@ -576,12 +598,20 @@ with open(sys.argv[1]) as in_h, open(sys.argv[2], "w") as out_java: else: ret_ty_info = type_mapping_generator.map_type(fn_line.group(2).strip() + " ret", True, None, False, False) is_const = fn_line.group(4) is not None + (nullable_params, ret_nullable) = doc_to_params_ret_nullable(fn_docs) + if ret_nullable: + assert False # This isn't yet handled on the Java side + ret_ty_info.nullable = True arg_tys = [] for idx, arg in enumerate(fn_line.group(5).split(',')): if arg == "": continue arg_conv_info = type_mapping_generator.map_type(arg, True, None, False, False) + if arg_conv_info.arg_name in nullable_params: + # Types that are actually null instead of all-0s aren't yet handled on the Java side: + assert arg_conv_info.rust_obj == "LDKPublicKey" + arg_conv_info.nullable = True arg_tys.append(arg_conv_info) field_fns.append(TraitMethInfo(fn_line.group(3), is_const, ret_ty_info, arg_tys, fn_docs)) diff --git a/java_strings.py b/java_strings.py index d4931cd9..82efd47b 100644 --- a/java_strings.py +++ b/java_strings.py @@ -96,6 +96,7 @@ public class bindings { self.util_fn_pfx = """package org.ldk.structs; import org.ldk.impl.bindings; import java.util.Arrays; +import javax.annotation.Nullable; import org.ldk.enums.*; public class UtilMethods { @@ -473,6 +474,7 @@ import org.ldk.impl.bindings; import org.ldk.enums.*; import org.ldk.util.*; import java.util.Arrays; +import javax.annotation.Nullable; """ self.c_fn_ty_pfx = "JNIEXPORT " @@ -1137,6 +1139,8 @@ import java.util.Arrays; meth_n = method_name[len(struct_meth) + 1 if len(struct_meth) != 0 else 0:].strip("_") if doc_comment is not None: out_java_struct += "\t/**\n\t * " + doc_comment.replace("\n", "\n\t * ") + "\n\t */\n" + if return_type_info.nullable: + out_java_struct += "\t@Nullable\n" if not takes_self: if meth_n == "new": out_java_struct += "\tpublic static " + return_type_info.java_hu_ty + " of(" @@ -1154,12 +1158,15 @@ import java.util.Arrays; continue if arg.java_ty != "void": if arg.arg_name in default_constructor_args: + assert not arg.nullable for explode_idx, explode_arg in enumerate(default_constructor_args[arg.arg_name]): if explode_idx != 0: out_java_struct += (", ") out_java_struct += ( explode_arg.java_hu_ty + " " + arg.arg_name + "_" + explode_arg.arg_name) else: + if arg.nullable: + out_java_struct += "@Nullable " out_java_struct += (arg.java_hu_ty + " " + arg.arg_name) out_java += (");\n") out_c += (") {\n") -- 2.30.2