Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/pigeon/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 26.1.8

* [kotlin] Adds option to add javax.annotation.Generated annotation.

## 26.1.7

* [objc] Updates to use module imports.
Expand Down
6 changes: 5 additions & 1 deletion packages/pigeon/lib/src/generator_tools.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ import 'generator.dart';
/// The current version of pigeon.
///
/// This must match the version in pubspec.yaml.
const String pigeonVersion = '26.1.7';
const String pigeonVersion = '26.1.8';

/// Annotation for generated code.
const String generatedAnnotation =
'@javax.annotation.Generated("dev.flutter.pigeon")';

/// Read all the content from [stdin] to a String.
String readStdin() {
Expand Down
2 changes: 1 addition & 1 deletion packages/pigeon/lib/src/java/java_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ class JavaGenerator extends StructuredGenerator<InternalJavaOptions> {
'@SuppressWarnings({"unused", "unchecked", "CodeBlock2Expr", "RedundantSuppression", "serial"})',
);
if (generatorOptions.useGeneratedAnnotation ?? false) {
indent.writeln('@javax.annotation.Generated("dev.flutter.pigeon")');
indent.writeln(generatedAnnotation);
}
indent.writeln('public class ${generatorOptions.className!} {');
indent.inc();
Expand Down
21 changes: 21 additions & 0 deletions packages/pigeon/lib/src/kotlin/kotlin_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ const String _pigeonMethodChannelCodec = 'PigeonMethodCodec';

const String _overflowClassName = '${classNamePrefix}CodecOverflow';

/// Kotlin file-level annotation for generated code.
const String kotlinGeneratedAnnotation = '@file:$generatedAnnotation';

/// Options that control how Kotlin code will be generated.
class KotlinOptions {
/// Creates a [KotlinOptions] object
Expand All @@ -44,6 +47,7 @@ class KotlinOptions {
this.errorClassName,
this.includeErrorClass = true,
this.fileSpecificClassNameComponent,
this.useGeneratedAnnotation = false,
});

/// The package where the generated class will live.
Expand All @@ -64,6 +68,11 @@ class KotlinOptions {
/// A String to augment class names to avoid cross file collisions.
final String? fileSpecificClassNameComponent;

/// Determines if the `javax.annotation.Generated` is used in the output. This
/// is false by default since that dependency isn't available in plugins by
/// default .
final bool useGeneratedAnnotation;

/// Creates a [KotlinOptions] from a Map representation where:
/// `x = KotlinOptions.fromMap(x.toMap())`.
static KotlinOptions fromMap(Map<String, Object> map) {
Expand All @@ -74,6 +83,7 @@ class KotlinOptions {
includeErrorClass: map['includeErrorClass'] as bool? ?? true,
fileSpecificClassNameComponent:
map['fileSpecificClassNameComponent'] as String?,
useGeneratedAnnotation: map['useGeneratedAnnotation'] as bool? ?? false,
);
}

Expand All @@ -87,6 +97,7 @@ class KotlinOptions {
'includeErrorClass': includeErrorClass,
if (fileSpecificClassNameComponent != null)
'fileSpecificClassNameComponent': fileSpecificClassNameComponent!,
'useGeneratedAnnotation': useGeneratedAnnotation,
};
return result;
}
Expand All @@ -108,6 +119,7 @@ class InternalKotlinOptions extends InternalOptions {
this.errorClassName,
this.includeErrorClass = true,
this.fileSpecificClassNameComponent,
this.useGeneratedAnnotation = false,
});

