Skip to content

Commit

Permalink
added generation of empty classes in dart
Browse files Browse the repository at this point in the history
  • Loading branch information
feduke-nukem committed Dec 24, 2024
1 parent 3515aba commit f9a3a92
Show file tree
Hide file tree
Showing 18 changed files with 161 additions and 25 deletions.
1 change: 1 addition & 0 deletions packages/pigeon/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## NEXT

* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4.
* [dart] fixes [160501](https://github.com/flutter/flutter/issues/160501).

## 22.7.0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,19 @@ data class StringEvent(val data: String) : PlatformEvent() {
}
}

/** Generated class from Pigeon that represents data sent in messages. */
class EmptyEvent() : PlatformEvent() {
companion object {
fun fromList(pigeonVar_list: List<Any?>): EmptyEvent {
return EmptyEvent()
}
}

fun toList(): List<Any?> {
return listOf()
}
}

private open class EventChannelMessagesPigeonCodec : StandardMessageCodec() {
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
return when (type) {
Expand All @@ -58,6 +71,9 @@ private open class EventChannelMessagesPigeonCodec : StandardMessageCodec() {
130.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let { StringEvent.fromList(it) }
}
131.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let { EmptyEvent.fromList(it) }
}
else -> super.readValueOfType(type, buffer)
}
}
Expand All @@ -72,6 +88,10 @@ private open class EventChannelMessagesPigeonCodec : StandardMessageCodec() {
stream.write(130)
writeValue(stream, value.toList())
}
is EmptyEvent -> {
stream.write(131)
writeValue(stream, value.toList())
}
else -> super.writeValue(stream, value)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

package dev.flutter.pigeon_example_app

import EmptyEvent
import ExampleHostApi
import FlutterError
import IntEvent
Expand Down Expand Up @@ -72,6 +73,10 @@ class EventListener : StreamEventsStreamHandler() {
eventSink?.success(StringEvent(data = event))
}

fun onEmptyEvent() {
eventSink?.success(EmptyEvent())
}

