Skip to content

Commit 70937eb

Browse files
authored
[jnigen] Use Kotlin signature in the docs of Kotlin methods (#2418)
Fixes #1236.
1 parent 12e33d1 commit 70937eb

File tree

7 files changed

+644
-52
lines changed

7 files changed

+644
-52
lines changed

pkgs/jnigen/example/kotlin_plugin/lib/kotlin_bindings.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ class Example extends jni$_.JObject {
9393
jni$_.JniResult Function(jni$_.Pointer<jni$_.Void>,
9494
jni$_.JMethodIDPtr, jni$_.Pointer<jni$_.Void>)>();
9595

96-
/// from: `public final java.lang.Object thinkBeforeAnswering(kotlin.coroutines.Continuation<? super java.lang.String> continuation)`
96+
/// from: `public suspend fun thinkBeforeAnswering(): kotlin.String`
9797
/// The returned object must be released after use, by calling the [release] method.
9898
core$_.Future<jni$_.JString> thinkBeforeAnswering() async {
9999
final $p = jni$_.ReceivePort();

pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/KotlinFunction.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ public class KotlinFunction {
2727
public int flags;
2828
public boolean isSuspend;
2929
public boolean isOperator;
30+
public boolean isPublic;
31+
public boolean isPrivate;
32+
public boolean isProtected;
33+
public boolean isInternal;
3034

3135
public static KotlinFunction fromKmFunction(KmFunction f) {
3236
var fun = new KotlinFunction();
@@ -52,6 +56,10 @@ public static KotlinFunction fromKmFunction(KmFunction f) {
5256
f.getTypeParameters().stream()
5357
.map(KotlinTypeParameter::fromKmTypeParameter)
5458
.collect(Collectors.toList());
59+
fun.isPublic = Flag.IS_PUBLIC.invoke(fun.flags);
60+
fun.isPrivate = Flag.IS_PRIVATE.invoke(fun.flags);
61+
fun.isProtected = Flag.IS_PROTECTED.invoke(fun.flags);
62+
fun.isInternal = Flag.IS_INTERNAL.invoke(fun.flags);
5563
return fun;
5664
}
5765
}

pkgs/jnigen/lib/src/bindings/dart_generator.dart

Lines changed: 70 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1365,10 +1365,15 @@ ${modifier}final _$name = $_protectedExtension
13651365

13661366
// Docs
13671367
s.write(' /// from: `');
1368-
s.writeAll(node.modifiers.map((m) => '$m '));
1369-
s.write('${node.returnType} ${node.name}(');
1370-
s.writeAll(node.params.map((p) => '${p.type} ${p.name}'), ', ');
1371-
s.writeln(')`');
1368+
if (node.kotlinFunction != null) {
1369+
_writeKotlinSignature(node);
1370+
s.writeln('`');
1371+
} else {
1372+
s.writeAll(node.modifiers.map((m) => '$m '));
1373+
s.write('${node.returnType} ${node.name}(');
1374+
s.writeAll(node.params.map((p) => '${p.type} ${p.name}'), ', ');
1375+
s.writeln(')`');
1376+
}
13721377
if (node.returnType is! PrimitiveType || node.isConstructor) {
13731378
s.writeln(_releaseInstruction);
13741379
}
@@ -1509,6 +1514,67 @@ ${modifier}final _$name = $_protectedExtension
15091514
''');
15101515
}
15111516
}
1517+
1518+
void _writeKotlinSignature(Method node) {
1519+
final kotlinFunction = node.kotlinFunction!;
1520+
final typeParams = [
1521+
...node.classDecl.allTypeParams,
1522+
...node.typeParams,
1523+
];
1524+
1525+
if (kotlinFunction.isPublic) {
1526+
s.write('public ');
1527+
}
1528+
if (kotlinFunction.isPrivate) {
1529+
s.write('private ');
1530+
}
1531+
if (kotlinFunction.isProtected) {
1532+
s.write('protected ');
1533+
}
1534+
if (kotlinFunction.isInternal) {
1535+
s.write('internal ');
1536+
}
1537+
if (kotlinFunction.isSuspend) {
1538+
s.write('suspend ');
1539+
}
1540+
if (kotlinFunction.isOperator) {
1541+
s.write('operator ');
1542+
}
1543+
s.write('fun ');
1544+
final whereClauses = <String>[];
1545+
if (kotlinFunction.typeParameters.isNotEmpty) {
1546+
s.write('<');
1547+
for (final t in kotlinFunction.typeParameters) {
1548+
final typeParameters = t.upperBounds
1549+
.map((bound) => '${t.name} : ${bound.toDocComment(typeParams)}');
1550+
if (typeParameters.length == 1) {
1551+
s.write(typeParameters.single);
1552+
} else {
1553+
s.write(t.name);
1554+
whereClauses.addAll(typeParameters);
1555+
}
1556+
}
1557+
s.write('> ');
1558+
}
1559+
s.write('${kotlinFunction.kotlinName}(');
1560+
s.writeAll(kotlinFunction.valueParameters.map((p) {
1561+
final KotlinType type;
1562+
final String prefix;
1563+
if (p.varargElementType != null) {
1564+
prefix = 'vararg ';
1565+
type = p.varargElementType!;
1566+
} else {
1567+
prefix = '';
1568+
type = p.type;
1569+
}
1570+
return '$prefix${p.name}: ${type.toDocComment(typeParams)}';
1571+
}), ', ');
1572+
s.write('): ${kotlinFunction.returnType.toDocComment(typeParams)}');
1573+
if (whereClauses.isNotEmpty) {
1574+
s.write(' where ');
1575+
s.writeAll(whereClauses, ', ');
1576+
}
1577+
}
15121578
}
15131579

15141580
/// Generates the method type param definition.

pkgs/jnigen/lib/src/elements/elements.dart

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1158,6 +1158,10 @@ class KotlinFunction {
11581158
required this.flags,
11591159
required this.isSuspend,
11601160
required this.isOperator,
1161+
required this.isPublic,
1162+
required this.isPrivate,
1163+
required this.isProtected,
1164+
required this.isInternal,
11611165
});
11621166

11631167
/// Name in the byte code.
@@ -1175,6 +1179,10 @@ class KotlinFunction {
11751179
final int flags;
11761180
final bool isSuspend;
11771181
final bool isOperator;
1182+
final bool isPublic;
1183+
final bool isPrivate;
1184+
final bool isProtected;
1185+
final bool isInternal;
11781186

11791187
factory KotlinFunction.fromJson(Map<String, dynamic> json) =>
11801188
_$KotlinFunctionFromJson(json);
@@ -1282,6 +1290,19 @@ class KotlinType implements Element<KotlinType> {
12821290
R accept<R>(Visitor<KotlinType, R> v) {
12831291
return v.visit(this);
12841292
}
1293+
1294+
String? toDocComment(List<TypeParam> typeParametersByIndex) {
1295+
final typeList = arguments.map((a) => switch (a) {
1296+
KotlinWildcard() => '*',
1297+
KotlinTypeProjection() => a.type.toDocComment(typeParametersByIndex),
1298+
});
1299+
final typeArgs = typeList.isNotEmpty ? '<${typeList.join(', ')}>' : '';
1300+
final typeName = name == null
1301+
? typeParametersByIndex[id].name
1302+
// Translate JVM internal form (aka binary name form) to Kotlin form.
1303+
: name!.replaceAll('/', '.').replaceAll('\$', '.');
1304+
return '$typeName$typeArgs${isNullable ? '?' : ''}';
1305+
}
12851306
}
12861307

12871308
@JsonEnum()

pkgs/jnigen/lib/src/elements/elements.g.dart

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)