Skip to content

[pigeon] Implement Screaming Snake Case Conversion for Kotlin Enum Cases #5918

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Feb 9, 2024
Merged
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
8 changes: 8 additions & 0 deletions packages/pigeon/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## 17.0.0

* **Breaking Change** [kotlin] Converts Kotlin enum case generation to SCREAMING_SNAKE_CASE.
* Updates `writeEnum` function to adhere to Kotlin naming conventions.
* Improves handling of complex names with enhanced regex patterns.
* Expands unit tests for comprehensive name conversion validation.
* **Migration Note**: This change modifies the naming convention of Kotlin enum cases generated from the Pigeon package. It is recommended to review the impact on your existing codebase and update any dependent code accordingly.

## 16.0.5

* Adds ProxyApi to AST generation.
Expand Down
2 changes: 1 addition & 1 deletion packages/pigeon/lib/generator_tools.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import 'ast.dart';
/// The current version of pigeon.
///
/// This must match the version in pubspec.yaml.
const String pigeonVersion = '16.0.5';
const String pigeonVersion = '17.0.0';

/// Read all the content from [stdin] to a String.
String readStdin() {
Expand Down
6 changes: 5 additions & 1 deletion packages/pigeon/lib/kotlin_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,11 @@ class KotlinGenerator extends StructuredGenerator<KotlinOptions> {
enumerate(anEnum.members, (int index, final EnumMember member) {
addDocumentationComments(
indent, member.documentationComments, _docCommentSpec);
indent.write('${member.name.toUpperCase()}($index)');
final String nameScreamingSnakeCase = member.name
.replaceAllMapped(
RegExp(r'(?<=[a-z])[A-Z]'), (Match m) => '_${m.group(0)}')
.toUpperCase();
indent.write('$nameScreamingSnakeCase($index)');
if (index != anEnum.members.length - 1) {
indent.addln(',');
} else {
Expand Down
2 changes: 2 additions & 0 deletions packages/pigeon/pigeons/core_tests.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ enum AnEnum {
one,
two,
three,
fortyTwo,
fourHundredTwentyTwo,
}

/// A class containing all supported types.
Expand Down
3 changes: 3 additions & 0 deletions packages/pigeon/pigeons/enum.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ enum EnumState {

/// This comment is to test enum member (Error) documentation comments.
Error,

/// This comment is to test enum member (SnakeCase) documentation comments.
SnakeCase,
}

/// This comment is to test class documentation comments.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@ protected static FlutterError createConnectionError(@NonNull String channelName)
public enum AnEnum {
ONE(0),
TWO(1),
THREE(2);
THREE(2),
FORTY_TWO(3),
FOUR_HUNDRED_TWENTY_TWO(4);

final int index;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ typedef NS_ENUM(NSUInteger, AnEnum) {
AnEnumOne = 0,
AnEnumTwo = 1,
AnEnumThree = 2,
AnEnumFortyTwo = 3,
AnEnumFourHundredTwentyTwo = 4,
};

/// Wrapper for AnEnum to allow for nullability.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ typedef NS_ENUM(NSUInteger, AnEnum) {
AnEnumOne = 0,
AnEnumTwo = 1,
AnEnumThree = 2,
AnEnumFortyTwo = 3,
AnEnumFourHundredTwentyTwo = 4,
};

/// Wrapper for AnEnum to allow for nullability.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ void runPigeonIntegrationTests(TargetGenerator targetGenerator) {
'd': false,
'e': null
},
anEnum: AnEnum.two,
anEnum: AnEnum.fortyTwo,
anObject: 1,
);

Expand Down Expand Up @@ -166,7 +166,7 @@ void runPigeonIntegrationTests(TargetGenerator targetGenerator) {
],
nullableMapWithAnnotations: <String?, String?>{},
nullableMapWithObject: <String?, Object?>{},
aNullableEnum: AnEnum.two,
aNullableEnum: AnEnum.fourHundredTwentyTwo,
aNullableObject: 0,
);

Expand Down Expand Up @@ -443,6 +443,15 @@ void runPigeonIntegrationTests(TargetGenerator targetGenerator) {
expect(receivedEnum, sentEnum);
});

testWidgets('multi word enums serialize and deserialize correctly',
(WidgetTester _) async {
final HostIntegrationCoreApi api = HostIntegrationCoreApi();

const AnEnum sentEnum = AnEnum.fortyTwo;
final AnEnum receivedEnum = await api.echoEnum(sentEnum);
expect(receivedEnum, sentEnum);
});

testWidgets('required named parameter', (WidgetTester _) async {
final HostIntegrationCoreApi api = HostIntegrationCoreApi();
// This number corresponds with the default value of this method.
Expand Down Expand Up @@ -648,6 +657,15 @@ void runPigeonIntegrationTests(TargetGenerator targetGenerator) {
expect(echoEnum, sentEnum);
});

testWidgets('multi word nullable enums serialize and deserialize correctly',
(WidgetTester _) async {
final HostIntegrationCoreApi api = HostIntegrationCoreApi();

const AnEnum sentEnum = AnEnum.fourHundredTwentyTwo;
final AnEnum? echoEnum = await api.echoNullableEnum(sentEnum);
expect(echoEnum, sentEnum);
});

testWidgets('null lists serialize and deserialize correctly',
(WidgetTester _) async {
final HostIntegrationCoreApi api = HostIntegrationCoreApi();
Expand Down Expand Up @@ -887,6 +905,15 @@ void runPigeonIntegrationTests(TargetGenerator targetGenerator) {
expect(echoEnum, sentEnum);
});

testWidgets('multi word enums serialize and deserialize correctly',
(WidgetTester _) async {
final HostIntegrationCoreApi api = HostIntegrationCoreApi();

const AnEnum sentEnum = AnEnum.fourHundredTwentyTwo;
final AnEnum echoEnum = await api.echoAsyncEnum(sentEnum);
expect(echoEnum, sentEnum);
});

testWidgets('nullable Int async serialize and deserialize correctly',
(WidgetTester _) async {
final HostIntegrationCoreApi api = HostIntegrationCoreApi();
Expand Down Expand Up @@ -1004,6 +1031,15 @@ void runPigeonIntegrationTests(TargetGenerator targetGenerator) {
expect(echoEnum, sentEnum);
});

testWidgets('nullable enums serialize and deserialize correctly',
(WidgetTester _) async {
final HostIntegrationCoreApi api = HostIntegrationCoreApi();

const AnEnum sentEnum = AnEnum.fortyTwo;
final AnEnum? echoEnum = await api.echoAsyncNullableEnum(sentEnum);
expect(echoEnum, sentEnum);
});

testWidgets('null Ints async serialize and deserialize correctly',
(WidgetTester _) async {
final HostIntegrationCoreApi api = HostIntegrationCoreApi();
Expand Down Expand Up @@ -1243,6 +1279,15 @@ void runPigeonIntegrationTests(TargetGenerator targetGenerator) {
expect(echoEnum, sentEnum);
});

testWidgets('multi word enums serialize and deserialize correctly',
(WidgetTester _) async {
final HostIntegrationCoreApi api = HostIntegrationCoreApi();

const AnEnum sentEnum = AnEnum.fortyTwo;
final AnEnum echoEnum = await api.callFlutterEchoEnum(sentEnum);
expect(echoEnum, sentEnum);
});

testWidgets('nullable booleans serialize and deserialize correctly',
(WidgetTester _) async {
final HostIntegrationCoreApi api = HostIntegrationCoreApi();
Expand Down Expand Up @@ -1407,6 +1452,15 @@ void runPigeonIntegrationTests(TargetGenerator targetGenerator) {
expect(echoEnum, sentEnum);
});

testWidgets('multi word nullable enums serialize and deserialize correctly',
(WidgetTester _) async {
final HostIntegrationCoreApi api = HostIntegrationCoreApi();

const AnEnum sentEnum = AnEnum.fourHundredTwentyTwo;
final AnEnum? echoEnum = await api.callFlutterEchoNullableEnum(sentEnum);
expect(echoEnum, sentEnum);
});

testWidgets('null enums serialize and deserialize correctly',
(WidgetTester _) async {
final HostIntegrationCoreApi api = HostIntegrationCoreApi();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ enum AnEnum {
one,
two,
three,
fortyTwo,
fourHundredTwentyTwo,
}

/// A class containing all supported types.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ enum EnumState {

/// This comment is to test enum member (Error) documentation comments.
Error,

/// This comment is to test enum member (SnakeCase) documentation comments.
SnakeCase,
}

/// This comment is to test class documentation comments.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ class CoreTestsError(
enum class AnEnum(val raw: Int) {
ONE(0),
TWO(1),
THREE(2);
THREE(2),
FORTY_TWO(3),
FOUR_HUNDRED_TWENTY_TWO(4);

companion object {
fun ofRaw(raw: Int): AnEnum? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ internal class EnumTest : TestCase() {
val api = mockk<EnumApi2Host>()

val channelName = "dev.flutter.pigeon.pigeon_integration_tests.EnumApi2Host.echo"
val input = DataWithEnum(EnumState.SUCCESS)
val input = DataWithEnum(EnumState.SNAKE_CASE)

val handlerSlot = slot<BinaryMessenger.BinaryMessageHandler>()

Expand Down Expand Up @@ -52,7 +52,7 @@ internal class EnumTest : TestCase() {
val binaryMessenger = mockk<BinaryMessenger>()
val api = EnumApi2Flutter(binaryMessenger)

val input = DataWithEnum(EnumState.SUCCESS)
val input = DataWithEnum(EnumState.SNAKE_CASE)

every { binaryMessenger.send(any(), any(), any()) } answers
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ enum AnEnum: Int {
case one = 0
case two = 1
case three = 2
case fortyTwo = 3
case fourHundredTwentyTwo = 4
}

/// A class containing all supported types.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ enum AnEnum: Int {
case one = 0
case two = 1
case three = 2
case fortyTwo = 3
case fourHundredTwentyTwo = 4
}

/// A class containing all supported types.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,13 @@ class ErrorOr {
std::variant<T, FlutterError> v_;
};

enum class AnEnum { one = 0, two = 1, three = 2 };
enum class AnEnum {
one = 0,
two = 1,
three = 2,
fortyTwo = 3,
fourHundredTwentyTwo = 4
};

// A class containing all supported types.
//
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: 16.0.5 # This must match the version in lib/generator_tools.dart
version: 17.0.0 # This must match the version in lib/generator_tools.dart

environment:
sdk: ">=3.0.0 <4.0.0"
Expand Down
16 changes: 8 additions & 8 deletions packages/pigeon/test/kotlin_generator_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -856,22 +856,22 @@ void main() {

test('gen one enum class', () {
final Enum anEnum = Enum(
name: 'Enum1',
name: 'SampleEnum',
members: <EnumMember>[
EnumMember(name: 'one'),
EnumMember(name: 'two'),
EnumMember(name: 'sampleVersion'),
EnumMember(name: 'sampleTest'),
],
);
final Class classDefinition = Class(
name: 'EnumClass',
fields: <NamedType>[
NamedType(
type: TypeDeclaration(
baseName: 'Enum1',
baseName: 'SampleEnum',
associatedEnum: emptyEnum,
isNullable: true,
),
name: 'enum1',
name: 'sampleEnum',
),
],
);
Expand All @@ -890,9 +890,9 @@ void main() {
dartPackageName: DEFAULT_PACKAGE_NAME,
);
final String code = sink.toString();
expect(code, contains('enum class Enum1(val raw: Int)'));
expect(code, contains('ONE(0)'));
expect(code, contains('TWO(1)'));
expect(code, contains('enum class SampleEnum(val raw: Int)'));
expect(code, contains('SAMPLE_VERSION(0)'));
expect(code, contains('SAMPLE_TEST(1)'));
});

Iterable<String> makeIterable(String string) sync* {
Expand Down