diff --git a/.github/workflows/pr-check-annotation.yml b/.github/workflows/pr-check-annotation.yml index 0e49f47d..1eabea7e 100644 --- a/.github/workflows/pr-check-annotation.yml +++ b/.github/workflows/pr-check-annotation.yml @@ -18,7 +18,7 @@ jobs: - name: Setup Flutter uses: subosito/flutter-action@v2 with: - flutter-version: 3.35.5 + flutter-version: 3.41.9 channel: stable cache: true - name: Check out repository code @@ -36,4 +36,4 @@ jobs: run: cd packages/reactive_forms_annotations && flutter analyze --no-fatal-infos - name: reactive_forms_annotations => code formatting - run: cd packages/reactive_forms_annotations && dart format --set-exit-if-changed lib \ No newline at end of file + run: cd packages/reactive_forms_annotations && dart format --set-exit-if-changed lib diff --git a/.github/workflows/pr-check-example.yml b/.github/workflows/pr-check-example.yml index ac3aeabf..1e8c8907 100644 --- a/.github/workflows/pr-check-example.yml +++ b/.github/workflows/pr-check-example.yml @@ -18,7 +18,7 @@ jobs: - name: Setup Flutter uses: subosito/flutter-action@v2 with: - flutter-version: 3.35.5 + flutter-version: 3.41.9 channel: stable cache: true - name: Check out repository code @@ -42,4 +42,4 @@ jobs: # run: cd packages/reactive_forms_generator/example && flutter pub get && dart format --set-exit-if-changed lib - name: reactive_forms_generator => example => test - run: cd packages/reactive_forms_generator/example && flutter test \ No newline at end of file + run: cd packages/reactive_forms_generator/example && flutter test diff --git a/.github/workflows/pr-check-generator-test.yml b/.github/workflows/pr-check-generator-test.yml index b02569e7..cdb375ff 100644 --- a/.github/workflows/pr-check-generator-test.yml +++ b/.github/workflows/pr-check-generator-test.yml @@ -18,7 +18,7 @@ jobs: - name: Setup Flutter uses: subosito/flutter-action@v2 with: - flutter-version: 3.35.5 + flutter-version: 3.41.9 channel: stable cache: true - name: Check out repository code @@ -33,4 +33,4 @@ jobs: run: melos bs - name: reactive_forms_generator => Code generation tests - run: cd packages/generator_tests && dart test && cd ../ \ No newline at end of file + run: cd packages/generator_tests && dart test && cd ../ diff --git a/.github/workflows/pr-check-generator.yml b/.github/workflows/pr-check-generator.yml index 814e1c5a..18d4fb16 100644 --- a/.github/workflows/pr-check-generator.yml +++ b/.github/workflows/pr-check-generator.yml @@ -18,7 +18,7 @@ jobs: - name: Setup Flutter uses: subosito/flutter-action@v2 with: - flutter-version: 3.35.5 + flutter-version: 3.41.9 channel: stable cache: true - name: Check out repository code @@ -36,4 +36,4 @@ jobs: run: flutter analyze --no-fatal-infos - name: code formatting - run: dart format --set-exit-if-changed lib \ No newline at end of file + run: dart format --set-exit-if-changed lib diff --git a/packages/generator_tests/pubspec.yaml b/packages/generator_tests/pubspec.yaml index d54b792f..07da7279 100644 --- a/packages/generator_tests/pubspec.yaml +++ b/packages/generator_tests/pubspec.yaml @@ -24,11 +24,11 @@ resolution: workspace dependencies: build: ^4.0.1 - source_gen: ^4.0.1 + source_gen: ^4.1.2 path: ^1.8.2 build_runner: ^2.10.1 code_builder: ^4.11.0 - dart_style: ^3.1.2 + dart_style: ^3.1.3 recase: ^4.1.0 reactive_forms_annotations: path: ../reactive_forms_annotations @@ -43,8 +43,3 @@ dev_dependencies: reactive_forms_generator: path: ../reactive_forms_generator flutter_lints: ^6.0.0 - -dependency_overrides: - analyzer: 8.2.0 - _fe_analyzer_shared: 89.0.0 - test_core: 0.6.8 \ No newline at end of file diff --git a/packages/generator_tests/test/doc/array_nullable_output_test.dart b/packages/generator_tests/test/doc/array_nullable_output_test.dart index 4895f598..c90b100a 100644 --- a/packages/generator_tests/test/doc/array_nullable_output_test.dart +++ b/packages/generator_tests/test/doc/array_nullable_output_test.dart @@ -204,6 +204,7 @@ class _ArrayNullableOFormBuilderState extends State { ArrayNullableOForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -246,7 +247,9 @@ class _ArrayNullableOFormBuilderState extends State { @override void didUpdateWidget(covariant ArrayNullableOFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -282,8 +285,12 @@ final _logArrayNullableOForm = Logger.detached('ArrayNullableOForm'); class ArrayNullableOForm implements FormModel { - ArrayNullableOForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + ArrayNullableOForm( + this.form, + this.path, + this._formModel, { + ArrayNullableO? initialModel, + }) : _ownInitialModel = initialModel; static const String emailListControlName = "emailList"; @@ -304,8 +311,10 @@ class ArrayNullableOForm final Map _disabled = {}; - @override - final Map initial; + ArrayNullableO? _ownInitialModel; + + late Map _ownInitialRawValue = + ArrayNullableOForm.formElements(_ownInitialModel).rawValue; String someListControlPath() => pathBuilder(someListControlName); @@ -1047,10 +1056,28 @@ class ArrayNullableOForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + ArrayNullableO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([ArrayNullableO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = ArrayNullableOForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1089,55 +1116,6 @@ class ArrayNullableOForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/generator_tests/test/doc/array_nullable_test.dart b/packages/generator_tests/test/doc/array_nullable_test.dart index 9a5e5696..505b7b42 100644 --- a/packages/generator_tests/test/doc/array_nullable_test.dart +++ b/packages/generator_tests/test/doc/array_nullable_test.dart @@ -207,6 +207,7 @@ class _ArrayNullableFormBuilderState extends State { ArrayNullableForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -249,7 +250,9 @@ class _ArrayNullableFormBuilderState extends State { @override void didUpdateWidget(covariant ArrayNullableFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -284,8 +287,12 @@ class _ArrayNullableFormBuilderState extends State { final _logArrayNullableForm = Logger.detached('ArrayNullableForm'); class ArrayNullableForm implements FormModel { - ArrayNullableForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + ArrayNullableForm( + this.form, + this.path, + this._formModel, { + ArrayNullable? initialModel, + }) : _ownInitialModel = initialModel; static const String emailListControlName = "emailList"; @@ -308,8 +315,10 @@ class ArrayNullableForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + ArrayNullable? _ownInitialModel; + + late Map _ownInitialRawValue = + ArrayNullableForm.formElements(_ownInitialModel).rawValue; String someListControlPath() => pathBuilder(someListControlName); @@ -1134,10 +1143,28 @@ class ArrayNullableForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + ArrayNullable? get initialModel { + return _ownInitialModel; + } + + void commitInitial([ArrayNullable? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = ArrayNullableForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1176,55 +1203,6 @@ class ArrayNullableForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/generator_tests/test/doc/create_output_test.dart b/packages/generator_tests/test/doc/create_output_test.dart index f23e45d2..72ec93de 100644 --- a/packages/generator_tests/test/doc/create_output_test.dart +++ b/packages/generator_tests/test/doc/create_output_test.dart @@ -248,6 +248,7 @@ class _MSICreateFormBuilderState extends State { MSICreateForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -290,7 +291,9 @@ class _MSICreateFormBuilderState extends State { @override void didUpdateWidget(covariant MSICreateFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -325,8 +328,12 @@ class _MSICreateFormBuilderState extends State { final _logMSICreateForm = Logger.detached('MSICreateForm'); class MSICreateForm implements FormModel { - MSICreateForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + MSICreateForm( + this.form, + this.path, + this._formModel, { + MSICreate? initialModel, + }) : _ownInitialModel = initialModel; static const String idControlName = "id"; @@ -358,8 +365,11 @@ class MSICreateForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + MSICreate? _ownInitialModel; + + late Map _ownInitialRawValue = MSICreateForm.formElements( + _ownInitialModel, + ).rawValue; String idControlPath() => pathBuilder(idControlName); @@ -1493,10 +1503,26 @@ class MSICreateForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + MSICreate? get initialModel { + return _ownInitialModel; + } + + void commitInitial([MSICreate? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = MSICreateForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1535,55 +1561,6 @@ class MSICreateForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -1666,7 +1643,8 @@ class MSICreateForm implements FormModel { final _logAddressForm = Logger.detached('AddressForm'); class AddressForm implements FormModel { - AddressForm(this.form, this.path, this._formModel) : initial = form.rawValue; + AddressForm(this.form, this.path, this._formModel, {Address? initialModel}) + : _ownInitialModel = initialModel; static const String streetControlName = "street"; @@ -1685,8 +1663,11 @@ class AddressForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + Address? _ownInitialModel; + + late Map _ownInitialRawValue = AddressForm.formElements( + _ownInitialModel, + ).rawValue; String streetControlPath() => pathBuilder(streetControlName); @@ -2182,10 +2163,26 @@ class AddressForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + Address? get initialModel { + return _ownInitialModel; + } + + void commitInitial([Address? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = AddressForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -2224,55 +2221,6 @@ class AddressForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -2322,8 +2270,12 @@ final _logPrimaryContactForm = Logger.detached('PrimaryContactForm'); class PrimaryContactForm implements FormModel { - PrimaryContactForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + PrimaryContactForm( + this.form, + this.path, + this._formModel, { + PrimaryContact? initialModel, + }) : _ownInitialModel = initialModel; static const String fullNameControlName = "fullName"; @@ -2340,8 +2292,10 @@ class PrimaryContactForm final Map _disabled = {}; - @override - final Map initial; + PrimaryContact? _ownInitialModel; + + late Map _ownInitialRawValue = + PrimaryContactForm.formElements(_ownInitialModel).rawValue; String fullNameControlPath() => pathBuilder(fullNameControlName); @@ -2730,10 +2684,28 @@ class PrimaryContactForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + PrimaryContact? get initialModel { + return _ownInitialModel; + } + + void commitInitial([PrimaryContact? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = PrimaryContactForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -2772,55 +2744,6 @@ class PrimaryContactForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -2865,8 +2788,12 @@ final _logAdminContactInformationForm = Logger.detached( class AdminContactInformationForm implements FormModel { - AdminContactInformationForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + AdminContactInformationForm( + this.form, + this.path, + this._formModel, { + AdminContactInformation? initialModel, + }) : _ownInitialModel = initialModel; static const String firstNameControlName = "firstName"; @@ -2883,8 +2810,10 @@ class AdminContactInformationForm final Map _disabled = {}; - @override - final Map initial; + AdminContactInformation? _ownInitialModel; + + late Map _ownInitialRawValue = + AdminContactInformationForm.formElements(_ownInitialModel).rawValue; String firstNameControlPath() => pathBuilder(firstNameControlName); @@ -3273,10 +3202,28 @@ class AdminContactInformationForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + AdminContactInformation? get initialModel { + return _ownInitialModel; + } + + void commitInitial([AdminContactInformation? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = AdminContactInformationForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -3315,55 +3262,6 @@ class AdminContactInformationForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/generator_tests/test/doc/delivery_list_output_test.dart b/packages/generator_tests/test/doc/delivery_list_output_test.dart index d436bfd6..d5ea0e6b 100644 --- a/packages/generator_tests/test/doc/delivery_list_output_test.dart +++ b/packages/generator_tests/test/doc/delivery_list_output_test.dart @@ -245,6 +245,7 @@ class _DeliveryListOFormBuilderState extends State { DeliveryListOForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -287,7 +288,9 @@ class _DeliveryListOFormBuilderState extends State { @override void didUpdateWidget(covariant DeliveryListOFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -323,8 +326,12 @@ final _logDeliveryListOForm = Logger.detached('DeliveryListOForm'); class DeliveryListOForm implements FormModel { - DeliveryListOForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + DeliveryListOForm( + this.form, + this.path, + this._formModel, { + DeliveryListO? initialModel, + }) : _ownInitialModel = initialModel; static const String deliveryListControlName = "deliveryList"; @@ -339,8 +346,10 @@ class DeliveryListOForm final Map _disabled = {}; - @override - final Map initial; + DeliveryListO? _ownInitialModel; + + late Map _ownInitialRawValue = + DeliveryListOForm.formElements(_ownInitialModel).rawValue; String deliveryListControlPath() => pathBuilder(deliveryListControlName); @@ -826,10 +835,28 @@ class DeliveryListOForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + DeliveryListO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([DeliveryListO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = DeliveryListOForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -868,55 +895,6 @@ class DeliveryListOForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -952,8 +930,12 @@ final _logDeliveryPointOForm = Logger.detached('DeliveryPointOForm'); class DeliveryPointOForm implements FormModel { - DeliveryPointOForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + DeliveryPointOForm( + this.form, + this.path, + this._formModel, { + DeliveryPointO? initialModel, + }) : _ownInitialModel = initialModel; static const String nameControlName = "name"; @@ -968,8 +950,10 @@ class DeliveryPointOForm final Map _disabled = {}; - @override - final Map initial; + DeliveryPointO? _ownInitialModel; + + late Map _ownInitialRawValue = + DeliveryPointOForm.formElements(_ownInitialModel).rawValue; String nameControlPath() => pathBuilder(nameControlName); @@ -1229,10 +1213,28 @@ class DeliveryPointOForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + DeliveryPointO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([DeliveryPointO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = DeliveryPointOForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1271,55 +1273,6 @@ class DeliveryPointOForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -1345,7 +1298,8 @@ class DeliveryPointOForm final _logAddressOForm = Logger.detached('AddressOForm'); class AddressOForm implements FormModel { - AddressOForm(this.form, this.path, this._formModel) : initial = form.rawValue; + AddressOForm(this.form, this.path, this._formModel, {AddressO? initialModel}) + : _ownInitialModel = initialModel; static const String streetControlName = "street"; @@ -1360,8 +1314,11 @@ class AddressOForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + AddressO? _ownInitialModel; + + late Map _ownInitialRawValue = AddressOForm.formElements( + _ownInitialModel, + ).rawValue; String streetControlPath() => pathBuilder(streetControlName); @@ -1639,10 +1596,26 @@ class AddressOForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + AddressO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([AddressO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = AddressOForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1681,55 +1654,6 @@ class AddressOForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -1762,7 +1686,8 @@ class AddressOForm implements FormModel { final _logClientOForm = Logger.detached('ClientOForm'); class ClientOForm implements FormModel { - ClientOForm(this.form, this.path, this._formModel) : initial = form.rawValue; + ClientOForm(this.form, this.path, this._formModel, {ClientO? initialModel}) + : _ownInitialModel = initialModel; static const String clientTypeControlName = "clientType"; @@ -1779,8 +1704,11 @@ class ClientOForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + ClientO? _ownInitialModel; + + late Map _ownInitialRawValue = ClientOForm.formElements( + _ownInitialModel, + ).rawValue; String clientTypeControlPath() => pathBuilder(clientTypeControlName); @@ -2144,10 +2072,26 @@ class ClientOForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + ClientO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([ClientO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = ClientOForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -2186,55 +2130,6 @@ class ClientOForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -2703,6 +2598,7 @@ class _StandaloneDeliveryPointFormBuilderState StandaloneDeliveryPointForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -2747,7 +2643,9 @@ class _StandaloneDeliveryPointFormBuilderState @override void didUpdateWidget(covariant StandaloneDeliveryPointFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -2785,8 +2683,12 @@ final _logStandaloneDeliveryPointForm = Logger.detached( class StandaloneDeliveryPointForm implements FormModel { - StandaloneDeliveryPointForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + StandaloneDeliveryPointForm( + this.form, + this.path, + this._formModel, { + DeliveryPointO? initialModel, + }) : _ownInitialModel = initialModel; static const String nameControlName = "name"; @@ -2801,8 +2703,10 @@ class StandaloneDeliveryPointForm final Map _disabled = {}; - @override - final Map initial; + DeliveryPointO? _ownInitialModel; + + late Map _ownInitialRawValue = + StandaloneDeliveryPointForm.formElements(_ownInitialModel).rawValue; String nameControlPath() => pathBuilder(nameControlName); @@ -3062,10 +2966,28 @@ class StandaloneDeliveryPointForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + DeliveryPointO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([DeliveryPointO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = StandaloneDeliveryPointForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -3104,55 +3026,6 @@ class StandaloneDeliveryPointForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/generator_tests/test/doc/delivery_list_test.dart b/packages/generator_tests/test/doc/delivery_list_test.dart index f5acd682..9f9bd690 100644 --- a/packages/generator_tests/test/doc/delivery_list_test.dart +++ b/packages/generator_tests/test/doc/delivery_list_test.dart @@ -237,6 +237,7 @@ class _DeliveryListFormBuilderState extends State { DeliveryListForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -279,7 +280,9 @@ class _DeliveryListFormBuilderState extends State { @override void didUpdateWidget(covariant DeliveryListFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -314,8 +317,12 @@ class _DeliveryListFormBuilderState extends State { final _logDeliveryListForm = Logger.detached('DeliveryListForm'); class DeliveryListForm implements FormModel { - DeliveryListForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + DeliveryListForm( + this.form, + this.path, + this._formModel, { + DeliveryList? initialModel, + }) : _ownInitialModel = initialModel; static const String deliveryListControlName = "deliveryList"; @@ -330,8 +337,11 @@ class DeliveryListForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + DeliveryList? _ownInitialModel; + + late Map _ownInitialRawValue = DeliveryListForm.formElements( + _ownInitialModel, + ).rawValue; String deliveryListControlPath() => pathBuilder(deliveryListControlName); @@ -816,10 +826,28 @@ class DeliveryListForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + DeliveryList? get initialModel { + return _ownInitialModel; + } + + void commitInitial([DeliveryList? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = DeliveryListForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -858,55 +886,6 @@ class DeliveryListForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -941,8 +920,12 @@ class DeliveryListForm implements FormModel { final _logDeliveryPointForm = Logger.detached('DeliveryPointForm'); class DeliveryPointForm implements FormModel { - DeliveryPointForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + DeliveryPointForm( + this.form, + this.path, + this._formModel, { + DeliveryPoint? initialModel, + }) : _ownInitialModel = initialModel; static const String nameControlName = "name"; @@ -957,8 +940,10 @@ class DeliveryPointForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + DeliveryPoint? _ownInitialModel; + + late Map _ownInitialRawValue = + DeliveryPointForm.formElements(_ownInitialModel).rawValue; String nameControlPath() => pathBuilder(nameControlName); @@ -1216,10 +1201,28 @@ class DeliveryPointForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + DeliveryPoint? get initialModel { + return _ownInitialModel; + } + + void commitInitial([DeliveryPoint? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = DeliveryPointForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1258,55 +1261,6 @@ class DeliveryPointForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -1332,7 +1286,8 @@ class DeliveryPointForm implements FormModel { final _logAddressForm = Logger.detached('AddressForm'); class AddressForm implements FormModel { - AddressForm(this.form, this.path, this._formModel) : initial = form.rawValue; + AddressForm(this.form, this.path, this._formModel, {Address? initialModel}) + : _ownInitialModel = initialModel; static const String streetControlName = "street"; @@ -1347,8 +1302,11 @@ class AddressForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + Address? _ownInitialModel; + + late Map _ownInitialRawValue = AddressForm.formElements( + _ownInitialModel, + ).rawValue; String streetControlPath() => pathBuilder(streetControlName); @@ -1625,10 +1583,26 @@ class AddressForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + Address? get initialModel { + return _ownInitialModel; + } + + void commitInitial([Address? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = AddressForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1667,55 +1641,6 @@ class AddressForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -1748,7 +1673,8 @@ class AddressForm implements FormModel { final _logClientForm = Logger.detached('ClientForm'); class ClientForm implements FormModel { - ClientForm(this.form, this.path, this._formModel) : initial = form.rawValue; + ClientForm(this.form, this.path, this._formModel, {Client? initialModel}) + : _ownInitialModel = initialModel; static const String clientTypeControlName = "clientType"; @@ -1765,8 +1691,11 @@ class ClientForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + Client? _ownInitialModel; + + late Map _ownInitialRawValue = ClientForm.formElements( + _ownInitialModel, + ).rawValue; String clientTypeControlPath() => pathBuilder(clientTypeControlName); @@ -2129,10 +2058,26 @@ class ClientForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + Client? get initialModel { + return _ownInitialModel; + } + + void commitInitial([Client? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = ClientForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -2171,55 +2116,6 @@ class ClientForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -2637,6 +2533,7 @@ class _StandaloneDeliveryPointFormBuilderState StandaloneDeliveryPointForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -2681,7 +2578,9 @@ class _StandaloneDeliveryPointFormBuilderState @override void didUpdateWidget(covariant StandaloneDeliveryPointFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -2719,8 +2618,12 @@ final _logStandaloneDeliveryPointForm = Logger.detached( class StandaloneDeliveryPointForm implements FormModel { - StandaloneDeliveryPointForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + StandaloneDeliveryPointForm( + this.form, + this.path, + this._formModel, { + DeliveryPoint? initialModel, + }) : _ownInitialModel = initialModel; static const String nameControlName = "name"; @@ -2735,8 +2638,10 @@ class StandaloneDeliveryPointForm final Map _disabled = {}; - @override - final Map initial; + DeliveryPoint? _ownInitialModel; + + late Map _ownInitialRawValue = + StandaloneDeliveryPointForm.formElements(_ownInitialModel).rawValue; String nameControlPath() => pathBuilder(nameControlName); @@ -2994,10 +2899,28 @@ class StandaloneDeliveryPointForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + DeliveryPoint? get initialModel { + return _ownInitialModel; + } + + void commitInitial([DeliveryPoint? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = StandaloneDeliveryPointForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -3036,55 +2959,6 @@ class StandaloneDeliveryPointForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/generator_tests/test/doc/freezed_class_output_test.dart b/packages/generator_tests/test/doc/freezed_class_output_test.dart index 467fb533..7a24711d 100644 --- a/packages/generator_tests/test/doc/freezed_class_output_test.dart +++ b/packages/generator_tests/test/doc/freezed_class_output_test.dart @@ -205,6 +205,7 @@ class _FreezedClassOFormBuilderState extends State { FreezedClassOForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -247,7 +248,9 @@ class _FreezedClassOFormBuilderState extends State { @override void didUpdateWidget(covariant FreezedClassOFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -283,8 +286,12 @@ final _logFreezedClassOForm = Logger.detached('FreezedClassOForm'); class FreezedClassOForm implements FormModel { - FreezedClassOForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + FreezedClassOForm( + this.form, + this.path, + this._formModel, { + FreezedClassO? initialModel, + }) : _ownInitialModel = initialModel; static const String genderControlName = "gender"; @@ -313,8 +320,10 @@ class FreezedClassOForm final Map _disabled = {}; - @override - final Map initial; + FreezedClassO? _ownInitialModel; + + late Map _ownInitialRawValue = + FreezedClassOForm.formElements(_ownInitialModel).rawValue; String genderControlPath() => pathBuilder(genderControlName); @@ -1272,10 +1281,28 @@ class FreezedClassOForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + FreezedClassO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([FreezedClassO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = FreezedClassOForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1314,55 +1341,6 @@ class FreezedClassOForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/generator_tests/test/doc/freezed_class_test.dart b/packages/generator_tests/test/doc/freezed_class_test.dart index 189a0577..08832c08 100644 --- a/packages/generator_tests/test/doc/freezed_class_test.dart +++ b/packages/generator_tests/test/doc/freezed_class_test.dart @@ -204,6 +204,7 @@ class _FreezedClassFormBuilderState extends State { FreezedClassForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -246,7 +247,9 @@ class _FreezedClassFormBuilderState extends State { @override void didUpdateWidget(covariant FreezedClassFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -281,8 +284,12 @@ class _FreezedClassFormBuilderState extends State { final _logFreezedClassForm = Logger.detached('FreezedClassForm'); class FreezedClassForm implements FormModel { - FreezedClassForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + FreezedClassForm( + this.form, + this.path, + this._formModel, { + FreezedClass? initialModel, + }) : _ownInitialModel = initialModel; static const String genderControlName = "gender"; @@ -305,8 +312,11 @@ class FreezedClassForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + FreezedClass? _ownInitialModel; + + late Map _ownInitialRawValue = FreezedClassForm.formElements( + _ownInitialModel, + ).rawValue; String genderControlPath() => pathBuilder(genderControlName); @@ -977,10 +987,28 @@ class FreezedClassForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + FreezedClass? get initialModel { + return _ownInitialModel; + } + + void commitInitial([FreezedClass? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = FreezedClassForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1019,55 +1047,6 @@ class FreezedClassForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/generator_tests/test/doc/generic_output_test.dart b/packages/generator_tests/test/doc/generic_output_test.dart index 8a16869a..f8e6dfb1 100644 --- a/packages/generator_tests/test/doc/generic_output_test.dart +++ b/packages/generator_tests/test/doc/generic_output_test.dart @@ -179,6 +179,7 @@ class _TagsOFormBuilderState extends State> { TagsOForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -221,7 +222,9 @@ class _TagsOFormBuilderState extends State> { @override void didUpdateWidget(covariant TagsOFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -256,7 +259,8 @@ class _TagsOFormBuilderState extends State> { final _logTagsOForm = Logger.detached('TagsOForm'); class TagsOForm implements FormModel, TagsOOutput> { - TagsOForm(this.form, this.path, this._formModel) : initial = form.rawValue; + TagsOForm(this.form, this.path, this._formModel, {TagsO? initialModel}) + : _ownInitialModel = initialModel; static const String tagsControlName = "tags"; @@ -269,8 +273,11 @@ class TagsOForm implements FormModel, TagsOOutput> { final Map _disabled = {}; - @override - final Map initial; + TagsO? _ownInitialModel; + + late Map _ownInitialRawValue = TagsOForm.formElements( + _ownInitialModel, + ).rawValue; String tagsControlPath() => pathBuilder(tagsControlName); @@ -447,10 +454,26 @@ class TagsOForm implements FormModel, TagsOOutput> { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + TagsO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([TagsO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = TagsOForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -489,55 +512,6 @@ class TagsOForm implements FormModel, TagsOOutput> { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/generator_tests/test/doc/generic_status_list_output_test.dart b/packages/generator_tests/test/doc/generic_status_list_output_test.dart index 8a7ef3db..ac0bc5ba 100644 --- a/packages/generator_tests/test/doc/generic_status_list_output_test.dart +++ b/packages/generator_tests/test/doc/generic_status_list_output_test.dart @@ -189,6 +189,7 @@ class _StatusListOFormBuilderState StatusListOForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -231,7 +232,9 @@ class _StatusListOFormBuilderState @override void didUpdateWidget(covariant StatusListOFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -267,8 +270,12 @@ final _logStatusListOForm = Logger.detached('StatusListOForm'); class StatusListOForm implements FormModel, StatusListOOutput> { - StatusListOForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + StatusListOForm( + this.form, + this.path, + this._formModel, { + StatusListO? initialModel, + }) : _ownInitialModel = initialModel; static const String listControlName = "list"; @@ -281,14 +288,17 @@ class StatusListOForm final Map _disabled = {}; - @override - final Map initial; + StatusListO? _ownInitialModel; + + late Map _ownInitialRawValue = StatusListOForm.formElements( + _ownInitialModel, + ).rawValue; String listControlPath() => pathBuilder(listControlName); - List get _listValue => listControl.rawValue.whereType().toList(); + List get _listValue => listControl.value ?? const []; - List get _listRawValue => listControl.rawValue.whereType().toList(); + List get _listRawValue => listControl.value ?? const []; bool get containsList { try { @@ -341,11 +351,8 @@ class StatusListOForm disabled: disabled, ); - FormArray get listControl => - form.control(listControlPath()) as FormArray; - - List> get listControlControls => - listControl.controls.cast>(); + FormControl> get listControl => + form.control(listControlPath()) as FormControl>; void listSetDisabled( bool disabled, { @@ -365,48 +372,6 @@ class StatusListOForm } } - void addListItem( - T? value, { - List>? asyncValidators, - List>? validators, - int? asyncValidatorsDebounceTime, - bool? disabled, - ValidatorsApplyMode validatorsApplyMode = ValidatorsApplyMode.merge, - }) { - List> resultingValidators = []; - List> resultingAsyncValidators = []; - - switch (validatorsApplyMode) { - case ValidatorsApplyMode.merge: - if (validators != null) { - resultingValidators.addAll(validators); - } - if (asyncValidators != null) { - resultingAsyncValidators.addAll(asyncValidators); - } - break; - case ValidatorsApplyMode.override: - if (validators != null) { - resultingValidators = validators; - } - - if (asyncValidators != null) { - resultingAsyncValidators = asyncValidators; - } - break; - } - - listControl.add( - FormControl( - value: value, - validators: resultingValidators, - asyncValidators: resultingAsyncValidators, - asyncValidatorsDebounceTime: asyncValidatorsDebounceTime ?? 250, - disabled: disabled ?? false, - ), - ); - } - @override @protected StatusListOOutput get model { @@ -481,10 +446,28 @@ class StatusListOForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + StatusListO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([StatusListO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = StatusListOForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -523,77 +506,19 @@ class StatusListOForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); static FormGroup formElements(StatusListO? statusListO) => FormGroup( { - listControlName: FormArray( - (statusListO?.list ?? []) - .map( - (e) => FormControl( - value: e, - validators: [], - asyncValidators: [], - asyncValidatorsDebounceTime: 250, - disabled: false, - ), - ) - .toList(), + listControlName: FormControl>( + value: statusListO?.list, validators: [], asyncValidators: [], asyncValidatorsDebounceTime: 250, disabled: false, + touched: false, ), }, validators: [], diff --git a/packages/generator_tests/test/doc/generic_status_list_test.dart b/packages/generator_tests/test/doc/generic_status_list_test.dart index 3868b7cd..9558208c 100644 --- a/packages/generator_tests/test/doc/generic_status_list_test.dart +++ b/packages/generator_tests/test/doc/generic_status_list_test.dart @@ -189,6 +189,7 @@ class _StatusListFormBuilderState StatusListForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -231,7 +232,9 @@ class _StatusListFormBuilderState @override void didUpdateWidget(covariant StatusListFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -267,8 +270,12 @@ final _logStatusListForm = Logger.detached('StatusListForm'); class StatusListForm implements FormModel, StatusList> { - StatusListForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + StatusListForm( + this.form, + this.path, + this._formModel, { + StatusList? initialModel, + }) : _ownInitialModel = initialModel; static const String listControlName = "list"; @@ -281,14 +288,17 @@ class StatusListForm final Map _disabled = {}; - @override - final Map initial; + StatusList? _ownInitialModel; + + late Map _ownInitialRawValue = StatusListForm.formElements( + _ownInitialModel, + ).rawValue; String listControlPath() => pathBuilder(listControlName); - List get _listValue => listControl.rawValue.whereType().toList(); + List get _listValue => listControl.value ?? const []; - List get _listRawValue => listControl.rawValue.whereType().toList(); + List get _listRawValue => listControl.value ?? const []; bool get containsList { try { @@ -341,11 +351,8 @@ class StatusListForm disabled: disabled, ); - FormArray get listControl => - form.control(listControlPath()) as FormArray; - - List> get listControlControls => - listControl.controls.cast>(); + FormControl> get listControl => + form.control(listControlPath()) as FormControl>; void listSetDisabled( bool disabled, { @@ -365,48 +372,6 @@ class StatusListForm } } - void addListItem( - T? value, { - List>? asyncValidators, - List>? validators, - int? asyncValidatorsDebounceTime, - bool? disabled, - ValidatorsApplyMode validatorsApplyMode = ValidatorsApplyMode.merge, - }) { - List> resultingValidators = []; - List> resultingAsyncValidators = []; - - switch (validatorsApplyMode) { - case ValidatorsApplyMode.merge: - if (validators != null) { - resultingValidators.addAll(validators); - } - if (asyncValidators != null) { - resultingAsyncValidators.addAll(asyncValidators); - } - break; - case ValidatorsApplyMode.override: - if (validators != null) { - resultingValidators = validators; - } - - if (asyncValidators != null) { - resultingAsyncValidators = asyncValidators; - } - break; - } - - listControl.add( - FormControl( - value: value, - validators: resultingValidators, - asyncValidators: resultingAsyncValidators, - asyncValidatorsDebounceTime: asyncValidatorsDebounceTime ?? 250, - disabled: disabled ?? false, - ), - ); - } - @override StatusList get model { final isValid = !currentForm.hasErrors && currentForm.errors.isEmpty; @@ -480,10 +445,28 @@ class StatusListForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + StatusList? get initialModel { + return _ownInitialModel; + } + + void commitInitial([StatusList? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = StatusListForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -522,77 +505,19 @@ class StatusListForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); static FormGroup formElements(StatusList? statusList) => FormGroup( { - listControlName: FormArray( - (statusList?.list ?? []) - .map( - (e) => FormControl( - value: e, - validators: [], - asyncValidators: [], - asyncValidatorsDebounceTime: 250, - disabled: false, - ), - ) - .toList(), + listControlName: FormControl>( + value: statusList?.list, validators: [], asyncValidators: [], asyncValidatorsDebounceTime: 250, disabled: false, + touched: false, ), }, validators: [], diff --git a/packages/generator_tests/test/doc/generic_test.dart b/packages/generator_tests/test/doc/generic_test.dart index a0b99ad1..4ff2830c 100644 --- a/packages/generator_tests/test/doc/generic_test.dart +++ b/packages/generator_tests/test/doc/generic_test.dart @@ -178,6 +178,7 @@ class _TagsFormBuilderState extends State> { TagsForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -220,7 +221,9 @@ class _TagsFormBuilderState extends State> { @override void didUpdateWidget(covariant TagsFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -255,7 +258,8 @@ class _TagsFormBuilderState extends State> { final _logTagsForm = Logger.detached('TagsForm'); class TagsForm implements FormModel, Tags> { - TagsForm(this.form, this.path, this._formModel) : initial = form.rawValue; + TagsForm(this.form, this.path, this._formModel, {Tags? initialModel}) + : _ownInitialModel = initialModel; static const String tagsControlName = "tags"; @@ -268,8 +272,11 @@ class TagsForm implements FormModel, Tags> { final Map _disabled = {}; - @override - final Map initial; + Tags? _ownInitialModel; + + late Map _ownInitialRawValue = TagsForm.formElements( + _ownInitialModel, + ).rawValue; String tagsControlPath() => pathBuilder(tagsControlName); @@ -445,10 +452,26 @@ class TagsForm implements FormModel, Tags> { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + Tags? get initialModel { + return _ownInitialModel; + } + + void commitInitial([Tags? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = TagsForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -487,55 +510,6 @@ class TagsForm implements FormModel, Tags> { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/generator_tests/test/doc/group_output_test.dart b/packages/generator_tests/test/doc/group_output_test.dart index 032302ad..57a5e092 100644 --- a/packages/generator_tests/test/doc/group_output_test.dart +++ b/packages/generator_tests/test/doc/group_output_test.dart @@ -222,7 +222,12 @@ class _GroupOFormBuilderState extends State { @override void initState() { - _formModel = GroupOForm(GroupOForm.formElements(widget.model), null, null); + _formModel = GroupOForm( + GroupOForm.formElements(widget.model), + null, + null, + initialModel: widget.model, + ); if (_formModel.form.disabled) { _formModel.form.markAsDisabled(); @@ -264,7 +269,9 @@ class _GroupOFormBuilderState extends State { @override void didUpdateWidget(covariant GroupOFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -299,7 +306,8 @@ class _GroupOFormBuilderState extends State { final _logGroupOForm = Logger.detached('GroupOForm'); class GroupOForm implements FormModel { - GroupOForm(this.form, this.path, this._formModel) : initial = form.rawValue; + GroupOForm(this.form, this.path, this._formModel, {GroupO? initialModel}) + : _ownInitialModel = initialModel; static const String personalControlName = "personal"; @@ -318,8 +326,11 @@ class GroupOForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + GroupO? _ownInitialModel; + + late Map _ownInitialRawValue = GroupOForm.formElements( + _ownInitialModel, + ).rawValue; String personalControlPath() => pathBuilder(personalControlName); @@ -826,10 +837,26 @@ class GroupOForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + GroupO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([GroupO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = GroupOForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -868,55 +895,6 @@ class GroupOForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -937,8 +915,12 @@ class GroupOForm implements FormModel { final _logPersonalOForm = Logger.detached('PersonalOForm'); class PersonalOForm implements FormModel { - PersonalOForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + PersonalOForm( + this.form, + this.path, + this._formModel, { + PersonalO? initialModel, + }) : _ownInitialModel = initialModel; static const String nameControlName = "name"; @@ -953,8 +935,11 @@ class PersonalOForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + PersonalO? _ownInitialModel; + + late Map _ownInitialRawValue = PersonalOForm.formElements( + _ownInitialModel, + ).rawValue; String nameControlPath() => pathBuilder(nameControlName); @@ -1232,10 +1217,26 @@ class PersonalOForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + PersonalO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([PersonalO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = PersonalOForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1274,55 +1275,6 @@ class PersonalOForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -1355,7 +1307,8 @@ class PersonalOForm implements FormModel { final _logPhoneOForm = Logger.detached('PhoneOForm'); class PhoneOForm implements FormModel { - PhoneOForm(this.form, this.path, this._formModel) : initial = form.rawValue; + PhoneOForm(this.form, this.path, this._formModel, {PhoneO? initialModel}) + : _ownInitialModel = initialModel; static const String phoneNumberControlName = "phoneNumber"; @@ -1370,8 +1323,11 @@ class PhoneOForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + PhoneO? _ownInitialModel; + + late Map _ownInitialRawValue = PhoneOForm.formElements( + _ownInitialModel, + ).rawValue; String phoneNumberControlPath() => pathBuilder(phoneNumberControlName); @@ -1659,10 +1615,26 @@ class PhoneOForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + PhoneO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([PhoneO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = PhoneOForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1701,55 +1673,6 @@ class PhoneOForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -1782,7 +1705,8 @@ class PhoneOForm implements FormModel { final _logAddressOForm = Logger.detached('AddressOForm'); class AddressOForm implements FormModel { - AddressOForm(this.form, this.path, this._formModel) : initial = form.rawValue; + AddressOForm(this.form, this.path, this._formModel, {AddressO? initialModel}) + : _ownInitialModel = initialModel; static const String streetControlName = "street"; @@ -1799,8 +1723,11 @@ class AddressOForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + AddressO? _ownInitialModel; + + late Map _ownInitialRawValue = AddressOForm.formElements( + _ownInitialModel, + ).rawValue; String streetControlPath() => pathBuilder(streetControlName); @@ -2187,10 +2114,26 @@ class AddressOForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + AddressO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([AddressO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = AddressOForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -2229,55 +2172,6 @@ class AddressOForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/generator_tests/test/doc/group_test.dart b/packages/generator_tests/test/doc/group_test.dart index f2fc81d7..2c76de0a 100644 --- a/packages/generator_tests/test/doc/group_test.dart +++ b/packages/generator_tests/test/doc/group_test.dart @@ -219,7 +219,12 @@ class _GroupFormBuilderState extends State { @override void initState() { - _formModel = GroupForm(GroupForm.formElements(widget.model), null, null); + _formModel = GroupForm( + GroupForm.formElements(widget.model), + null, + null, + initialModel: widget.model, + ); if (_formModel.form.disabled) { _formModel.form.markAsDisabled(); @@ -261,7 +266,9 @@ class _GroupFormBuilderState extends State { @override void didUpdateWidget(covariant GroupFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -296,7 +303,8 @@ class _GroupFormBuilderState extends State { final _logGroupForm = Logger.detached('GroupForm'); class GroupForm implements FormModel { - GroupForm(this.form, this.path, this._formModel) : initial = form.rawValue; + GroupForm(this.form, this.path, this._formModel, {Group? initialModel}) + : _ownInitialModel = initialModel; static const String personalControlName = "personal"; @@ -315,8 +323,11 @@ class GroupForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + Group? _ownInitialModel; + + late Map _ownInitialRawValue = GroupForm.formElements( + _ownInitialModel, + ).rawValue; String personalControlPath() => pathBuilder(personalControlName); @@ -819,10 +830,26 @@ class GroupForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + Group? get initialModel { + return _ownInitialModel; + } + + void commitInitial([Group? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = GroupForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -858,55 +885,6 @@ class GroupForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -927,7 +905,8 @@ class GroupForm implements FormModel { final _logPersonalForm = Logger.detached('PersonalForm'); class PersonalForm implements FormModel { - PersonalForm(this.form, this.path, this._formModel) : initial = form.rawValue; + PersonalForm(this.form, this.path, this._formModel, {Personal? initialModel}) + : _ownInitialModel = initialModel; static const String nameControlName = "name"; @@ -942,8 +921,11 @@ class PersonalForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + Personal? _ownInitialModel; + + late Map _ownInitialRawValue = PersonalForm.formElements( + _ownInitialModel, + ).rawValue; String nameControlPath() => pathBuilder(nameControlName); @@ -1220,10 +1202,26 @@ class PersonalForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + Personal? get initialModel { + return _ownInitialModel; + } + + void commitInitial([Personal? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = PersonalForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1262,55 +1260,6 @@ class PersonalForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -1343,7 +1292,8 @@ class PersonalForm implements FormModel { final _logPhoneForm = Logger.detached('PhoneForm'); class PhoneForm implements FormModel { - PhoneForm(this.form, this.path, this._formModel) : initial = form.rawValue; + PhoneForm(this.form, this.path, this._formModel, {Phone? initialModel}) + : _ownInitialModel = initialModel; static const String phoneNumberControlName = "phoneNumber"; @@ -1358,8 +1308,11 @@ class PhoneForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + Phone? _ownInitialModel; + + late Map _ownInitialRawValue = PhoneForm.formElements( + _ownInitialModel, + ).rawValue; String phoneNumberControlPath() => pathBuilder(phoneNumberControlName); @@ -1643,10 +1596,26 @@ class PhoneForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + Phone? get initialModel { + return _ownInitialModel; + } + + void commitInitial([Phone? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = PhoneForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1682,55 +1651,6 @@ class PhoneForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -1763,7 +1683,8 @@ class PhoneForm implements FormModel { final _logAddressForm = Logger.detached('AddressForm'); class AddressForm implements FormModel { - AddressForm(this.form, this.path, this._formModel) : initial = form.rawValue; + AddressForm(this.form, this.path, this._formModel, {Address? initialModel}) + : _ownInitialModel = initialModel; static const String streetControlName = "street"; @@ -1780,8 +1701,11 @@ class AddressForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + Address? _ownInitialModel; + + late Map _ownInitialRawValue = AddressForm.formElements( + _ownInitialModel, + ).rawValue; String streetControlPath() => pathBuilder(streetControlName); @@ -2163,10 +2087,26 @@ class AddressForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + Address? get initialModel { + return _ownInitialModel; + } + + void commitInitial([Address? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = AddressForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -2205,55 +2145,6 @@ class AddressForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/generator_tests/test/doc/login_extended_nullable_output_test.dart b/packages/generator_tests/test/doc/login_extended_nullable_output_test.dart index 1792fa6f..0ebe5a5b 100644 --- a/packages/generator_tests/test/doc/login_extended_nullable_output_test.dart +++ b/packages/generator_tests/test/doc/login_extended_nullable_output_test.dart @@ -214,6 +214,7 @@ class _LoginExtendedNullableOFormBuilderState LoginExtendedNullableOForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -258,7 +259,9 @@ class _LoginExtendedNullableOFormBuilderState @override void didUpdateWidget(covariant LoginExtendedNullableOFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -296,8 +299,12 @@ final _logLoginExtendedNullableOForm = Logger.detached( class LoginExtendedNullableOForm implements FormModel { - LoginExtendedNullableOForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + LoginExtendedNullableOForm( + this.form, + this.path, + this._formModel, { + LoginExtendedNullableO? initialModel, + }) : _ownInitialModel = initialModel; static const String emailControlName = "email"; @@ -322,8 +329,10 @@ class LoginExtendedNullableOForm final Map _disabled = {}; - @override - final Map initial; + LoginExtendedNullableO? _ownInitialModel; + + late Map _ownInitialRawValue = + LoginExtendedNullableOForm.formElements(_ownInitialModel).rawValue; String emailControlPath() => pathBuilder(emailControlName); @@ -1125,10 +1134,28 @@ class LoginExtendedNullableOForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + LoginExtendedNullableO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([LoginExtendedNullableO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = LoginExtendedNullableOForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1167,55 +1194,6 @@ class LoginExtendedNullableOForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/generator_tests/test/doc/login_extended_nullable_test.dart b/packages/generator_tests/test/doc/login_extended_nullable_test.dart index 2c6cd01a..0c5bb6d4 100644 --- a/packages/generator_tests/test/doc/login_extended_nullable_test.dart +++ b/packages/generator_tests/test/doc/login_extended_nullable_test.dart @@ -214,6 +214,7 @@ class _LoginExtendedNullableFormBuilderState LoginExtendedNullableForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -258,7 +259,9 @@ class _LoginExtendedNullableFormBuilderState @override void didUpdateWidget(covariant LoginExtendedNullableFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -296,8 +299,12 @@ final _logLoginExtendedNullableForm = Logger.detached( class LoginExtendedNullableForm implements FormModel { - LoginExtendedNullableForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + LoginExtendedNullableForm( + this.form, + this.path, + this._formModel, { + LoginExtendedNullable? initialModel, + }) : _ownInitialModel = initialModel; static const String emailControlName = "email"; @@ -322,8 +329,10 @@ class LoginExtendedNullableForm final Map _disabled = {}; - @override - final Map initial; + LoginExtendedNullable? _ownInitialModel; + + late Map _ownInitialRawValue = + LoginExtendedNullableForm.formElements(_ownInitialModel).rawValue; String emailControlPath() => pathBuilder(emailControlName); @@ -1124,10 +1133,28 @@ class LoginExtendedNullableForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + LoginExtendedNullable? get initialModel { + return _ownInitialModel; + } + + void commitInitial([LoginExtendedNullable? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = LoginExtendedNullableForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1166,55 +1193,6 @@ class LoginExtendedNullableForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/generator_tests/test/doc/login_extended_output_test.dart b/packages/generator_tests/test/doc/login_extended_output_test.dart index 8bf0f7ba..99e26f4c 100644 --- a/packages/generator_tests/test/doc/login_extended_output_test.dart +++ b/packages/generator_tests/test/doc/login_extended_output_test.dart @@ -261,6 +261,7 @@ class _LoginExtendedOFormBuilderState extends State { LoginExtendedOForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -303,7 +304,9 @@ class _LoginExtendedOFormBuilderState extends State { @override void didUpdateWidget(covariant LoginExtendedOFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -339,8 +342,12 @@ final _logLoginExtendedOForm = Logger.detached('LoginExtendedOForm'); class LoginExtendedOForm implements FormModel { - LoginExtendedOForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + LoginExtendedOForm( + this.form, + this.path, + this._formModel, { + LoginExtendedO? initialModel, + }) : _ownInitialModel = initialModel; static const String emailControlName = "email"; @@ -371,8 +378,10 @@ class LoginExtendedOForm final Map _disabled = {}; - @override - final Map initial; + LoginExtendedO? _ownInitialModel; + + late Map _ownInitialRawValue = + LoginExtendedOForm.formElements(_ownInitialModel).rawValue; String emailControlPath() => pathBuilder(emailControlName); @@ -1298,10 +1307,28 @@ class LoginExtendedOForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + LoginExtendedO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([LoginExtendedO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = LoginExtendedOForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1340,55 +1367,6 @@ class LoginExtendedOForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/generator_tests/test/doc/login_extended_test.dart b/packages/generator_tests/test/doc/login_extended_test.dart index 6aba0296..8ef8c41e 100644 --- a/packages/generator_tests/test/doc/login_extended_test.dart +++ b/packages/generator_tests/test/doc/login_extended_test.dart @@ -256,6 +256,7 @@ class _LoginExtendedFormBuilderState extends State { LoginExtendedForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -298,7 +299,9 @@ class _LoginExtendedFormBuilderState extends State { @override void didUpdateWidget(covariant LoginExtendedFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -333,8 +336,12 @@ class _LoginExtendedFormBuilderState extends State { final _logLoginExtendedForm = Logger.detached('LoginExtendedForm'); class LoginExtendedForm implements FormModel { - LoginExtendedForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + LoginExtendedForm( + this.form, + this.path, + this._formModel, { + LoginExtended? initialModel, + }) : _ownInitialModel = initialModel; static const String emailControlName = "email"; @@ -363,8 +370,10 @@ class LoginExtendedForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + LoginExtended? _ownInitialModel; + + late Map _ownInitialRawValue = + LoginExtendedForm.formElements(_ownInitialModel).rawValue; String emailControlPath() => pathBuilder(emailControlName); @@ -1186,10 +1195,28 @@ class LoginExtendedForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + LoginExtended? get initialModel { + return _ownInitialModel; + } + + void commitInitial([LoginExtended? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = LoginExtendedForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1228,55 +1255,6 @@ class LoginExtendedForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/generator_tests/test/doc/login_output_test.dart b/packages/generator_tests/test/doc/login_output_test.dart index 378d5020..2d91b9d9 100644 --- a/packages/generator_tests/test/doc/login_output_test.dart +++ b/packages/generator_tests/test/doc/login_output_test.dart @@ -210,7 +210,12 @@ class _LoginOFormBuilderState extends State { @override void initState() { - _formModel = LoginOForm(LoginOForm.formElements(widget.model), null, null); + _formModel = LoginOForm( + LoginOForm.formElements(widget.model), + null, + null, + initialModel: widget.model, + ); if (_formModel.form.disabled) { _formModel.form.markAsDisabled(); @@ -252,7 +257,9 @@ class _LoginOFormBuilderState extends State { @override void didUpdateWidget(covariant LoginOFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -287,7 +294,8 @@ class _LoginOFormBuilderState extends State { final _logLoginOForm = Logger.detached('LoginOForm'); class LoginOForm implements FormModel { - LoginOForm(this.form, this.path, this._formModel) : initial = form.rawValue; + LoginOForm(this.form, this.path, this._formModel, {LoginO? initialModel}) + : _ownInitialModel = initialModel; static const String emailControlName = "email"; @@ -302,8 +310,11 @@ class LoginOForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + LoginO? _ownInitialModel; + + late Map _ownInitialRawValue = LoginOForm.formElements( + _ownInitialModel, + ).rawValue; String emailControlPath() => pathBuilder(emailControlName); @@ -582,10 +593,26 @@ class LoginOForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + LoginO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([LoginO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = LoginOForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -624,55 +651,6 @@ class LoginOForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/generator_tests/test/doc/login_test.dart b/packages/generator_tests/test/doc/login_test.dart index 06e96e7b..fc0eceab 100644 --- a/packages/generator_tests/test/doc/login_test.dart +++ b/packages/generator_tests/test/doc/login_test.dart @@ -194,7 +194,12 @@ class _LoginFormBuilderState extends State { @override void initState() { - _formModel = LoginForm(LoginForm.formElements(widget.model), null, null); + _formModel = LoginForm( + LoginForm.formElements(widget.model), + null, + null, + initialModel: widget.model, + ); if (_formModel.form.disabled) { _formModel.form.markAsDisabled(); @@ -236,7 +241,9 @@ class _LoginFormBuilderState extends State { @override void didUpdateWidget(covariant LoginFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -271,7 +278,8 @@ class _LoginFormBuilderState extends State { final _logLoginForm = Logger.detached('LoginForm'); class LoginForm implements FormModel { - LoginForm(this.form, this.path, this._formModel) : initial = form.rawValue; + LoginForm(this.form, this.path, this._formModel, {Login? initialModel}) + : _ownInitialModel = initialModel; static const String emailControlName = "email"; @@ -286,8 +294,11 @@ class LoginForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + Login? _ownInitialModel; + + late Map _ownInitialRawValue = LoginForm.formElements( + _ownInitialModel, + ).rawValue; String emailControlPath() => pathBuilder(emailControlName); @@ -541,10 +552,26 @@ class LoginForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + Login? get initialModel { + return _ownInitialModel; + } + + void commitInitial([Login? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = LoginForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -580,55 +607,6 @@ class LoginForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/generator_tests/test/doc/mailing_list_output_test.dart b/packages/generator_tests/test/doc/mailing_list_output_test.dart index 6110f280..6ca5595a 100644 --- a/packages/generator_tests/test/doc/mailing_list_output_test.dart +++ b/packages/generator_tests/test/doc/mailing_list_output_test.dart @@ -200,6 +200,7 @@ class _MailingListOFormBuilderState extends State { MailingListOForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -242,7 +243,9 @@ class _MailingListOFormBuilderState extends State { @override void didUpdateWidget(covariant MailingListOFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -277,8 +280,12 @@ class _MailingListOFormBuilderState extends State { final _logMailingListOForm = Logger.detached('MailingListOForm'); class MailingListOForm implements FormModel { - MailingListOForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + MailingListOForm( + this.form, + this.path, + this._formModel, { + MailingListO? initialModel, + }) : _ownInitialModel = initialModel; static const String emailListControlName = "emailList"; @@ -291,8 +298,11 @@ class MailingListOForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + MailingListO? _ownInitialModel; + + late Map _ownInitialRawValue = MailingListOForm.formElements( + _ownInitialModel, + ).rawValue; String emailListControlPath() => pathBuilder(emailListControlName); @@ -493,10 +503,28 @@ class MailingListOForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + MailingListO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([MailingListO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = MailingListOForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -535,55 +563,6 @@ class MailingListOForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/generator_tests/test/doc/mailing_list_test.dart b/packages/generator_tests/test/doc/mailing_list_test.dart index 99fe08f3..9f712d31 100644 --- a/packages/generator_tests/test/doc/mailing_list_test.dart +++ b/packages/generator_tests/test/doc/mailing_list_test.dart @@ -198,6 +198,7 @@ class _MailingListFormBuilderState extends State { MailingListForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -240,7 +241,9 @@ class _MailingListFormBuilderState extends State { @override void didUpdateWidget(covariant MailingListFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -275,8 +278,12 @@ class _MailingListFormBuilderState extends State { final _logMailingListForm = Logger.detached('MailingListForm'); class MailingListForm implements FormModel { - MailingListForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + MailingListForm( + this.form, + this.path, + this._formModel, { + MailingList? initialModel, + }) : _ownInitialModel = initialModel; static const String emailListControlName = "emailList"; @@ -289,8 +296,11 @@ class MailingListForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + MailingList? _ownInitialModel; + + late Map _ownInitialRawValue = MailingListForm.formElements( + _ownInitialModel, + ).rawValue; String emailListControlPath() => pathBuilder(emailListControlName); @@ -490,10 +500,28 @@ class MailingListForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + MailingList? get initialModel { + return _ownInitialModel; + } + + void commitInitial([MailingList? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = MailingListForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -532,55 +560,6 @@ class MailingListForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/generator_tests/test/doc/nested_generics_output_test.dart b/packages/generator_tests/test/doc/nested_generics_output_test.dart index 84fc42a5..c176e4fc 100644 --- a/packages/generator_tests/test/doc/nested_generics_output_test.dart +++ b/packages/generator_tests/test/doc/nested_generics_output_test.dart @@ -234,6 +234,7 @@ class _ProductDetailsOFormBuilderState

ProductDetailsOForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -276,7 +277,9 @@ class _ProductDetailsOFormBuilderState

@override void didUpdateWidget(covariant ProductDetailsOFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -312,8 +315,12 @@ final _logProductDetailsOForm = Logger.detached('ProductDetailsOForm'); class ProductDetailsOForm

implements FormModel, ProductDetailsOOutput> { - ProductDetailsOForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + ProductDetailsOForm( + this.form, + this.path, + this._formModel, { + ProductDetailsO? initialModel, + }) : _ownInitialModel = initialModel; static const String descriptionControlName = "description"; @@ -328,8 +335,10 @@ class ProductDetailsOForm

final Map _disabled = {}; - @override - final Map initial; + ProductDetailsO? _ownInitialModel; + + late Map _ownInitialRawValue = + ProductDetailsOForm.formElements(_ownInitialModel).rawValue; String descriptionControlPath() => pathBuilder(descriptionControlName); @@ -614,10 +623,28 @@ class ProductDetailsOForm

bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + ProductDetailsO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([ProductDetailsO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = ProductDetailsOForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -656,55 +683,6 @@ class ProductDetailsOForm

emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -733,7 +711,8 @@ final _logIdOForm = Logger.detached('IdOForm'); class IdOForm

implements FormModel, IdOOutput> { - IdOForm(this.form, this.path, this._formModel) : initial = form.rawValue; + IdOForm(this.form, this.path, this._formModel, {IdO? initialModel}) + : _ownInitialModel = initialModel; static const String companyNameControlName = "companyName"; @@ -748,8 +727,11 @@ class IdOForm

final Map _disabled = {}; - @override - final Map initial; + IdO? _ownInitialModel; + + late Map _ownInitialRawValue = IdOForm.formElements( + _ownInitialModel, + ).rawValue; String companyNameControlPath() => pathBuilder(companyNameControlName); @@ -1029,10 +1011,26 @@ class IdOForm

bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + IdO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([IdO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = IdOForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1071,55 +1069,6 @@ class IdOForm

emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -1560,6 +1509,7 @@ class _IdOFormBuilderState

IdOForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -1602,7 +1552,9 @@ class _IdOFormBuilderState

@override void didUpdateWidget(covariant IdOFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); diff --git a/packages/generator_tests/test/doc/nested_generics_test.dart b/packages/generator_tests/test/doc/nested_generics_test.dart index 4d8e31f2..f82720ee 100644 --- a/packages/generator_tests/test/doc/nested_generics_test.dart +++ b/packages/generator_tests/test/doc/nested_generics_test.dart @@ -231,6 +231,7 @@ class _ProductDetailsFormBuilderState

ProductDetailsForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -273,7 +274,9 @@ class _ProductDetailsFormBuilderState

@override void didUpdateWidget(covariant ProductDetailsFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -309,8 +312,12 @@ final _logProductDetailsForm = Logger.detached('ProductDetailsForm'); class ProductDetailsForm

implements FormModel, ProductDetails> { - ProductDetailsForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + ProductDetailsForm( + this.form, + this.path, + this._formModel, { + ProductDetails? initialModel, + }) : _ownInitialModel = initialModel; static const String descriptionControlName = "description"; @@ -325,8 +332,10 @@ class ProductDetailsForm

final Map _disabled = {}; - @override - final Map initial; + ProductDetails? _ownInitialModel; + + late Map _ownInitialRawValue = + ProductDetailsForm.formElements(_ownInitialModel).rawValue; String descriptionControlPath() => pathBuilder(descriptionControlName); @@ -607,10 +616,28 @@ class ProductDetailsForm

bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + ProductDetails? get initialModel { + return _ownInitialModel; + } + + void commitInitial([ProductDetails? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = ProductDetailsForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -649,55 +676,6 @@ class ProductDetailsForm

emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -726,7 +704,8 @@ final _logIdForm = Logger.detached('IdForm'); class IdForm

implements FormModel, Id> { - IdForm(this.form, this.path, this._formModel) : initial = form.rawValue; + IdForm(this.form, this.path, this._formModel, {Id? initialModel}) + : _ownInitialModel = initialModel; static const String companyNameControlName = "companyName"; @@ -741,8 +720,11 @@ class IdForm

final Map _disabled = {}; - @override - final Map initial; + Id? _ownInitialModel; + + late Map _ownInitialRawValue = IdForm.formElements( + _ownInitialModel, + ).rawValue; String companyNameControlPath() => pathBuilder(companyNameControlName); @@ -1021,10 +1003,26 @@ class IdForm

bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + Id? get initialModel { + return _ownInitialModel; + } + + void commitInitial([Id? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = IdForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1063,55 +1061,6 @@ class IdForm

emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -1529,6 +1478,7 @@ class _IdFormBuilderState

IdForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -1571,7 +1521,9 @@ class _IdFormBuilderState

@override void didUpdateWidget(covariant IdFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); diff --git a/packages/generator_tests/test/doc/nested_output.test.dart b/packages/generator_tests/test/doc/nested_output.test.dart index c86cd893..14be01e0 100644 --- a/packages/generator_tests/test/doc/nested_output.test.dart +++ b/packages/generator_tests/test/doc/nested_output.test.dart @@ -211,6 +211,7 @@ class _SubGroupOFormBuilderState extends State { SubGroupOForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -253,7 +254,9 @@ class _SubGroupOFormBuilderState extends State { @override void didUpdateWidget(covariant SubGroupOFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -288,8 +291,12 @@ class _SubGroupOFormBuilderState extends State { final _logSubGroupOForm = Logger.detached('SubGroupOForm'); class SubGroupOForm implements FormModel { - SubGroupOForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + SubGroupOForm( + this.form, + this.path, + this._formModel, { + SubGroupO? initialModel, + }) : _ownInitialModel = initialModel; static const String idControlName = "id"; @@ -302,8 +309,11 @@ class SubGroupOForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + SubGroupO? _ownInitialModel; + + late Map _ownInitialRawValue = SubGroupOForm.formElements( + _ownInitialModel, + ).rawValue; String idControlPath() => pathBuilder(idControlName); @@ -454,10 +464,26 @@ class SubGroupOForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + SubGroupO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([SubGroupO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = SubGroupOForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -496,55 +522,6 @@ class SubGroupOForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -950,7 +927,12 @@ class _GroupOFormBuilderState extends State { @override void initState() { - _formModel = GroupOForm(GroupOForm.formElements(widget.model), null, null); + _formModel = GroupOForm( + GroupOForm.formElements(widget.model), + null, + null, + initialModel: widget.model, + ); if (_formModel.form.disabled) { _formModel.form.markAsDisabled(); @@ -992,7 +974,9 @@ class _GroupOFormBuilderState extends State { @override void didUpdateWidget(covariant GroupOFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -1027,7 +1011,8 @@ class _GroupOFormBuilderState extends State { final _logGroupOForm = Logger.detached('GroupOForm'); class GroupOForm implements FormModel { - GroupOForm(this.form, this.path, this._formModel) : initial = form.rawValue; + GroupOForm(this.form, this.path, this._formModel, {GroupO? initialModel}) + : _ownInitialModel = initialModel; static const String idControlName = "id"; @@ -1042,8 +1027,11 @@ class GroupOForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + GroupO? _ownInitialModel; + + late Map _ownInitialRawValue = GroupOForm.formElements( + _ownInitialModel, + ).rawValue; String idControlPath() => pathBuilder(idControlName); @@ -1385,10 +1373,26 @@ class GroupOForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + GroupO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([GroupO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = GroupOForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1427,55 +1431,6 @@ class GroupOForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -1863,6 +1818,7 @@ class _NestedOFormBuilderState extends State { NestedOForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -1905,7 +1861,9 @@ class _NestedOFormBuilderState extends State { @override void didUpdateWidget(covariant NestedOFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -1940,7 +1898,8 @@ class _NestedOFormBuilderState extends State { final _logNestedOForm = Logger.detached('NestedOForm'); class NestedOForm implements FormModel { - NestedOForm(this.form, this.path, this._formModel) : initial = form.rawValue; + NestedOForm(this.form, this.path, this._formModel, {NestedO? initialModel}) + : _ownInitialModel = initialModel; static const String groupListControlName = "groupList"; @@ -1953,8 +1912,11 @@ class NestedOForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + NestedO? _ownInitialModel; + + late Map _ownInitialRawValue = NestedOForm.formElements( + _ownInitialModel, + ).rawValue; String groupListControlPath() => pathBuilder(groupListControlName); @@ -2215,10 +2177,26 @@ class NestedOForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + NestedO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([NestedO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = NestedOForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -2257,55 +2235,6 @@ class NestedOForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/generator_tests/test/doc/profile_output_test.dart b/packages/generator_tests/test/doc/profile_output_test.dart index 1faf181f..6320929f 100644 --- a/packages/generator_tests/test/doc/profile_output_test.dart +++ b/packages/generator_tests/test/doc/profile_output_test.dart @@ -432,6 +432,7 @@ class _ProfileOFormBuilderState extends State { ProfileOForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -474,7 +475,9 @@ class _ProfileOFormBuilderState extends State { @override void didUpdateWidget(covariant ProfileOFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -509,7 +512,8 @@ class _ProfileOFormBuilderState extends State { final _logProfileOForm = Logger.detached('ProfileOForm'); class ProfileOForm implements FormModel { - ProfileOForm(this.form, this.path, this._formModel) : initial = form.rawValue; + ProfileOForm(this.form, this.path, this._formModel, {ProfileO? initialModel}) + : _ownInitialModel = initialModel; static const String idControlName = "id"; @@ -540,8 +544,11 @@ class ProfileOForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + ProfileO? _ownInitialModel; + + late Map _ownInitialRawValue = ProfileOForm.formElements( + _ownInitialModel, + ).rawValue; String idControlPath() => pathBuilder(idControlName); @@ -1442,10 +1449,26 @@ class ProfileOForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + ProfileO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([ProfileO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = ProfileOForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1484,55 +1507,6 @@ class ProfileOForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -1613,8 +1587,12 @@ final _logIncidenceFilterOForm = Logger.detached('IncidenceFilterOForm'); class IncidenceFilterOForm implements FormModel { - IncidenceFilterOForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + IncidenceFilterOForm( + this.form, + this.path, + this._formModel, { + IncidenceFilterO? initialModel, + }) : _ownInitialModel = initialModel; static const String isMobilityEnabledControlName = "isMobilityEnabled"; @@ -1637,8 +1615,10 @@ class IncidenceFilterOForm final Map _disabled = {}; - @override - final Map initial; + IncidenceFilterO? _ownInitialModel; + + late Map _ownInitialRawValue = + IncidenceFilterOForm.formElements(_ownInitialModel).rawValue; String isMobilityEnabledControlPath() => pathBuilder(isMobilityEnabledControlName); @@ -2213,10 +2193,28 @@ class IncidenceFilterOForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + IncidenceFilterO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([IncidenceFilterO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = IncidenceFilterOForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -2255,55 +2253,6 @@ class IncidenceFilterOForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -2370,8 +2319,12 @@ final _logThresholdSettingOForm = Logger.detached('ThresholdSettingOForm'); class ThresholdSettingOForm implements FormModel { - ThresholdSettingOForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + ThresholdSettingOForm( + this.form, + this.path, + this._formModel, { + ThresholdSettingO? initialModel, + }) : _ownInitialModel = initialModel; static const String isEnabledControlName = "isEnabled"; @@ -2386,8 +2339,10 @@ class ThresholdSettingOForm final Map _disabled = {}; - @override - final Map initial; + ThresholdSettingO? _ownInitialModel; + + late Map _ownInitialRawValue = + ThresholdSettingOForm.formElements(_ownInitialModel).rawValue; String isEnabledControlPath() => pathBuilder(isEnabledControlName); @@ -2625,10 +2580,28 @@ class ThresholdSettingOForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + ThresholdSettingO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([ThresholdSettingO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = ThresholdSettingOForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -2667,55 +2640,6 @@ class ThresholdSettingOForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -2750,8 +2674,12 @@ final _logTimerSettingOForm = Logger.detached('TimerSettingOForm'); class TimerSettingOForm implements FormModel { - TimerSettingOForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + TimerSettingOForm( + this.form, + this.path, + this._formModel, { + TimerSettingO? initialModel, + }) : _ownInitialModel = initialModel; static const String isEnabledControlName = "isEnabled"; @@ -2766,8 +2694,10 @@ class TimerSettingOForm final Map _disabled = {}; - @override - final Map initial; + TimerSettingO? _ownInitialModel; + + late Map _ownInitialRawValue = + TimerSettingOForm.formElements(_ownInitialModel).rawValue; String isEnabledControlPath() => pathBuilder(isEnabledControlName); @@ -2999,10 +2929,28 @@ class TimerSettingOForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + TimerSettingO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([TimerSettingO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = TimerSettingOForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -3041,55 +2989,6 @@ class TimerSettingOForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/generator_tests/test/doc/profile_test.dart b/packages/generator_tests/test/doc/profile_test.dart index e8e11417..acdf8f37 100644 --- a/packages/generator_tests/test/doc/profile_test.dart +++ b/packages/generator_tests/test/doc/profile_test.dart @@ -426,6 +426,7 @@ class _ProfileFormBuilderState extends State { ProfileForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -468,7 +469,9 @@ class _ProfileFormBuilderState extends State { @override void didUpdateWidget(covariant ProfileFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -503,7 +506,8 @@ class _ProfileFormBuilderState extends State { final _logProfileForm = Logger.detached('ProfileForm'); class ProfileForm implements FormModel { - ProfileForm(this.form, this.path, this._formModel) : initial = form.rawValue; + ProfileForm(this.form, this.path, this._formModel, {Profile? initialModel}) + : _ownInitialModel = initialModel; static const String idControlName = "id"; @@ -534,8 +538,11 @@ class ProfileForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + Profile? _ownInitialModel; + + late Map _ownInitialRawValue = ProfileForm.formElements( + _ownInitialModel, + ).rawValue; String idControlPath() => pathBuilder(idControlName); @@ -1435,10 +1442,26 @@ class ProfileForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + Profile? get initialModel { + return _ownInitialModel; + } + + void commitInitial([Profile? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = ProfileForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1477,55 +1500,6 @@ class ProfileForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -1606,8 +1580,12 @@ final _logIncidenceFilterForm = Logger.detached('IncidenceFilterForm'); class IncidenceFilterForm implements FormModel { - IncidenceFilterForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + IncidenceFilterForm( + this.form, + this.path, + this._formModel, { + IncidenceFilter? initialModel, + }) : _ownInitialModel = initialModel; static const String isMobilityEnabledControlName = "isMobilityEnabled"; @@ -1630,8 +1608,10 @@ class IncidenceFilterForm final Map _disabled = {}; - @override - final Map initial; + IncidenceFilter? _ownInitialModel; + + late Map _ownInitialRawValue = + IncidenceFilterForm.formElements(_ownInitialModel).rawValue; String isMobilityEnabledControlPath() => pathBuilder(isMobilityEnabledControlName); @@ -2205,10 +2185,28 @@ class IncidenceFilterForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + IncidenceFilter? get initialModel { + return _ownInitialModel; + } + + void commitInitial([IncidenceFilter? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = IncidenceFilterForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -2247,55 +2245,6 @@ class IncidenceFilterForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -2361,8 +2310,12 @@ final _logThresholdSettingForm = Logger.detached('ThresholdSettingForm'); class ThresholdSettingForm implements FormModel { - ThresholdSettingForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + ThresholdSettingForm( + this.form, + this.path, + this._formModel, { + ThresholdSetting? initialModel, + }) : _ownInitialModel = initialModel; static const String isEnabledControlName = "isEnabled"; @@ -2377,8 +2330,10 @@ class ThresholdSettingForm final Map _disabled = {}; - @override - final Map initial; + ThresholdSetting? _ownInitialModel; + + late Map _ownInitialRawValue = + ThresholdSettingForm.formElements(_ownInitialModel).rawValue; String isEnabledControlPath() => pathBuilder(isEnabledControlName); @@ -2612,10 +2567,28 @@ class ThresholdSettingForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + ThresholdSetting? get initialModel { + return _ownInitialModel; + } + + void commitInitial([ThresholdSetting? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = ThresholdSettingForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -2654,55 +2627,6 @@ class ThresholdSettingForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -2736,8 +2660,12 @@ class ThresholdSettingForm final _logTimerSettingForm = Logger.detached('TimerSettingForm'); class TimerSettingForm implements FormModel { - TimerSettingForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + TimerSettingForm( + this.form, + this.path, + this._formModel, { + TimerSetting? initialModel, + }) : _ownInitialModel = initialModel; static const String isEnabledControlName = "isEnabled"; @@ -2752,8 +2680,11 @@ class TimerSettingForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + TimerSetting? _ownInitialModel; + + late Map _ownInitialRawValue = TimerSettingForm.formElements( + _ownInitialModel, + ).rawValue; String isEnabledControlPath() => pathBuilder(isEnabledControlName); @@ -2984,10 +2915,28 @@ class TimerSettingForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + TimerSetting? get initialModel { + return _ownInitialModel; + } + + void commitInitial([TimerSetting? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = TimerSettingForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -3026,55 +2975,6 @@ class TimerSettingForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/generator_tests/test/doc/recursive_test.dart b/packages/generator_tests/test/doc/recursive_test.dart index 8762d4a8..6d54a18e 100644 --- a/packages/generator_tests/test/doc/recursive_test.dart +++ b/packages/generator_tests/test/doc/recursive_test.dart @@ -205,6 +205,7 @@ class _SecuredAreaFormBuilderState extends State { SecuredAreaForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -247,7 +248,9 @@ class _SecuredAreaFormBuilderState extends State { @override void didUpdateWidget(covariant SecuredAreaFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -282,8 +285,12 @@ class _SecuredAreaFormBuilderState extends State { final _logSecuredAreaForm = Logger.detached('SecuredAreaForm'); class SecuredAreaForm implements FormModel { - SecuredAreaForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + SecuredAreaForm( + this.form, + this.path, + this._formModel, { + SecuredArea? initialModel, + }) : _ownInitialModel = initialModel; static const String idControlName = "id"; @@ -302,8 +309,11 @@ class SecuredAreaForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + SecuredArea? _ownInitialModel; + + late Map _ownInitialRawValue = SecuredAreaForm.formElements( + _ownInitialModel, + ).rawValue; String idControlPath() => pathBuilder(idControlName); @@ -894,10 +904,28 @@ class SecuredAreaForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + SecuredArea? get initialModel { + return _ownInitialModel; + } + + void commitInitial([SecuredArea? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = SecuredAreaForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -936,55 +964,6 @@ class SecuredAreaForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -1024,8 +1003,12 @@ class SecuredAreaForm implements FormModel { final _logParcelSystemForm = Logger.detached('ParcelSystemForm'); class ParcelSystemForm implements FormModel { - ParcelSystemForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + ParcelSystemForm( + this.form, + this.path, + this._formModel, { + ParcelSystem? initialModel, + }) : _ownInitialModel = initialModel; static const String hasParcelSystemControlName = "hasParcelSystem"; @@ -1040,8 +1023,11 @@ class ParcelSystemForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + ParcelSystem? _ownInitialModel; + + late Map _ownInitialRawValue = ParcelSystemForm.formElements( + _ownInitialModel, + ).rawValue; String hasParcelSystemControlPath() => pathBuilder(hasParcelSystemControlName); @@ -1282,10 +1268,28 @@ class ParcelSystemForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + ParcelSystem? get initialModel { + return _ownInitialModel; + } + + void commitInitial([ParcelSystem? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = ParcelSystemForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1324,55 +1328,6 @@ class ParcelSystemForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -1399,8 +1354,12 @@ final _logParcelSystemDataForm = Logger.detached('ParcelSystemDataForm'); class ParcelSystemDataForm implements FormModel { - ParcelSystemDataForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + ParcelSystemDataForm( + this.form, + this.path, + this._formModel, { + ParcelSystemData? initialModel, + }) : _ownInitialModel = initialModel; static const String idControlName = "id"; @@ -1413,8 +1372,10 @@ class ParcelSystemDataForm final Map _disabled = {}; - @override - final Map initial; + ParcelSystemData? _ownInitialModel; + + late Map _ownInitialRawValue = + ParcelSystemDataForm.formElements(_ownInitialModel).rawValue; String idControlPath() => pathBuilder(idControlName); @@ -1587,10 +1548,28 @@ class ParcelSystemDataForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + ParcelSystemData? get initialModel { + return _ownInitialModel; + } + + void commitInitial([ParcelSystemData? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = ParcelSystemDataForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1629,55 +1608,6 @@ class ParcelSystemDataForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/generator_tests/test/doc/renamed_basic_output_test.dart b/packages/generator_tests/test/doc/renamed_basic_output_test.dart index c10375cc..31328c71 100644 --- a/packages/generator_tests/test/doc/renamed_basic_output_test.dart +++ b/packages/generator_tests/test/doc/renamed_basic_output_test.dart @@ -197,6 +197,7 @@ class _SomeWiredNameFormBuilderState extends State { SomeWiredNameForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -239,7 +240,9 @@ class _SomeWiredNameFormBuilderState extends State { @override void didUpdateWidget(covariant SomeWiredNameFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -275,8 +278,12 @@ final _logSomeWiredNameForm = Logger.detached('SomeWiredNameForm'); class SomeWiredNameForm implements FormModel { - SomeWiredNameForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + SomeWiredNameForm( + this.form, + this.path, + this._formModel, { + RenamedBasicO? initialModel, + }) : _ownInitialModel = initialModel; static const String emailControlName = "email"; @@ -291,8 +298,10 @@ class SomeWiredNameForm final Map _disabled = {}; - @override - final Map initial; + RenamedBasicO? _ownInitialModel; + + late Map _ownInitialRawValue = + SomeWiredNameForm.formElements(_ownInitialModel).rawValue; String emailControlPath() => pathBuilder(emailControlName); @@ -571,10 +580,28 @@ class SomeWiredNameForm bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + RenamedBasicO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([RenamedBasicO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = SomeWiredNameForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -613,55 +640,6 @@ class SomeWiredNameForm emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/generator_tests/test/doc/renamed_basic_test.dart b/packages/generator_tests/test/doc/renamed_basic_test.dart index da7d63f4..b04d33b1 100644 --- a/packages/generator_tests/test/doc/renamed_basic_test.dart +++ b/packages/generator_tests/test/doc/renamed_basic_test.dart @@ -197,6 +197,7 @@ class _SomeWiredNameFormBuilderState extends State { SomeWiredNameForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -239,7 +240,9 @@ class _SomeWiredNameFormBuilderState extends State { @override void didUpdateWidget(covariant SomeWiredNameFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -274,8 +277,12 @@ class _SomeWiredNameFormBuilderState extends State { final _logSomeWiredNameForm = Logger.detached('SomeWiredNameForm'); class SomeWiredNameForm implements FormModel { - SomeWiredNameForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + SomeWiredNameForm( + this.form, + this.path, + this._formModel, { + RenamedBasic? initialModel, + }) : _ownInitialModel = initialModel; static const String emailControlName = "email"; @@ -290,8 +297,10 @@ class SomeWiredNameForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + RenamedBasic? _ownInitialModel; + + late Map _ownInitialRawValue = + SomeWiredNameForm.formElements(_ownInitialModel).rawValue; String emailControlPath() => pathBuilder(emailControlName); @@ -522,10 +531,28 @@ class SomeWiredNameForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + RenamedBasic? get initialModel { + return _ownInitialModel; + } + + void commitInitial([RenamedBasic? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = SomeWiredNameForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -564,55 +591,6 @@ class SomeWiredNameForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/generator_tests/test/doc/user_profile_output_test.dart b/packages/generator_tests/test/doc/user_profile_output_test.dart index abc82a6d..937020f8 100644 --- a/packages/generator_tests/test/doc/user_profile_output_test.dart +++ b/packages/generator_tests/test/doc/user_profile_output_test.dart @@ -223,6 +223,7 @@ class _UserProfileOFormBuilderState extends State { UserProfileOForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -265,7 +266,9 @@ class _UserProfileOFormBuilderState extends State { @override void didUpdateWidget(covariant UserProfileOFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -300,8 +303,12 @@ class _UserProfileOFormBuilderState extends State { final _logUserProfileOForm = Logger.detached('UserProfileOForm'); class UserProfileOForm implements FormModel { - UserProfileOForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + UserProfileOForm( + this.form, + this.path, + this._formModel, { + UserProfileO? initialModel, + }) : _ownInitialModel = initialModel; static const String idControlName = "id"; @@ -322,8 +329,11 @@ class UserProfileOForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + UserProfileO? _ownInitialModel; + + late Map _ownInitialRawValue = UserProfileOForm.formElements( + _ownInitialModel, + ).rawValue; String idControlPath() => pathBuilder(idControlName); @@ -873,10 +883,28 @@ class UserProfileOForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + UserProfileO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([UserProfileO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = UserProfileOForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -915,55 +943,6 @@ class UserProfileOForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -1006,7 +985,8 @@ class UserProfileOForm implements FormModel { final _logAddressOForm = Logger.detached('AddressOForm'); class AddressOForm implements FormModel { - AddressOForm(this.form, this.path, this._formModel) : initial = form.rawValue; + AddressOForm(this.form, this.path, this._formModel, {AddressO? initialModel}) + : _ownInitialModel = initialModel; static const String streetControlName = "street"; @@ -1023,8 +1003,11 @@ class AddressOForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + AddressO? _ownInitialModel; + + late Map _ownInitialRawValue = AddressOForm.formElements( + _ownInitialModel, + ).rawValue; String streetControlPath() => pathBuilder(streetControlName); @@ -1411,10 +1394,26 @@ class AddressOForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + AddressO? get initialModel { + return _ownInitialModel; + } + + void commitInitial([AddressO? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = AddressOForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1453,55 +1452,6 @@ class AddressOForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/generator_tests/test/doc/user_profile_test.dart b/packages/generator_tests/test/doc/user_profile_test.dart index add9ce22..e13e6a28 100644 --- a/packages/generator_tests/test/doc/user_profile_test.dart +++ b/packages/generator_tests/test/doc/user_profile_test.dart @@ -221,6 +221,7 @@ class _UserProfileFormBuilderState extends State { UserProfileForm.formElements(widget.model), null, null, + initialModel: widget.model, ); if (_formModel.form.disabled) { @@ -263,7 +264,9 @@ class _UserProfileFormBuilderState extends State { @override void didUpdateWidget(covariant UserProfileFormBuilder oldWidget) { if (widget.model != oldWidget.model) { - _formModel.updateValue(widget.model); + _formModel + ..updateValue(widget.model) + ..commitInitial(widget.model); } super.didUpdateWidget(oldWidget); @@ -298,8 +301,12 @@ class _UserProfileFormBuilderState extends State { final _logUserProfileForm = Logger.detached('UserProfileForm'); class UserProfileForm implements FormModel { - UserProfileForm(this.form, this.path, this._formModel) - : initial = form.rawValue; + UserProfileForm( + this.form, + this.path, + this._formModel, { + UserProfile? initialModel, + }) : _ownInitialModel = initialModel; static const String idControlName = "id"; @@ -320,8 +327,11 @@ class UserProfileForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + UserProfile? _ownInitialModel; + + late Map _ownInitialRawValue = UserProfileForm.formElements( + _ownInitialModel, + ).rawValue; String idControlPath() => pathBuilder(idControlName); @@ -822,10 +832,28 @@ class UserProfileForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + UserProfile? get initialModel { + return _ownInitialModel; + } + + void commitInitial([UserProfile? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = UserProfileForm.formElements( + _ownInitialModel, + ).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -864,55 +892,6 @@ class UserProfileForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); @@ -955,7 +934,8 @@ class UserProfileForm implements FormModel { final _logAddressForm = Logger.detached('AddressForm'); class AddressForm implements FormModel { - AddressForm(this.form, this.path, this._formModel) : initial = form.rawValue; + AddressForm(this.form, this.path, this._formModel, {Address? initialModel}) + : _ownInitialModel = initialModel; static const String streetControlName = "street"; @@ -972,8 +952,11 @@ class AddressForm implements FormModel { final Map _disabled = {}; - @override - final Map initial; + Address? _ownInitialModel; + + late Map _ownInitialRawValue = AddressForm.formElements( + _ownInitialModel, + ).rawValue; String streetControlPath() => pathBuilder(streetControlName); @@ -1355,10 +1338,26 @@ class AddressForm implements FormModel { bool get hasChanged { return !const DeepCollectionEquality().equals( currentForm.rawValue, - initial, + FormModel.sliceByPath(initialRawValue, path), ); } + @override + Map get initialRawValue { + return _formModel != null + ? _formModel!.initialRawValue + : _ownInitialRawValue; + } + + Address? get initialModel { + return _ownInitialModel; + } + + void commitInitial([Address? newModel]) { + _ownInitialModel = newModel ?? rawModel; + _ownInitialRawValue = AddressForm.formElements(_ownInitialModel).rawValue; + } + @override FormGroup get currentForm { return path == null ? form : form.control(path!) as FormGroup; @@ -1397,55 +1396,6 @@ class AddressForm implements FormModel { emitEvent: emitEvent, ); - @override - void updateInitial(Map? value, String? path) { - if (_formModel != null) { - _formModel?.updateInitial(currentForm.rawValue, path); - return; - } - - if (value == null) return; - - if (path == null || path.isEmpty) { - initial.addAll(value); - return; - } - - final keys = path.split('.'); - Object? current = initial; - for (var i = 0; i < keys.length - 1; i++) { - final key = keys[i]; - - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current = current[index]; - continue; - } - } - - if (current is Map) { - if (!current.containsKey(key)) { - current[key] = {}; - } - current = current[key]; - continue; - } - - return; - } - - final key = keys.last; - if (current is List) { - final index = int.tryParse(key); - if (index != null && index >= 0 && index < current.length) { - current[index] = value; - } - } else if (current is Map) { - current[key] = value; - } - } - String pathBuilder(String? pathItem) => [path, pathItem].whereType().join("."); diff --git a/packages/reactive_forms_annotations/CHANGELOG.md b/packages/reactive_forms_annotations/CHANGELOG.md index 8b4bf0ce..15f84b73 100644 --- a/packages/reactive_forms_annotations/CHANGELOG.md +++ b/packages/reactive_forms_annotations/CHANGELOG.md @@ -1,3 +1,7 @@ +## [8.5.0-beta9] + +* analyzer 9 compatibility + ## [8.3.0] * hasChanges fix diff --git a/packages/reactive_forms_annotations/pubspec.yaml b/packages/reactive_forms_annotations/pubspec.yaml index 2659e7df..071ff321 100644 --- a/packages/reactive_forms_annotations/pubspec.yaml +++ b/packages/reactive_forms_annotations/pubspec.yaml @@ -2,7 +2,7 @@ name: reactive_forms_annotations description: Annotations for reactive_forms_generator repository: https://github.com/artflutter/reactive_forms_generator -version: 8.4.0 +version: 8.5.0-beta9 environment: sdk: ">=3.8.0 <4.0.0" @@ -16,4 +16,4 @@ dependencies: sdk: flutter dev_dependencies: - flutter_lints: ^6.0.0 \ No newline at end of file + flutter_lints: ^6.0.0 diff --git a/packages/reactive_forms_generator/CHANGELOG.md b/packages/reactive_forms_generator/CHANGELOG.md index 1fdc9fa0..31c8d51e 100644 --- a/packages/reactive_forms_generator/CHANGELOG.md +++ b/packages/reactive_forms_generator/CHANGELOG.md @@ -1,3 +1,8 @@ +## [8.5.0-beta9] + +* analyzer 9 compatibility +* refactor annotation argument parsing + ## [8.4.0] * fix hasChanges diff --git a/packages/reactive_forms_generator/lib/src/extensions.dart b/packages/reactive_forms_generator/lib/src/extensions.dart index 2485191d..e6ab0dde 100644 --- a/packages/reactive_forms_generator/lib/src/extensions.dart +++ b/packages/reactive_forms_generator/lib/src/extensions.dart @@ -1,14 +1,10 @@ import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/nullability_suffix.dart'; import 'package:analyzer/dart/element/type.dart'; -import 'package:code_builder/code_builder.dart'; -import 'package:reactive_forms_generator/src/output/x.dart'; +import 'package:code_builder/code_builder.dart' hide FunctionType, RecordType; import 'package:reactive_forms_generator/src/types.dart'; import 'package:recase/recase.dart'; -// ignore: implementation_imports -import 'package:analyzer/src/dart/element/type.dart'; - import '../utils.dart'; extension ConstructorElementExt on ConstructorElement { @@ -19,6 +15,8 @@ extension ConstructorElementExt on ConstructorElement { extension ClassElementExt on ClassElement { String get fullTypeName => thisType.toString(); + String get toReferenceType => reactiveOutputTypeName(thisType); + String get generics { final generics = genericTypes.map((e) => e.symbol).join(', '); @@ -176,10 +174,11 @@ extension ParameterElementExt on FormalParameterElement { final typeParameter = typeArguments.first; - return (typeParameter.element is ClassElement || - typeParameter.element is EnumElement || - typeParameter.element is TypeDefiningElement) && - !typeParameter.element!.hasRfGroupAnnotation; + final element = typeParameter.element; + + return element != null && + (element is InterfaceElement || element is TypeAliasElement) && + !element.hasRfGroupAnnotation; } bool get isFormControl { @@ -225,9 +224,7 @@ extension ParameterElementExt on FormalParameterElement { return type.getName(withNullability: false); } - var builder = ElementDisplayStringBuilder2(withNullability: true); - (type as TypeImpl).appendTo(builder); - return builder.toString(); + return reactiveOutputTypeName(type); } bool isOutputNullable(List requiredValidators) { @@ -308,3 +305,209 @@ extension DartTypeExt on DartType { }; } } + +String reactiveOutputTypeName(DartType type, {bool withNullability = true}) { + return _ReactiveOutputTypeNameWriter( + withNullability: withNullability, + ).write(type); +} + +class _ReactiveOutputTypeNameWriter { + _ReactiveOutputTypeNameWriter({required this.withNullability}); + + final bool withNullability; + + String write(DartType type) { + return switch (type) { + InterfaceType() => _writeInterfaceType(type), + RecordType() => _writeRecordType(type), + FunctionType() => _writeFunctionType(type), + TypeParameterType() => _writeTypeParameterType(type), + DynamicType() => 'dynamic', + VoidType() => 'void', + NeverType() => 'Never${_writeNullability(type)}', + InvalidType() => 'InvalidType', + _ => _writeFallbackType(type), + }; + } + + String _writeInterfaceType(InterfaceType type) { + final element = type.element; + final postfix = + ElementRfExt(element).hasRfGroupAnnotation || + ElementRfExt(element).hasRfAnnotation + ? 'Output' + : ''; + + return '${element.name ?? ''}$postfix' + '${_writeTypeArguments(type.typeArguments)}' + '${_writeNullability(type)}'; + } + + String _writeFunctionType(FunctionType type) { + return '${write(type.returnType)} Function' + '${_writeTypeParameters(type.typeParameters)}' + '${_writeFormalParameters(type.formalParameters)}' + '${_writeNullability(type)}'; + } + + String _writeRecordType(RecordType type) { + final positionalFields = type.positionalFields; + final namedFields = type.namedFields; + final fieldCount = positionalFields.length + namedFields.length; + final buffer = StringBuffer('('); + + var index = 0; + for (final field in positionalFields) { + buffer.write(write(field.type)); + if (index++ < fieldCount - 1) { + buffer.write(', '); + } + } + + if (namedFields.isNotEmpty) { + buffer.write('{'); + for (final field in namedFields) { + buffer + ..write(write(field.type)) + ..write(' ') + ..write(field.name); + if (index++ < fieldCount - 1) { + buffer.write(', '); + } + } + buffer.write('}'); + } + + if (positionalFields.length == 1 && namedFields.isEmpty) { + buffer.write(','); + } + + buffer + ..write(')') + ..write(_writeNullability(type)); + + return buffer.toString(); + } + + String _writeTypeParameterType(TypeParameterType type) { + return '${type.element.displayName}${_writeNullability(type)}'; + } + + String _writeFormalParameters(List parameters) { + final buffer = StringBuffer('('); + var lastKind = _FormalParameterKind.none; + var lastClose = ''; + + void openGroup(_FormalParameterKind kind, String open, String close) { + if (lastKind == kind) { + return; + } + + buffer.write(lastClose); + buffer.write(open); + lastKind = kind; + lastClose = close; + } + + for (var i = 0; i < parameters.length; i++) { + if (i != 0) { + buffer.write(', '); + } + + final parameter = parameters[i]; + if (parameter.isRequiredPositional) { + openGroup(_FormalParameterKind.requiredPositional, '', ''); + } else if (parameter.isOptionalPositional) { + openGroup(_FormalParameterKind.optionalPositional, '[', ']'); + } else if (parameter.isNamed) { + openGroup(_FormalParameterKind.named, '{', '}'); + } + + buffer.write(_writeFormalParameter(parameter)); + } + + buffer + ..write(lastClose) + ..write(')'); + + return buffer.toString(); + } + + String _writeFormalParameter(FormalParameterElement parameter) { + final buffer = StringBuffer(); + if (parameter.isRequiredNamed) { + buffer.write('required '); + } + + buffer.write(write(parameter.type)); + if (parameter.isNamed) { + final name = parameter.name; + if (name != null) { + buffer.write(' $name'); + } + } + + return buffer.toString(); + } + + String _writeTypeArguments(List typeArguments) { + if (typeArguments.isEmpty) { + return ''; + } + + return '<${typeArguments.map(write).join(', ')}>'; + } + + String _writeTypeParameters(List elements) { + if (elements.isEmpty) { + return ''; + } + + return '<${elements.map(_writeTypeParameter).join(', ')}>'; + } + + String _writeTypeParameter(TypeParameterElement element) { + final buffer = StringBuffer(element.name ?? element.displayName); + final bound = element.bound; + if (bound != null) { + buffer + ..write(' extends ') + ..write(write(bound)); + } + + return buffer.toString(); + } + + String _writeNullability(DartType type) { + if (!withNullability) { + return ''; + } + + return switch (type.nullabilitySuffix) { + NullabilitySuffix.question => '?', + NullabilitySuffix.star => '*', + NullabilitySuffix.none => '', + }; + } + + String _writeFallbackType(DartType type) { + final name = type.getDisplayString(); + if (withNullability) { + return name; + } + + return switch (type.nullabilitySuffix) { + NullabilitySuffix.question || + NullabilitySuffix.star => name.substring(0, name.length - 1), + NullabilitySuffix.none => name, + }; + } +} + +enum _FormalParameterKind { + none, + requiredPositional, + optionalPositional, + named, +} diff --git a/packages/reactive_forms_generator/lib/src/form_elements/form_array_generator.dart b/packages/reactive_forms_generator/lib/src/form_elements/form_array_generator.dart index 205f5462..28b68062 100644 --- a/packages/reactive_forms_generator/lib/src/form_elements/form_array_generator.dart +++ b/packages/reactive_forms_generator/lib/src/form_elements/form_array_generator.dart @@ -6,7 +6,7 @@ import 'package:reactive_forms_generator/src/form_elements/form_element_generato import 'package:reactive_forms_generator/src/types.dart'; import 'package:reactive_forms_generator/src/extensions.dart'; import 'package:recase/recase.dart'; -import 'package:source_gen/src/type_checker.dart'; +import 'package:source_gen/source_gen.dart'; import 'package:analyzer/src/dart/element/element.dart' as e; diff --git a/packages/reactive_forms_generator/lib/src/form_generator.dart b/packages/reactive_forms_generator/lib/src/form_generator.dart index 16068404..9cb40bb0 100644 --- a/packages/reactive_forms_generator/lib/src/form_generator.dart +++ b/packages/reactive_forms_generator/lib/src/form_generator.dart @@ -722,7 +722,7 @@ class FormGenerator { // ); // final astDeclaration = classNode as u.ClassDeclarationImpl; - final renamedClass = ClassRenameVisitor(); + const renamedClass = ClassRenameVisitor(); ast.accept(renamedClass); final x = ast.declarations; diff --git a/packages/reactive_forms_generator/lib/src/output/rf_annotation_arguments.dart b/packages/reactive_forms_generator/lib/src/output/rf_annotation_arguments.dart new file mode 100644 index 00000000..530d393d --- /dev/null +++ b/packages/reactive_forms_generator/lib/src/output/rf_annotation_arguments.dart @@ -0,0 +1,130 @@ +import 'package:analyzer/dart/ast/ast.dart'; +import 'package:collection/collection.dart'; + +const _rfAnnotationNames = { + 'RfControl', + 'FormControlAnnotation', + 'RfArray', + 'FormArrayAnnotation', + 'RfGroup', + 'FormGroupAnnotation', +}; + +extension AnnotationNamedArguments on Annotation { + Iterable get namedArguments => + arguments?.arguments.whereType() ?? + const []; + + Expression? namedArgument(String name) { + return namedArguments + .firstWhereOrNull((argument) => argument.name.label.name == name) + ?.expression; + } + + Map get namedArgumentExpressions { + return Map.unmodifiable({ + for (final argument in namedArguments) + argument.name.label.name: argument.expression, + }); + } + + Map get namedArgumentSources { + return Map.unmodifiable({ + for (final argument in namedArguments) + argument.name.label.name: argument.expression.toSource(), + }); + } +} + +extension FormalParameterRfAnnotation on FormalParameter { + Annotation? get rfAnnotation { + return metadata.firstWhereOrNull((annotation) { + return _rfAnnotationNames.contains(annotation.rfAnnotationName); + }); + } +} + +extension ValidatorExpressionMatcher on Expression? { + bool containsAnyValidator(Iterable validators) { + final expression = this; + if (expression == null) { + return false; + } + + final matcher = _ValidatorMatcher(validators); + return matcher.matches(expression); + } +} + +extension on Annotation { + String get rfAnnotationName => name.toSource().split('.').last; +} + +class _ValidatorMatcher { + _ValidatorMatcher(Iterable validators) + : _rawValidators = validators.map((validator) => validator.trim()).toSet(), + _validatorNames = validators + .map(_validatorName) + .whereType() + .toSet(); + + final Set _rawValidators; + final Set _validatorNames; + + bool matches(Expression expression) { + if (_rawValidators.isEmpty && _validatorNames.isEmpty) { + return false; + } + + if (expression is ListLiteral) { + return expression.elements.whereType().any( + _matchesValidatorExpression, + ); + } + + return _matchesValidatorExpression(expression); + } + + bool _matchesValidatorExpression(Expression expression) { + final expressionName = _expressionValidatorName(expression); + if (expressionName != null && _validatorNames.contains(expressionName)) { + return true; + } + + return _rawValidators.contains(expression.toSource().trim()); + } + + static String? _expressionValidatorName(Expression expression) { + return switch (expression) { + InstanceCreationExpression() => + expression.constructorName.type.name.lexeme, + MethodInvocation() => expression.methodName.name, + FunctionExpressionInvocation() => _expressionValidatorName( + expression.function, + ), + PrefixedIdentifier() => expression.identifier.name, + PropertyAccess() => expression.propertyName.name, + SimpleIdentifier() => expression.name, + _ => null, + }; + } + + static String? _validatorName(String validator) { + var source = validator.trim(); + if (source.isEmpty) { + return null; + } + + source = source.replaceFirst(RegExp(r'^(const|new)\s+'), ''); + + final parenIndex = source.indexOf('('); + if (parenIndex >= 0) { + source = source.substring(0, parenIndex); + } + + source = source.split('.').last.trim(); + source = source.replaceFirst(RegExp(r'<.*>$'), ''); + + return source.isEmpty ? null : source; + } +} diff --git a/packages/reactive_forms_generator/lib/src/output/rf_annotation_arguments_visitor.dart b/packages/reactive_forms_generator/lib/src/output/rf_annotation_arguments_visitor.dart index de4c9317..a36037bd 100644 --- a/packages/reactive_forms_generator/lib/src/output/rf_annotation_arguments_visitor.dart +++ b/packages/reactive_forms_generator/lib/src/output/rf_annotation_arguments_visitor.dart @@ -1,391 +1,253 @@ // ignore_for_file: implementation_imports -// import 'package:analyzer/dart/element/nullability_suffix.dart'; -// import 'package:analyzer/dart/element/type.dart'; -import 'package:analyzer/src/dart/ast/ast.dart'; -import 'package:analyzer/dart/ast/visitor.dart'; import 'package:analyzer/dart/ast/token.dart'; +import 'package:analyzer/dart/ast/visitor.dart'; +import 'package:analyzer/src/dart/ast/ast.dart'; import 'package:analyzer/src/dart/ast/token.dart'; import 'package:analyzer/src/dart/ast/utilities.dart'; import 'package:reactive_forms_generator/src/output/extensions.dart'; -// import 'package:reactive_forms_generator/src/types.dart'; -// import 'package:analyzer/src/dart/element/element.dart'; +extension RfAnnotationArguments on Annotation { + Expression? namedArgument(String name) { + final argumentList = arguments; + if (argumentList == null) { + return null; + } -class RfAnnotationArgumentsVisitor extends RecursiveAstVisitor { - final arguments = {}; + for (final argument in argumentList.arguments) { + if (argument is NamedExpression && argument.name.label.name == name) { + return argument.expression; + } + } - @override - visitArgumentList(ArgumentList node) { - for (var argument in node.arguments) { + return null; + } + + Map get namedArgumentSources { + final argumentList = arguments; + if (argumentList == null) { + return const {}; + } + + final result = {}; + for (final argument in argumentList.arguments) { if (argument is NamedExpression) { - arguments.addEntries([ - MapEntry( - argument.name.label.name, - argument.expression.toSource().toString(), - ), - ]); - } else { - // For positional arguments + result[argument.name.label.name] = argument.expression.toSource(); + } + } + + return result; + } +} + +extension RfParameterAnnotation on FormalParameter { + Annotation? get rfAnnotation { + for (final annotation in metadata) { + final name = annotation.name.toSource().split('.').last; + if (name.startsWith('Rf')) { + return annotation; } } - return super.visitArgumentList(node); + + return null; } } -class ClassRenameVisitor extends GeneralizingAstVisitor { - // List updatedClass = []; +extension RfValidatorArgument on Expression? { + bool containsAnyValidator(Iterable validators) { + final expression = this; + if (expression == null) { + return false; + } + + if (expression is ListLiteral) { + return expression.elements.any((element) { + final source = element.toSource(); + return validators.any(source.contains); + }); + } + + final source = expression.toSource(); + return validators.any(source.contains); + } +} - ClassRenameVisitor(); +class ClassRenameVisitor extends RecursiveAstVisitor { + const ClassRenameVisitor(); @override void visitClassDeclaration(ClassDeclaration node) { if (node is ClassDeclarationImpl) { - final newNode = ClassDeclarationImpl( - comment: null, - metadata: node.metadata - // .where( - // (e) => !e.name.toString().startsWith('Rf'), - // ) - .toList(), - augmentKeyword: node.augmentKeyword, - abstractKeyword: node.abstractKeyword, - macroKeyword: node.macroKeyword, - sealedKeyword: node.sealedKeyword, - baseKeyword: node.baseKeyword, - interfaceKeyword: node.interfaceKeyword, - finalKeyword: node.finalKeyword, - mixinKeyword: node.mixinKeyword, - classKeyword: node.classKeyword, - name: StringToken(TokenType.STRING, '${node.name.lexeme}Output', 0), - typeParameters: node.typeParameters, - extendsClause: node.extendsClause, - withClause: node.withClause != null - ? WithClauseImpl( - withKeyword: node.withClause!.withKeyword, - mixinTypes: node.withClause!.mixinTypes.map((e) { - return NamedTypeImpl( - importPrefix: e.importPrefix, - name: StringToken( - TokenType.STRING, - '${e.name.lexeme}Output', - 0, - ), - typeArguments: e.typeArguments, - question: e.question, - ); - }).toList(), - ) - : null, - implementsClause: node.implementsClause, - nativeClause: node.nativeClause, - leftBracket: node.leftBracket, - members: node.members.map((e) { - return switch (e) { - final ConstructorDeclarationImpl _ => ConstructorDeclarationImpl( - comment: null, - metadata: e.metadata, - augmentKeyword: e.augmentKeyword, - externalKeyword: e.externalKeyword, - constKeyword: e.constKeyword, - factoryKeyword: e.factoryKeyword, - returnType: SimpleIdentifierImpl( - token: StringToken( - TokenType.STRING, - '${e.returnType.name}Output', - 0, - ), - ), - period: e.period, - name: e.name, - parameters: e.parameters, - separator: e.separator, - initializers: e.initializers, - redirectedConstructor: e.redirectedConstructor != null - ? ConstructorNameImpl( - type: NamedTypeImpl( - importPrefix: - e.redirectedConstructor!.type.importPrefix, - name: StringToken( - TokenType.STRING, - '${e.redirectedConstructor!.type.name}Output', - 0, - ), - typeArguments: - e.redirectedConstructor!.type.typeArguments, - question: e.redirectedConstructor!.type.question, - ), - period: e.redirectedConstructor!.period, - name: e.redirectedConstructor!.name, - ) - : null, - body: switch (e.body) { - final BlockFunctionBody _ => e.body, - final EmptyFunctionBodyImpl _ => e.body, - final ExpressionFunctionBodyImpl _ => - ExpressionFunctionBodyImpl( - keyword: (e.body as ExpressionFunctionBodyImpl).keyword, - star: (e.body as ExpressionFunctionBodyImpl).star, - functionDefinition: (e.body as ExpressionFunctionBodyImpl) - .functionDefinition, - expression: switch ((e.body as ExpressionFunctionBodyImpl) - .expression) { - MethodInvocationImpl() => MethodInvocationImpl( - target: - ((e.body as ExpressionFunctionBodyImpl).expression - as MethodInvocationImpl) - .target, - operator: - ((e.body as ExpressionFunctionBodyImpl).expression - as MethodInvocationImpl) - .operator, - methodName: SimpleIdentifierImpl( - token: StringToken( - TokenType.STRING, - ((e.body as ExpressionFunctionBodyImpl).expression - as MethodInvocationImpl) - .methodName - .name - .replaceFirst( - e.returnType.name, - '${e.returnType.name}Output', - ), - 0, - ), - ), - typeArguments: - ((e.body as ExpressionFunctionBodyImpl).expression - as MethodInvocationImpl) - .typeArguments, - argumentList: - ((e.body as ExpressionFunctionBodyImpl).expression - as MethodInvocationImpl) - .argumentList, - ), - _ => (e.body as ExpressionFunctionBodyImpl).expression, - }, - semicolon: (e.body as ExpressionFunctionBodyImpl).semicolon, - ), - final NativeFunctionBodyImpl _ => e.body, - }, - ), - final FieldDeclarationImpl _ => FieldDeclarationImpl( - comment: null, - metadata: e.metadata, - abstractKeyword: e.abstractKeyword, - augmentKeyword: e.augmentKeyword, - covariantKeyword: e.covariantKeyword, - externalKeyword: e.externalKeyword, - staticKeyword: e.staticKeyword, - fields: VariableDeclarationListImpl( - comment: null, - metadata: e.fields.metadata, - lateKeyword: e.fields.lateKeyword, - keyword: e.fields.keyword, - type: e.fields.type?.newTypeO, - variables: e.fields.variables.map((e) { - return e; - }).toList(), - ), - //e.fields - semicolon: e.semicolon, - ), - final MethodDeclarationImpl _ => MethodDeclarationImpl( - comment: null, - metadata: e.metadata, - augmentKeyword: e.augmentKeyword, - externalKeyword: e.externalKeyword, - modifierKeyword: e.modifierKeyword, - returnType: e.returnType, - propertyKeyword: e.propertyKeyword, - operatorKeyword: e.operatorKeyword, - name: e.name, - typeParameters: e.typeParameters, - parameters: e.parameters, - body: e.body, - ), - }; - }).toList(), - rightBracket: node.rightBracket, - ); - - NodeReplacer.replace(node, newNode); + NodeReplacer.replace(node, node.outputClass); } - super.visitClassDeclaration(node); } +} - // @override - // void visitSimpleFormalParameter(SimpleFormalParameter node) { - // print(node); - // - // if (node is SimpleFormalParameterImpl) { - // if (node.metadata.hasRfGroupAnnotation) {} - // if (node.metadata.hasRfArrayAnnotation) { - // final type = node.type; - // final x = switch(type) { - // null => type, - // GenericFunctionTypeImpl() => type, - // NamedTypeImpl() => type.typeArguments NamedTypeImpl(), - // RecordTypeAnnotationImpl() => type, - // }; - // } - // } - // node.visitChildren(this); - // } +extension on ClassDeclarationImpl { + ClassDeclarationImpl get outputClass { + return ClassDeclarationImpl( + comment: null, + metadata: metadata.toList(), + augmentKeyword: augmentKeyword, + abstractKeyword: abstractKeyword, + sealedKeyword: sealedKeyword, + baseKeyword: baseKeyword, + interfaceKeyword: interfaceKeyword, + finalKeyword: finalKeyword, + mixinKeyword: mixinKeyword, + classKeyword: classKeyword, + name: _outputToken(name.lexeme), + namePart: ClassNamePartImplStub(), + typeParameters: typeParameters, + extendsClause: extendsClause, + withClause: withClause?.outputWithClause, + implementsClause: implementsClause, + nativeClause: nativeClause, + body: ClassBodyImplStub(), + leftBracket: leftBracket, + members: members.map((member) => member.outputMember).toList(), + rightBracket: rightBracket, + ); + } +} - // @override - // void visitFormalParameter(FormalParameter node) { - // final x = node; - // - // // final ppp = x.metadata.required; - // // - // // // x.metadata.map((e) { - // // // e.arguments. - // // // return e.name.toString().startsWith('Rf'); - // // // } ); - // // - // switch (node) { - // case DefaultFormalParameterImpl(): - // final p = node; - // final hasDefaultValue = - // node.parameter.declaredElement?.hasDefaultValue == true; - // final hasDefaultAnnotation = node.parameter.metadata.fold( - // false, (acc, e) => acc || e.name.toString().startsWith('Default')); - // - // final hasRfGroupAnnotation = node.parameter.declaredElement?.type - // .element?.hasRfGroupAnnotation == - // true; - // - // final type = node.parameter.declaredElement?.type; - // final isList = type != null && - // type.isDartCoreList == true && - // type is ParameterizedType && - // type.typeArguments.firstOrNull?.element?.hasRfGroupAnnotation == - // true; - // - // // final hasRfGroupAnnotation = node.parameter.declaredElement?.type - // // .element?.hasRfGroupAnnotation == - // // true; - // final isNullable = - // node.parameter.declaredElement?.type.nullabilitySuffix == - // NullabilitySuffix.question; - // - // if (!isNullable && - // (hasRfGroupAnnotation || isList) && - // (hasDefaultValue || hasDefaultAnnotation)) { - // NodeReplacer.replace(node, node.newParameter2); - // } - // // if (node.metadata.required) { - // // NodeReplacer.replace(node, node.newParameter); - // // - // // final enclosingElement = - // // node.declaredElement?.enclosingElement?.enclosingElement; - // // - // // // if (enclosingElement is ClassElementImpl) { - // // // final t = RfParameterVisitor2(name: node.name.toString()); - // // // enclosingElement.accept(t); - // // // - // // // final f = t.field; - // // // - // // // if (f != null) { - // // // - // // // NodeReplacer.replace(f, field.newField); - // // // } - // // // - // // // print(f); - // // // } - // // // - // // // // if (t.field != nu) final fields = enclosingElement.fields; - // // // // - // // // // for (var field in fields) { - // // // // if (field.name == node.name.toString()) { - // // // // NodeReplacer.replace(field, field.newField); - // // // // } - // // // // } - // // // } - // // } - // break; - // // TODO: Handle this case. - // case FieldFormalParameter(): - // // TODO: Handle this case. - // case FunctionTypedFormalParameter(): - // // TODO: Handle this case. - // case SimpleFormalParameter(): - // // TODO: Handle this case. - // case SuperFormalParameter(): - // // TODO: Handle this case. - // case FieldFormalParameterImpl(): - // // TODO: Handle this case. - // case FunctionTypedFormalParameterImpl(): - // // TODO: Handle this case. - // case SimpleFormalParameterImpl(): - // // TODO: Handle this case. - // case SuperFormalParameterImpl(): - // // TODO: Handle this case. - // case FieldFormalParameterImpl(): - // // TODO: Handle this case. - // case FunctionTypedFormalParameterImpl(): - // // TODO: Handle this case. - // case SimpleFormalParameterImpl(): - // // TODO: Handle this case. - // case SuperFormalParameterImpl(): - // // TODO: Handle this case. - // case DefaultFormalParameter(): - // break; - // } - // - // super.visitNode(node); - // } +extension on WithClauseImpl { + WithClauseImpl get outputWithClause { + return WithClauseImpl( + withKeyword: withKeyword, + mixinTypes: mixinTypes.map((type) => type.outputNamedType).toList(), + ); + } +} - // @override - // visitFormalParameterList(FormalParameterList node) { - // for (var e in node.parameters) { - // final rfAnnotationVisitor = RfAnnotationVisitor(); - // final rfAnnotationArguments = RfAnnotationArgumentsVisitor(); - // e.visitChildren(rfAnnotationVisitor); - // - // if (rfAnnotationVisitor.rfAnnotation != null) { - // e.visitChildren(rfAnnotationArguments); - // } - // - // if (rfAnnotationArguments.arguments.containsKey('validators') && - // rfAnnotationArguments.arguments['validators'] - // ?.contains('RequiredValidator()') == - // true) { - // fieldFormalParameter[e.name.toString()] = e; - // } - // } - // - // node.visitChildren(this); - // return null; - // } +extension on ClassMemberImpl { + ClassMemberImpl get outputMember { + return switch (this) { + final ConstructorDeclarationImpl member => member.outputConstructor, + final FieldDeclarationImpl member => member.outputField, + final MethodDeclarationImpl member => member, + }; + } +} - @override - void visitConstructorDeclaration(ConstructorDeclaration node) { - if (node is ConstructorDeclarationImpl && node.name == null) { - final updatedNode = ConstructorDeclarationImpl( - comment: null, - metadata: node.metadata, - augmentKeyword: node.augmentKeyword, - externalKeyword: node.externalKeyword, - constKeyword: node.constKeyword, - factoryKeyword: node.factoryKeyword, - returnType: SimpleIdentifierImpl( - token: StringToken( - TokenType.STRING, - '${node.returnType.name}Output', - 0, +extension on ConstructorDeclarationImpl { + ConstructorDeclarationImpl get outputConstructor { + return ConstructorDeclarationImpl( + comment: null, + metadata: metadata, + augmentKeyword: augmentKeyword, + externalKeyword: externalKeyword, + constKeyword: constKeyword, + factoryKeyword: factoryKeyword, + returnType: SimpleIdentifierImpl(token: _outputToken(returnType.name)), + period: period, + name: name, + parameters: parameters, + separator: separator, + initializers: initializers, + redirectedConstructor: redirectedConstructor?.outputConstructorName, + body: body.outputBody(returnType.name), + ); + } +} + +extension on ConstructorNameImpl { + ConstructorNameImpl get outputConstructorName { + return ConstructorNameImpl( + type: type.outputNamedType, + period: period, + name: name, + ); + } +} + +extension on FunctionBodyImpl { + FunctionBodyImpl outputBody(String returnTypeName) { + return switch (this) { + final ExpressionFunctionBodyImpl body => body.outputExpressionBody( + returnTypeName, + ), + _ => this, + }; + } +} + +extension on ExpressionFunctionBodyImpl { + ExpressionFunctionBodyImpl outputExpressionBody(String returnTypeName) { + return ExpressionFunctionBodyImpl( + keyword: keyword, + star: star, + functionDefinition: functionDefinition, + expression: expression.outputExpression(returnTypeName), + semicolon: semicolon, + ); + } +} + +extension on ExpressionImpl { + ExpressionImpl outputExpression(String returnTypeName) { + return switch (this) { + final MethodInvocationImpl expression => + expression.outputMethodInvocation(returnTypeName), + _ => this, + }; + } +} + +extension on MethodInvocationImpl { + MethodInvocationImpl outputMethodInvocation(String returnTypeName) { + return MethodInvocationImpl( + target: target, + operator: operator, + methodName: SimpleIdentifierImpl( + token: _identifierToken( + methodName.name.replaceFirst( + returnTypeName, + '${returnTypeName}Output', ), ), - period: node.period, - name: node.name, - parameters: node.parameters, - separator: node.separator, - initializers: node.initializers, - redirectedConstructor: node.redirectedConstructor, - body: node.body, - ); - NodeReplacer.replace(node, updatedNode); - } - super.visitConstructorDeclaration(node); + ), + typeArguments: typeArguments, + argumentList: argumentList, + ); } } + +extension on FieldDeclarationImpl { + FieldDeclarationImpl get outputField { + return FieldDeclarationImpl( + comment: null, + metadata: metadata, + abstractKeyword: abstractKeyword, + augmentKeyword: augmentKeyword, + covariantKeyword: covariantKeyword, + externalKeyword: externalKeyword, + staticKeyword: staticKeyword, + fields: VariableDeclarationListImpl( + comment: null, + metadata: fields.metadata, + lateKeyword: fields.lateKeyword, + keyword: fields.keyword, + type: fields.type?.newTypeO, + variables: fields.variables.toList(), + ), + semicolon: semicolon, + ); + } +} + +extension on NamedTypeImpl { + NamedTypeImpl get outputNamedType { + return NamedTypeImpl( + importPrefix: importPrefix, + name: _outputToken(name.lexeme), + typeArguments: typeArguments, + question: question, + ); + } +} + +StringToken _outputToken(String name) => _identifierToken('${name}Output'); + +StringToken _identifierToken(String name) { + return StringToken(TokenType.IDENTIFIER, name, 0); +} diff --git a/packages/reactive_forms_generator/lib/src/output/rf_paramater_visitor.dart b/packages/reactive_forms_generator/lib/src/output/rf_paramater_visitor.dart index c8ce1577..4aa78cf7 100644 --- a/packages/reactive_forms_generator/lib/src/output/rf_paramater_visitor.dart +++ b/packages/reactive_forms_generator/lib/src/output/rf_paramater_visitor.dart @@ -14,8 +14,7 @@ import "package:collection/collection.dart"; import 'package:reactive_forms_generator/src/form_elements/form_element_generator.dart'; import 'package:reactive_forms_generator/src/output/extensions.dart'; import 'package:reactive_forms_generator/src/types.dart'; -import 'package:reactive_forms_generator/src/output/rf_annotation_arguments_visitor.dart'; -import 'package:reactive_forms_generator/src/output/rf_annotation_visitor.dart'; +import 'package:reactive_forms_generator/src/output/rf_annotation_arguments.dart'; import 'package:analyzer/dart/ast/token.dart'; import 'package:analyzer/src/dart/ast/token.dart'; import 'package:analyzer/src/dart/ast/utilities.dart'; @@ -157,22 +156,11 @@ class RfParameterVisitor extends GeneralizingAstVisitor { @override visitFormalParameterList(FormalParameterList node) { for (var e in node.parameters) { - final rfAnnotationVisitor = RfAnnotationVisitor(); - final rfAnnotationArguments = RfAnnotationArgumentsVisitor(); - e.visitChildren(rfAnnotationVisitor); + final validators = e.rfAnnotation?.namedArgument( + FormElementGenerator.validatorKey, + ); - if (rfAnnotationVisitor.rfAnnotation != null) { - e.visitChildren(rfAnnotationArguments); - } - - final validators = - rfAnnotationArguments.arguments[FormElementGenerator.validatorKey]; - - final p = requiredValidators.fold(false, (acc, e) { - return acc || validators?.contains(e) == true; - }); - - if (p) { + if (validators.containsAnyValidator(requiredValidators)) { fieldFormalParameter[e.name.toString()] = e; } } diff --git a/packages/reactive_forms_generator/lib/src/output/x.dart b/packages/reactive_forms_generator/lib/src/output/x.dart deleted file mode 100644 index 11a54549..00000000 --- a/packages/reactive_forms_generator/lib/src/output/x.dart +++ /dev/null @@ -1,557 +0,0 @@ -// ignore_for_file: implementation_imports -import 'package:analyzer/dart/element/element.dart'; -import 'package:analyzer/dart/element/nullability_suffix.dart'; -import 'package:analyzer/dart/element/type.dart'; -import 'package:analyzer/src/dart/element/type.dart'; -import 'package:analyzer/src/dart/element/display_string_builder.dart'; -import 'package:analyzer/src/dart/element/element.dart'; -import 'package:analyzer/src/dart/element/type_algebra.dart'; -import 'package:analyzer/src/dart/element/type_algebra.dart' - show replaceTypeParameters; -import 'package:reactive_forms_generator/src/types.dart'; - -class ElementDisplayStringBuilder2 extends ElementDisplayStringBuilder { - final StringBuffer _buffer = StringBuffer(); - - /// Whether to include the nullability ('?' characters) in a display string. - final bool _withNullability; - - /// Whether to allow a display string to be written in multiple lines. - final bool _multiline; - - ElementDisplayStringBuilder2({ - required bool withNullability, - bool multiline = false, - }) : _withNullability = withNullability, - _multiline = multiline, - super(preferTypeAlias: false); - - @override - String toString() => _buffer.toString(); - - @override - void writeAbstractElement(ElementImpl element) { - _write(element.name ?? ''); - } - - @override - void writeClassElement(ClassElementImpl element) { - if (element.firstFragment.isAugmentation) { - _write('augment '); - } - - if (element.isSealed) { - _write('sealed '); - } else if (element.isAbstract) { - _write('abstract '); - } - if (element.isBase) { - _write('base '); - } else if (element.isInterface) { - _write('interface '); - } else if (element.isFinal) { - _write('final '); - } - if (element.isMixinClass) { - _write('mixin '); - } - - _write('class '); - _write(element.displayName); - - _writeTypeParameters(element.typeParameters); - - _writeTypeIfNotObject(' extends ', element.supertype); - _writeTypesIfNotEmpty(' with ', element.mixins); - _writeTypesIfNotEmpty(' implements ', element.interfaces); - } - - // CompilationUnitElement method removed for compatibility - void writeCompilationUnitElement(dynamic element) { - // Simplified implementation - _write(''); - } - - @override - void writeConstructorElement(ConstructorElement element) { - _writeType(element.returnType); - _write(' '); - - _write(element.displayName); - - _writeFormalParameters( - element.formalParameters, - forElement: true, - allowMultiline: true, - ); - } - - @override - void writeDynamicType() { - _write('dynamic'); - } - - @override - void writeEnumElement(EnumElement element) { - _write('enum '); - _write(element.displayName); - _writeTypeParameters(element.typeParameters); - _writeTypesIfNotEmpty(' with ', element.mixins); - _writeTypesIfNotEmpty(' implements ', element.interfaces); - } - - @override - void writeExecutableElement(ExecutableElement element, String name) { - if (element.firstFragment.isAugmentation) { - _write('augment '); - } - - if (element.kind != ElementKind.SETTER) { - _writeType(element.returnType); - _write(' '); - } - - _write(name); - - if (element.kind != ElementKind.GETTER) { - _writeTypeParameters(element.typeParameters); - _writeFormalParameters( - element.formalParameters, - forElement: true, - allowMultiline: true, - ); - } - } - - // LibraryExportElement method removed for compatibility - void writeExportElement(dynamic element) { - _write('export '); - } - - @override - void writeExtensionElement(ExtensionElement element) { - _write('extension '); - _write(element.displayName); - _writeTypeParameters(element.typeParameters); - _write(' on '); - _writeType(element.extendedType); - } - - void writeFormalParameter(FormalParameterElement element) { - if (element.isRequiredPositional) { - _writeWithoutDelimiters(element, forElement: true); - } else if (element.isOptionalPositional) { - _write('['); - _writeWithoutDelimiters(element, forElement: true); - _write(']'); - } else if (element.isNamed) { - _write('{'); - _writeWithoutDelimiters(element, forElement: true); - _write('}'); - } - } - - @override - void writeFunctionType(FunctionType type) { - type = _uniqueTypeParameters(type); - - _writeType(type.returnType); - _write(' Function'); - _writeTypeParameters(type.typeParameters); - _writeFormalParameters(type.formalParameters, forElement: false); - _writeNullability(type.nullabilitySuffix); - } - - @override - void writeGenericFunctionTypeElement(GenericFunctionTypeElementImpl element) { - _writeType(element.returnType); - _write(' Function'); - _writeTypeParameters(element.typeParameters); - _writeFormalParameters(element.formalParameters, forElement: true); - } - - // LibraryImportElement method removed for compatibility - void writeImportElement(dynamic element) { - _write('import '); - } - - @override - void writeInterfaceType(InterfaceType type) { - final namePostfix = - type.element.hasRfGroupAnnotation || - ElementRfExt(type.element).hasRfAnnotation - ? 'Output' - : ''; - _write('${type.element.name}$namePostfix'); - _writeTypeArguments(type.typeArguments); - - _writeNullability(type.nullabilitySuffix); - } - - @override - void writeInvalidType() { - _write('InvalidType'); - } - - @override - void writeLibraryElement(LibraryElementImpl element) { - _write('library '); - _write('${element.source.uri}'); - } - - @override - void writeMixinElement(MixinElementImpl element) { - if (element.firstFragment.isAugmentation) { - _write('augment '); - } - if (element.isBase) { - _write('base '); - } - _write('mixin '); - _write(element.displayName); - _writeTypeParameters(element.typeParameters); - _writeTypesIfNotEmpty(' on ', element.superclassConstraints); - _writeTypesIfNotEmpty(' implements ', element.interfaces); - } - - @override - void writeNeverType(NeverType type) { - _write('Never'); - _writeNullability(type.nullabilitySuffix); - } - - // PartElement method removed for compatibility - void writePartElement(dynamic element) { - _write('part '); - } - - @override - void writePrefixElement(PrefixElementImpl element) { - _write('as '); - _write(element.displayName); - } - - @override - void writeRecordType(RecordType type) { - final positionalFields = type.positionalFields; - final namedFields = type.namedFields; - final fieldCount = positionalFields.length + namedFields.length; - _write('('); - - var index = 0; - for (final field in positionalFields) { - _writeType(field.type); - if (index++ < fieldCount - 1) { - _write(', '); - } - } - - if (namedFields.isNotEmpty) { - _write('{'); - for (final field in namedFields) { - _writeType(field.type); - _write(' '); - _write(field.name); - if (index++ < fieldCount - 1) { - _write(', '); - } - } - _write('}'); - } - - // Add trailing comma for record types with only one position field. - if (positionalFields.length == 1 && namedFields.isEmpty) { - _write(','); - } - - _write(')'); - _writeNullability(type.nullabilitySuffix); - } - - @override - void writeTypeAliasElement(TypeAliasElementImpl element) { - _write('typedef '); - _write(element.displayName); - _writeTypeParameters(element.typeParameters); - _write(' = '); - - var aliasedElement = element.aliasedElement; - if (aliasedElement != null) { - aliasedElement.appendTo(this); - } else { - _writeType(element.aliasedType); - } - } - - void writeTypeParameter(TypeParameterElement element) { - // Variance handling removed for compatibility - - _write(element.displayName); - - var bound = element.bound; - if (bound != null) { - _write(' extends '); - _writeType(bound); - } - } - - @override - void writeTypeParameterType(TypeParameterTypeImpl type) { - final promotedBound = type.promotedBound; - if (promotedBound != null) { - final hasSuffix = type.nullabilitySuffix != NullabilitySuffix.none; - if (hasSuffix) { - _write('('); - } - _write(type.element.displayName); - _write(' & '); - _writeType(promotedBound); - if (hasSuffix) { - _write(')'); - } - } else { - _write(type.element.displayName); - } - _writeNullability(type.nullabilitySuffix); - } - - @override - void writeUnknownInferredType() { - _write('_'); - } - - @override - void writeVariableElement(VariableElement element) { - switch (element) { - case FieldElement() when element.firstFragment.isAugmentation: - case TopLevelVariableElement() when element.firstFragment.isAugmentation: - _write('augment '); - } - - _writeType(element.type); - _write(' '); - _write(element.displayName); - } - - @override - void writeVoidType() { - _write('void'); - } - - void _write(String str) { - _buffer.write(str); - } - - void _writeFormalParameters( - List parameters, { - required bool forElement, - bool allowMultiline = false, - }) { - // Assume the display string looks better wrapped when there are at least - // three parameters. This avoids having to pre-compute the single-line - // version and know the length of the function name/return type. - var multiline = allowMultiline && _multiline && parameters.length >= 3; - - // The prefix for open groups is included in separator for single-line but - // not for multiline so must be added explicitly. - var openGroupPrefix = multiline ? ' ' : ''; - var separator = multiline ? ',' : ', '; - var trailingComma = multiline ? ',\n' : ''; - var parameterPrefix = multiline ? '\n ' : ''; - - _write('('); - - _WriteFormalParameterKind? lastKind; - var lastClose = ''; - - void openGroup(_WriteFormalParameterKind kind, String open, String close) { - if (lastKind != kind) { - _write(lastClose); - if (lastKind != null) { - // We only need to include the space before the open group if there - // was a previous parameter, otherwise it goes immediately after the - // open paren. - _write(openGroupPrefix); - } - _write(open); - lastKind = kind; - lastClose = close; - } - } - - for (var i = 0; i < parameters.length; i++) { - if (i != 0) { - _write(separator); - } - - var parameter = parameters[i]; - if (parameter.isRequiredPositional) { - openGroup(_WriteFormalParameterKind.requiredPositional, '', ''); - } else if (parameter.isOptionalPositional) { - openGroup(_WriteFormalParameterKind.optionalPositional, '[', ']'); - } else if (parameter.isNamed) { - openGroup(_WriteFormalParameterKind.named, '{', '}'); - } - _write(parameterPrefix); - _writeWithoutDelimiters(parameter, forElement: forElement); - } - - _write(trailingComma); - _write(lastClose); - _write(')'); - } - - void _writeNullability(NullabilitySuffix nullabilitySuffix) { - if (_withNullability) { - switch (nullabilitySuffix) { - case NullabilitySuffix.question: - _write('?'); - case NullabilitySuffix.star: - _write('*'); - case NullabilitySuffix.none: - } - } - } - - void _writeType(DartType type) { - (type as TypeImpl).appendTo(this); - } - - void _writeTypeArguments(List typeArguments) { - if (typeArguments.isEmpty) { - return; - } - - _write('<'); - for (var i = 0; i < typeArguments.length; i++) { - if (i != 0) { - _write(', '); - } - (typeArguments[i] as TypeImpl).appendTo(this); - } - _write('>'); - } - - void _writeTypeIfNotObject(String prefix, DartType? type) { - if (type != null && !type.isDartCoreObject) { - _write(prefix); - _writeType(type); - } - } - - void _writeTypeParameters(List elements) { - if (elements.isEmpty) return; - - _write('<'); - for (var i = 0; i < elements.length; i++) { - if (i != 0) { - _write(', '); - } - (elements[i] as TypeParameterElementImpl).appendTo(this); - } - _write('>'); - } - - void _writeTypes(List types) { - for (var i = 0; i < types.length; i++) { - if (i != 0) { - _write(', '); - } - _writeType(types[i]); - } - } - - void _writeTypesIfNotEmpty(String prefix, List types) { - if (types.isNotEmpty) { - _write(prefix); - _writeTypes(types); - } - } - - void _writeWithoutDelimiters( - FormalParameterElement element, { - required bool forElement, - }) { - if (element.isRequiredNamed) { - _write('required '); - } - - _writeType(element.type); - - if (forElement || element.isNamed) { - _write(' '); - _write(element.displayName); - } - - if (forElement) { - var defaultValueCode = element.defaultValueCode; - if (defaultValueCode != null) { - _write(' = '); - _write(defaultValueCode); - } - } - } - - static FunctionType _uniqueTypeParameters(FunctionType type) { - if (type.typeParameters.isEmpty) { - return type; - } - - var referencedTypeParameters = {}; - - void collectTypeParameters(DartType? type) { - if (type is TypeParameterType) { - referencedTypeParameters.add(type.element); - } else if (type is FunctionType) { - for (var typeParameter in type.typeParameters) { - collectTypeParameters(typeParameter.bound); - } - for (var parameter in type.formalParameters) { - collectTypeParameters(parameter.type); - } - collectTypeParameters(type.returnType); - } else if (type is InterfaceType) { - for (var typeArgument in type.typeArguments) { - collectTypeParameters(typeArgument); - } - } - } - - collectTypeParameters(type); - referencedTypeParameters.removeAll(type.typeParameters); - - var namesToAvoid = {}; - for (var typeParameter in referencedTypeParameters) { - namesToAvoid.add(typeParameter.displayName); - } - - var newTypeParameters = []; - for (var typeParameter in type.typeParameters) { - var name = typeParameter.name ?? 'T'; - for (var counter = 0; !namesToAvoid.add(name); counter++) { - const unicodeSubscriptZero = 0x2080; - const unicodeZero = 0x30; - - var subscript = String.fromCharCodes( - '$counter'.codeUnits.map((n) { - return unicodeSubscriptZero + (n - unicodeZero); - }), - ); - - name = '${typeParameter.name ?? 'T'}$subscript'; - } - - // Simplified type parameter creation for compatibility - // Note: This is a simplified approach that may need refinement - var newTypeParameter = typeParameter; // Use original for now - newTypeParameters.add(newTypeParameter); - } - - return replaceTypeParameters( - type as FunctionTypeImpl, - newTypeParameters.cast(), - ); - } -} - -enum _WriteFormalParameterKind { requiredPositional, optionalPositional, named } diff --git a/packages/reactive_forms_generator/lib/src/reactive_forms_generator/field_value_method.dart b/packages/reactive_forms_generator/lib/src/reactive_forms_generator/field_value_method.dart index 225f9bc9..b6bc0410 100644 --- a/packages/reactive_forms_generator/lib/src/reactive_forms_generator/field_value_method.dart +++ b/packages/reactive_forms_generator/lib/src/reactive_forms_generator/field_value_method.dart @@ -1,19 +1,10 @@ -// ignore_for_file: implementation_imports - -import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/nullability_suffix.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:code_builder/code_builder.dart'; -import 'package:analyzer/src/dart/element/type.dart'; import 'package:reactive_forms_generator/src/extensions.dart'; -import 'package:reactive_forms_generator/src/output/x.dart'; -// import 'package:reactive_forms_generator/src/output/x.dart'; import 'package:reactive_forms_generator/src/reactive_form_generator_method.dart'; -// import 'package:reactive_forms_generator/src/types.dart'; -// import 'package:analyzer/src/dart/element/display_string_builder.dart'; - class FieldValueMethod extends ReactiveFormGeneratorMethod { FieldValueMethod(super.field, super.output, super.requiredValidators); @@ -112,17 +103,6 @@ class FieldRawValueMethod extends FieldValueMethod { } } -extension Care on ClassElement { - String get toReferenceType { - var builder = ElementDisplayStringBuilder2( - withNullability: true, - // preferTypeAlias: false, - ); - (thisType as TypeImpl).appendTo(builder); - return builder.toString(); - } -} - // extension Pare on ParameterElement { // // } diff --git a/packages/reactive_forms_generator/lib/src/types.dart b/packages/reactive_forms_generator/lib/src/types.dart index 3175cee1..f1e33ff8 100644 --- a/packages/reactive_forms_generator/lib/src/types.dart +++ b/packages/reactive_forms_generator/lib/src/types.dart @@ -78,40 +78,6 @@ extension NodeListImplAnnotationImplExt on NodeListImpl { } } -extension on Annotatable { - Map annotationParams1(TypeChecker? typeChecker) { - final result = {}; - final annotation = typeChecker?.firstAnnotationOf(this); - try { - if (annotation != null) { - for (final meta in metadata.annotations) { - final obj = meta.computeConstantValue()!; - - final isExactlyType = typeChecker?.isExactlyType(obj.type!) ?? false; - if (isExactlyType) { - final argumentList = - (meta as ElementAnnotationImpl).annotationAst.arguments - as ArgumentListImpl; - for (var argument in argumentList.arguments) { - final argumentNamedExpression = argument as NamedExpressionImpl; - result.addEntries([ - MapEntry( - argumentNamedExpression.name.label.toSource(), - argumentNamedExpression.expression.toSource(), - ), - ]); - } - } - } - } - - return result; - } catch (e) { - return result; - } - } -} - // extension FormalParameterElementExt on FormalParameterElement { // Map annotationParams(TypeChecker? typeChecker) { // final result = {}; @@ -168,11 +134,34 @@ extension ElementRfExt on Element { Map annotationParams(TypeChecker? typeChecker) { final result = {}; - if (this is Annotatable) { - return (this as Annotatable).annotationParams1(typeChecker); - } + final annotation = typeChecker?.firstAnnotationOf(this); + try { + if (annotation != null) { + for (final meta in metadata.annotations) { + final obj = meta.computeConstantValue(); - return result; + final type = obj?.type; + if (type != null && typeChecker?.isExactlyType(type) == true) { + final argumentList = + (meta as ElementAnnotationImpl).annotationAst.arguments + as ArgumentListImpl; + for (var argument in argumentList.arguments) { + final argumentNamedExpression = argument as NamedExpressionImpl; + result.addEntries([ + MapEntry( + argumentNamedExpression.name.label.toSource(), + argumentNamedExpression.expression.toSource(), + ), + ]); + } + } + } + } + + return result; + } catch (e) { + return result; + } // final annotation = typeChecker?.firstAnnotationOf(this); // try { // if (annotation != null) { diff --git a/packages/reactive_forms_generator/pubspec.yaml b/packages/reactive_forms_generator/pubspec.yaml index 32d13391..3276ab30 100644 --- a/packages/reactive_forms_generator/pubspec.yaml +++ b/packages/reactive_forms_generator/pubspec.yaml @@ -2,7 +2,7 @@ name: reactive_forms_generator description: Generator for reactive_forms. Generates form classes based on model. repository: https://github.com/artflutter/reactive_forms_generator -version: 8.4.0 +version: 8.5.0-beta9 environment: sdk: ">=3.8.0 <4.0.0" @@ -10,9 +10,8 @@ resolution: workspace dependencies: build: ^4.0.1 - source_gen: ^4.0.1 - _fe_analyzer_shared: '>=89.0.0 <98.0.0' - analyzer: '>=9.0.0 <12.0.0' + source_gen: ^4.1.2 + analyzer: ^9.0.0 path: ^1.8.1 build_runner: ^2.7.0 code_builder: ^4.10.1 @@ -24,8 +23,9 @@ dev_dependencies: build_test: ^3.4.1 logging: ^1.2.0 flutter_lints: ^6.0.0 + test: ^1.25.15 #dependency_overrides: # build_resolvers: ^2.1.0 # test_api: ^0.4.18 -# source_helper: ^1.3.3 \ No newline at end of file +# source_helper: ^1.3.3 diff --git a/packages/reactive_forms_generator/test/rf_annotation_arguments_test.dart b/packages/reactive_forms_generator/test/rf_annotation_arguments_test.dart new file mode 100644 index 00000000..01e76398 --- /dev/null +++ b/packages/reactive_forms_generator/test/rf_annotation_arguments_test.dart @@ -0,0 +1,127 @@ +import 'package:analyzer/dart/analysis/utilities.dart'; +import 'package:analyzer/dart/ast/ast.dart'; +import 'package:collection/collection.dart'; +import 'package:reactive_forms_generator/src/output/rf_annotation_arguments.dart'; +import 'package:test/test.dart'; + +void main() { + group('AnnotationNamedArguments', () { + test('returns null and empty sources when annotation has no arguments', () { + final annotation = _firstAnnotation('@RfControl this.email'); + + expect(annotation.namedArgument('validators'), isNull); + expect(annotation.namedArgumentSources, isEmpty); + }); + + test( + 'finds named arguments by exact name and ignores positional arguments', + () { + final annotation = _firstAnnotation( + "@RfControl('ignored', validators: const [RequiredValidator()], " + 'disabled: true) this.email', + ); + + expect( + annotation.namedArgument('validators')?.toSource(), + 'const [RequiredValidator()]', + ); + expect(annotation.namedArgument('validator'), isNull); + expect(annotation.namedArgumentSources, { + 'validators': 'const [RequiredValidator()]', + 'disabled': 'true', + }); + }, + ); + + test('returns unmodifiable named argument maps', () { + final annotation = _firstAnnotation( + '@RfControl(disabled: true) this.email', + ); + final sources = annotation.namedArgumentSources; + + expect(() => sources['disabled'] = 'false', throwsUnsupportedError); + }); + }); + + group('FormalParameterRfAnnotation', () { + test('ignores unsupported RF-prefixed annotations', () { + final parameter = _firstParameter('@RfSomethingElse() this.email'); + + expect(parameter.rfAnnotation, isNull); + }); + + test('finds supported short and long annotation names', () { + final shortName = _firstParameter('@RfControl() this.email'); + final longName = _firstParameter('@FormControlAnnotation() this.email'); + + expect(shortName.rfAnnotation?.name.toSource(), 'RfControl'); + expect(longName.rfAnnotation?.name.toSource(), 'FormControlAnnotation'); + }); + + test('finds aliased annotations by the final identifier name', () { + final parameter = _firstParameter('@annotations.RfControl() this.email'); + + expect(parameter.rfAnnotation?.name.toSource(), 'annotations.RfControl'); + }); + }); + + group('ValidatorExpressionMatcher', () { + test('matches configured constructor validators in list literals', () { + final expression = _validatorsExpression('const [RequiredValidator()]'); + + expect(expression.containsAnyValidator(['RequiredValidator()']), isTrue); + }); + + test('does not match partial validator names', () { + final expression = _validatorsExpression('const [MyRequiredValidator()]'); + + expect(expression.containsAnyValidator(['RequiredValidator()']), isFalse); + }); + + test('matches identifiers and property accesses by selected name', () { + final identifier = _validatorsExpression('const [requiredValidator]'); + final propertyAccess = _validatorsExpression( + 'const [Validators.required]', + ); + + expect(identifier.containsAnyValidator(['requiredValidator()']), isTrue); + expect( + propertyAccess.containsAnyValidator(['Validators.required']), + isTrue, + ); + }); + }); +} + +Annotation _firstAnnotation(String parameterSource) { + return _firstParameter(parameterSource).metadata.single; +} + +Expression _validatorsExpression(String validatorsSource) { + return _firstAnnotation( + '@RfControl(validators: $validatorsSource) this.email', + ).namedArgument('validators')!; +} + +FormalParameter _firstParameter(String parameterSource) { + final unit = parseString( + content: + ''' +class User { + final String email; + + User($parameterSource); +} +''', + ).unit; + + return unit.declarations + .whereType() + .single + .members + .whereType() + .single + .parameters + .parameters + .firstWhereOrNull((parameter) => parameter.name?.lexeme == 'email')!; +} diff --git a/pubspec.lock b/pubspec.lock index 23d3653e..737966e1 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -2,21 +2,21 @@ # See https://dart.dev/tools/pub/glossary#lockfile packages: _fe_analyzer_shared: - dependency: "direct overridden" + dependency: transitive description: name: _fe_analyzer_shared - sha256: dd3d2ad434b9510001d089e8de7556d50c834481b9abc2891a0184a8493a19dc + sha256: "5b7468c326d2f8a4f630056404ca0d291ade42918f4a3c6233618e724f39da8e" url: "https://pub.dev" source: hosted - version: "89.0.0" + version: "92.0.0" analyzer: - dependency: "direct overridden" + dependency: transitive description: name: analyzer - sha256: c22b6e7726d1f9e5db58c7251606076a71ca0dbcf76116675edfadbec0c9e875 + sha256: "70e4b1ef8003c64793a9e268a551a82869a8a96f39deb73dea28084b0e8bf75e" url: "https://pub.dev" source: hosted - version: "8.2.0" + version: "9.0.0" ansi_styles: dependency: transitive description: @@ -37,10 +37,10 @@ packages: dependency: transitive description: name: async - sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" + sha256: e2eb0491ba5ddb6177742d2da23904574082139b07c1e33b8503b9f46f3e1a37 url: "https://pub.dev" source: hosted - version: "2.13.0" + version: "2.13.1" boolean_selector: dependency: transitive description: @@ -53,42 +53,42 @@ packages: dependency: transitive description: name: build - sha256: dfb67ccc9a78c642193e0c2d94cb9e48c2c818b3178a86097d644acdcde6a8d9 + sha256: a156715e7cd728130c592f30552575908aae5b100005fbc1f0fb16b3c03a3d10 url: "https://pub.dev" source: hosted - version: "4.0.2" + version: "4.0.6" build_config: dependency: transitive description: name: build_config - sha256: "4f64382b97504dc2fcdf487d5aae33418e08b4703fc21249e4db6d804a4d0187" + sha256: "4070d2a59f8eec34c97c86ceb44403834899075f66e8a9d59706f8e7834f6f71" url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.3.0" build_daemon: dependency: transitive description: name: build_daemon - sha256: "409002f1adeea601018715d613115cfaf0e31f512cb80ae4534c79867ae2363d" + sha256: bf05f6e12cfea92d3c09308d7bcdab1906cd8a179b023269eed00c071004b957 url: "https://pub.dev" source: hosted - version: "4.1.0" + version: "4.1.1" build_runner: dependency: "direct dev" description: name: build_runner - sha256: a9461b8e586bf018dd4afd2e13b49b08c6a844a4b226c8d1d10f3a723cdd78c3 + sha256: "1523ce62448ebac2c15a8ba5fbad8acac169788658a7dd2a1c2d9c2a9318b9a6" url: "https://pub.dev" source: hosted - version: "2.10.1" + version: "2.15.0" build_test: dependency: transitive description: name: build_test - sha256: "86124991e1df069c0993fd1c29dc4e112b73884543f6d9d1d3c2ddb1d6f61dc0" + sha256: e69ade870705d5ad4d8b7e479d0ca71d0a9932ca04be6d278d97de45a32da07e url: "https://pub.dev" source: hosted - version: "3.5.1" + version: "3.5.15" built_collection: dependency: transitive description: @@ -101,10 +101,10 @@ packages: dependency: transitive description: name: built_value - sha256: a30f0a0e38671e89a492c44d005b5545b830a961575bbd8336d42869ff71066d + sha256: "34e4067d30ce212937df995f03b69992eea683539ceeac7f679a1f1eba055b56" url: "https://pub.dev" source: hosted - version: "8.12.0" + version: "8.12.6" characters: dependency: transitive description: @@ -165,10 +165,10 @@ packages: dependency: transitive description: name: code_builder - sha256: "11654819532ba94c34de52ff5feb52bd81cba1de00ef2ed622fd50295f9d4243" + sha256: "6a6cab2ba4680d6423f34a9b972a4c9a94ebe1b62ecec4e1a1f2cba91fd1319d" url: "https://pub.dev" source: hosted - version: "4.11.0" + version: "4.11.1" collection: dependency: transitive description: @@ -221,10 +221,10 @@ packages: dependency: transitive description: name: dart_style - sha256: c87dfe3d56f183ffe9106a18aebc6db431fc7c98c31a54b952a77f3d54a85697 + sha256: a9c30492da18ff84efe2422ba2d319a89942d93e58eb0b73d32abe822ef54b7b url: "https://pub.dev" source: hosted - version: "3.1.2" + version: "3.1.3" dartz: dependency: transitive description: @@ -237,10 +237,10 @@ packages: dependency: transitive description: name: equatable - sha256: "567c64b3cb4cf82397aac55f4f0cbd3ca20d77c6c03bedbc4ceaddc08904aef7" + sha256: "3e0141505477fd8ad55d6eb4e7776d3fe8430be8e497ccb1521370c3f21a3e2b" url: "https://pub.dev" source: hosted - version: "2.0.7" + version: "2.0.8" fake_async: dependency: transitive description: @@ -292,10 +292,10 @@ packages: dependency: transitive description: name: freezed - sha256: "13065f10e135263a4f5a4391b79a8efc5fb8106f8dd555a9e49b750b45393d77" + sha256: f23ea33b3863f119b58ed1b586e881a46bd28715ddcc4dbc33104524e3434131 url: "https://pub.dev" source: hosted - version: "3.2.3" + version: "3.2.5" freezed_annotation: dependency: transitive description: @@ -340,10 +340,10 @@ packages: dependency: transitive description: name: http - sha256: bb2ce4590bc2667c96f318d68cac1b5a7987ec819351d32b1c987239a815e007 + sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412" url: "https://pub.dev" source: hosted - version: "1.5.0" + version: "1.6.0" http_multi_server: dependency: transitive description: @@ -380,18 +380,18 @@ packages: dependency: transitive description: name: json_annotation - sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" + sha256: cb09e7dac6210041fad964ed7fbee004f14258b4eca4040f72d1234062ace4c8 url: "https://pub.dev" source: hosted - version: "4.9.0" + version: "4.11.0" json_serializable: dependency: transitive description: name: json_serializable - sha256: "33a040668b31b320aafa4822b7b1e177e163fc3c1e835c6750319d4ab23aa6fe" + sha256: "44729f5c45748e6748f6b9a57ab8f7e4336edc8ae41fc295070e3814e616a6c0" url: "https://pub.dev" source: hosted - version: "6.11.1" + version: "6.13.0" leak_tracker: dependency: transitive description: @@ -420,10 +420,10 @@ packages: dependency: transitive description: name: lints - sha256: a5e2b223cb7c9c8efdc663ef484fdd95bb243bff242ef5b13e26883547fce9a0 + sha256: "12f842a479589fea194fe5c5a3095abc7be0c1f2ddfa9a0e76aed1dbd26a87df" url: "https://pub.dev" source: hosted - version: "6.0.0" + version: "6.1.0" logging: dependency: transitive description: @@ -452,10 +452,10 @@ packages: dependency: "direct dev" description: name: melos - sha256: e3379a08af92a719a76d4cce9644c98dc87554e0fa3f2a93eb9a04bb295d4a03 + sha256: "91e2cc619f5753446bb606eef745abc3416902d5515e36086027226ac812bd6f" url: "https://pub.dev" source: hosted - version: "7.4.1" + version: "7.6.0" meta: dependency: transitive description: @@ -476,10 +476,10 @@ packages: dependency: transitive description: name: mustache_template - sha256: daa42be75f2ccfb287c24a75e7ac594f2ea0b32bf9ebe7c15154aa45b2dfb2de + sha256: "544ff0b837836f5ad6b351e7a676ff7c2cad4fa412c465908aeb9358caddb6fc" url: "https://pub.dev" source: hosted - version: "2.0.2" + version: "2.0.4" nested: dependency: transitive description: @@ -516,10 +516,10 @@ packages: dependency: transitive description: name: petitparser - sha256: "1a97266a94f7350d30ae522c0af07890c70b8e62c71e8e3920d1db4d23c057d1" + sha256: "91bd59303e9f769f108f8df05e371341b15d59e995e6806aefab827b58336675" url: "https://pub.dev" source: hosted - version: "7.0.1" + version: "7.0.2" platform: dependency: transitive description: @@ -641,18 +641,18 @@ packages: dependency: transitive description: name: source_gen - sha256: "9098ab86015c4f1d8af6486b547b11100e73b193e1899015033cb3e14ad20243" + sha256: ec37cc0e6694374cbef59ed79685572c870a54ede6fa30a3e420feb3adffea02 url: "https://pub.dev" source: hosted - version: "4.0.2" + version: "4.2.3" source_helper: dependency: transitive description: name: source_helper - sha256: "6a3c6cc82073a8797f8c4dc4572146114a39652851c157db37e964d9c7038723" + sha256: "4227d54ceefd0bb8ca4c8fcb96e1719dc53f1ee1b6e2ca9d7a6069da160e4eae" url: "https://pub.dev" source: hosted - version: "1.3.8" + version: "1.3.12" source_map_stack_trace: dependency: transitive description: @@ -673,10 +673,10 @@ packages: dependency: transitive description: name: source_span - sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" + sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab" url: "https://pub.dev" source: hosted - version: "1.10.1" + version: "1.10.2" stack_trace: dependency: transitive description: @@ -721,26 +721,26 @@ packages: dependency: transitive description: name: test - sha256: "8d9ceddbab833f180fbefed08afa76d7c03513dfdba87ffcec2718b02bbcbf20" + sha256: "280d6d890011ca966ad08df7e8a4ddfab0fb3aa49f96ed6de56e3521347a9ae7" url: "https://pub.dev" source: hosted - version: "1.31.0" + version: "1.30.0" test_api: - dependency: "direct overridden" + dependency: transitive description: name: test_api - sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd + sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a" url: "https://pub.dev" source: hosted - version: "0.7.4" + version: "0.7.10" test_core: - dependency: "direct overridden" + dependency: transitive description: name: test_core - sha256: "84d17c3486c8dfdbe5e12a50c8ae176d15e2a771b96909a9442b40173649ccaa" + sha256: "0381bd1585d1a924763c308100f2138205252fb90c9d4eeaf28489ee65ccde51" url: "https://pub.dev" source: hosted - version: "0.6.8" + version: "0.6.16" typed_data: dependency: transitive description: @@ -761,18 +761,18 @@ packages: dependency: transitive description: name: vm_service - sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60" + sha256: "0016aef94fc66495ac78af5859181e3f3bf2026bd8eecc72b9565601e19ab360" url: "https://pub.dev" source: hosted - version: "15.0.2" + version: "15.2.0" watcher: dependency: transitive description: name: watcher - sha256: "592ab6e2892f67760543fb712ff0177f4ec76c031f02f5b4ff8d3fc5eb9fb61a" + sha256: "1398c9f081a753f9226febe8900fce8f7d0a67163334e1c94a2438339d79d635" url: "https://pub.dev" source: hosted - version: "1.1.4" + version: "1.2.1" web: dependency: transitive description: @@ -825,10 +825,10 @@ packages: dependency: transitive description: name: yaml_edit - sha256: fb38626579fb345ad00e674e2af3a5c9b0cc4b9bfb8fd7f7ff322c7c9e62aef5 + sha256: "07c9e63ba42519745182b88ca12264a7ba2484d8239958778dfe4d44fe760488" url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.2.4" sdks: dart: ">=3.9.0 <4.0.0" flutter: ">=3.18.0-18.0.pre.54" diff --git a/pubspec.yaml b/pubspec.yaml index f85253c4..c5d3bb54 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -9,9 +9,6 @@ workspace: environment: sdk: ">=3.8.0 <4.0.0" -dependency_overrides: - test_api: 0.7.4 - dev_dependencies: build_runner: ^2.4.15 melos: ^7.4.1