Skip to content

Commit 9ef0df9

Browse files
committed
[pigeon] Use a const for custom type ids for gobject generated files (#156100)
Adds a custom type identifier to generated gobject headers for the user. Calling fl_value_new_custom_object is now possible with that constant. This fixes flutter/flutter#156100
1 parent d3c5cca commit 9ef0df9

File tree

6 files changed

+160
-24
lines changed

6 files changed

+160
-24
lines changed

packages/pigeon/CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
## NEXT
1+
## 25.4.0
22

3+
* [gobject] Adds type id constants in header files so that they can be used by the user.
34
* Updates minimum supported SDK version to Flutter 3.24/Dart 3.5.
45

56
## 25.3.2

packages/pigeon/CONTRIBUTING.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,14 @@ generators with that AST.
1919
## Source Index
2020

2121
* [ast.dart](./lib/src/ast.dart) - The data structure for representing the Abstract Syntax Tree.
22-
* [dart_generator.dart](./lib/src/dart_generator.dart) - The Dart code generator.
23-
* [java_generator.dart](./lib/src/java_generator.dart) - The Java code generator.
24-
* [kotlin_generator.dart](./lib/src/kotlin_generator.dart) - The Kotlin code generator.
25-
* [objc_generator.dart](./lib/src/objc_generator.dart) - The Objective-C code
22+
* [dart_generator.dart](./lib/src/dart/dart_generator.dart) - The Dart code generator.
23+
* [java_generator.dart](./lib/src/java/java_generator.dart) - The Java code generator.
24+
* [kotlin_generator.dart](./lib/src/kotlin/kotlin_generator.dart) - The Kotlin code generator.
25+
* [objc_generator.dart](./lib/src/objc/objc_generator.dart) - The Objective-C code
2626
generator (header and source files).
27-
* [swift_generator.dart](./lib/src/swift_generator.dart) - The Swift code generator.
28-
* [cpp_generator.dart](./lib/src/cpp_generator.dart) - The C++ code generator.
27+
* [swift_generator.dart](./lib/src/swift/swift_generator.dart) - The Swift code generator.
28+
* [cpp_generator.dart](./lib/src/cpp/cpp_generator.dart) - The C++ code generator.
29+
* [gobject_generator.dart](./lib/src/gobject/gobject_generator.dart) - The GObject code generator.
2930
* [generator_tools.dart](./lib/src/generator_tools.dart) - Shared code between generators.
3031
* [pigeon_cl.dart](./lib/src/pigeon_cl.dart) - The top-level function executed by
3132
the command line tool in [bin/][./bin].

packages/pigeon/lib/src/generator_tools.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import 'generator.dart';
1515
/// The current version of pigeon.
1616
///
1717
/// This must match the version in pubspec.yaml.
18-
const String pigeonVersion = '25.3.2';
18+
const String pigeonVersion = '25.4.0';
1919

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

packages/pigeon/lib/src/gobject/gobject_generator.dart

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,16 @@ class GObjectHeaderGenerator
338338
indent.newln();
339339
_writeDeclareFinalType(indent, module, _codecBaseName,
340340
parentClassName: _standardCodecName);
341+
342+
final Iterable<EnumeratedType> customTypes =
343+
getEnumeratedTypes(root, excludeSealedClasses: true);
344+
345+
for (final EnumeratedType customType in customTypes) {
346+
final String customTypeId = _getCustomTypeId(module, customType);
347+
indent.newln();
348+
indent
349+
.writeln('const uint8_t $customTypeId = ${customType.enumeration};');
350+
}
341351
}
342352

