Skip to content

Commit 77e7a14

Browse files
authored
[pigeon] Adds Kotlin documentation comment support (#2665)
1 parent 2b92ce4 commit 77e7a14

File tree

5 files changed

+131
-8
lines changed

5 files changed

+131
-8
lines changed

packages/pigeon/CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 4.2.1
2+
3+
* Adds documentation comment support for Kotlin.
4+
15
## 4.2.0
26

37
* Adds experimental support for Kotlin generation.

packages/pigeon/lib/generator_tools.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import 'dart:mirrors';
99
import 'ast.dart';
1010

1111
/// The current version of pigeon. This must match the version in pubspec.yaml.
12-
const String pigeonVersion = '4.2.0';
12+
const String pigeonVersion = '4.2.1';
1313

1414
/// Read all the content from [stdin] to a String.
1515
String readStdin() {

packages/pigeon/lib/kotlin_generator.dart

+48-6
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,23 @@ import 'functional.dart';
77
import 'generator_tools.dart';
88
import 'pigeon_lib.dart' show TaskQueueType;
99

10+
/// Documentation open symbol.
11+
const String _docCommentPrefix = '/**';
12+
13+
/// Documentation continuation symbol.
14+
const String _docCommentContinuation = ' *';
15+
16+
/// Documentation close symbol.
17+
const String _docCommentSuffix = ' */';
18+
19+
/// Documentation comment spec.
20+
const DocumentCommentSpecification _docCommentSpec =
21+
DocumentCommentSpecification(
22+
_docCommentPrefix,
23+
closeCommentToken: _docCommentSuffix,
24+
blockContinuationToken: _docCommentContinuation,
25+
);
26+
1027
/// Options that control how Kotlin code will be generated.
1128
class KotlinOptions {
1229
/// Creates a [KotlinOptions] object
@@ -112,8 +129,12 @@ void _writeHostApi(Indent indent, Api api, Root root) {
112129

113130
final String apiName = api.name;
114131

115-
indent.writeln(
116-
'/** Generated interface from Pigeon that represents a handler of messages from Flutter. */');
132+
const List<String> generatedMessages = <String>[
133+
' Generated interface from Pigeon that represents a handler of messages from Flutter.'
134+
];
135+
addDocumentationComments(indent, api.documentationComments, _docCommentSpec,
136+
generatorComments: generatedMessages);
137+
117138
indent.write('interface $apiName ');
118139
indent.scoped('{', '}', () {
119140
for (final Method method in api.methods) {
@@ -132,6 +153,10 @@ void _writeHostApi(Indent indent, Api api, Root root) {
132153
final String returnType = method.returnType.isVoid
133154
? ''
134155
: _nullsafeKotlinTypeForDartType(method.returnType);
156+
157+
addDocumentationComments(
158+
indent, method.documentationComments, _docCommentSpec);
159+
135160
if (method.isAsynchronous) {
136161
argSignature.add('callback: ($returnType) -> Unit');
137162
indent.writeln('fun ${method.name}(${argSignature.join(', ')})');
@@ -256,8 +281,12 @@ String _getSafeArgumentName(int count, NamedType argument) =>
256281
/// }
257282
void _writeFlutterApi(Indent indent, Api api) {
258283
assert(api.location == ApiLocation.flutter);
259-
indent.writeln(
260-
'/** Generated class from Pigeon that represents Flutter messages that can be called from Kotlin. */');
284+
const List<String> generatedMessages = <String>[
285+
' Generated class from Pigeon that represents Flutter messages that can be called from Kotlin.'
286+
];
287+
addDocumentationComments(indent, api.documentationComments, _docCommentSpec,
288+
generatorComments: generatedMessages);
289+
261290
final String apiName = api.name;
262291
indent.writeln('@Suppress("UNCHECKED_CAST")');
263292
indent.write('class $apiName(private val binaryMessenger: BinaryMessenger) ');
@@ -277,6 +306,10 @@ void _writeFlutterApi(Indent indent, Api api) {
277306
? ''
278307
: _nullsafeKotlinTypeForDartType(func.returnType);
279308
String sendArgument;
309+
310+
addDocumentationComments(
311+
indent, func.documentationComments, _docCommentSpec);
312+
280313
if (func.arguments.isEmpty) {
281314
indent.write('fun ${func.name}(callback: ($returnType) -> Unit) ');
282315
sendArgument = 'null';
@@ -430,6 +463,8 @@ void generateKotlin(KotlinOptions options, Root root, StringSink sink) {
430463
}
431464

432465
void writeEnum(Enum anEnum) {
466+
addDocumentationComments(
467+
indent, anEnum.documentationComments, _docCommentSpec);
433468
indent.write('enum class ${anEnum.name}(val raw: Int) ');
434469
indent.scoped('{', '}', () {
435470
// We use explicit indexing here as use of the ordinal() method is
@@ -460,6 +495,8 @@ void generateKotlin(KotlinOptions options, Root root, StringSink sink) {
460495

461496
void writeDataClass(Class klass) {
462497
void writeField(NamedType field) {
498+
addDocumentationComments(
499+
indent, field.documentationComments, _docCommentSpec);
463500
indent.write(
464501
'val ${field.name}: ${_nullsafeKotlinTypeForDartType(field.type)}');
465502
final String defaultNil = field.type.isNullable ? ' = null' : '';
@@ -566,8 +603,13 @@ void generateKotlin(KotlinOptions options, Root root, StringSink sink) {
566603
});
567604
}
568605

569-
indent.writeln(
570-
'/** Generated class from Pigeon that represents data sent in messages. */');
606+
const List<String> generatedMessages = <String>[
607+
' Generated class from Pigeon that represents data sent in messages.'
608+
];
609+
addDocumentationComments(
610+
indent, klass.documentationComments, _docCommentSpec,
611+
generatorComments: generatedMessages);
612+
571613
indent.write('data class ${klass.name}(');
572614
indent.scoped('', '', () {
573615
for (final NamedType element in klass.fields) {

packages/pigeon/pubspec.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: pigeon
22
description: Code generator tool to make communication between Flutter and the host platform type-safe and easier.
33
repository: https://github.com/flutter/packages/tree/main/packages/pigeon
44
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3Apigeon
5-
version: 4.2.0 # This must match the version in lib/generator_tools.dart
5+
version: 4.2.1 # This must match the version in lib/generator_tools.dart
66

77
environment:
88
sdk: ">=2.12.0 <3.0.0"

packages/pigeon/test/kotlin_generator_test.dart

+77
Original file line numberDiff line numberDiff line change
@@ -993,4 +993,81 @@ void main() {
993993
final String code = sink.toString();
994994
expect(code, contains('val input: String\n'));
995995
});
996+
997+
test('transfers documentation comments', () {
998+
final List<String> comments = <String>[
999+
' api comment',
1000+
' api method comment',
1001+
' class comment',
1002+
' class field comment',
1003+
' enum comment',
1004+
];
1005+
int count = 0;
1006+
1007+
final Root root = Root(
1008+
apis: <Api>[
1009+
Api(
1010+
name: 'api',
1011+
location: ApiLocation.flutter,
1012+
documentationComments: <String>[comments[count++]],
1013+
methods: <Method>[
1014+
Method(
1015+
name: 'method',
1016+
returnType: const TypeDeclaration.voidDeclaration(),
1017+
documentationComments: <String>[comments[count++]],
1018+
arguments: <NamedType>[
1019+
NamedType(
1020+
name: 'field',
1021+
type: const TypeDeclaration(
1022+
baseName: 'int',
1023+
isNullable: true,
1024+
),
1025+
),
1026+
],
1027+
)
1028+
],
1029+
)
1030+
],
1031+
classes: <Class>[
1032+
Class(
1033+
name: 'class',
1034+
documentationComments: <String>[comments[count++]],
1035+
fields: <NamedType>[
1036+
NamedType(
1037+
documentationComments: <String>[comments[count++]],
1038+
type: const TypeDeclaration(
1039+
baseName: 'Map',
1040+
isNullable: true,
1041+
typeArguments: <TypeDeclaration>[
1042+
TypeDeclaration(baseName: 'String', isNullable: true),
1043+
TypeDeclaration(baseName: 'int', isNullable: true),
1044+
]),
1045+
name: 'field1',
1046+
),
1047+
],
1048+
),
1049+
],
1050+
enums: <Enum>[
1051+
Enum(
1052+
name: 'enum',
1053+
documentationComments: <String>[comments[count++]],
1054+
members: <String>[
1055+
'one',
1056+
'two',
1057+
],
1058+
),
1059+
],
1060+
);
1061+
final StringBuffer sink = StringBuffer();
1062+
const KotlinOptions kotlinOptions = KotlinOptions();
1063+
generateKotlin(kotlinOptions, root, sink);
1064+
final String code = sink.toString();
1065+
for (final String comment in comments) {
1066+
// This regex finds the comment only between the open and close comment block
1067+
expect(
1068+
RegExp(r'(?<=\/\*\*.*?)' + comment + r'(?=.*?\*\/)', dotAll: true)
1069+
.hasMatch(code),
1070+
true);
1071+
}
1072+
});
9961073
}

0 commit comments

Comments
 (0)