/// Creates InternalKotlinOptions from KotlinOptions.
Expand All @@ -119,6 +131,7 @@ class InternalKotlinOptions extends InternalOptions {
copyrightHeader = options.copyrightHeader ?? copyrightHeader,
errorClassName = options.errorClassName,
includeErrorClass = options.includeErrorClass,
useGeneratedAnnotation = options.useGeneratedAnnotation,
fileSpecificClassNameComponent =
options.fileSpecificClassNameComponent ??
kotlinOut.split('/').lastOrNull?.split('.').first;
Expand All @@ -143,6 +156,11 @@ class InternalKotlinOptions extends InternalOptions {

/// A String to augment class names to avoid cross file collisions.
final String? fileSpecificClassNameComponent;

/// Determines if the `javax.annotation.Generated` is used in the output. This
/// is false by default since that dependency isn't available in plugins by
/// default .
final bool useGeneratedAnnotation;
}

/// Options that control how Kotlin code will be generated for a specific
Expand Down Expand Up @@ -192,6 +210,9 @@ class KotlinGenerator extends StructuredGenerator<InternalKotlinOptions> {
indent.writeln('// ${getGeneratedCodeWarning()}');
indent.writeln('// $seeAlsoWarning');
indent.writeln('@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass")');
if (generatorOptions.useGeneratedAnnotation) {
indent.writeln(kotlinGeneratedAnnotation);
}
}

@override
Expand Down
6 changes: 6 additions & 0 deletions packages/pigeon/lib/src/pigeon_lib.dart
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,10 @@ ${_argParser.usage}''';
help: 'The package that generated Kotlin code will be in.',
aliases: const <String>['experimental_kotlin_package'],
)
..addFlag(
'kotlin_use_generated_annotation',
help: 'Adds javax.annotation.Generated annotation to the output.',
)
..addOption(
'cpp_header_out',
help: 'Path to generated C++ header file (.h).',
Expand Down Expand Up @@ -638,6 +642,8 @@ ${_argParser.usage}''';
kotlinOut: results['kotlin_out'] as String?,
kotlinOptions: KotlinOptions(
package: results['kotlin_package'] as String?,
useGeneratedAnnotation:
results['kotlin_use_generated_annotation'] as bool? ?? false,
),
cppHeaderOut: results['cpp_header_out'] as String?,
cppSourceOut: results['cpp_source_out'] as String?,
Expand Down
2 changes: 1 addition & 1 deletion packages/pigeon/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: pigeon
description: Code generator tool to make communication between Flutter and the host platform type-safe and easier.
repository: https://github.com/flutter/packages/tree/main/packages/pigeon
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+pigeon%22
version: 26.1.7 # This must match the version in lib/src/generator_tools.dart
version: 26.1.8 # This must match the version in lib/src/generator_tools.dart

environment:
sdk: ^3.9.0
Expand Down
91 changes: 47 additions & 44 deletions packages/pigeon/test/java_generator_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import 'package:pigeon/pigeon.dart';
import 'package:pigeon/src/ast.dart';
import 'package:pigeon/src/generator_tools.dart';
import 'package:pigeon/src/java/java_generator.dart';
import 'package:test/test.dart';

Expand Down Expand Up @@ -1611,51 +1612,53 @@ void main() {
);
});

