WIP: Multiple same type component usage #201

Closed
malo wants to merge 7 commits from components/feat/enable-multiple-same-type-components-usage into master
Showing only changes of commit e231f14162 - Show all commits

View File

@ -0,0 +1,101 @@
// Copyright (C) 2023 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import 'dart:async';
import 'package:analyzer/dart/element/element.dart';
import 'package:build/build.dart';
import 'package:source_gen/source_gen.dart';
import 'package:wyatt_component_copy_with_extension/wyatt_component_copy_with_extension.dart';
class ComponentMultiProxyGenerator
extends GeneratorForAnnotation<ComponentProxyExtension> {
@override
FutureOr<String> generateForAnnotatedElement(
Element element,
ConstantReader annotation,
BuildStep buildStep,
) {
/// Check element type
if (element is! ClassElement) {
throw InvalidGenerationSourceError(
'Only classes can be annotated with "CopyWith". "$element" is '
'not a ClassElement.',
element: element,
);
}
final classAnnotation = ComponentProxyExtension(
skipFields: annotation.peek('skipFields')?.boolValue ?? true,
);
final multiProxyClassName =
element.displayName.replaceAll('Component', 'MultiProxy');
final generatedCode = StringBuffer()
..write(
'@ComponentCopyWithExtension() class '
'\$$multiProxyClassName extends ${element.displayName} with '
'\$\$${multiProxyClassName}CWMixin {',
)
..write('final bool? freezed; '
'final ${element.displayName} Function(BuildContext context) select;')
..write('\$$multiProxyClassName(');
if (classAnnotation.skipFields ?? true) {
generatedCode.write('this.select,');
for (final field in element.constructors.first.parameters
.where((element) => element.isNamed == false)) {
generatedCode.write('super.${field.displayName},');
}
generatedCode
..write('{')
..write('this.freezed,');
for (final field in element.constructors.first.parameters
.where((element) => element.isNamed)) {
if (field.isRequiredNamed) {
generatedCode.write('required ');
}
generatedCode.write('super.${field.displayName},');
}
generatedCode
..write('});')
..write(' factory \$$multiProxyClassName.multi( '
' ${element.displayName} Function(BuildContext context) test, '
'{bool freezed = true}) => '
'\$$multiProxyClassName( '
'test, '
'freezed: freezed,); ')
..write(
' ${element.displayName}? compo; '
'@override '
'Widget build(BuildContext context) { final component = '
'(compo ??= select(context)).copyWith.call(',
);
for (final field in element.constructors.first.parameters) {
generatedCode.write('${field.displayName}:${field.displayName},');
}
generatedCode
..write(');')
..write('if (!(freezed ?? true)) { '
'compo = null; } '
'return component; '
'}} ');
}
return generatedCode.toString();
}
}