fun onEventsDone() {
eventSink?.endOfStream()
eventSink = null
Expand All @@ -93,6 +98,11 @@ fun sendEvents(eventListener: EventListener) {
eventListener.onIntEvent(count.toLong())
count++
}
} else if (count % 5 == 0) {
handler.post {
eventListener.onEmptyEvent()
count++
}
} else {
handler.post {
eventListener.onStringEvent(count.toString())
Expand Down
8 changes: 8 additions & 0 deletions packages/pigeon/example/app/ios/Runner/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ class EventListener: StreamEventsStreamHandler {
}
}

func onEmptyEvent() {
if let eventSink = eventSink {
eventSink.success(EmptyEvent())
}
}

func onEventsDone() {
eventSink?.endOfStream()
eventSink = nil
Expand All @@ -84,6 +90,8 @@ func sendEvents(_ eventListener: EventListener) {
} else {
if (count % 2) == 0 {
eventListener.onIntEvent(event: Int64(count))
} else if (count % 5) == 0 {
eventListener.onEmptyEvent()
} else {
eventListener.onStringEvent(event: String(count))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,28 @@ struct StringEvent: PlatformEvent {
}
}

/// Generated class from Pigeon that represents data sent in messages.
struct EmptyEvent: PlatformEvent {

// swift-format-ignore: AlwaysUseLowerCamelCase
static func fromList(_ pigeonVar_list: [Any?]) -> EmptyEvent? {

return EmptyEvent()
}
func toList() -> [Any?] {
return []
}
}

private class EventChannelMessagesPigeonCodecReader: FlutterStandardReader {
override func readValue(ofType type: UInt8) -> Any? {
switch type {
case 129:
return IntEvent.fromList(self.readValue() as! [Any?])
case 130:
return StringEvent.fromList(self.readValue() as! [Any?])
case 131:
return EmptyEvent.fromList(self.readValue() as! [Any?])
default:
return super.readValue(ofType: type)
}
Expand All @@ -88,6 +103,9 @@ private class EventChannelMessagesPigeonCodecWriter: FlutterStandardWriter {
} else if let value = value as? StringEvent {
super.writeByte(130)
super.writeValue(value.toList())
} else if let value = value as? EmptyEvent {
super.writeByte(131)
super.writeValue(value.toList())
} else {
super.writeValue(value)
}
Expand Down
2 changes: 2 additions & 0 deletions packages/pigeon/example/app/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ class _MyHomePageState extends State<MyHomePage> {
case StringEvent():
final String stringData = event.data;
yield '$stringData, ';
case EmptyEvent():
yield 'EmptyEvent, ';
}
}
}
Expand Down
16 changes: 16 additions & 0 deletions packages/pigeon/example/app/lib/src/event_channel_messages.g.dart
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,17 @@ class StringEvent extends PlatformEvent {
}
}

class EmptyEvent extends PlatformEvent {
Object encode() {
return <Object?>[];
}

static EmptyEvent decode(Object result) {
result as List<Object?>;
return EmptyEvent();
}
}

class _PigeonCodec extends StandardMessageCodec {
const _PigeonCodec();
@override
Expand All @@ -68,6 +79,9 @@ class _PigeonCodec extends StandardMessageCodec {
} else if (value is StringEvent) {
buffer.putUint8(130);
writeValue(buffer, value.encode());
} else if (value is EmptyEvent) {
buffer.putUint8(131);
writeValue(buffer, value.encode());
} else {
super.writeValue(buffer, value);
}
Expand All @@ -80,6 +94,8 @@ class _PigeonCodec extends StandardMessageCodec {
return IntEvent.decode(readValue(buffer)!);
case 130:
return StringEvent.decode(readValue(buffer)!);
case 131:
return EmptyEvent.decode(readValue(buffer)!);
default:
return super.readValueOfType(type, buffer);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ class StringEvent extends PlatformEvent {
StringEvent(this.data);
String data;
}

class EmptyEvent extends PlatformEvent {}

// #enddocregion sealed-definitions

// #docregion event-definitions
Expand Down
22 changes: 13 additions & 9 deletions packages/pigeon/lib/dart_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -169,20 +169,24 @@ class DartGenerator extends StructuredGenerator<DartOptions> {
: '';

indent.write('${sealed}class ${classDefinition.name} $implements');

indent.addScoped('{', '}', () {
if (classDefinition.fields.isEmpty) {
if (classDefinition.isSealed) {
return;
}
_writeConstructor(indent, classDefinition);
indent.newln();
for (final NamedType field
in getFieldsInSerializationOrder(classDefinition)) {
addDocumentationComments(
indent, field.documentationComments, _docCommentSpec);

final String datatype = _addGenericTypesNullable(field.type);
indent.writeln('$datatype ${field.name};');
if (classDefinition.fields.isNotEmpty) {
_writeConstructor(indent, classDefinition);
indent.newln();
for (final NamedType field
in getFieldsInSerializationOrder(classDefinition)) {
addDocumentationComments(
indent, field.documentationComments, _docCommentSpec);

final String datatype = _addGenericTypesNullable(field.type);
indent.writeln('$datatype ${field.name};');
indent.newln();
}
}
writeClassEncode(
generatorOptions,
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 @@ -241,7 +241,11 @@ class KotlinGenerator extends StructuredGenerator<KotlinOptions> {
bool private = false,
}) {
final String privateString = private ? 'private ' : '';
final String classType = classDefinition.isSealed ? 'sealed' : 'data';
final String classType = classDefinition.isSealed
? 'sealed'
: classDefinition.fields.isNotEmpty
? 'data'
: '';
final String inheritance = classDefinition.superClass != null
? ' : ${classDefinition.superClassName}()'
: '';
Expand Down
24 changes: 24 additions & 0 deletions packages/pigeon/test/dart_generator_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1807,4 +1807,28 @@ name: foobar
expect(code, contains('buffer.putUint8(4);'));
expect(code, contains('buffer.putInt64(value);'));
});

// https://github.com/flutter/flutter/issues/160501
test('gen one empty class', () {
final Class classDefinition = Class(
name: 'Foobar',
fields: <NamedType>[],
);
final Root root = Root(
apis: <Api>[],
classes: <Class>[classDefinition],
enums: <Enum>[],
);
final StringBuffer sink = StringBuffer();
const DartGenerator generator = DartGenerator();
generator.generate(
const DartOptions(),
root,
sink,
dartPackageName: DEFAULT_PACKAGE_NAME,
);
final String code = sink.toString();
expect(code, contains('Object encode()'));
expect(code, contains('static Foobar decode(Object result)'));
});
}
26 changes: 26 additions & 0 deletions packages/pigeon/test/kotlin_generator_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1856,4 +1856,30 @@ void main() {
// There should be only one occurrence of 'is Foo' in the block
expect(count, 1);
});

// https://github.com/flutter/flutter/issues/160501
test('gen one empty class', () {
final Class classDefinition = Class(
name: 'Foobar',
fields: <NamedType>[],
);
final Root root = Root(
apis: <Api>[],
classes: <Class>[classDefinition],
enums: <Enum>[],
);
final StringBuffer sink = StringBuffer();
const KotlinOptions kotlinOptions = KotlinOptions();
const KotlinGenerator generator = KotlinGenerator();
generator.generate(
kotlinOptions,
root,
sink,
dartPackageName: DEFAULT_PACKAGE_NAME,
);
final String code = sink.toString();

/// The generated class should not be data class
expect(code, isNot(contains('data class')));
});
}
4 changes: 2 additions & 2 deletions script/tool/lib/src/common/package_looping_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ abstract class PackageLoopingCommand extends PackageCommand {
if (minFlutterVersion != null) {
final Pubspec pubspec = package.parsePubspec();
final VersionConstraint? flutterConstraint =
pubspec.environment?['flutter'];
pubspec.environment['flutter'];
if (flutterConstraint != null &&
!flutterConstraint.allows(minFlutterVersion)) {
return PackageResult.skip(
Expand All @@ -350,7 +350,7 @@ abstract class PackageLoopingCommand extends PackageCommand {

if (minDartVersion != null) {
final Pubspec pubspec = package.parsePubspec();
final VersionConstraint? dartConstraint = pubspec.environment?['sdk'];
final VersionConstraint? dartConstraint = pubspec.environment['sdk'];
if (dartConstraint != null && !dartConstraint.allows(minDartVersion)) {
return PackageResult.skip('Does not support Dart $minDartVersion');
}
Expand Down
4 changes: 2 additions & 2 deletions script/tool/lib/src/create_all_packages_app_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ dependencies {}
final Pubspec originalPubspec = app.parsePubspec();
const String dartSdkKey = 'sdk';
final VersionConstraint dartSdkConstraint =
originalPubspec.environment?[dartSdkKey] ??
originalPubspec.environment[dartSdkKey] ??
VersionConstraint.compatibleWith(
Version.parse('3.0.0'),
);
Expand Down Expand Up @@ -342,7 +342,7 @@ publish_to: none
version: ${pubspec.version}
environment:${_pubspecMapString(pubspec.environment!)}
environment:${_pubspecMapString(pubspec.environment)}
dependencies:${_pubspecMapString(pubspec.dependencies)}
Expand Down
4 changes: 2 additions & 2 deletions script/tool/lib/src/pubspec_check_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -488,9 +488,9 @@ class PubspecCheckCommand extends PackageLoopingCommand {
}

final Version? dartConstraintMin =
_minimumForConstraint(pubspec.environment?['sdk']);
_minimumForConstraint(pubspec.environment['sdk']);
final Version? flutterConstraintMin =
_minimumForConstraint(pubspec.environment?['flutter']);
_minimumForConstraint(pubspec.environment['flutter']);

// Validate the Flutter constraint, if any.
if (flutterConstraintMin != null && minMinFlutterVersion != null) {
Expand Down
2 changes: 1 addition & 1 deletion script/tool/lib/src/update_min_sdk_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ class UpdateMinSdkCommand extends PackageLoopingCommand {
/// Returns the given "environment" section's [key] constraint as a range,
/// if the key is present and has a range.
VersionRange? _sdkRange(Pubspec pubspec, String key) {
final VersionConstraint? constraint = pubspec.environment?[key];
final VersionConstraint? constraint = pubspec.environment[key];
if (constraint is VersionRange) {
return constraint;
}
Expand Down
2 changes: 1 addition & 1 deletion script/tool/test/create_all_packages_app_command_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ android {
final Pubspec generatedPubspec = command.app.parsePubspec();

const String dartSdkKey = 'sdk';
expect(generatedPubspec.environment?[dartSdkKey].toString(),
expect(generatedPubspec.environment[dartSdkKey].toString(),
existingSdkConstraint);
});

Expand Down
Loading

0 comments on commit f9a3a92

Please sign in to comment.