test('generated annotation', () {
final classDefinition = Class(name: 'Foobar', fields: <NamedType>[]);
final root = Root(
apis: <Api>[],
classes: <Class>[classDefinition],
enums: <Enum>[],
);
final sink = StringBuffer();
const javaOptions = InternalJavaOptions(
className: 'Messages',
useGeneratedAnnotation: true,
javaOut: '',
);
const generator = JavaGenerator();
generator.generate(
javaOptions,
root,
sink,
dartPackageName: DEFAULT_PACKAGE_NAME,
);
final code = sink.toString();
expect(code, contains('@javax.annotation.Generated("dev.flutter.pigeon")'));
});
group('generated annotation', () {
late Class classDefinition;
late Root root;
late StringBuffer sink;
late JavaGenerator generator;

test('no generated annotation', () {
final classDefinition = Class(name: 'Foobar', fields: <NamedType>[]);
final root = Root(
apis: <Api>[],
classes: <Class>[classDefinition],
enums: <Enum>[],
);
final sink = StringBuffer();
const javaOptions = InternalJavaOptions(className: 'Messages', javaOut: '');
const generator = JavaGenerator();
generator.generate(
javaOptions,
root,
sink,
dartPackageName: DEFAULT_PACKAGE_NAME,
);
final code = sink.toString();
expect(
code,
isNot(contains('@javax.annotation.Generated("dev.flutter.pigeon")')),
);
setUp(() {
classDefinition = Class(name: 'Foobar', fields: <NamedType>[]);
root = Root(
apis: <Api>[],
classes: <Class>[classDefinition],
enums: <Enum>[],
);
sink = StringBuffer();
generator = const JavaGenerator();
});

test('with generated annotation', () {
const javaOptions = InternalJavaOptions(
className: 'Messages',
useGeneratedAnnotation: true,
javaOut: '',
);
generator.generate(
javaOptions,
root,
sink,
dartPackageName: DEFAULT_PACKAGE_NAME,
);
final code = sink.toString();
expect(code, contains(generatedAnnotation));
});

test('without generated annotation', () {
const javaOptions = InternalJavaOptions(
className: 'Messages',
javaOut: '',
);
generator.generate(
javaOptions,
root,
sink,
dartPackageName: DEFAULT_PACKAGE_NAME,
);
final code = sink.toString();
expect(code, isNot(contains(generatedAnnotation)));
});
});

test('transfers documentation comments', () {
Expand Down
43 changes: 43 additions & 0 deletions packages/pigeon/test/kotlin_generator_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -982,6 +982,49 @@ void main() {
expect(code, startsWith('// hello world'));
});

group('generated annotation', () {
late Root root;
late KotlinGenerator generator;
late StringBuffer sink;

setUp(() {
root = Root(apis: <Api>[], classes: <Class>[], enums: <Enum>[]);
generator = const KotlinGenerator();
sink = StringBuffer();
});

test('with generated annotation', () {
final kotlinOptions = InternalKotlinOptions(
copyrightHeader: makeIterable('hello world'),
kotlinOut: '',
useGeneratedAnnotation: true,
);
generator.generate(
kotlinOptions,
root,
sink,
dartPackageName: DEFAULT_PACKAGE_NAME,
);
final code = sink.toString();
expect(code, contains(kotlinGeneratedAnnotation));
});

test('without generated annotation', () {
final kotlinOptions = InternalKotlinOptions(
copyrightHeader: makeIterable('hello world'),
kotlinOut: '',
);
generator.generate(
kotlinOptions,
root,
sink,
dartPackageName: DEFAULT_PACKAGE_NAME,
);
final code = sink.toString();
expect(code, isNot(contains(kotlinGeneratedAnnotation)));
});
});

test('generics - list', () {
final classDefinition = Class(
name: 'Foobar',
Expand Down
7 changes: 7 additions & 0 deletions packages/pigeon/test/pigeon_lib_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,13 @@ void main() {
expect(opts.kotlinOptions?.package, equals('com.google.foo'));
});

test('parse args - kotlin_use_generated_annotation', () {
final PigeonOptions opts = Pigeon.parseArgs(<String>[
'--kotlin_use_generated_annotation',
]);
expect(opts.kotlinOptions!.useGeneratedAnnotation, isTrue);
});

test('parse args - cpp_header_out', () {
final PigeonOptions opts = Pigeon.parseArgs(<String>[
'--cpp_header_out',
Expand Down
23 changes: 22 additions & 1 deletion packages/pigeon/tool/shared/generation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,21 @@ Future<int> generateTestPigeons({
return generateCode;
}
}

// Test case for useGeneratedAnnotation feature with core_tests
final String corePascalCaseName = _snakeToPascalCase('core_tests');
final int generateCodeWithAnnotation = await runPigeon(
input: './pigeons/core_tests.dart',
kotlinOut:
'$outputBase/android/src/main/kotlin/com/example/test_plugin/${corePascalCaseName}WithAnnotation.gen.kt',
kotlinPackage: 'com.example.test_plugin',
kotlinErrorClassName: 'FlutterError',
kotlinUseGeneratedAnnotation: true,
);
if (generateCodeWithAnnotation != 0) {
return generateCodeWithAnnotation;
}

return 0;
}

Expand All @@ -217,6 +232,7 @@ Future<int> runPigeon({
String? kotlinPackage,
String? kotlinErrorClassName,
bool kotlinIncludeErrorClass = true,
bool kotlinUseGeneratedAnnotation = false,
bool swiftIncludeErrorClass = true,
String? swiftOut,
String? swiftErrorClassName,
Expand All @@ -230,6 +246,7 @@ Future<int> runPigeon({
String? gobjectModule,
String? javaOut,
String? javaPackage,
bool javaUseGeneratedAnnotation = false,
String? objcHeaderOut,
String? objcSourceOut,
String objcPrefix = '',
Expand Down Expand Up @@ -285,12 +302,16 @@ Future<int> runPigeon({
? null
: GObjectOptions(module: gobjectModule),
javaOut: javaOut,
javaOptions: JavaOptions(package: javaPackage),
javaOptions: JavaOptions(
package: javaPackage,
useGeneratedAnnotation: javaUseGeneratedAnnotation,
),
kotlinOut: kotlinOut,
kotlinOptions: KotlinOptions(
package: kotlinPackage,
errorClassName: kotlinErrorClassName,
includeErrorClass: kotlinIncludeErrorClass,
useGeneratedAnnotation: kotlinUseGeneratedAnnotation,
),
objcHeaderOut: objcHeaderOut,
objcSourceOut: objcSourceOut,
Expand Down