[jnigen] Non static nested class construction (https://github.com/dart-lang/jnigen/issues/297)
Construct the non-static nested classes correctly
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/TypeUtils.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/TypeUtils.java
index 7cb6f1e..521c02d 100644
--- a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/TypeUtils.java
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/TypeUtils.java
@@ -20,7 +20,11 @@
class TypeUtils {
public static String parentName(Type type) {
- return type.getClassName().split("\\$")[0];
+ var className = type.getClassName();
+ if (!className.contains("$")) {
+ return null;
+ }
+ return className.split("\\$")[0];
}
public static String simpleName(Type type) {
diff --git a/pkgs/jnigen/lib/src/bindings/c_generator.dart b/pkgs/jnigen/lib/src/bindings/c_generator.dart
index 7ca6ef1..dedef76 100644
--- a/pkgs/jnigen/lib/src/bindings/c_generator.dart
+++ b/pkgs/jnigen/lib/src/bindings/c_generator.dart
@@ -390,9 +390,12 @@
@override
String visit(Param node) {
final paramName =
- _cTypeKeywords.contains(node.name) ? '${node.name}0' : node.name;
- final type = node.type.accept(const _CReturnType());
- if (addReturnType) return '$type $paramName';
+ (_cTypeKeywords.contains(node.name) ? '${node.name}0' : node.name)
+ .replaceAll('\$', '_');
+ if (addReturnType) {
+ final type = node.type.accept(const _CReturnType());
+ return '$type $paramName';
+ }
return paramName;
}
}
diff --git a/pkgs/jnigen/lib/src/bindings/dart_generator.dart b/pkgs/jnigen/lib/src/bindings/dart_generator.dart
index a1559cf..2854e6b 100644
--- a/pkgs/jnigen/lib/src/bindings/dart_generator.dart
+++ b/pkgs/jnigen/lib/src/bindings/dart_generator.dart
@@ -333,7 +333,7 @@
.map((typeParam) => 'this.$typeParam,')
.join(_newLine(depth: 2));
final superClass = (node.classDecl.superclass!.type as DeclaredType);
- final superTypeClassesCall = superClass.classDecl.isObject()
+ final superTypeClassesCall = superClass.classDecl.isObject
? ''
: superClass.params
.accept(_TypeClassGenerator(resolver))
@@ -1331,7 +1331,7 @@
@override
Map<String, List<OutsideInBuffer>> visitDeclaredType(DeclaredType node) {
- if (node.classDecl.isObject()) {
+ if (node.classDecl.isObject) {
return {};
}
final offset = node.classDecl.allTypeParams.length - node.params.length;
diff --git a/pkgs/jnigen/lib/src/bindings/linker.dart b/pkgs/jnigen/lib/src/bindings/linker.dart
index cdddaf5..d6b44a5 100644
--- a/pkgs/jnigen/lib/src/bindings/linker.dart
+++ b/pkgs/jnigen/lib/src/bindings/linker.dart
@@ -92,20 +92,7 @@
log.finest('Linking ${node.binaryName}.');
_linked.add(node);
- node.parent = resolve(node.parentName);
- node.parent!.accept(this);
- // Add type params of outer classes to the nested classes
- final allTypeParams = <TypeParam>[];
- if (!node.modifiers.contains('static')) {
- for (final typeParam in node.parent!.allTypeParams) {
- if (!node.allTypeParams.contains(typeParam)) {
- // Add only if it's not shadowing another type param.
- allTypeParams.add(typeParam);
- }
- }
- }
- allTypeParams.addAll(node.typeParams);
- node.allTypeParams = allTypeParams;
+ node.parent = node.parentName == null ? null : resolve(node.parentName);
final typeLinker = _TypeLinker(resolve);
node.superclass ??= TypeUsage.object;
diff --git a/pkgs/jnigen/lib/src/bindings/renamer.dart b/pkgs/jnigen/lib/src/bindings/renamer.dart
index d5f9a73..607216e 100644
--- a/pkgs/jnigen/lib/src/bindings/renamer.dart
+++ b/pkgs/jnigen/lib/src/bindings/renamer.dart
@@ -65,6 +65,7 @@
'throw',
'true',
'try',
+ 'type', // Is used for type classes.
'typedef',
'var',
'void',
@@ -213,8 +214,8 @@
node.finalName = _renameConflict(nameCounts, name);
node.classDecl.methodNumsAfterRenaming[sig] = nameCounts[name]! - 1;
}
- log.fine(
- 'Method ${node.classDecl.binaryName}#${node.name} is named ${node.finalName}');
+ log.fine('Method ${node.classDecl.binaryName}#${node.name}'
+ ' is named ${node.finalName}');
final paramRenamer = _ParamRenamer(config);
for (final param in node.params) {
@@ -242,8 +243,8 @@
nameCounts,
node.name,
);
- log.fine(
- 'Field ${node.classDecl.binaryName}#${node.name} is named ${node.finalName}');
+ log.fine('Field ${node.classDecl.binaryName}#${node.name}'
+ ' is named ${node.finalName}');
}
}
diff --git a/pkgs/jnigen/lib/src/bindings/unnester.dart b/pkgs/jnigen/lib/src/bindings/unnester.dart
new file mode 100644
index 0000000..0052205
--- /dev/null
+++ b/pkgs/jnigen/lib/src/bindings/unnester.dart
@@ -0,0 +1,83 @@
+// Copyright (c) 2023, 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.
+
+import '../elements/elements.dart';
+import 'visitor.dart';
+
+/// A [Visitor] that processes nested classes.
+///
+/// Nested classes are not supported in Dart. So this "unnests" them into
+/// separate classes.
+class Unnester extends Visitor<Classes, void> {
+ @override
+ void visit(node) {
+ final classProcessor = _ClassUnnester();
+ for (final classDecl in node.decls.values) {
+ classDecl.accept(classProcessor);
+ }
+ }
+}
+
+class _ClassUnnester extends Visitor<ClassDecl, void> {
+ final processed = <ClassDecl>{};
+
+ @override
+ void visit(ClassDecl node) {
+ if (processed.contains(node)) return;
+ processed.add(node);
+ // We need to visit the ancestors first.
+ node.parent?.accept(this);
+
+ // Add type params of outer classes to the nested classes.
+ final allTypeParams = <TypeParam>[];
+ if (!node.isStatic) {
+ allTypeParams.addAll(node.parent?.allTypeParams ?? []);
+ }
+ allTypeParams.addAll(node.typeParams);
+ node.allTypeParams = allTypeParams;
+
+ if (node.isNested && !node.isStatic) {
+ const methodProcessor = _MethodUnnester();
+ for (final method in node.methods) {
+ method.accept(methodProcessor);
+ }
+ }
+ }
+}
+
+class _MethodUnnester extends Visitor<Method, void> {
+ const _MethodUnnester();
+
+ @override
+ void visit(Method node) {
+ assert(!node.classDecl.isStatic);
+ assert(node.classDecl.isNested);
+ if (node.isCtor || node.isStatic) {
+ // Non-static nested classes take an instance of their outer class as the
+ // first parameter. This is not accounted for by the summarizer, so we
+ // manually add it as the first parameter.
+ final parentTypeParamCount = node.classDecl.allTypeParams.length -
+ node.classDecl.typeParams.length;
+ final parentTypeParams = [
+ for (final typeParam
+ in node.classDecl.allTypeParams.take(parentTypeParamCount)) ...[
+ TypeUsage(
+ shorthand: typeParam.name, kind: Kind.typeVariable, typeJson: {})
+ ..type = TypeVar(name: typeParam.name),
+ ]
+ ];
+ final parentType = DeclaredType(
+ binaryName: node.classDecl.parent!.binaryName,
+ params: parentTypeParams,
+ )..classDecl = node.classDecl.parent!;
+ final parentTypeUsage = TypeUsage(
+ shorthand: parentType.binaryName, kind: Kind.declared, typeJson: {})
+ ..type = parentType;
+ final param = Param(name: '\$parent', type: parentTypeUsage);
+ // Make the list modifiable.
+ if (node.params.isEmpty) node.params = [];
+ node.params.insert(0, param);
+ }
+ }
+}
diff --git a/pkgs/jnigen/lib/src/config/config_types.dart b/pkgs/jnigen/lib/src/config/config_types.dart
index 63a418c..58fc9a5 100644
--- a/pkgs/jnigen/lib/src/config/config_types.dart
+++ b/pkgs/jnigen/lib/src/config/config_types.dart
@@ -401,7 +401,8 @@
..finalName = decl['name']
..typeClassName = decl['type_class']
..superCount = decl['super_count']
- ..allTypeParams = [];
+ ..allTypeParams = []
+ ..parent = null;
for (final typeParamEntry
in ((decl['type_params'] as YamlMap?)?.entries) ??
<MapEntry<dynamic, dynamic>>[]) {
diff --git a/pkgs/jnigen/lib/src/elements/elements.dart b/pkgs/jnigen/lib/src/elements/elements.dart
index 15f2f45..51c19b9 100644
--- a/pkgs/jnigen/lib/src/elements/elements.dart
+++ b/pkgs/jnigen/lib/src/elements/elements.dart
@@ -167,7 +167,9 @@
@override
String get name => finalName;
- bool isObject() => superCount == 0;
+ bool get isObject => superCount == 0;
+
+ bool get isNested => parentName != null;
}
@JsonEnum()
@@ -455,7 +457,7 @@
final List<Annotation> annotations;
final JavaDocComment? javadoc;
final List<TypeParam> typeParams;
- final List<Param> params;
+ List<Param> params;
final TypeUsage returnType;
/// The [ClassDecl] where this method is defined.
diff --git a/pkgs/jnigen/lib/src/generate_bindings.dart b/pkgs/jnigen/lib/src/generate_bindings.dart
index 5c9dc9b..87727dc 100644
--- a/pkgs/jnigen/lib/src/generate_bindings.dart
+++ b/pkgs/jnigen/lib/src/generate_bindings.dart
@@ -9,6 +9,7 @@
import 'bindings/dart_generator.dart';
import 'bindings/excluder.dart';
import 'bindings/linker.dart';
+import 'bindings/unnester.dart';
import 'bindings/renamer.dart';
import 'elements/elements.dart';
import 'summary/summary.dart';
@@ -36,6 +37,7 @@
classes.accept(Excluder(config));
await classes.accept(Linker(config));
+ classes.accept(Unnester());
classes.accept(Renamer(config));
final cBased = config.outputConfig.bindingsType == BindingsType.cBased;
diff --git a/pkgs/jnigen/test/simple_package_test/c_based/c_bindings/simple_package.c b/pkgs/jnigen/test/simple_package_test/c_based/c_bindings/simple_package.c
index e388ec7..4a170e7 100644
--- a/pkgs/jnigen/test/simple_package_test/c_based/c_bindings/simple_package.c
+++ b/pkgs/jnigen/test/simple_package_test/c_based/c_bindings/simple_package.c
@@ -1513,7 +1513,7 @@
jmethodID _m_GrandParent_Parent__ctor = NULL;
FFI_PLUGIN_EXPORT
-JniResult GrandParent_Parent__ctor(jobject parentValue, jobject value) {
+JniResult GrandParent_Parent__ctor(jobject _parent, jobject newValue) {
load_env();
load_class_global_ref(
&_c_GrandParent_Parent,
@@ -1521,12 +1521,13 @@
if (_c_GrandParent_Parent == NULL)
return (JniResult){.value = {.j = 0}, .exception = check_exception()};
load_method(_c_GrandParent_Parent, &_m_GrandParent_Parent__ctor, "<init>",
- "(Ljava/lang/Object;Ljava/lang/Object;)V");
+ "(Lcom/github/dart_lang/jnigen/generics/GrandParent;Ljava/lang/"
+ "Object;)V");
if (_m_GrandParent_Parent__ctor == NULL)
return (JniResult){.value = {.j = 0}, .exception = check_exception()};
jobject _result =
(*jniEnv)->NewObject(jniEnv, _c_GrandParent_Parent,
- _m_GrandParent_Parent__ctor, parentValue, value);
+ _m_GrandParent_Parent__ctor, _parent, newValue);
return to_global_ref_result(_result);
}
@@ -1596,9 +1597,7 @@
jmethodID _m_GrandParent_Parent_Child__ctor = NULL;
FFI_PLUGIN_EXPORT
-JniResult GrandParent_Parent_Child__ctor(jobject grandParentValue,
- jobject parentValue,
- jobject value) {
+JniResult GrandParent_Parent_Child__ctor(jobject _parent, jobject newValue) {
load_env();
load_class_global_ref(
&_c_GrandParent_Parent_Child,
@@ -1607,12 +1606,13 @@
return (JniResult){.value = {.j = 0}, .exception = check_exception()};
load_method(_c_GrandParent_Parent_Child, &_m_GrandParent_Parent_Child__ctor,
"<init>",
- "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V");
+ "(Lcom/github/dart_lang/jnigen/generics/GrandParent$Parent;Ljava/"
+ "lang/Object;)V");
if (_m_GrandParent_Parent_Child__ctor == NULL)
return (JniResult){.value = {.j = 0}, .exception = check_exception()};
jobject _result = (*jniEnv)->NewObject(jniEnv, _c_GrandParent_Parent_Child,
_m_GrandParent_Parent_Child__ctor,
- grandParentValue, parentValue, value);
+ _parent, newValue);
return to_global_ref_result(_result);
}
@@ -1773,7 +1773,8 @@
jmethodID _m_GrandParent_StaticParent_Child__ctor = NULL;
FFI_PLUGIN_EXPORT
-JniResult GrandParent_StaticParent_Child__ctor(jobject parentValue,
+JniResult GrandParent_StaticParent_Child__ctor(jobject _parent,
+ jobject parentValue,
jobject value) {
load_env();
load_class_global_ref(
@@ -1781,14 +1782,16 @@
"com/github/dart_lang/jnigen/generics/GrandParent$StaticParent$Child");
if (_c_GrandParent_StaticParent_Child == NULL)
return (JniResult){.value = {.j = 0}, .exception = check_exception()};
- load_method(_c_GrandParent_StaticParent_Child,
- &_m_GrandParent_StaticParent_Child__ctor, "<init>",
- "(Ljava/lang/Object;Ljava/lang/Object;)V");
+ load_method(
+ _c_GrandParent_StaticParent_Child,
+ &_m_GrandParent_StaticParent_Child__ctor, "<init>",
+ "(Lcom/github/dart_lang/jnigen/generics/GrandParent$StaticParent;Ljava/"
+ "lang/Object;Ljava/lang/Object;)V");
if (_m_GrandParent_StaticParent_Child__ctor == NULL)
return (JniResult){.value = {.j = 0}, .exception = check_exception()};
jobject _result = (*jniEnv)->NewObject(
jniEnv, _c_GrandParent_StaticParent_Child,
- _m_GrandParent_StaticParent_Child__ctor, parentValue, value);
+ _m_GrandParent_StaticParent_Child__ctor, _parent, parentValue, value);
return to_global_ref_result(_result);
}
@@ -1934,18 +1937,19 @@
jmethodID _m_MyMap_MyEntry__ctor = NULL;
FFI_PLUGIN_EXPORT
-JniResult MyMap_MyEntry__ctor(jobject key, jobject value) {
+JniResult MyMap_MyEntry__ctor(jobject _parent, jobject key, jobject value) {
load_env();
load_class_global_ref(&_c_MyMap_MyEntry,
"com/github/dart_lang/jnigen/generics/MyMap$MyEntry");
if (_c_MyMap_MyEntry == NULL)
return (JniResult){.value = {.j = 0}, .exception = check_exception()};
load_method(_c_MyMap_MyEntry, &_m_MyMap_MyEntry__ctor, "<init>",
- "(Ljava/lang/Object;Ljava/lang/Object;)V");
+ "(Lcom/github/dart_lang/jnigen/generics/MyMap;Ljava/lang/"
+ "Object;Ljava/lang/Object;)V");
if (_m_MyMap_MyEntry__ctor == NULL)
return (JniResult){.value = {.j = 0}, .exception = check_exception()};
- jobject _result = (*jniEnv)->NewObject(jniEnv, _c_MyMap_MyEntry,
- _m_MyMap_MyEntry__ctor, key, value);
+ jobject _result = (*jniEnv)->NewObject(
+ jniEnv, _c_MyMap_MyEntry, _m_MyMap_MyEntry__ctor, _parent, key, value);
return to_global_ref_result(_result);
}
diff --git a/pkgs/jnigen/test/simple_package_test/c_based/dart_bindings/simple_package.dart b/pkgs/jnigen/test/simple_package_test/c_based/dart_bindings/simple_package.dart
index 5cdec37..4e16f1e 100644
--- a/pkgs/jnigen/test/simple_package_test/c_based/dart_bindings/simple_package.dart
+++ b/pkgs/jnigen/test/simple_package_test/c_based/dart_bindings/simple_package.dart
@@ -1578,22 +1578,22 @@
jni.JniResult Function(
ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
- /// from: public void <init>(T parentValue, S value)
+ /// from: public void <init>(com.github.dart_lang.jnigen.generics.GrandParent $parent, S newValue)
/// The returned object must be deleted after use, by calling the `delete` method.
factory GrandParent_Parent(
- $T parentValue,
- $S value, {
+ GrandParent<$T> $parent,
+ $S newValue, {
jni.JObjType<$T>? T,
jni.JObjType<$S>? S,
}) {
T ??= jni.lowestCommonSuperType([
- parentValue.$type,
+ ($parent.$type as $GrandParentType).T,
]) as jni.JObjType<$T>;
S ??= jni.lowestCommonSuperType([
- value.$type,
+ newValue.$type,
]) as jni.JObjType<$S>;
return GrandParent_Parent.fromRef(
- T, S, _ctor(parentValue.reference, value.reference).object);
+ T, S, _ctor($parent.reference, newValue.reference).object);
}
}
@@ -1747,40 +1747,32 @@
static final _ctor = jniLookup<
ffi.NativeFunction<
- jni.JniResult Function(
- ffi.Pointer<ffi.Void>,
- ffi.Pointer<ffi.Void>,
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
ffi.Pointer<ffi.Void>)>>("GrandParent_Parent_Child__ctor")
.asFunction<
- jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
- ffi.Pointer<ffi.Void>)>();
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
- /// from: public void <init>(T grandParentValue, S parentValue, U value)
+ /// from: public void <init>(com.github.dart_lang.jnigen.generics.GrandParent$Parent $parent, U newValue)
/// The returned object must be deleted after use, by calling the `delete` method.
factory GrandParent_Parent_Child(
- $T grandParentValue,
- $S parentValue,
- $U value, {
+ GrandParent_Parent<$T, $S> $parent,
+ $U newValue, {
jni.JObjType<$T>? T,
jni.JObjType<$S>? S,
jni.JObjType<$U>? U,
}) {
T ??= jni.lowestCommonSuperType([
- grandParentValue.$type,
+ ($parent.$type as $GrandParent_ParentType).T,
]) as jni.JObjType<$T>;
S ??= jni.lowestCommonSuperType([
- parentValue.$type,
+ ($parent.$type as $GrandParent_ParentType).S,
]) as jni.JObjType<$S>;
U ??= jni.lowestCommonSuperType([
- value.$type,
+ newValue.$type,
]) as jni.JObjType<$U>;
return GrandParent_Parent_Child.fromRef(
- T,
- S,
- U,
- _ctor(grandParentValue.reference, parentValue.reference,
- value.reference)
- .object);
+ T, S, U, _ctor($parent.reference, newValue.reference).object);
}
}
@@ -2006,16 +1998,17 @@
static final _ctor = jniLookup<
ffi.NativeFunction<
- jni.JniResult Function(
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
"GrandParent_StaticParent_Child__ctor")
.asFunction<
- jni.JniResult Function(
- ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>();
- /// from: public void <init>(S parentValue, U value)
+ /// from: public void <init>(com.github.dart_lang.jnigen.generics.GrandParent$StaticParent $parent, S parentValue, U value)
/// The returned object must be deleted after use, by calling the `delete` method.
factory GrandParent_StaticParent_Child(
+ GrandParent_StaticParent<$S> $parent,
$S parentValue,
$U value, {
jni.JObjType<$S>? S,
@@ -2023,12 +2016,16 @@
}) {
S ??= jni.lowestCommonSuperType([
parentValue.$type,
+ ($parent.$type as $GrandParent_StaticParentType).S,
]) as jni.JObjType<$S>;
U ??= jni.lowestCommonSuperType([
value.$type,
]) as jni.JObjType<$U>;
return GrandParent_StaticParent_Child.fromRef(
- S, U, _ctor(parentValue.reference, value.reference).object);
+ S,
+ U,
+ _ctor($parent.reference, parentValue.reference, value.reference)
+ .object);
}
}
@@ -2270,15 +2267,18 @@
static final _ctor = jniLookup<
ffi.NativeFunction<
- jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
ffi.Pointer<ffi.Void>)>>("MyMap_MyEntry__ctor")
.asFunction<
- jni.JniResult Function(
- ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>();
- /// from: public void <init>(K key, V value)
+ /// from: public void <init>(com.github.dart_lang.jnigen.generics.MyMap $parent, K key, V value)
/// The returned object must be deleted after use, by calling the `delete` method.
factory MyMap_MyEntry(
+ MyMap<$K, $V> $parent,
$K key,
$V value, {
jni.JObjType<$K>? K,
@@ -2286,12 +2286,14 @@
}) {
K ??= jni.lowestCommonSuperType([
key.$type,
+ ($parent.$type as $MyMapType).K,
]) as jni.JObjType<$K>;
V ??= jni.lowestCommonSuperType([
value.$type,
+ ($parent.$type as $MyMapType).V,
]) as jni.JObjType<$V>;
return MyMap_MyEntry.fromRef(
- K, V, _ctor(key.reference, value.reference).object);
+ K, V, _ctor($parent.reference, key.reference, value.reference).object);
}
}
diff --git a/pkgs/jnigen/test/simple_package_test/dart_only/dart_bindings/simple_package.dart b/pkgs/jnigen/test/simple_package_test/dart_only/dart_bindings/simple_package.dart
index 76effbb..fb92e1d 100644
--- a/pkgs/jnigen/test/simple_package_test/dart_only/dart_bindings/simple_package.dart
+++ b/pkgs/jnigen/test/simple_package_test/dart_only/dart_bindings/simple_package.dart
@@ -1459,27 +1459,29 @@
jni.Jni.env.SetObjectField(reference, _id_value, value.reference);
static final _id_ctor = jni.Jni.accessors.getMethodIDOf(
- _class.reference, r"<init>", r"(Ljava/lang/Object;Ljava/lang/Object;)V");
+ _class.reference,
+ r"<init>",
+ r"(Lcom/github/dart_lang/jnigen/generics/GrandParent;Ljava/lang/Object;)V");
- /// from: public void <init>(T parentValue, S value)
+ /// from: public void <init>(com.github.dart_lang.jnigen.generics.GrandParent $parent, S newValue)
/// The returned object must be deleted after use, by calling the `delete` method.
factory GrandParent_Parent(
- $T parentValue,
- $S value, {
+ GrandParent<$T> $parent,
+ $S newValue, {
jni.JObjType<$T>? T,
jni.JObjType<$S>? S,
}) {
T ??= jni.lowestCommonSuperType([
- parentValue.$type,
+ ($parent.$type as $GrandParentType).T,
]) as jni.JObjType<$T>;
S ??= jni.lowestCommonSuperType([
- value.$type,
+ newValue.$type,
]) as jni.JObjType<$S>;
return GrandParent_Parent.fromRef(
T,
S,
jni.Jni.accessors.newObjectWithArgs(_class.reference, _id_ctor,
- [parentValue.reference, value.reference]).object);
+ [$parent.reference, newValue.reference]).object);
}
}
@@ -1605,37 +1607,35 @@
set value($U value) =>
jni.Jni.env.SetObjectField(reference, _id_value, value.reference);
- static final _id_ctor = jni.Jni.accessors.getMethodIDOf(_class.reference,
- r"<init>", r"(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V");
+ static final _id_ctor = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"<init>",
+ r"(Lcom/github/dart_lang/jnigen/generics/GrandParent$Parent;Ljava/lang/Object;)V");
- /// from: public void <init>(T grandParentValue, S parentValue, U value)
+ /// from: public void <init>(com.github.dart_lang.jnigen.generics.GrandParent$Parent $parent, U newValue)
/// The returned object must be deleted after use, by calling the `delete` method.
factory GrandParent_Parent_Child(
- $T grandParentValue,
- $S parentValue,
- $U value, {
+ GrandParent_Parent<$T, $S> $parent,
+ $U newValue, {
jni.JObjType<$T>? T,
jni.JObjType<$S>? S,
jni.JObjType<$U>? U,
}) {
T ??= jni.lowestCommonSuperType([
- grandParentValue.$type,
+ ($parent.$type as $GrandParent_ParentType).T,
]) as jni.JObjType<$T>;
S ??= jni.lowestCommonSuperType([
- parentValue.$type,
+ ($parent.$type as $GrandParent_ParentType).S,
]) as jni.JObjType<$S>;
U ??= jni.lowestCommonSuperType([
- value.$type,
+ newValue.$type,
]) as jni.JObjType<$U>;
return GrandParent_Parent_Child.fromRef(
T,
S,
U,
- jni.Jni.accessors.newObjectWithArgs(_class.reference, _id_ctor, [
- grandParentValue.reference,
- parentValue.reference,
- value.reference
- ]).object);
+ jni.Jni.accessors.newObjectWithArgs(_class.reference, _id_ctor,
+ [$parent.reference, newValue.reference]).object);
}
}
@@ -1838,11 +1838,14 @@
jni.Jni.env.SetObjectField(reference, _id_value, value.reference);
static final _id_ctor = jni.Jni.accessors.getMethodIDOf(
- _class.reference, r"<init>", r"(Ljava/lang/Object;Ljava/lang/Object;)V");
+ _class.reference,
+ r"<init>",
+ r"(Lcom/github/dart_lang/jnigen/generics/GrandParent$StaticParent;Ljava/lang/Object;Ljava/lang/Object;)V");
- /// from: public void <init>(S parentValue, U value)
+ /// from: public void <init>(com.github.dart_lang.jnigen.generics.GrandParent$StaticParent $parent, S parentValue, U value)
/// The returned object must be deleted after use, by calling the `delete` method.
factory GrandParent_StaticParent_Child(
+ GrandParent_StaticParent<$S> $parent,
$S parentValue,
$U value, {
jni.JObjType<$S>? S,
@@ -1850,6 +1853,7 @@
}) {
S ??= jni.lowestCommonSuperType([
parentValue.$type,
+ ($parent.$type as $GrandParent_StaticParentType).S,
]) as jni.JObjType<$S>;
U ??= jni.lowestCommonSuperType([
value.$type,
@@ -1857,8 +1861,11 @@
return GrandParent_StaticParent_Child.fromRef(
S,
U,
- jni.Jni.accessors.newObjectWithArgs(_class.reference, _id_ctor,
- [parentValue.reference, value.reference]).object);
+ jni.Jni.accessors.newObjectWithArgs(_class.reference, _id_ctor, [
+ $parent.reference,
+ parentValue.reference,
+ value.reference
+ ]).object);
}
}
@@ -2084,11 +2091,14 @@
jni.Jni.env.SetObjectField(reference, _id_value, value.reference);
static final _id_ctor = jni.Jni.accessors.getMethodIDOf(
- _class.reference, r"<init>", r"(Ljava/lang/Object;Ljava/lang/Object;)V");
+ _class.reference,
+ r"<init>",
+ r"(Lcom/github/dart_lang/jnigen/generics/MyMap;Ljava/lang/Object;Ljava/lang/Object;)V");
- /// from: public void <init>(K key, V value)
+ /// from: public void <init>(com.github.dart_lang.jnigen.generics.MyMap $parent, K key, V value)
/// The returned object must be deleted after use, by calling the `delete` method.
factory MyMap_MyEntry(
+ MyMap<$K, $V> $parent,
$K key,
$V value, {
jni.JObjType<$K>? K,
@@ -2096,15 +2106,17 @@
}) {
K ??= jni.lowestCommonSuperType([
key.$type,
+ ($parent.$type as $MyMapType).K,
]) as jni.JObjType<$K>;
V ??= jni.lowestCommonSuperType([
value.$type,
+ ($parent.$type as $MyMapType).V,
]) as jni.JObjType<$V>;
return MyMap_MyEntry.fromRef(
K,
V,
jni.Jni.accessors.newObjectWithArgs(_class.reference, _id_ctor,
- [key.reference, value.reference]).object);
+ [$parent.reference, key.reference, value.reference]).object);
}
}
diff --git a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/generics/GrandParent.java b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/generics/GrandParent.java
index a12675a..b703403 100644
--- a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/generics/GrandParent.java
+++ b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/generics/GrandParent.java
@@ -12,11 +12,11 @@
}
public Parent<String> stringParent() {
- return new Parent<>(value, "Hello");
+ return new Parent<>("Hello");
}
public <S> Parent<S> varParent(S nestedValue) {
- return new Parent<>(value, nestedValue);
+ return new Parent<>(nestedValue);
}
public static StaticParent<String> stringStaticParent() {
@@ -54,9 +54,9 @@
public T parentValue;
public S value;
- public Parent(T parentValue, S value) {
- this.parentValue = parentValue;
- this.value = value;
+ public Parent(S newValue) {
+ parentValue = GrandParent.this.value;
+ value = newValue;
}
public class Child<U> {
@@ -64,10 +64,10 @@
public S parentValue;
public U value;
- public Child(T grandParentValue, S parentValue, U value) {
- this.grandParentValue = grandParentValue;
- this.parentValue = parentValue;
- this.value = value;
+ public Child(U newValue) {
+ this.grandParentValue = GrandParent.this.value;
+ this.parentValue = Parent.this.value;
+ this.value = newValue;
}
}
}
diff --git a/pkgs/jnigen/test/simple_package_test/runtime_test_registrant.dart b/pkgs/jnigen/test/simple_package_test/runtime_test_registrant.dart
index 6472985..f3075ac 100644
--- a/pkgs/jnigen/test/simple_package_test/runtime_test_registrant.dart
+++ b/pkgs/jnigen/test/simple_package_test/runtime_test_registrant.dart
@@ -417,6 +417,22 @@
});
});
});
+ test('Constructing non-static nested classes', () {
+ using((arena) {
+ final grandParent = GrandParent(1.toJInteger())..deletedIn(arena);
+ final parent = GrandParent_Parent(grandParent, 2.toJInteger())
+ ..deletedIn(arena);
+ final child = GrandParent_Parent_Child(parent, 3.toJInteger())
+ ..deletedIn(arena);
+ expect(grandParent.value.intValue(deleteOriginal: true), 1);
+ expect(parent.parentValue.intValue(deleteOriginal: true), 1);
+ expect(parent.value.intValue(deleteOriginal: true), 2);
+ expect(child.grandParentValue.intValue(deleteOriginal: true), 1);
+ expect(child.parentValue.intValue(deleteOriginal: true), 2);
+ expect(child.value.intValue(deleteOriginal: true), 3);
+ });
+ });
+
group('Generic type inference', () {
test('MyStack.of1', () {
using((arena) {