writeDataClass method

  1. @override
void writeDataClass(
  1. CppOptions generatorOptions,
  2. Root root,
  3. Indent indent,
  4. Class classDefinition, {
  5. required String dartPackageName,
  6. 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();
}