Dart supports the part of statement which unfortunately doesn't work with this otherwise amazing package.
I'm using the BLoC library and specify events and states as unions. I like to generate just one file instead of two, so I want to use the part of statement in the event and state files which will point to the "core" bloc file.
part of 'sign_in_form_bloc.dart';
@immutable
abstract class SignInFormEvent with _$SignInFormEvent {
const factory SignInFormEvent.emailChanged(String emailStr) = _EmailChanged;
const factory SignInFormEvent.passwordChanged(String passwordStr) =
_PasswordChanged;
}
Then, the BLoC file contains the actual part '*.freezed.dart' directive.
import 'package:flutter/foundation.dart';
part 'sign_in_form_event.dart';
part 'sign_in_form_state.dart';
part 'sign_in_form_bloc.freezed.dart';
class SignInFormBloc extends Bloc<SignInFormEvent, SignInFormState> {...}
While doing the things described above worked flawlessly with sum_types, freezed outputs a [SEVERE] error upon generation looking like this:
[SEVERE] freezed:freezed on lib/application/auth/sign_in_form/sign_in_form_bloc.dart:
Error formatting generated source code for package:workout_app_prep/application/auth/sign_in_form/sign_in_form_bloc.dartwhich was output to lib/application/auth/sign_in_form/sign_in_form_bloc.freezed.dart.
This may indicate an issue in the generated code or in the formatter.
Please check the generated code and file an issue on source_gen if appropriate.
Could not format because the source could not be parsed:
line 367, column 9: Unexpected text ')'.
โท
367 โ class _$) with DiagnosticableTreeMixin implements ) {
โ ^
โต
line 367, column 51: Expected a type name.
Basically it adds a DiagnosticableTreeMixin to the generated file's classes.
Using only the part statement as seen in the examples does work:
import 'package:flutter/foundation.dart';
part 'sign_in_form_event.freezed.dart';
@immutable
abstract class SignInFormEvent with _$SignInFormEvent {
const factory SignInFormEvent.emailChanged(String emailStr) = _EmailChanged;
const factory SignInFormEvent.passwordChanged(String passwordStr) =
_PasswordChanged;
}
Basically it adds a DiagnosticableTreeMixin to the generated file's classes.
That's expected
It sounds more like a problem with parsing the name.
Could you give a minimalist way of reproducing the error?
When creating the demo project, I probably found the root of the issue. Code gen kicks in even for classes which don't extend _$SomeClass. While this minimal project written as a console app produces errors, they are not the same as in the case which I described with the BLoC.
UPDATE: The repository now also contains a minimal example with BLoC where Event is freezed and State is just a regular class marked as @immutable.
I'll take a look, thanks
Note that removing the @immutable on NonFreezedClass will fix the issue.
I'll think of a proper fix. The main problem is, since the interface is generated, the analyzer doesn't pick it up because it doesn't exist yet
Removing @immutable works in the example, even with BLoC. For some reason though, this doesn't work on my real code. I can't really share it as there's a lot of specifics going on and it's definitely not a minimal example.
In the meantime, I'll try to migrate the regular class to a freezed data class. That should work ๐ค
I think that instead of "don't generate if it doesn't mix-in _$MyCLass", I'll go with "don't generate if the class has a property"
Sounds reasonable. Anyway, this issue forced me to rethink my legacy approach to pure immutable classes and now I use freezed even for them. Works perfectly, thanks again!
I just have to use static methods instead of factories to have "predefined state configurations" which is a bit of an antipattern in Dart but I can live with that ๐
I just have to use static methods instead of factories to have "predefined state configurations" which is a bit of an antipattern in Dart but I can live with that ๐
What do you mean?
Well, the static method is an anti-pattern, isn't it? I even have to ignore lint.
@immutable
abstract class SignInFormState with _$SignInFormState {
const factory SignInFormState({
EmailAddress validatedEmailAddress,
Password validatedPassword,
bool autovalidate,
bool isSubmitting,
Either<AuthFailure, Unit> isSuccess,
}) = _SignInFormState;
// ignore: prefer_constructors_over_static_methods
static SignInFormState initial() {
return SignInFormState(
validatedEmailAddress: EmailAddress(''),
validatedPassword: Password(''),
autovalidate: false,
isSubmitting: false,
isSuccess: null,
);
}
}
Yeah I forgot to test that. I'll fix it.
But to be fair, your example should be a static const instead of a static function
Kind of, but EmailAddress cannot be const anyway as there's some validation going on inside of it. Otherwise, you're correct.
Done ๐
Most helpful comment
Done ๐