generate method

  1. @override
Future<String> generate(
  1. LibraryReader library,
  2. BuildStep _
)

Generates Dart code for an input Dart library.

May create additional outputs through the buildStep, but the 'primary' output is Dart code returned through the Future. If there is nothing to generate for this library may return null, or a Future that resolves to null or the empty string.

Implementation

@override
Future<String> generate(LibraryReader library, _) async {
  var result = StringBuffer();

  for (var element in library.allElements.whereType<ClassElement>()) {
    if (BuiltNodeElementSource.needsBuiltValue(element)) {
      _TypeNodeElement type;

      var elementName = element.name.substring(0, element.name.length - 5);
      var tagName = elementName.toLowerCase();
      var generic = element.allSupertypes
          .firstWhereOrNull(
            (element) => element.element.name == 'BuiltNodeElement',
          )
          ?.typeArguments
          .first;
      var noEvents = element.allSupertypes.firstWhereOrNull(
        (element) => element.element.name == 'NoEvents',
      );

      var attributesElement = element
          .getField('attributes')
          ?.computeConstantValue()
          ?.toListValue()
          ?.map(_mapperAttributeDartObject)
          .cast()
          .toList();

      var attributesExtendElement;

      if (attributesElement == null) {
        attributesExtendElement = element
            .getField('attributesExtend')
            ?.computeConstantValue()
            ?.toListValue()
            ?.map(_mapperAttributeDartObject)
            .cast()
            .toList();
      }

      var attributes =
          attributesElement ??
          <Attribute>[
            ...?attributesExtendElement,
            ...(attributesHtml.values),
            if (noEvents == null) ...attributesEvents,
          ];

      switch (generic.toString()) {
        case 'ChildNodeElement':
          type = _TypeNodeElement.child;
          break;
        default:
          type = _TypeNodeElement.single;
      }

      result.writeln('// Code for "$element"');
      result.writeln(
        'class $elementName extends ${_extendsNodeElement[type]} implements ${element.name} {',
      );
      result.writeAll([
        'const $elementName({',
        if (type == _TypeNodeElement.child) ...[
          'NodeElement? child, List<NodeElement>? children,',
        ],
        ...attributes.map((e) => ' ${e.init},').toList(),
        '})',
        if (type == _TypeNodeElement.child) ...[
          ' : super(child: child, children: children)',
        ],
        ';\n\n',
        ...attributes.map((e) => ' ${e.type}\n').toList(),
      ]);
      result.writeAll([
        '\n@override\n',
        'String build() => [',
        '\'<$tagName\',',
        ...attributes.map((e) => ' ${e.html},').toList(),
        '\'>\'',
        if (type == _TypeNodeElement.child) ...[
          ', super.build()',
          ', \'</$tagName>\'',
        ],
        '].join();',
      ]);
      result.writeln('}');
    }
  }

  return result.toString();
}