Skip to content
Open
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 @@
## 27.2.0

* Adds support for empty data classes.

## 27.1.1

* [dart] Adds usage documentation to generated event channel methods, and
Expand Down
20 changes: 13 additions & 7 deletions packages/pigeon/lib/src/dart/dart_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -222,17 +222,19 @@ class DartGenerator extends StructuredGenerator<InternalDartOptions> {

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 = addGenericTypes(field.type);
indent.writeln('$datatype ${field.name};');
if (classDefinition.fields.isNotEmpty) {
indent.newln();
for (final NamedType field in getFieldsInSerializationOrder(classDefinition)) {
addDocumentationComments(indent, field.documentationComments, docCommentSpec);

final String datatype = addGenericTypes(field.type);
indent.writeln('$datatype ${field.name};');
indent.newln();
}
}
Comment on lines +229 to 238

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

When generating Dart code for an empty class, there is no blank line written between the constructor and the _writeToList method. Adding a blank line here improves the readability of the generated code and aligns with Dart style guidelines for class member spacing.

Suggested change
if (classDefinition.fields.isNotEmpty) {
indent.newln();
for (final NamedType field in getFieldsInSerializationOrder(classDefinition)) {
addDocumentationComments(indent, field.documentationComments, docCommentSpec);
final String datatype = addGenericTypes(field.type);
indent.writeln('$datatype ${field.name};');
indent.newln();
}
}
if (classDefinition.fields.isNotEmpty) {
indent.newln();
for (final NamedType field in getFieldsInSerializationOrder(classDefinition)) {
addDocumentationComments(indent, field.documentationComments, docCommentSpec);
final String datatype = addGenericTypes(field.type);
indent.writeln('$datatype ${field.name};');
indent.newln();
}
} else {
indent.newln();
}

_writeToList(indent, classDefinition);
indent.newln();
Expand Down Expand Up @@ -264,6 +266,10 @@ class DartGenerator extends StructuredGenerator<InternalDartOptions> {

void _writeConstructor(Indent indent, Class classDefinition) {
indent.write(classDefinition.name);
if (classDefinition.fields.isEmpty) {
indent.addln('();');
return;
}
indent.addScoped('({', '});', () {
for (final NamedType field in getFieldsInSerializationOrder(classDefinition)) {
final required = !field.type.isNullable && field.defaultValue == null ? 'required ' : '';
Expand Down
2 changes: 1 addition & 1 deletion packages/pigeon/lib/src/generator_tools.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import 'generator.dart';
/// The current version of pigeon.
///
/// This must match the version in pubspec.yaml.
const String pigeonVersion = '27.1.1';
const String pigeonVersion = '27.2.0';

/// Default plugin package name.
const String defaultPluginPackageName = 'dev.flutter.pigeon';
Expand Down
6 changes: 5 additions & 1 deletion packages/pigeon/lib/src/java/java_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,11 @@ class JavaGenerator extends StructuredGenerator<InternalJavaOptions> {
final Iterable<String> checks = classDefinition.fields.map((NamedType field) {
return 'pigeonDeepEquals(${field.name}, that.${field.name})';
});
indent.writeln('return ${checks.join(' && ')};');
if (checks.isEmpty) {
indent.writeln('return true;');
} else {
indent.writeln('return ${checks.join(' && ')};');
}
});
indent.newln();

Expand Down
33 changes: 22 additions & 11 deletions packages/pigeon/lib/src/kotlin/kotlin_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -399,24 +399,35 @@ class KotlinGenerator extends StructuredGenerator<InternalKotlinOptions> {

void _writeDataClassSignature(Indent indent, Class classDefinition, {bool private = false}) {
final privateString = private ? 'private ' : '';
final classType = classDefinition.isSealed ? 'sealed' : 'data';
final String classType;
if (classDefinition.isSealed) {
classType = 'sealed ';
} else if (classDefinition.fields.isEmpty) {
classType = '';
} else {
classType = 'data ';
}
final inheritance = classDefinition.superClass != null
? ' : ${classDefinition.superClassName}()'
: '';
indent.write('$privateString$classType class ${classDefinition.name} ');
indent.write('$privateString${classType}class ${classDefinition.name} ');
if (classDefinition.isSealed) {
return;
}
indent.addScoped('(', ')$inheritance', () {
for (final NamedType element in getFieldsInSerializationOrder(classDefinition)) {
_writeClassField(indent, element);
if (getFieldsInSerializationOrder(classDefinition).last != element) {
indent.addln(',');
} else {
indent.newln();
if (classDefinition.fields.isEmpty) {
indent.add(inheritance);
} else {
indent.addScoped('(', ')$inheritance', () {
for (final NamedType element in getFieldsInSerializationOrder(classDefinition)) {
_writeClassField(indent, element);
if (getFieldsInSerializationOrder(classDefinition).last != element) {
indent.addln(',');
} else {
indent.newln();
}
}
}
});
});
}
}

@override
Expand Down
10 changes: 5 additions & 5 deletions packages/pigeon/lib/src/objc/objc_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,9 @@ class ObjcSourceGenerator extends StructuredGenerator<InternalObjcOptions> {
final String className = _className(generatorOptions.prefix, classDefinition.name);

indent.writeln('@implementation $className');
_writeObjcSourceClassInitializer(generatorOptions, root, indent, classDefinition, className);
if (classDefinition.fields.isNotEmpty) {
_writeObjcSourceClassInitializer(generatorOptions, root, indent, classDefinition, className);
}
writeClassDecode(
generatorOptions,
root,
Expand Down Expand Up @@ -1900,10 +1902,8 @@ void _writeDataClassDeclaration(
addDocumentationComments(indent, classDefinition.documentationComments, _docCommentSpec);

indent.writeln('@interface ${_className(prefix, classDefinition.name)} : NSObject');
if (getFieldsInSerializationOrder(classDefinition).isNotEmpty) {
if (getFieldsInSerializationOrder(
classDefinition,
).map((NamedType e) => !e.type.isNullable).any((bool e) => e)) {
if (classDefinition.fields.isNotEmpty) {
if (classDefinition.fields.any((NamedType e) => !e.type.isNullable)) {
indent.writeln(
'$_docCommentPrefix `init` unavailable to enforce nonnull fields, see the `make` class method.',
);
Expand Down
4 changes: 4 additions & 0 deletions packages/pigeon/pigeons/core_tests.dart
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ class AllClassesWrapper {
this.classMap,
this.nullableClassList,
this.nullableClassMap,
this.anEmptyClass,
);
AllNullableTypes allNullableTypes;
AllNullableTypesWithoutRecursion? allNullableTypesWithoutRecursion;
Expand All @@ -273,6 +274,7 @@ class AllClassesWrapper {
List<AllNullableTypesWithoutRecursion?>? nullableClassList;
Map<int?, AllTypes?> classMap;
Map<int?, AllNullableTypesWithoutRecursion?>? nullableClassMap;
AnEmptyClass? anEmptyClass;
}

/// The core interface that each host language plugin must implement in
Expand Down Expand Up @@ -1465,3 +1467,5 @@ class TestMessage {
// ignore: always_specify_types, strict_raw_type
List? testList;
}

class AnEmptyClass {}
2 changes: 2 additions & 0 deletions packages/pigeon/pigeons/event_channel_tests.dart
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ class ClassEvent extends PlatformEvent {
final EventAllNullableTypes value;
}

class EmptyEvent extends PlatformEvent {}

@EventChannelApi()
abstract class EventChannelMethods {
int streamInts();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/** Generated class from Pigeon. */
@SuppressWarnings({"unused", "unchecked", "CodeBlock2Expr", "RedundantSuppression", "serial"})
Expand Down Expand Up @@ -3005,6 +3006,16 @@ public void setNullableClassMap(
this.nullableClassMap = setterArg;
}

private @Nullable AnEmptyClass anEmptyClass;

public @Nullable AnEmptyClass getAnEmptyClass() {
return anEmptyClass;
}

public void setAnEmptyClass(@Nullable AnEmptyClass setterArg) {
this.anEmptyClass = setterArg;
}

/** Constructor is non-public to enforce null safety; use Builder. */
AllClassesWrapper() {}

Expand All @@ -3024,7 +3035,8 @@ && pigeonDeepEquals(allTypes, that.allTypes)
&& pigeonDeepEquals(classList, that.classList)
&& pigeonDeepEquals(nullableClassList, that.nullableClassList)
&& pigeonDeepEquals(classMap, that.classMap)
&& pigeonDeepEquals(nullableClassMap, that.nullableClassMap);
&& pigeonDeepEquals(nullableClassMap, that.nullableClassMap)
&& pigeonDeepEquals(anEmptyClass, that.anEmptyClass);
}

@Override
Expand All @@ -3038,7 +3050,8 @@ public int hashCode() {
classList,
nullableClassList,
classMap,
nullableClassMap
nullableClassMap,
anEmptyClass
};
return pigeonDeepHashCode(fields);
}
Expand Down Expand Up @@ -3066,6 +3079,9 @@ public String toString() {
+ ", "
+ "nullableClassMap="
+ nullableClassMap
+ ", "
+ "anEmptyClass="
+ anEmptyClass
+ "}";
}

Expand Down Expand Up @@ -3130,6 +3146,14 @@ public static final class Builder {
return this;
}

private @Nullable AnEmptyClass anEmptyClass;

@CanIgnoreReturnValue
public @NonNull Builder setAnEmptyClass(@Nullable AnEmptyClass setterArg) {
this.anEmptyClass = setterArg;
return this;
}

public @NonNull AllClassesWrapper build() {
AllClassesWrapper pigeonReturn = new AllClassesWrapper();
pigeonReturn.setAllNullableTypes(allNullableTypes);
Expand All @@ -3139,20 +3163,22 @@ public static final class Builder {
pigeonReturn.setNullableClassList(nullableClassList);
pigeonReturn.setClassMap(classMap);
pigeonReturn.setNullableClassMap(nullableClassMap);
pigeonReturn.setAnEmptyClass(anEmptyClass);
return pigeonReturn;
}
}

@NonNull
ArrayList<Object> toList() {
ArrayList<Object> toListResult = new ArrayList<>(7);
ArrayList<Object> toListResult = new ArrayList<>(8);
toListResult.add(allNullableTypes);
toListResult.add(allNullableTypesWithoutRecursion);
toListResult.add(allTypes);
toListResult.add(classList);
toListResult.add(nullableClassList);
toListResult.add(classMap);
toListResult.add(nullableClassMap);
toListResult.add(anEmptyClass);
return toListResult;
}

Expand All @@ -3174,6 +3200,8 @@ ArrayList<Object> toList() {
Object nullableClassMap = pigeonVar_list.get(6);
pigeonResult.setNullableClassMap(
(Map<Long, AllNullableTypesWithoutRecursion>) nullableClassMap);
Object anEmptyClass = pigeonVar_list.get(7);
pigeonResult.setAnEmptyClass((AnEmptyClass) anEmptyClass);
return pigeonResult;
}
}
Expand Down Expand Up @@ -3249,6 +3277,50 @@ ArrayList<Object> toList() {
}
}

/** Generated class from Pigeon that represents data sent in messages. */
public static final class AnEmptyClass {
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
AnEmptyClass that = (AnEmptyClass) o;
return true;
}

@Override
public int hashCode() {
return Objects.hash(getClass());
}

@Override
public String toString() {
return "AnEmptyClass{}";
}

public static final class Builder {

public @NonNull AnEmptyClass build() {
AnEmptyClass pigeonReturn = new AnEmptyClass();
return pigeonReturn;
}
}

@NonNull
ArrayList<Object> toList() {
ArrayList<Object> toListResult = new ArrayList<>(0);
return toListResult;
}

static @NonNull AnEmptyClass fromList(@NonNull ArrayList<Object> pigeonVar_list) {
AnEmptyClass pigeonResult = new AnEmptyClass();
return pigeonResult;
}
}

private static class PigeonCodec extends StandardMessageCodec {
public static final PigeonCodec INSTANCE = new PigeonCodec();

Expand Down Expand Up @@ -3279,6 +3351,8 @@ protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) {
return AllClassesWrapper.fromList((ArrayList<Object>) readValue(buffer));
case (byte) 136:
return TestMessage.fromList((ArrayList<Object>) readValue(buffer));
case (byte) 137:
return AnEmptyClass.fromList((ArrayList<Object>) readValue(buffer));
default:
return super.readValueOfType(type, buffer);
}
Expand Down Expand Up @@ -3310,6 +3384,9 @@ protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) {
} else if (value instanceof TestMessage) {
stream.write(136);
writeValue(stream, ((TestMessage) value).toList());
} else if (value instanceof AnEmptyClass) {
stream.write(137);
writeValue(stream, ((AnEmptyClass) value).toList());
} else {
super.writeValue(stream, value);
}
Expand Down
Loading
Loading