343353
@override
@@ -1023,14 +1033,15 @@ class GObjectSourceGenerator
10231033
final String customTypeName = _getClassName(module, customType.name);
10241034
final String snakeCustomTypeName =
10251035
_snakeCaseFromCamelCase(customTypeName);
1036+
final String customTypeId = _getCustomTypeId(module, customType);
10261037
indent.newln();
10271038
final String valueType = customType.type == CustomTypes.customClass
10281039
? '$customTypeName*'
10291040
: 'FlValue*';
10301041
indent.writeScoped(
10311042
'static gboolean ${codecMethodPrefix}_write_$snakeCustomTypeName($_standardCodecName* codec, GByteArray* buffer, $valueType value, GError** error) {',
10321043
'}', () {
1033-
indent.writeln('uint8_t type = ${customType.enumeration};');
1044+
indent.writeln('uint8_t type = $customTypeId;');
10341045
indent.writeln('g_byte_array_append(buffer, &type, sizeof(uint8_t));');
10351046
if (customType.type == CustomTypes.customClass) {
10361047
indent.writeln(
@@ -1053,7 +1064,8 @@ class GObjectSourceGenerator
10531064
indent.writeScoped('switch (fl_value_get_custom_type(value)) {', '}',
10541065
() {
10551066
for (final EnumeratedType customType in customTypes) {
1056-
indent.writeln('case ${customType.enumeration}:');
1067+
final String customTypeId = _getCustomTypeId(module, customType);
1068+
indent.writeln('case $customTypeId:');
10571069
indent.nest(1, () {
10581070
final String customTypeName =
10591071
_getClassName(module, customType.name);
@@ -1082,6 +1094,7 @@ class GObjectSourceGenerator
10821094
final String customTypeName = _getClassName(module, customType.name);
10831095
final String snakeCustomTypeName =
10841096
_snakeCaseFromCamelCase(customTypeName);
1097+
final String customTypeId = _getCustomTypeId(module, customType);
10851098
indent.newln();
10861099
indent.writeScoped(
10871100
'static FlValue* ${codecMethodPrefix}_read_$snakeCustomTypeName($_standardCodecName* codec, GBytes* buffer, size_t* offset, GError** error) {',
@@ -1102,10 +1115,10 @@ class GObjectSourceGenerator
11021115
});
11031116
indent.newln();
11041117
indent.writeln(
1105-
'return fl_value_new_custom_object(${customType.enumeration}, G_OBJECT(value));');
1118+
'return fl_value_new_custom_object($customTypeId, G_OBJECT(value));');
11061119
} else if (customType.type == CustomTypes.customEnum) {
11071120
indent.writeln(
1108-
'return fl_value_new_custom(${customType.enumeration}, fl_standard_message_codec_read_value(codec, buffer, offset, error), (GDestroyNotify)fl_value_unref);');
1121+
'return fl_value_new_custom($customTypeId, fl_standard_message_codec_read_value(codec, buffer, offset, error), (GDestroyNotify)fl_value_unref);');
11091122
}
11101123
});
11111124
}
@@ -1117,9 +1130,10 @@ class GObjectSourceGenerator
11171130
indent.writeScoped('switch (type) {', '}', () {
11181131
for (final EnumeratedType customType in customTypes) {
11191132
final String customTypeName = _getClassName(module, customType.name);
1133+
final String customTypeId = _getCustomTypeId(module, customType);
11201134
final String snakeCustomTypeName =
11211135
_snakeCaseFromCamelCase(customTypeName);
1122-
indent.writeln('case ${customType.enumeration}:');
1136+
indent.writeln('case $customTypeId:');
11231137
indent.nest(1, () {
11241138
indent.writeln(
11251139
'return ${codecMethodPrefix}_read_$snakeCustomTypeName(codec, buffer, offset, error);');
@@ -1885,6 +1899,11 @@ String _getClassName(String module, String name) {
18851899
return '$module$name';
18861900
}
18871901

1902+
// Returns the GObject enum name for [name].
1903+
String _getEnumName(String module, String name) {
1904+
return '${module}_$name';
1905+
}
1906+
18881907
// Returns the name to use for a class field with [name].
18891908
String _getFieldName(String name) {
18901909
final List<String> reservedNames = <String>['type'];
@@ -1922,6 +1941,19 @@ String _getMethodPrefix(String module, String name) {
19221941
return _snakeCaseFromCamelCase(className);
19231942
}
19241943

1944+
// Returns the code for the custom type id definition for [customType].
1945+
String _getCustomTypeId(String module, EnumeratedType customType) {
1946+
final String customTypeName = switch (customType.type) {
1947+
CustomTypes.customClass => _getClassName(module, customType.name),
1948+
CustomTypes.customEnum => _getEnumName(module, customType.name),
1949+
};
1950+
1951+
final String snakeCustomTypeName = _snakeCaseFromCamelCase(customTypeName);
1952+
1953+
final String customTypeId = '${snakeCustomTypeName}_type_id';
1954+
return customTypeId;
1955+
}
1956+
19251957
// Returns an enumeration value in C++ form.
19261958
String _getEnumValue(String module, String enumName, String memberName) {
19271959
final String snakeEnumName = _snakeCaseFromCamelCase(enumName);
@@ -2062,12 +2094,14 @@ String _referenceValue(String module, TypeDeclaration type, String variableName,
20622094
}
20632095
}
20642096

2065-
int _getTypeEnumeration(Root root, TypeDeclaration type) {
2066-
return getEnumeratedTypes(root, excludeSealedClasses: true)
2067-
.firstWhere((EnumeratedType t) =>
2068-
(type.isClass && t.associatedClass == type.associatedClass) ||
2069-
(type.isEnum && t.associatedEnum == type.associatedEnum))
2070-
.enumeration;
2097+
String _getCustomTypeIdFromDeclaration(
2098+
Root root, TypeDeclaration type, String module) {
2099+
return _getCustomTypeId(
2100+
module,
2101+
getEnumeratedTypes(root, excludeSealedClasses: true).firstWhere(
2102+
(EnumeratedType t) =>
2103+
(type.isClass && t.associatedClass == type.associatedClass) ||
2104+
(type.isEnum && t.associatedEnum == type.associatedEnum)));
20712105
}
20722106

20732107
// Returns code to convert the native data type stored in [variableName] to a FlValue.
@@ -2078,12 +2112,15 @@ String _makeFlValue(
20782112
{String? lengthVariableName}) {
20792113
final String value;
20802114
if (type.isClass) {
2081-
final int enumeration = _getTypeEnumeration(root, type);
2082-
value = 'fl_value_new_custom_object($enumeration, G_OBJECT($variableName))';
2115+
final String customTypeId =
2116+
_getCustomTypeIdFromDeclaration(root, type, module);
2117+
value =
2118+
'fl_value_new_custom_object($customTypeId, G_OBJECT($variableName))';
20832119
} else if (type.isEnum) {
2084-
final int enumeration = _getTypeEnumeration(root, type);
2120+
final String customTypeId =
2121+
_getCustomTypeIdFromDeclaration(root, type, module);
20852122
value =
2086-
'fl_value_new_custom($enumeration, fl_value_new_int(${type.isNullable ? '*$variableName' : variableName}), (GDestroyNotify)fl_value_unref)';
2123+
'fl_value_new_custom($customTypeId, fl_value_new_int(${type.isNullable ? '*$variableName' : variableName}), (GDestroyNotify)fl_value_unref)';
20872124
} else if (_isFlValueWrappedType(type)) {
20882125
value = 'fl_value_ref($variableName)';
20892126
} else if (type.baseName == 'void') {

packages/pigeon/pubspec.yaml

Lines changed: 1 addition & 1 deletion
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%3A%22p%3A+pigeon%22
5-
version: 25.3.2 # This must match the version in lib/src/generator_tools.dart
5+
version: 25.4.0 # This must match the version in lib/src/generator_tools.dart
66

77
environment:
88
sdk: ^3.5.0

packages/pigeon/test/gobject_generator_test.dart

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -831,4 +831,101 @@ void main() {
831831
}
832832
expect(code, contains(' * ///'));
833833
});
834+
835+
test('generates_custom_class_id_constants', () {
836+
final Class parameterObjectClass =
837+
Class(name: 'ParameterObject', fields: <NamedType>[
838+
NamedType(
839+
type: const TypeDeclaration(baseName: 'bool', isNullable: false),
840+
name: 'aValue'),
841+
]);
842+
final Class objectClass = Class(name: 'Object', fields: <NamedType>[]);
843+
final Enum anEnum = Enum(
844+
name: 'enum',
845+
members: <EnumMember>[EnumMember(name: 'one'), EnumMember(name: 'two')],
846+
);
847+
final Root root = Root(
848+
apis: <Api>[
849+
AstHostApi(name: 'Api', methods: <Method>[
850+
Method(
851+
name: 'doSomething',
852+
location: ApiLocation.host,
853+
parameters: <Parameter>[
854+
Parameter(
855+
name: 'anObject',
856+
type: TypeDeclaration(
857+
baseName: 'ParameterObject',
858+
isNullable: false,
859+
associatedClass: parameterObjectClass,
860+
)),
861+
Parameter(
862+
name: 'aGenericObject',
863+
type: TypeDeclaration(
864+
baseName: 'Object',
865+
isNullable: false,
866+
associatedClass: objectClass,
867+
)),
868+
],
869+
returnType: TypeDeclaration(
870+
baseName: 'anObject',
871+
isNullable: false,
872+
associatedClass: parameterObjectClass,
873+
),
874+
),
875+
])
876+
],
877+
classes: <Class>[parameterObjectClass, objectClass],
878+
enums: <Enum>[anEnum],
879+
);
880+
{
881+
final StringBuffer sink = StringBuffer();
882+
const GObjectGenerator generator = GObjectGenerator();
883+
final OutputFileOptions<InternalGObjectOptions> generatorOptions =
884+
OutputFileOptions<InternalGObjectOptions>(
885+
fileType: FileType.header,
886+
languageOptions: const InternalGObjectOptions(
887+
headerIncludePath: '',
888+
gobjectHeaderOut: '',
889+
gobjectSourceOut: '',
890+
),
891+
);
892+
generator.generate(
893+
generatorOptions,
894+
root,
895+
sink,
896+
dartPackageName: DEFAULT_PACKAGE_NAME,
897+
);
898+
final String code = sink.toString();
899+
expect(code, contains('const uint8_t test_package_enum_type_id = 129;'));
900+
expect(
901+
code,
902+
contains(
903+
'const uint8_t test_package_parameter_object_type_id = 130;'));
904+
expect(
905+
code, contains('const uint8_t test_package_object_type_id = 131;'));
906+
}
907+
{
908+
final StringBuffer sink = StringBuffer();
909+
const GObjectGenerator generator = GObjectGenerator();
910+
final OutputFileOptions<InternalGObjectOptions> generatorOptions =
911+
OutputFileOptions<InternalGObjectOptions>(
912+
fileType: FileType.source,
913+
languageOptions: const InternalGObjectOptions(
914+
headerIncludePath: '',
915+
gobjectHeaderOut: '',
916+
gobjectSourceOut: '',
917+
),
918+
);
919+
generator.generate(
920+
generatorOptions,
921+
root,
922+
sink,
923+
dartPackageName: DEFAULT_PACKAGE_NAME,
924+
);
925+
final String code = sink.toString();
926+
expect(code.contains('129'), isFalse);
927+
expect(code.contains('130'), isFalse);
928+
expect(code.contains('131'), isFalse);
929+
}
930+
});
834931
}

0 commit comments

Comments
 (0)