writeDataClass method
void
writeDataClass(
- CppOptions generatorOptions,
- Root root,
- Indent indent,
- Class classDefinition, {
- required String dartPackageName,
- bool isOverflowClass = false,
override
Writes a single data class to indent
.
Implementation
@override
void writeDataClass(
CppOptions generatorOptions,
Root root,
Indent indent,
Class classDefinition, {
required String dartPackageName,
bool isOverflowClass = false,
}) {
// When generating for a Pigeon unit test, add a test fixture friend class to
// allow unit testing private methods, since testing serialization via public
// methods is essentially an end-to-end test.
String? testFixtureClass;
if (generatorOptions.namespace?.endsWith('_pigeontest') ?? false) {
testFixtureClass =
'${_pascalCaseFromSnakeCase(generatorOptions.namespace!.replaceAll('_pigeontest', ''))}Test';
}
indent.newln();
const List<String> generatedMessages = <String>[
' Generated class from Pigeon that represents data sent in messages.'
];
addDocumentationComments(
indent, classDefinition.documentationComments, _docCommentSpec,
generatorComments: generatedMessages);
final Iterable<NamedType> orderedFields =
getFieldsInSerializationOrder(classDefinition);
indent.write('class ${classDefinition.name} ');
indent.addScoped('{', '};', () {
_writeAccessBlock(indent, _ClassAccess.public, () {
final Iterable<NamedType> requiredFields =
orderedFields.where((NamedType type) => !type.type.isNullable);
// Minimal constructor, if needed.
if (requiredFields.length != orderedFields.length) {
_writeClassConstructor(root, indent, classDefinition, requiredFields,
'Constructs an object setting all non-nullable fields.');
}
// All-field constructor.
_writeClassConstructor(root, indent, classDefinition, orderedFields,
'Constructs an object setting all fields.');
// If any fields are pointer type, then the class requires a custom
// copy constructor, so declare the rule-of-five group of functions.
if (orderedFields.any((NamedType field) => _isPointerField(
getFieldHostDatatype(field, _baseCppTypeForBuiltinDartType)))) {
final String className = classDefinition.name;
// Add the default destructor, since unique_ptr destroys itself.
_writeFunctionDeclaration(indent, '~$className', defaultImpl: true);
// Declare custom copy/assign to deep-copy the pointer.
_writeFunctionDeclaration(indent, className,
isConstructor: true,
isCopy: true,
parameters: <String>['const $className& other']);
_writeFunctionDeclaration(indent, 'operator=',
returnType: '$className&',
parameters: <String>['const $className& other']);
// Re-add the default move operations, since they work fine with
// unique_ptr.
_writeFunctionDeclaration(indent, className,
isConstructor: true,
isCopy: true,
parameters: <String>['$className&& other'],
defaultImpl: true);
_writeFunctionDeclaration(indent, 'operator=',
returnType: '$className&',
parameters: <String>['$className&& other'],
defaultImpl: true,
noexcept: true);
}
for (final NamedType field in orderedFields) {
addDocumentationComments(
indent, field.documentationComments, _docCommentSpec);
final HostDatatype baseDatatype =
getFieldHostDatatype(field, _baseCppTypeForBuiltinDartType);
// Declare a getter and setter.
_writeFunctionDeclaration(indent, _makeGetterName(field),
returnType: _getterReturnType(baseDatatype), isConst: true);
final String setterName = _makeSetterName(field);
_writeFunctionDeclaration(indent, setterName,
returnType: _voidType,
parameters: <String>[
'${_unownedArgumentType(baseDatatype)} value_arg'
]);
if (field.type.isNullable) {
// Add a second setter that takes the non-nullable version of the
// argument for convenience, since setting literal values with the
// pointer version is non-trivial.
final HostDatatype nonNullType = _nonNullableType(baseDatatype);
_writeFunctionDeclaration(indent, setterName,
returnType: _voidType,
parameters: <String>[
'${_unownedArgumentType(nonNullType)} value_arg'
]);
}
indent.newln();
}
});
_writeAccessBlock(indent, _ClassAccess.private, () {
_writeFunctionDeclaration(indent, 'FromEncodableList',
returnType: isOverflowClass
? 'flutter::EncodableValue'
: classDefinition.name,
parameters: <String>['const flutter::EncodableList& list'],
isStatic: true);
_writeFunctionDeclaration(indent, 'ToEncodableList',
returnType: 'flutter::EncodableList', isConst: true);
if (isOverflowClass) {
_writeFunctionDeclaration(indent, 'Unwrap',
returnType: 'flutter::EncodableValue');
}
if (!isOverflowClass && root.requiresOverflowClass) {
indent.writeln('friend class $_overflowClassName;');
}
for (final Class friend in root.classes) {
if (friend != classDefinition &&
friend.fields.any((NamedType element) =>
element.type.baseName == classDefinition.name)) {
indent.writeln('friend class ${friend.name};');
}
}
for (final Api api in root.apis
.where((Api api) => api is AstFlutterApi || api is AstHostApi)) {
// TODO(gaaclarke): Find a way to be more precise with our
// friendships.
indent.writeln('friend class ${api.name};');
}
indent.writeln('friend class $_codecSerializerName;');
if (testFixtureClass != null) {
indent.writeln('friend class $testFixtureClass;');
}
for (final NamedType field in orderedFields) {
final HostDatatype hostDatatype =
getFieldHostDatatype(field, _baseCppTypeForBuiltinDartType);
indent.writeln(
'${_fieldType(hostDatatype)} ${_makeInstanceVariableName(field)};');
}
});
}, nestCount: 0);
indent.newln();
}