diff --git a/pkgs/jnigen/example/in_app_java/jnigen.yaml b/pkgs/jnigen/example/in_app_java/jnigen.yaml index e34427068..f77215b14 100644 --- a/pkgs/jnigen/example/in_app_java/jnigen.yaml +++ b/pkgs/jnigen/example/in_app_java/jnigen.yaml @@ -14,3 +14,4 @@ source_path: classes: - 'com.example.in_app_java.AndroidUtils' # from source_path - 'android.os.Build' # from gradle's compile classpath + - 'java.util.HashMap' # from gradle's compile classpath diff --git a/pkgs/jnigen/example/in_app_java/lib/android_utils.dart b/pkgs/jnigen/example/in_app_java/lib/android_utils.dart index 1b6cc084d..6929631cc 100644 --- a/pkgs/jnigen/example/in_app_java/lib/android_utils.dart +++ b/pkgs/jnigen/example/in_app_java/lib/android_utils.dart @@ -407,3 +407,400 @@ extension $BuildArray on jni.JArray { (this as jni.JArray)[index] = value; } } + +/// from: java.util.HashMap +class HashMap + extends jni.JObject { + late final jni.JObjType? _$type; + @override + jni.JObjType get $type => _$type ??= type( + $K, + $V, + ); + + final jni.JObjType $K; + final jni.JObjType $V; + + HashMap.fromRef( + this.$K, + this.$V, + jni.JObjectPtr ref, + ) : super.fromRef(ref); + + /// The type which includes information such as the signature of this class. + static $HashMapType type( + jni.JObjType $K, + jni.JObjType $V, + ) { + return $HashMapType( + $K, + $V, + ); + } + + static final _ctor = jniLookup< + ffi.NativeFunction>( + "HashMap__ctor") + .asFunction(); + + /// from: public void (int i, float f) + HashMap(this.$K, this.$V, int i, double f) + : super.fromRef(_ctor(i, f).object); + + static final _ctor1 = + jniLookup>( + "HashMap__ctor1") + .asFunction(); + + /// from: public void (int i) + HashMap.ctor1(this.$K, this.$V, int i) : super.fromRef(_ctor1(i).object); + + static final _ctor2 = + jniLookup>("HashMap__ctor2") + .asFunction(); + + /// from: public void () + HashMap.ctor2(this.$K, this.$V) : super.fromRef(_ctor2().object); + + static final _ctor3 = jniLookup< + ffi.NativeFunction< + jni.JniResult Function(ffi.Pointer)>>("HashMap__ctor3") + .asFunction)>(); + + /// from: public void (java.util.Map map) + HashMap.ctor3(this.$K, this.$V, jni.JObject map) + : super.fromRef(_ctor3(map.reference).object); + + static final _size = jniLookup< + ffi.NativeFunction< + jni.JniResult Function(ffi.Pointer)>>("HashMap__size") + .asFunction)>(); + + /// from: public int size() + int size() => _size(reference).integer; + + static final _isEmpty = jniLookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer)>>("HashMap__isEmpty") + .asFunction)>(); + + /// from: public boolean isEmpty() + bool isEmpty() => _isEmpty(reference).boolean; + + static final _get0 = jniLookup< + ffi.NativeFunction< + jni.JniResult Function(ffi.Pointer, + ffi.Pointer)>>("HashMap__get0") + .asFunction< + jni.JniResult Function( + ffi.Pointer, ffi.Pointer)>(); + + /// from: public V get(java.lang.Object object) + /// The returned object must be deleted after use, by calling the `delete` method. + V get0(jni.JObject object) => + $V.fromRef(_get0(reference, object.reference).object); + + static final _containsKey = jniLookup< + ffi.NativeFunction< + jni.JniResult Function(ffi.Pointer, + ffi.Pointer)>>("HashMap__containsKey") + .asFunction< + jni.JniResult Function( + ffi.Pointer, ffi.Pointer)>(); + + /// from: public boolean containsKey(java.lang.Object object) + bool containsKey(jni.JObject object) => + _containsKey(reference, object.reference).boolean; + + static final _put = jniLookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer)>>("HashMap__put") + .asFunction< + jni.JniResult Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer)>(); + + /// from: public V put(K object, V object1) + /// The returned object must be deleted after use, by calling the `delete` method. + V put(K object, V object1) => + $V.fromRef(_put(reference, object.reference, object1.reference).object); + + static final _putAll = jniLookup< + ffi.NativeFunction< + jni.JniResult Function(ffi.Pointer, + ffi.Pointer)>>("HashMap__putAll") + .asFunction< + jni.JniResult Function( + ffi.Pointer, ffi.Pointer)>(); + + /// from: public void putAll(java.util.Map map) + void putAll(jni.JObject map) => _putAll(reference, map.reference).check(); + + static final _remove = jniLookup< + ffi.NativeFunction< + jni.JniResult Function(ffi.Pointer, + ffi.Pointer)>>("HashMap__remove") + .asFunction< + jni.JniResult Function( + ffi.Pointer, ffi.Pointer)>(); + + /// from: public V remove(java.lang.Object object) + /// The returned object must be deleted after use, by calling the `delete` method. + V remove(jni.JObject object) => + $V.fromRef(_remove(reference, object.reference).object); + + static final _clear = jniLookup< + ffi.NativeFunction< + jni.JniResult Function(ffi.Pointer)>>("HashMap__clear") + .asFunction)>(); + + /// from: public void clear() + void clear() => _clear(reference).check(); + + static final _containsValue = jniLookup< + ffi.NativeFunction< + jni.JniResult Function(ffi.Pointer, + ffi.Pointer)>>("HashMap__containsValue") + .asFunction< + jni.JniResult Function( + ffi.Pointer, ffi.Pointer)>(); + + /// from: public boolean containsValue(java.lang.Object object) + bool containsValue(jni.JObject object) => + _containsValue(reference, object.reference).boolean; + + static final _keySet = jniLookup< + ffi.NativeFunction< + jni.JniResult Function(ffi.Pointer)>>("HashMap__keySet") + .asFunction)>(); + + /// from: public java.util.Set keySet() + /// The returned object must be deleted after use, by calling the `delete` method. + jni.JObject keySet() => + const jni.JObjectType().fromRef(_keySet(reference).object); + + static final _values = jniLookup< + ffi.NativeFunction< + jni.JniResult Function(ffi.Pointer)>>("HashMap__values") + .asFunction)>(); + + /// from: public java.util.Collection values() + /// The returned object must be deleted after use, by calling the `delete` method. + jni.JObject values() => + const jni.JObjectType().fromRef(_values(reference).object); + + static final _entrySet = jniLookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer)>>("HashMap__entrySet") + .asFunction)>(); + + /// from: public java.util.Set entrySet() + /// The returned object must be deleted after use, by calling the `delete` method. + jni.JObject entrySet() => + const jni.JObjectType().fromRef(_entrySet(reference).object); + + static final _getOrDefault = jniLookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer)>>("HashMap__getOrDefault") + .asFunction< + jni.JniResult Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer)>(); + + /// from: public V getOrDefault(java.lang.Object object, V object1) + /// The returned object must be deleted after use, by calling the `delete` method. + V getOrDefault(jni.JObject object, V object1) => $V.fromRef( + _getOrDefault(reference, object.reference, object1.reference).object); + + static final _putIfAbsent = jniLookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer)>>("HashMap__putIfAbsent") + .asFunction< + jni.JniResult Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer)>(); + + /// from: public V putIfAbsent(K object, V object1) + /// The returned object must be deleted after use, by calling the `delete` method. + V putIfAbsent(K object, V object1) => $V.fromRef( + _putIfAbsent(reference, object.reference, object1.reference).object); + + static final _remove1 = jniLookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer)>>("HashMap__remove1") + .asFunction< + jni.JniResult Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer)>(); + + /// from: public boolean remove(java.lang.Object object, java.lang.Object object1) + bool remove1(jni.JObject object, jni.JObject object1) => + _remove1(reference, object.reference, object1.reference).boolean; + + static final _replace = jniLookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer)>>("HashMap__replace") + .asFunction< + jni.JniResult Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer, ffi.Pointer)>(); + + /// from: public boolean replace(K object, V object1, V object2) + bool replace(K object, V object1, V object2) => _replace( + reference, object.reference, object1.reference, object2.reference) + .boolean; + + static final _replace1 = jniLookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer)>>("HashMap__replace1") + .asFunction< + jni.JniResult Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer)>(); + + /// from: public V replace(K object, V object1) + /// The returned object must be deleted after use, by calling the `delete` method. + V replace1(K object, V object1) => $V.fromRef( + _replace1(reference, object.reference, object1.reference).object); + + static final _computeIfAbsent = jniLookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer)>>("HashMap__computeIfAbsent") + .asFunction< + jni.JniResult Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer)>(); + + /// from: public V computeIfAbsent(K object, java.util.function.Function function) + /// The returned object must be deleted after use, by calling the `delete` method. + V computeIfAbsent(K object, jni.JObject function) => $V.fromRef( + _computeIfAbsent(reference, object.reference, function.reference).object); + + static final _computeIfPresent = jniLookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer)>>("HashMap__computeIfPresent") + .asFunction< + jni.JniResult Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer)>(); + + /// from: public V computeIfPresent(K object, java.util.function.BiFunction biFunction) + /// The returned object must be deleted after use, by calling the `delete` method. + V computeIfPresent(K object, jni.JObject biFunction) => $V.fromRef( + _computeIfPresent(reference, object.reference, biFunction.reference) + .object); + + static final _compute = jniLookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer)>>("HashMap__compute") + .asFunction< + jni.JniResult Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer)>(); + + /// from: public V compute(K object, java.util.function.BiFunction biFunction) + /// The returned object must be deleted after use, by calling the `delete` method. + V compute(K object, jni.JObject biFunction) => $V.fromRef( + _compute(reference, object.reference, biFunction.reference).object); + + static final _merge = jniLookup< + ffi.NativeFunction< + jni.JniResult Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer)>>("HashMap__merge") + .asFunction< + jni.JniResult Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer, ffi.Pointer)>(); + + /// from: public V merge(K object, V object1, java.util.function.BiFunction biFunction) + /// The returned object must be deleted after use, by calling the `delete` method. + V merge(K object, V object1, jni.JObject biFunction) => $V.fromRef(_merge( + reference, object.reference, object1.reference, biFunction.reference) + .object); + + static final _forEach = jniLookup< + ffi.NativeFunction< + jni.JniResult Function(ffi.Pointer, + ffi.Pointer)>>("HashMap__forEach") + .asFunction< + jni.JniResult Function( + ffi.Pointer, ffi.Pointer)>(); + + /// from: public void forEach(java.util.function.BiConsumer biConsumer) + void forEach(jni.JObject biConsumer) => + _forEach(reference, biConsumer.reference).check(); + + static final _replaceAll = jniLookup< + ffi.NativeFunction< + jni.JniResult Function(ffi.Pointer, + ffi.Pointer)>>("HashMap__replaceAll") + .asFunction< + jni.JniResult Function( + ffi.Pointer, ffi.Pointer)>(); + + /// from: public void replaceAll(java.util.function.BiFunction biFunction) + void replaceAll(jni.JObject biFunction) => + _replaceAll(reference, biFunction.reference).check(); + + static final _clone = jniLookup< + ffi.NativeFunction< + jni.JniResult Function(ffi.Pointer)>>("HashMap__clone") + .asFunction)>(); + + /// from: public java.lang.Object clone() + /// The returned object must be deleted after use, by calling the `delete` method. + jni.JObject clone() => + const jni.JObjectType().fromRef(_clone(reference).object); +} + +class $HashMapType + extends jni.JObjType> { + final jni.JObjType $K; + final jni.JObjType $V; + + const $HashMapType( + this.$K, + this.$V, + ); + + @override + String get signature => r"Ljava/util/HashMap;"; + + @override + HashMap fromRef(jni.JObjectPtr ref) => HashMap.fromRef($K, $V, ref); +} + +extension $HashMapArray + on jni.JArray> { + HashMap operator [](int index) { + return (elementType as $HashMapType) + .fromRef(elementAt(index, jni.JniCallType.objectType).object); + } + + void operator []=(int index, HashMap value) { + (this as jni.JArray)[index] = value; + } +} diff --git a/pkgs/jnigen/example/in_app_java/lib/main.dart b/pkgs/jnigen/example/in_app_java/lib/main.dart index 901eb76b0..61c9d2b17 100644 --- a/pkgs/jnigen/example/in_app_java/lib/main.dart +++ b/pkgs/jnigen/example/in_app_java/lib/main.dart @@ -11,9 +11,24 @@ import 'android_utils.dart'; JObject activity = JObject.fromRef(Jni.getCurrentActivity()); -/// Display device model number as Toast +final hashmap = HashMap.ctor2(JString.type, JString.type); + +extension IntX on int { + JString toJString() { + return toString().toJString(); + } +} + +/// Display device model number and the number of times this was called +/// as Toast. void showToast() { - AndroidUtils.showToast(activity, Build.MODEL, 0); + final toastCount = + hashmap.getOrDefault("toastCount".toJString(), 0.toJString()); + final newToastCount = (int.parse(toastCount.toDartString()) + 1).toJString(); + hashmap.put("toastCount".toJString(), newToastCount); + final message = + '${newToastCount.toDartString()} - ${Build.MODEL.toDartString()}'; + AndroidUtils.showToast(activity, message.toJString(), 0); } void main() { diff --git a/pkgs/jnigen/example/in_app_java/src/android_utils/android_utils.c b/pkgs/jnigen/example/in_app_java/src/android_utils/android_utils.c index b1e887aff..1a1cb55cb 100644 --- a/pkgs/jnigen/example/in_app_java/src/android_utils/android_utils.c +++ b/pkgs/jnigen/example/in_app_java/src/android_utils/android_utils.c @@ -472,3 +472,472 @@ JniResult get_Build__USER() { (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__USER)); return (JniResult){.result = {.l = _result}, .exception = check_exception()}; } + +// java.util.HashMap +jclass _c_HashMap = NULL; + +jmethodID _m_HashMap__ctor = NULL; +FFI_PLUGIN_EXPORT +JniResult HashMap__ctor(int32_t i, float f) { + load_env(); + load_class_gr(&_c_HashMap, "java/util/HashMap"); + if (_c_HashMap == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + load_method(_c_HashMap, &_m_HashMap__ctor, "", "(IF)V"); + if (_m_HashMap__ctor == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + jobject _result = + (*jniEnv)->NewObject(jniEnv, _c_HashMap, _m_HashMap__ctor, i, f); + return (JniResult){.result = {.l = to_global_ref(_result)}, + .exception = check_exception()}; +} + +jmethodID _m_HashMap__ctor1 = NULL; +FFI_PLUGIN_EXPORT +JniResult HashMap__ctor1(int32_t i) { + load_env(); + load_class_gr(&_c_HashMap, "java/util/HashMap"); + if (_c_HashMap == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + load_method(_c_HashMap, &_m_HashMap__ctor1, "", "(I)V"); + if (_m_HashMap__ctor1 == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + jobject _result = + (*jniEnv)->NewObject(jniEnv, _c_HashMap, _m_HashMap__ctor1, i); + return (JniResult){.result = {.l = to_global_ref(_result)}, + .exception = check_exception()}; +} + +jmethodID _m_HashMap__ctor2 = NULL; +FFI_PLUGIN_EXPORT +JniResult HashMap__ctor2() { + load_env(); + load_class_gr(&_c_HashMap, "java/util/HashMap"); + if (_c_HashMap == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + load_method(_c_HashMap, &_m_HashMap__ctor2, "", "()V"); + if (_m_HashMap__ctor2 == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + jobject _result = (*jniEnv)->NewObject(jniEnv, _c_HashMap, _m_HashMap__ctor2); + return (JniResult){.result = {.l = to_global_ref(_result)}, + .exception = check_exception()}; +} + +jmethodID _m_HashMap__ctor3 = NULL; +FFI_PLUGIN_EXPORT +JniResult HashMap__ctor3(jobject map) { + load_env(); + load_class_gr(&_c_HashMap, "java/util/HashMap"); + if (_c_HashMap == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + load_method(_c_HashMap, &_m_HashMap__ctor3, "", "(Ljava/util/Map;)V"); + if (_m_HashMap__ctor3 == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + jobject _result = + (*jniEnv)->NewObject(jniEnv, _c_HashMap, _m_HashMap__ctor3, map); + return (JniResult){.result = {.l = to_global_ref(_result)}, + .exception = check_exception()}; +} + +jmethodID _m_HashMap__size = NULL; +FFI_PLUGIN_EXPORT +JniResult HashMap__size(jobject self_) { + load_env(); + load_class_gr(&_c_HashMap, "java/util/HashMap"); + if (_c_HashMap == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + load_method(_c_HashMap, &_m_HashMap__size, "size", "()I"); + if (_m_HashMap__size == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + int32_t _result = (*jniEnv)->CallIntMethod(jniEnv, self_, _m_HashMap__size); + return (JniResult){.result = {.i = _result}, .exception = check_exception()}; +} + +jmethodID _m_HashMap__isEmpty = NULL; +FFI_PLUGIN_EXPORT +JniResult HashMap__isEmpty(jobject self_) { + load_env(); + load_class_gr(&_c_HashMap, "java/util/HashMap"); + if (_c_HashMap == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + load_method(_c_HashMap, &_m_HashMap__isEmpty, "isEmpty", "()Z"); + if (_m_HashMap__isEmpty == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + uint8_t _result = + (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_HashMap__isEmpty); + return (JniResult){.result = {.z = _result}, .exception = check_exception()}; +} + +jmethodID _m_HashMap__get0 = NULL; +FFI_PLUGIN_EXPORT +JniResult HashMap__get0(jobject self_, jobject object) { + load_env(); + load_class_gr(&_c_HashMap, "java/util/HashMap"); + if (_c_HashMap == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + load_method(_c_HashMap, &_m_HashMap__get0, "get", + "(Ljava/lang/Object;)Ljava/lang/Object;"); + if (_m_HashMap__get0 == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + jobject _result = + (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_HashMap__get0, object); + return (JniResult){.result = {.l = to_global_ref(_result)}, + .exception = check_exception()}; +} + +jmethodID _m_HashMap__containsKey = NULL; +FFI_PLUGIN_EXPORT +JniResult HashMap__containsKey(jobject self_, jobject object) { + load_env(); + load_class_gr(&_c_HashMap, "java/util/HashMap"); + if (_c_HashMap == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + load_method(_c_HashMap, &_m_HashMap__containsKey, "containsKey", + "(Ljava/lang/Object;)Z"); + if (_m_HashMap__containsKey == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + uint8_t _result = (*jniEnv)->CallBooleanMethod( + jniEnv, self_, _m_HashMap__containsKey, object); + return (JniResult){.result = {.z = _result}, .exception = check_exception()}; +} + +jmethodID _m_HashMap__put = NULL; +FFI_PLUGIN_EXPORT +JniResult HashMap__put(jobject self_, jobject object, jobject object1) { + load_env(); + load_class_gr(&_c_HashMap, "java/util/HashMap"); + if (_c_HashMap == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + load_method(_c_HashMap, &_m_HashMap__put, "put", + "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); + if (_m_HashMap__put == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_HashMap__put, + object, object1); + return (JniResult){.result = {.l = to_global_ref(_result)}, + .exception = check_exception()}; +} + +jmethodID _m_HashMap__putAll = NULL; +FFI_PLUGIN_EXPORT +JniResult HashMap__putAll(jobject self_, jobject map) { + load_env(); + load_class_gr(&_c_HashMap, "java/util/HashMap"); + if (_c_HashMap == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + load_method(_c_HashMap, &_m_HashMap__putAll, "putAll", "(Ljava/util/Map;)V"); + if (_m_HashMap__putAll == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_HashMap__putAll, map); + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; +} + +jmethodID _m_HashMap__remove = NULL; +FFI_PLUGIN_EXPORT +JniResult HashMap__remove(jobject self_, jobject object) { + load_env(); + load_class_gr(&_c_HashMap, "java/util/HashMap"); + if (_c_HashMap == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + load_method(_c_HashMap, &_m_HashMap__remove, "remove", + "(Ljava/lang/Object;)Ljava/lang/Object;"); + if (_m_HashMap__remove == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + jobject _result = + (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_HashMap__remove, object); + return (JniResult){.result = {.l = to_global_ref(_result)}, + .exception = check_exception()}; +} + +jmethodID _m_HashMap__clear = NULL; +FFI_PLUGIN_EXPORT +JniResult HashMap__clear(jobject self_) { + load_env(); + load_class_gr(&_c_HashMap, "java/util/HashMap"); + if (_c_HashMap == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + load_method(_c_HashMap, &_m_HashMap__clear, "clear", "()V"); + if (_m_HashMap__clear == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_HashMap__clear); + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; +} + +jmethodID _m_HashMap__containsValue = NULL; +FFI_PLUGIN_EXPORT +JniResult HashMap__containsValue(jobject self_, jobject object) { + load_env(); + load_class_gr(&_c_HashMap, "java/util/HashMap"); + if (_c_HashMap == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + load_method(_c_HashMap, &_m_HashMap__containsValue, "containsValue", + "(Ljava/lang/Object;)Z"); + if (_m_HashMap__containsValue == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + uint8_t _result = (*jniEnv)->CallBooleanMethod( + jniEnv, self_, _m_HashMap__containsValue, object); + return (JniResult){.result = {.z = _result}, .exception = check_exception()}; +} + +jmethodID _m_HashMap__keySet = NULL; +FFI_PLUGIN_EXPORT +JniResult HashMap__keySet(jobject self_) { + load_env(); + load_class_gr(&_c_HashMap, "java/util/HashMap"); + if (_c_HashMap == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + load_method(_c_HashMap, &_m_HashMap__keySet, "keySet", "()Ljava/util/Set;"); + if (_m_HashMap__keySet == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + jobject _result = + (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_HashMap__keySet); + return (JniResult){.result = {.l = to_global_ref(_result)}, + .exception = check_exception()}; +} + +jmethodID _m_HashMap__values = NULL; +FFI_PLUGIN_EXPORT +JniResult HashMap__values(jobject self_) { + load_env(); + load_class_gr(&_c_HashMap, "java/util/HashMap"); + if (_c_HashMap == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + load_method(_c_HashMap, &_m_HashMap__values, "values", + "()Ljava/util/Collection;"); + if (_m_HashMap__values == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + jobject _result = + (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_HashMap__values); + return (JniResult){.result = {.l = to_global_ref(_result)}, + .exception = check_exception()}; +} + +jmethodID _m_HashMap__entrySet = NULL; +FFI_PLUGIN_EXPORT +JniResult HashMap__entrySet(jobject self_) { + load_env(); + load_class_gr(&_c_HashMap, "java/util/HashMap"); + if (_c_HashMap == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + load_method(_c_HashMap, &_m_HashMap__entrySet, "entrySet", + "()Ljava/util/Set;"); + if (_m_HashMap__entrySet == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + jobject _result = + (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_HashMap__entrySet); + return (JniResult){.result = {.l = to_global_ref(_result)}, + .exception = check_exception()}; +} + +jmethodID _m_HashMap__getOrDefault = NULL; +FFI_PLUGIN_EXPORT +JniResult HashMap__getOrDefault(jobject self_, + jobject object, + jobject object1) { + load_env(); + load_class_gr(&_c_HashMap, "java/util/HashMap"); + if (_c_HashMap == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + load_method(_c_HashMap, &_m_HashMap__getOrDefault, "getOrDefault", + "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); + if (_m_HashMap__getOrDefault == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + jobject _result = (*jniEnv)->CallObjectMethod( + jniEnv, self_, _m_HashMap__getOrDefault, object, object1); + return (JniResult){.result = {.l = to_global_ref(_result)}, + .exception = check_exception()}; +} + +jmethodID _m_HashMap__putIfAbsent = NULL; +FFI_PLUGIN_EXPORT +JniResult HashMap__putIfAbsent(jobject self_, jobject object, jobject object1) { + load_env(); + load_class_gr(&_c_HashMap, "java/util/HashMap"); + if (_c_HashMap == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + load_method(_c_HashMap, &_m_HashMap__putIfAbsent, "putIfAbsent", + "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); + if (_m_HashMap__putIfAbsent == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + jobject _result = (*jniEnv)->CallObjectMethod( + jniEnv, self_, _m_HashMap__putIfAbsent, object, object1); + return (JniResult){.result = {.l = to_global_ref(_result)}, + .exception = check_exception()}; +} + +jmethodID _m_HashMap__remove1 = NULL; +FFI_PLUGIN_EXPORT +JniResult HashMap__remove1(jobject self_, jobject object, jobject object1) { + load_env(); + load_class_gr(&_c_HashMap, "java/util/HashMap"); + if (_c_HashMap == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + load_method(_c_HashMap, &_m_HashMap__remove1, "remove", + "(Ljava/lang/Object;Ljava/lang/Object;)Z"); + if (_m_HashMap__remove1 == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + uint8_t _result = (*jniEnv)->CallBooleanMethod( + jniEnv, self_, _m_HashMap__remove1, object, object1); + return (JniResult){.result = {.z = _result}, .exception = check_exception()}; +} + +jmethodID _m_HashMap__replace = NULL; +FFI_PLUGIN_EXPORT +JniResult HashMap__replace(jobject self_, + jobject object, + jobject object1, + jobject object2) { + load_env(); + load_class_gr(&_c_HashMap, "java/util/HashMap"); + if (_c_HashMap == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + load_method(_c_HashMap, &_m_HashMap__replace, "replace", + "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Z"); + if (_m_HashMap__replace == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + uint8_t _result = (*jniEnv)->CallBooleanMethod( + jniEnv, self_, _m_HashMap__replace, object, object1, object2); + return (JniResult){.result = {.z = _result}, .exception = check_exception()}; +} + +jmethodID _m_HashMap__replace1 = NULL; +FFI_PLUGIN_EXPORT +JniResult HashMap__replace1(jobject self_, jobject object, jobject object1) { + load_env(); + load_class_gr(&_c_HashMap, "java/util/HashMap"); + if (_c_HashMap == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + load_method(_c_HashMap, &_m_HashMap__replace1, "replace", + "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); + if (_m_HashMap__replace1 == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + jobject _result = (*jniEnv)->CallObjectMethod( + jniEnv, self_, _m_HashMap__replace1, object, object1); + return (JniResult){.result = {.l = to_global_ref(_result)}, + .exception = check_exception()}; +} + +jmethodID _m_HashMap__computeIfAbsent = NULL; +FFI_PLUGIN_EXPORT +JniResult HashMap__computeIfAbsent(jobject self_, + jobject object, + jobject function) { + load_env(); + load_class_gr(&_c_HashMap, "java/util/HashMap"); + if (_c_HashMap == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + load_method( + _c_HashMap, &_m_HashMap__computeIfAbsent, "computeIfAbsent", + "(Ljava/lang/Object;Ljava/util/function/Function;)Ljava/lang/Object;"); + if (_m_HashMap__computeIfAbsent == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + jobject _result = (*jniEnv)->CallObjectMethod( + jniEnv, self_, _m_HashMap__computeIfAbsent, object, function); + return (JniResult){.result = {.l = to_global_ref(_result)}, + .exception = check_exception()}; +} + +jmethodID _m_HashMap__computeIfPresent = NULL; +FFI_PLUGIN_EXPORT +JniResult HashMap__computeIfPresent(jobject self_, + jobject object, + jobject biFunction) { + load_env(); + load_class_gr(&_c_HashMap, "java/util/HashMap"); + if (_c_HashMap == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + load_method( + _c_HashMap, &_m_HashMap__computeIfPresent, "computeIfPresent", + "(Ljava/lang/Object;Ljava/util/function/BiFunction;)Ljava/lang/Object;"); + if (_m_HashMap__computeIfPresent == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + jobject _result = (*jniEnv)->CallObjectMethod( + jniEnv, self_, _m_HashMap__computeIfPresent, object, biFunction); + return (JniResult){.result = {.l = to_global_ref(_result)}, + .exception = check_exception()}; +} + +jmethodID _m_HashMap__compute = NULL; +FFI_PLUGIN_EXPORT +JniResult HashMap__compute(jobject self_, jobject object, jobject biFunction) { + load_env(); + load_class_gr(&_c_HashMap, "java/util/HashMap"); + if (_c_HashMap == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + load_method( + _c_HashMap, &_m_HashMap__compute, "compute", + "(Ljava/lang/Object;Ljava/util/function/BiFunction;)Ljava/lang/Object;"); + if (_m_HashMap__compute == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + jobject _result = (*jniEnv)->CallObjectMethod( + jniEnv, self_, _m_HashMap__compute, object, biFunction); + return (JniResult){.result = {.l = to_global_ref(_result)}, + .exception = check_exception()}; +} + +jmethodID _m_HashMap__merge = NULL; +FFI_PLUGIN_EXPORT +JniResult HashMap__merge(jobject self_, + jobject object, + jobject object1, + jobject biFunction) { + load_env(); + load_class_gr(&_c_HashMap, "java/util/HashMap"); + if (_c_HashMap == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + load_method(_c_HashMap, &_m_HashMap__merge, "merge", + "(Ljava/lang/Object;Ljava/lang/Object;Ljava/util/function/" + "BiFunction;)Ljava/lang/Object;"); + if (_m_HashMap__merge == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + jobject _result = (*jniEnv)->CallObjectMethod( + jniEnv, self_, _m_HashMap__merge, object, object1, biFunction); + return (JniResult){.result = {.l = to_global_ref(_result)}, + .exception = check_exception()}; +} + +jmethodID _m_HashMap__forEach = NULL; +FFI_PLUGIN_EXPORT +JniResult HashMap__forEach(jobject self_, jobject biConsumer) { + load_env(); + load_class_gr(&_c_HashMap, "java/util/HashMap"); + if (_c_HashMap == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + load_method(_c_HashMap, &_m_HashMap__forEach, "forEach", + "(Ljava/util/function/BiConsumer;)V"); + if (_m_HashMap__forEach == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_HashMap__forEach, biConsumer); + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; +} + +jmethodID _m_HashMap__replaceAll = NULL; +FFI_PLUGIN_EXPORT +JniResult HashMap__replaceAll(jobject self_, jobject biFunction) { + load_env(); + load_class_gr(&_c_HashMap, "java/util/HashMap"); + if (_c_HashMap == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + load_method(_c_HashMap, &_m_HashMap__replaceAll, "replaceAll", + "(Ljava/util/function/BiFunction;)V"); + if (_m_HashMap__replaceAll == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_HashMap__replaceAll, biFunction); + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; +} + +jmethodID _m_HashMap__clone = NULL; +FFI_PLUGIN_EXPORT +JniResult HashMap__clone(jobject self_) { + load_env(); + load_class_gr(&_c_HashMap, "java/util/HashMap"); + if (_c_HashMap == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + load_method(_c_HashMap, &_m_HashMap__clone, "clone", "()Ljava/lang/Object;"); + if (_m_HashMap__clone == NULL) + return (JniResult){.result = {.j = 0}, .exception = check_exception()}; + jobject _result = + (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_HashMap__clone); + return (JniResult){.result = {.l = to_global_ref(_result)}, + .exception = check_exception()}; +} diff --git a/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/pdmodel/PDDocument.dart b/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/pdmodel/PDDocument.dart index 4f9512e43..f32c1190c 100644 --- a/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/pdmodel/PDDocument.dart +++ b/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/pdmodel/PDDocument.dart @@ -484,7 +484,7 @@ class PDDocument extends jni.JObject { ///@return a List of PDSignatureFields ///@throws IOException if no document catalog can be found. jni.JObject getSignatureFields() => - jni.JObjectType().fromRef(_getSignatureFields(reference).object); + const jni.JObjectType().fromRef(_getSignatureFields(reference).object); static final _getSignatureDictionaries = jniLookup< ffi.NativeFunction< @@ -498,8 +498,8 @@ class PDDocument extends jni.JObject { /// Retrieve all signature dictionaries from the document. ///@return a List of PDSignatureFields ///@throws IOException if no document catalog can be found. - jni.JObject getSignatureDictionaries() => - jni.JObjectType().fromRef(_getSignatureDictionaries(reference).object); + jni.JObject getSignatureDictionaries() => const jni.JObjectType() + .fromRef(_getSignatureDictionaries(reference).object); static final _registerTrueTypeFontForClosing = jniLookup< ffi.NativeFunction< diff --git a/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/pdmodel/PDDocumentInformation.dart b/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/pdmodel/PDDocumentInformation.dart index f1527676b..46928c010 100644 --- a/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/pdmodel/PDDocumentInformation.dart +++ b/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/pdmodel/PDDocumentInformation.dart @@ -377,7 +377,7 @@ class PDDocumentInformation extends jni.JObject { ///@return all metadata key strings. ///@since Apache PDFBox 1.3.0 jni.JObject getMetadataKeys() => - jni.JObjectType().fromRef(_getMetadataKeys(reference).object); + const jni.JObjectType().fromRef(_getMetadataKeys(reference).object); static final _getCustomMetadataValue = jniLookup< ffi.NativeFunction< diff --git a/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/text/PDFTextStripper.dart b/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/text/PDFTextStripper.dart index 45eea01cb..e442778ff 100644 --- a/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/text/PDFTextStripper.dart +++ b/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/text/PDFTextStripper.dart @@ -100,8 +100,8 @@ class PDFTextStripper extends jni.JObject { /// text after second article /// /// Most PDFs won't have any beads, so charactersByArticle will contain a single entry. - jni.JObject get charactersByArticle => - jni.JObjectType().fromRef(_get_charactersByArticle(reference).object); + jni.JObject get charactersByArticle => const jni.JObjectType() + .fromRef(_get_charactersByArticle(reference).object); static final _set_charactersByArticle = jniLookup< ffi.NativeFunction< jni.JThrowablePtr Function( @@ -642,8 +642,8 @@ class PDFTextStripper extends jni.JObject { /// Character strings are grouped by articles. It is quite common that there will only be a single article. This /// returns a List that contains List objects, the inner lists will contain TextPosition objects. ///@return A double List of TextPositions for all text strings on the page. - jni.JObject getCharactersByArticle() => - jni.JObjectType().fromRef(_getCharactersByArticle(reference).object); + jni.JObject getCharactersByArticle() => const jni.JObjectType() + .fromRef(_getCharactersByArticle(reference).object); static final _setSuppressDuplicateOverlappingText = jniLookup< ffi.NativeFunction< @@ -1191,7 +1191,7 @@ class PDFTextStripper extends jni.JObject { /// This method returns a list of such regular expression Patterns. ///@return a list of Pattern objects. jni.JObject getListItemPatterns() => - jni.JObjectType().fromRef(_getListItemPatterns(reference).object); + const jni.JObjectType().fromRef(_getListItemPatterns(reference).object); static final _matchPattern = jniLookup< ffi.NativeFunction< diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmClassSignatureVisitor.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmClassSignatureVisitor.java new file mode 100644 index 000000000..8805c7f14 --- /dev/null +++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmClassSignatureVisitor.java @@ -0,0 +1,54 @@ +// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +package com.github.dart_lang.jnigen.apisummarizer.disasm; + +import com.github.dart_lang.jnigen.apisummarizer.elements.ClassDecl; +import com.github.dart_lang.jnigen.apisummarizer.elements.TypeParam; +import com.github.dart_lang.jnigen.apisummarizer.elements.TypeUsage; +import org.objectweb.asm.signature.SignatureVisitor; + +public class AsmClassSignatureVisitor extends SignatureVisitor { + private final ClassDecl decl; + private int interfaceIndex = -1; + + public AsmClassSignatureVisitor(ClassDecl decl) { + super(AsmConstants.API); + this.decl = decl; + } + + @Override + public void visitFormalTypeParameter(String name) { + var typeParam = new TypeParam(); + typeParam.name = name; + decl.typeParams.add(typeParam); + } + + @Override + public SignatureVisitor visitClassBound() { + var typeUsage = new TypeUsage(); + // ClassDecl initially has no type parameters. In visitFormalTypeParameter we add them + // and sequentially visitClassBound and visitInterfaceBound. + decl.typeParams.get(decl.typeParams.size() - 1).bounds.add(typeUsage); + return new AsmTypeUsageSignatureVisitor(typeUsage); + } + + @Override + public SignatureVisitor visitInterfaceBound() { + var typeUsage = new TypeUsage(); + decl.typeParams.get(decl.typeParams.size() - 1).bounds.add(typeUsage); + return new AsmTypeUsageSignatureVisitor(typeUsage); + } + + @Override + public SignatureVisitor visitSuperclass() { + return new AsmTypeUsageSignatureVisitor(decl.superclass); + } + + @Override + public SignatureVisitor visitInterface() { + interfaceIndex++; + return new AsmTypeUsageSignatureVisitor(decl.interfaces.get(interfaceIndex)); + } +} diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmClassVisitor.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmClassVisitor.java index c82234201..f542fe86c 100644 --- a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmClassVisitor.java +++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmClassVisitor.java @@ -12,6 +12,7 @@ import com.github.dart_lang.jnigen.apisummarizer.util.StreamUtil; import java.util.*; import org.objectweb.asm.*; +import org.objectweb.asm.signature.SignatureReader; public class AsmClassVisitor extends ClassVisitor implements AsmAnnotatedElementVisitor { private static Param param( @@ -53,6 +54,10 @@ public void visit( current.superclass = TypeUtils.typeUsage(Type.getObjectType(superName), null); current.interfaces = StreamUtil.map(interfaces, i -> TypeUtils.typeUsage(Type.getObjectType(i), null)); + if (signature != null) { + var reader = new SignatureReader(signature); + reader.accept(new AsmClassSignatureVisitor(current)); + } super.visit(version, access, name, signature, superName, interfaces); } @@ -66,11 +71,16 @@ public FieldVisitor visitField( if (name.contains("$")) { return null; } + var field = new Field(); field.name = name; field.type = TypeUtils.typeUsage(Type.getType(descriptor), signature); field.defaultValue = value; field.modifiers = TypeUtils.access(access); + if (signature != null) { + var reader = new SignatureReader(signature); + reader.accept(new AsmTypeUsageSignatureVisitor(field.type)); + } peekVisiting().fields.add(field); return new AsmFieldVisitor(field); } @@ -101,6 +111,10 @@ public MethodVisitor visitMethod( method.returnType = TypeUtils.typeUsage(type.getReturnType(), signature); method.modifiers = TypeUtils.access(access); method.params = params; + if (signature != null) { + var reader = new SignatureReader(signature); + reader.accept(new AsmMethodSignatureVisitor(method)); + } peekVisiting().methods.add(method); return new AsmMethodVisitor(method); } diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmMethodSignatureVisitor.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmMethodSignatureVisitor.java new file mode 100644 index 000000000..9067f9eb9 --- /dev/null +++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmMethodSignatureVisitor.java @@ -0,0 +1,60 @@ +// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +package com.github.dart_lang.jnigen.apisummarizer.disasm; + +import com.github.dart_lang.jnigen.apisummarizer.elements.Method; +import com.github.dart_lang.jnigen.apisummarizer.elements.TypeParam; +import com.github.dart_lang.jnigen.apisummarizer.elements.TypeUsage; +import org.objectweb.asm.signature.SignatureVisitor; + +public class AsmMethodSignatureVisitor extends SignatureVisitor { + private final Method method; + private int paramIndex = -1; + + public AsmMethodSignatureVisitor(Method method) { + super(AsmConstants.API); + this.method = method; + } + + @Override + public void visitFormalTypeParameter(String name) { + var typeParam = new TypeParam(); + typeParam.name = name; + method.typeParams.add(typeParam); + } + + @Override + public SignatureVisitor visitClassBound() { + var typeUsage = new TypeUsage(); + // Method initially has no type parameters. In visitFormalTypeParameter we add them + // and sequentially visitClassBound and visitInterfaceBound. + method.typeParams.get(method.typeParams.size() - 1).bounds.add(typeUsage); + return new AsmTypeUsageSignatureVisitor(typeUsage); + } + + @Override + public SignatureVisitor visitInterfaceBound() { + var typeUsage = new TypeUsage(); + method.typeParams.get(method.typeParams.size() - 1).bounds.add(typeUsage); + return new AsmTypeUsageSignatureVisitor(typeUsage); + } + + @Override + public SignatureVisitor visitReturnType() { + return new AsmTypeUsageSignatureVisitor(method.returnType); + } + + @Override + public SignatureVisitor visitParameterType() { + paramIndex++; + return new AsmTypeUsageSignatureVisitor(method.params.get(paramIndex).type); + } + + @Override + public SignatureVisitor visitExceptionType() { + // Do nothing. + return new AsmTypeUsageSignatureVisitor(new TypeUsage()); + } +} diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmTypeUsageSignatureVisitor.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmTypeUsageSignatureVisitor.java new file mode 100644 index 000000000..dc0f5a477 --- /dev/null +++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmTypeUsageSignatureVisitor.java @@ -0,0 +1,99 @@ +// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +package com.github.dart_lang.jnigen.apisummarizer.disasm; + +import com.github.dart_lang.jnigen.apisummarizer.elements.TypeUsage; +import java.util.ArrayList; +import org.objectweb.asm.signature.SignatureVisitor; + +public class AsmTypeUsageSignatureVisitor extends SignatureVisitor { + private final TypeUsage typeUsage; + + public AsmTypeUsageSignatureVisitor(TypeUsage typeUsage) { + super(AsmConstants.API); + this.typeUsage = typeUsage; + } + + @Override + public void visitBaseType(char descriptor) { + typeUsage.kind = TypeUsage.Kind.PRIMITIVE; + var name = ""; + switch (descriptor) { + case 'Z': + name = "boolean"; + break; + case 'B': + name = "byte"; + break; + case 'C': + name = "char"; + break; + case 'D': + name = "double"; + break; + case 'F': + name = "float"; + break; + case 'I': + name = "int"; + break; + case 'J': + name = "long"; + break; + case 'L': + name = "object"; + break; + case 'S': + name = "short"; + break; + case 'V': + name = "void"; + break; + } + typeUsage.shorthand = name; + typeUsage.type = new TypeUsage.PrimitiveType(name); + } + + @Override + public SignatureVisitor visitArrayType() { + typeUsage.kind = TypeUsage.Kind.ARRAY; + typeUsage.shorthand = "java.lang.Object[]"; + var elementType = new TypeUsage(); + typeUsage.type = new TypeUsage.Array(elementType); + return new AsmTypeUsageSignatureVisitor(elementType); + } + + @Override + public void visitTypeVariable(String name) { + typeUsage.kind = TypeUsage.Kind.TYPE_VARIABLE; + typeUsage.shorthand = name; + typeUsage.type = new TypeUsage.TypeVar(name); + } + + @Override + public void visitClassType(String name) { + typeUsage.kind = TypeUsage.Kind.DECLARED; + typeUsage.shorthand = name.substring(0, name.length()).replace('/', '.'); + var components = name.split("[/$]"); + var simpleName = components[components.length - 1]; + typeUsage.type = new TypeUsage.DeclaredType(name, simpleName, new ArrayList<>()); + } + + @Override + public SignatureVisitor visitTypeArgument(char wildcard) { + // TODO(#141) support wildcards + // TODO(#144) support extend/super clauses + assert (typeUsage.type instanceof TypeUsage.DeclaredType); + var typeArg = new TypeUsage(); + ((TypeUsage.DeclaredType) typeUsage.type).params.add(typeArg); + return new AsmTypeUsageSignatureVisitor(typeArg); + } + + @Override + public void visitInnerClassType(String name) { + super.visitInnerClassType(name); + // TODO(#139) support nested generic classes + } +} diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/ClassDecl.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/ClassDecl.java index 8131a553b..42e069e4f 100644 --- a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/ClassDecl.java +++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/ClassDecl.java @@ -32,11 +32,11 @@ public class ClassDecl { public String parentName; public String packageName; - public List typeParams; + public List typeParams = new ArrayList<>(); public List methods = new ArrayList<>(); public List fields = new ArrayList<>(); public TypeUsage superclass; - public List interfaces; + public List interfaces = new ArrayList<>(); public boolean hasStaticInit; public boolean hasInstanceInit; public JavaDocComment javadoc; diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/Method.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/Method.java index bb558f472..0711c10c1 100644 --- a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/Method.java +++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/Method.java @@ -12,7 +12,7 @@ public class Method { public Set modifiers = new HashSet<>(); public String name; - public List typeParams; + public List typeParams = new ArrayList<>(); public List params = new ArrayList<>(); public TypeUsage returnType; diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/TypeParam.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/TypeParam.java index 9045578ee..8172ee6d8 100644 --- a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/TypeParam.java +++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/TypeParam.java @@ -4,9 +4,10 @@ package com.github.dart_lang.jnigen.apisummarizer.elements; +import java.util.ArrayList; import java.util.List; public class TypeParam { public String name; - public List bounds; + public List bounds = new ArrayList<>(); } diff --git a/pkgs/jnigen/lib/src/bindings/common.dart b/pkgs/jnigen/lib/src/bindings/common.dart index 5c5a2c831..19fba1139 100644 --- a/pkgs/jnigen/lib/src/bindings/common.dart +++ b/pkgs/jnigen/lib/src/bindings/common.dart @@ -320,15 +320,16 @@ abstract class BindingsGenerator { if (resolver != null) { final type = t.type as DeclaredType; final resolved = resolver.resolve(type.binaryName); - if (resolved == null) { + final resolvedClass = resolver.resolveClass(type.binaryName); + if (resolved == null || + resolvedClass == null || + !resolvedClass.isIncluded) { return jniObjectType; } // All type parameters of this type final allTypeParams = - (resolver.resolveClass(type.binaryName)?.allTypeParams ?? []) - .map((param) => param.name) - .toList(); + resolvedClass.allTypeParams.map((param) => param.name).toList(); // The ones that are declared. final paramTypeClasses = @@ -405,11 +406,19 @@ abstract class BindingsGenerator { final resolved = resolver.resolve(type.binaryName); final resolvedClass = resolver.resolveClass(type.binaryName); + if (resolved == null || + resolvedClass == null || + !resolvedClass.isIncluded) { + return _TypeClass( + '${addConst ? 'const ' : ''}$jniObjectTypeClass()', + true, + ); + } + // All type params of this type - final allTypeParams = resolvedClass?.allTypeParams - .map((param) => '$typeParamPrefix${param.name}') - .toList() ?? - []; + final allTypeParams = resolvedClass.allTypeParams + .map((param) => '$typeParamPrefix${param.name}') + .toList(); // The ones that are declared. final paramTypeClasses = type.params.map( @@ -426,11 +435,12 @@ abstract class BindingsGenerator { final args = allTypeParams.join(','); - final canBeConst = allTypeParams.length == paramTypeClasses.length && - paramTypeClasses.every((e) => e.canBeConst); + final canBeConst = (allTypeParams.length == paramTypeClasses.length && + paramTypeClasses.every((e) => e.canBeConst)) || + allTypeParams.isEmpty; final ifConst = addConst && canBeConst ? 'const ' : ''; - if (resolved == null || resolved == jniObjectType) { + if (resolved == jniObjectType) { return _TypeClass('$ifConst$jniObjectTypeClass()', true); } else if (resolved == jniStringType) { return _TypeClass('$ifConst$jniStringTypeClass()', true); diff --git a/pkgs/jnigen/lib/src/writers/files_writer.dart b/pkgs/jnigen/lib/src/writers/files_writer.dart index 9e78ea341..73619152d 100644 --- a/pkgs/jnigen/lib/src/writers/files_writer.dart +++ b/pkgs/jnigen/lib/src/writers/files_writer.dart @@ -34,6 +34,16 @@ class FilePathResolver implements SymbolResolver { 'java.lang.String': 'jni.JString', }; + static final predefinedClasses = { + 'java.lang.String': ClassDecl( + binaryName: 'java.lang.String', + packageName: 'java.lang', + simpleName: 'String', + ) + ..isIncluded = true + ..isPreprocessed = true, + }; + /// A map of all classes by their names final Map classes; @@ -165,6 +175,9 @@ class FilePathResolver implements SymbolResolver { @override ClassDecl? resolveClass(String binaryName) { + if (predefinedClasses.containsKey(binaryName)) { + return predefinedClasses[binaryName]; + } return classes[binaryName]; } } diff --git a/pkgs/jnigen/lib/src/writers/single_file_writer.dart b/pkgs/jnigen/lib/src/writers/single_file_writer.dart index ee6875fe0..8d8e5c745 100644 --- a/pkgs/jnigen/lib/src/writers/single_file_writer.dart +++ b/pkgs/jnigen/lib/src/writers/single_file_writer.dart @@ -14,6 +14,15 @@ class SingleFileResolver implements SymbolResolver { static const predefined = { 'java.lang.String': 'jni.JString', }; + static final predefinedClasses = { + 'java.lang.String': ClassDecl( + binaryName: 'java.lang.String', + packageName: 'java.lang', + simpleName: 'String', + ) + ..isIncluded = true + ..isPreprocessed = true, + }; Map inputClasses; SingleFileResolver(this.inputClasses); @override @@ -29,6 +38,9 @@ class SingleFileResolver implements SymbolResolver { @override ClassDecl? resolveClass(String binaryName) { + if (predefinedClasses.containsKey(binaryName)) { + return predefinedClasses[binaryName]; + } return inputClasses[binaryName]; } } diff --git a/pkgs/jnigen/test/jackson_core_test/generate.dart b/pkgs/jnigen/test/jackson_core_test/generate.dart index 37749d5cb..c804e5792 100644 --- a/pkgs/jnigen/test/jackson_core_test/generate.dart +++ b/pkgs/jnigen/test/jackson_core_test/generate.dart @@ -56,13 +56,17 @@ Config getConfig( ], logLevel: Level.INFO, exclude: BindingExclusions( - fields: excludeAll([ - ['com.fasterxml.jackson.core.JsonFactory', 'DEFAULT_QUOTE_CHAR'], - ['com.fasterxml.jackson.core.Base64Variant', 'PADDING_CHAR_NONE'], - ['com.fasterxml.jackson.core.base.ParserMinimalBase', 'CHAR_NULL'], - ['com.fasterxml.jackson.core.io.UTF32Reader', 'NC'], - ]), - ), + // TODO(#31): Remove field exclusions. + fields: excludeAll([ + ['com.fasterxml.jackson.core.JsonFactory', 'DEFAULT_QUOTE_CHAR'], + ['com.fasterxml.jackson.core.Base64Variant', 'PADDING_CHAR_NONE'], + ['com.fasterxml.jackson.core.base.ParserMinimalBase', 'CHAR_NULL'], + ['com.fasterxml.jackson.core.io.UTF32Reader', 'NC'], + ]), + // TODO(#159): Remove class exclusions. + classes: ClassNameFilter.exclude( + 'com.fasterxml.jackson.core.JsonFactoryBuilder', + )), ); return config; } diff --git a/pkgs/jnigen/test/jackson_core_test/third_party/lib/com/fasterxml/jackson/core/JsonFactory.dart b/pkgs/jnigen/test/jackson_core_test/third_party/lib/com/fasterxml/jackson/core/JsonFactory.dart index 32377ce53..be5fc9f29 100644 --- a/pkgs/jnigen/test/jackson_core_test/third_party/lib/com/fasterxml/jackson/core/JsonFactory.dart +++ b/pkgs/jnigen/test/jackson_core_test/third_party/lib/com/fasterxml/jackson/core/JsonFactory.dart @@ -205,7 +205,7 @@ class JsonFactory extends jni.JObject { ///@return Builder instance to use ///@since 2.10 jni.JObject rebuild() => - jni.JObjectType().fromRef(jniAccessors.callMethodWithArgs( + const jni.JObjectType().fromRef(jniAccessors.callMethodWithArgs( reference, _id_rebuild, jni.JniCallType.objectType, []).object); static final _id_builder = jniAccessors.getStaticMethodIDOf( @@ -223,7 +223,7 @@ class JsonFactory extends jni.JObject { /// will be fixed in 3.0. ///@return Builder instance to use static jni.JObject builder() => - jni.JObjectType().fromRef(jniAccessors.callStaticMethodWithArgs( + const jni.JObjectType().fromRef(jniAccessors.callStaticMethodWithArgs( _classRef, _id_builder, jni.JniCallType.objectType, []).object); static final _id_copy = jniAccessors.getMethodIDOf( @@ -345,7 +345,7 @@ class JsonFactory extends jni.JObject { /// from: public java.lang.Class getFormatReadFeatureType() /// The returned object must be deleted after use, by calling the `delete` method. jni.JObject getFormatReadFeatureType() => - jni.JObjectType().fromRef(jniAccessors.callMethodWithArgs(reference, + const jni.JObjectType().fromRef(jniAccessors.callMethodWithArgs(reference, _id_getFormatReadFeatureType, jni.JniCallType.objectType, []).object); static final _id_getFormatWriteFeatureType = jniAccessors.getMethodIDOf( @@ -354,7 +354,7 @@ class JsonFactory extends jni.JObject { /// from: public java.lang.Class getFormatWriteFeatureType() /// The returned object must be deleted after use, by calling the `delete` method. jni.JObject getFormatWriteFeatureType() => - jni.JObjectType().fromRef(jniAccessors.callMethodWithArgs( + const jni.JObjectType().fromRef(jniAccessors.callMethodWithArgs( reference, _id_getFormatWriteFeatureType, jni.JniCallType.objectType, []).object); diff --git a/pkgs/jnigen/test/jackson_core_test/third_party/lib/com/fasterxml/jackson/core/JsonParser.dart b/pkgs/jnigen/test/jackson_core_test/third_party/lib/com/fasterxml/jackson/core/JsonParser.dart index 4d049fb3e..2e1305edb 100644 --- a/pkgs/jnigen/test/jackson_core_test/third_party/lib/com/fasterxml/jackson/core/JsonParser.dart +++ b/pkgs/jnigen/test/jackson_core_test/third_party/lib/com/fasterxml/jackson/core/JsonParser.dart @@ -72,7 +72,7 @@ class JsonParser extends jni.JObject { /// set needs to be passed). ///@since 2.12 static jni.JObject get DEFAULT_READ_CAPABILITIES => - jni.JObjectType().fromRef(jniAccessors + const jni.JObjectType().fromRef(jniAccessors .getStaticField(_classRef, _id_DEFAULT_READ_CAPABILITIES, jni.JniCallType.objectType) .object); @@ -305,7 +305,7 @@ class JsonParser extends jni.JObject { ///@return Set of read capabilities for content to read via this parser ///@since 2.12 jni.JObject getReadCapabilities() => - jni.JObjectType().fromRef(jniAccessors.callMethodWithArgs(reference, + const jni.JObjectType().fromRef(jniAccessors.callMethodWithArgs(reference, _id_getReadCapabilities, jni.JniCallType.objectType, []).object); static final _id_version = jniAccessors.getMethodIDOf( @@ -2144,7 +2144,7 @@ class JsonParser extends jni.JObject { /// issue at format layer jni.JObject readValuesAs( jni.JObjType $T, jni.JObject valueType) => - jni.JObjectType().fromRef(jniAccessors.callMethodWithArgs( + const jni.JObjectType().fromRef(jniAccessors.callMethodWithArgs( reference, _id_readValuesAs, jni.JniCallType.objectType, @@ -2168,7 +2168,7 @@ class JsonParser extends jni.JObject { /// issue at format layer jni.JObject readValuesAs1( jni.JObjType $T, jni.JObject valueTypeRef) => - jni.JObjectType().fromRef(jniAccessors.callMethodWithArgs( + const jni.JObjectType().fromRef(jniAccessors.callMethodWithArgs( reference, _id_readValuesAs1, jni.JniCallType.objectType, diff --git a/pkgs/jnigen/test/simple_package_test/generate.dart b/pkgs/jnigen/test/simple_package_test/generate.dart index 657dd9048..962fe17b5 100644 --- a/pkgs/jnigen/test/simple_package_test/generate.dart +++ b/pkgs/jnigen/test/simple_package_test/generate.dart @@ -39,7 +39,7 @@ void compileJavaSources(String workingDir, List files) async { final procRes = Process.runSync('javac', files, workingDirectory: workingDir); if (procRes.exitCode != 0) { throw "javac exited with ${procRes.exitCode}\n" - "$procRes.stderr"; + "${procRes.stderr}"; } } diff --git a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/generics/StringValuedMap.java b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/generics/StringValuedMap.java index 0f025b873..c005ae0d3 100644 --- a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/generics/StringValuedMap.java +++ b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/generics/StringValuedMap.java @@ -1,3 +1,7 @@ +// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + package com.github.dart_lang.jnigen.generics; public class StringValuedMap extends MyMap {}