jankuss / genq

Instant Data Class Generation for Dart
MIT License
133 stars 0 forks source link

Is it possible to generate class methods? #30

Open guilhermearaujo opened 4 months ago

guilhermearaujo commented 4 months ago

Today we use freezed to generate some class methods like this:

import 'package:freezed_annotation/freezed_annotation.dart';

part 'something_state.freezed.dart';

@freezed
class SomethingState with _$SomethingState {
  const factory SomethingState.initial() = _Initial;
  const factory SomethingState.loading() = _Loading;
  const factory SomethingState.invalid(String errorMessage) = _Invalid;
}
and freezed outputs: ```dart // coverage:ignore-file // GENERATED CODE - DO NOT MODIFY BY HAND // ignore_for_file: type=lint // ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark part of 'something_state.dart'; // ************************************************************************** // FreezedGenerator // ************************************************************************** T _$identity(T value) => value; final _privateConstructorUsedError = UnsupportedError( 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); /// @nodoc mixin _$SomethingState { @optionalTypeArgs TResult when({ required TResult Function() initial, required TResult Function() loading, required TResult Function(String errorMessage) invalid, }) => throw _privateConstructorUsedError; @optionalTypeArgs TResult? whenOrNull({ TResult? Function()? initial, TResult? Function()? loading, TResult? Function(String errorMessage)? invalid, }) => throw _privateConstructorUsedError; @optionalTypeArgs TResult maybeWhen({ TResult Function()? initial, TResult Function()? loading, TResult Function(String errorMessage)? invalid, required TResult orElse(), }) => throw _privateConstructorUsedError; @optionalTypeArgs TResult map({ required TResult Function(_Initial value) initial, required TResult Function(_Loading value) loading, required TResult Function(_Invalid value) invalid, }) => throw _privateConstructorUsedError; @optionalTypeArgs TResult? mapOrNull({ TResult? Function(_Initial value)? initial, TResult? Function(_Loading value)? loading, TResult? Function(_Invalid value)? invalid, }) => throw _privateConstructorUsedError; @optionalTypeArgs TResult maybeMap({ TResult Function(_Initial value)? initial, TResult Function(_Loading value)? loading, TResult Function(_Invalid value)? invalid, required TResult orElse(), }) => throw _privateConstructorUsedError; } /// @nodoc abstract class $SomethingStateCopyWith<$Res> { factory $SomethingStateCopyWith( SomethingState value, $Res Function(SomethingState) then) = _$SomethingStateCopyWithImpl<$Res, SomethingState>; } /// @nodoc class _$SomethingStateCopyWithImpl<$Res, $Val extends SomethingState> implements $SomethingStateCopyWith<$Res> { _$SomethingStateCopyWithImpl(this._value, this._then); // ignore: unused_field final $Val _value; // ignore: unused_field final $Res Function($Val) _then; } /// @nodoc abstract class _$$InitialImplCopyWith<$Res> { factory _$$InitialImplCopyWith( _$InitialImpl value, $Res Function(_$InitialImpl) then) = __$$InitialImplCopyWithImpl<$Res>; } /// @nodoc class __$$InitialImplCopyWithImpl<$Res> extends _$SomethingStateCopyWithImpl<$Res, _$InitialImpl> implements _$$InitialImplCopyWith<$Res> { __$$InitialImplCopyWithImpl( _$InitialImpl _value, $Res Function(_$InitialImpl) _then) : super(_value, _then); } /// @nodoc class _$InitialImpl implements _Initial { const _$InitialImpl(); @override String toString() { return 'SomethingState.initial()'; } @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is _$InitialImpl); } @override int get hashCode => runtimeType.hashCode; @override @optionalTypeArgs TResult when({ required TResult Function() initial, required TResult Function() loading, required TResult Function(String errorMessage) invalid, }) { return initial(); } @override @optionalTypeArgs TResult? whenOrNull({ TResult? Function()? initial, TResult? Function()? loading, TResult? Function(String errorMessage)? invalid, }) { return initial?.call(); } @override @optionalTypeArgs TResult maybeWhen({ TResult Function()? initial, TResult Function()? loading, TResult Function(String errorMessage)? invalid, required TResult orElse(), }) { if (initial != null) { return initial(); } return orElse(); } @override @optionalTypeArgs TResult map({ required TResult Function(_Initial value) initial, required TResult Function(_Loading value) loading, required TResult Function(_Invalid value) invalid, }) { return initial(this); } @override @optionalTypeArgs TResult? mapOrNull({ TResult? Function(_Initial value)? initial, TResult? Function(_Loading value)? loading, TResult? Function(_Invalid value)? invalid, }) { return initial?.call(this); } @override @optionalTypeArgs TResult maybeMap({ TResult Function(_Initial value)? initial, TResult Function(_Loading value)? loading, TResult Function(_Invalid value)? invalid, required TResult orElse(), }) { if (initial != null) { return initial(this); } return orElse(); } } abstract class _Initial implements SomethingState { const factory _Initial() = _$InitialImpl; } /// @nodoc abstract class _$$LoadingImplCopyWith<$Res> { factory _$$LoadingImplCopyWith( _$LoadingImpl value, $Res Function(_$LoadingImpl) then) = __$$LoadingImplCopyWithImpl<$Res>; } /// @nodoc class __$$LoadingImplCopyWithImpl<$Res> extends _$SomethingStateCopyWithImpl<$Res, _$LoadingImpl> implements _$$LoadingImplCopyWith<$Res> { __$$LoadingImplCopyWithImpl( _$LoadingImpl _value, $Res Function(_$LoadingImpl) _then) : super(_value, _then); } /// @nodoc class _$LoadingImpl implements _Loading { const _$LoadingImpl(); @override String toString() { return 'SomethingState.loading()'; } @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is _$LoadingImpl); } @override int get hashCode => runtimeType.hashCode; @override @optionalTypeArgs TResult when({ required TResult Function() initial, required TResult Function() loading, required TResult Function(String errorMessage) invalid, }) { return loading(); } @override @optionalTypeArgs TResult? whenOrNull({ TResult? Function()? initial, TResult? Function()? loading, TResult? Function(String errorMessage)? invalid, }) { return loading?.call(); } @override @optionalTypeArgs TResult maybeWhen({ TResult Function()? initial, TResult Function()? loading, TResult Function(String errorMessage)? invalid, required TResult orElse(), }) { if (loading != null) { return loading(); } return orElse(); } @override @optionalTypeArgs TResult map({ required TResult Function(_Initial value) initial, required TResult Function(_Loading value) loading, required TResult Function(_Invalid value) invalid, }) { return loading(this); } @override @optionalTypeArgs TResult? mapOrNull({ TResult? Function(_Initial value)? initial, TResult? Function(_Loading value)? loading, TResult? Function(_Invalid value)? invalid, }) { return loading?.call(this); } @override @optionalTypeArgs TResult maybeMap({ TResult Function(_Initial value)? initial, TResult Function(_Loading value)? loading, TResult Function(_Invalid value)? invalid, required TResult orElse(), }) { if (loading != null) { return loading(this); } return orElse(); } } abstract class _Loading implements SomethingState { const factory _Loading() = _$LoadingImpl; } /// @nodoc abstract class _$$InvalidImplCopyWith<$Res> { factory _$$InvalidImplCopyWith( _$InvalidImpl value, $Res Function(_$InvalidImpl) then) = __$$InvalidImplCopyWithImpl<$Res>; @useResult $Res call({String errorMessage}); } /// @nodoc class __$$InvalidImplCopyWithImpl<$Res> extends _$SomethingStateCopyWithImpl<$Res, _$InvalidImpl> implements _$$InvalidImplCopyWith<$Res> { __$$InvalidImplCopyWithImpl( _$InvalidImpl _value, $Res Function(_$InvalidImpl) _then) : super(_value, _then); @pragma('vm:prefer-inline') @override $Res call({ Object? errorMessage = null, }) { return _then(_$InvalidImpl( null == errorMessage ? _value.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable as String, )); } } /// @nodoc class _$InvalidImpl implements _Invalid { const _$InvalidImpl(this.errorMessage); @override final String errorMessage; @override String toString() { return 'SomethingState.invalid(errorMessage: $errorMessage)'; } @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is _$InvalidImpl && (identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); } @override int get hashCode => Object.hash(runtimeType, errorMessage); @JsonKey(ignore: true) @override @pragma('vm:prefer-inline') _$$InvalidImplCopyWith<_$InvalidImpl> get copyWith => __$$InvalidImplCopyWithImpl<_$InvalidImpl>(this, _$identity); @override @optionalTypeArgs TResult when({ required TResult Function() initial, required TResult Function() loading, required TResult Function(String errorMessage) invalid, }) { return invalid(errorMessage); } @override @optionalTypeArgs TResult? whenOrNull({ TResult? Function()? initial, TResult? Function()? loading, TResult? Function(String errorMessage)? invalid, }) { return invalid?.call(errorMessage); } @override @optionalTypeArgs TResult maybeWhen({ TResult Function()? initial, TResult Function()? loading, TResult Function(String errorMessage)? invalid, required TResult orElse(), }) { if (invalid != null) { return invalid(errorMessage); } return orElse(); } @override @optionalTypeArgs TResult map({ required TResult Function(_Initial value) initial, required TResult Function(_Loading value) loading, required TResult Function(_Invalid value) invalid, }) { return invalid(this); } @override @optionalTypeArgs TResult? mapOrNull({ TResult? Function(_Initial value)? initial, TResult? Function(_Loading value)? loading, TResult? Function(_Invalid value)? invalid, }) { return invalid?.call(this); } @override @optionalTypeArgs TResult maybeMap({ TResult Function(_Initial value)? initial, TResult Function(_Loading value)? loading, TResult Function(_Invalid value)? invalid, required TResult orElse(), }) { if (invalid != null) { return invalid(this); } return orElse(); } } abstract class _Invalid implements SomethingState { const factory _Invalid(final String errorMessage) = _$InvalidImpl; String get errorMessage; @JsonKey(ignore: true) _$$InvalidImplCopyWith<_$InvalidImpl> get copyWith => throw _privateConstructorUsedError; } ```

Is it possible to use genq to do the same?

jankuss commented 4 months ago

It is not possible as of now.

I'm a bit torn on this feature - I think the syntactic sugar would be a very nice addition, as the alternative for sealed classes is quite verbose.

I'm not sure though if we should generate the map, maybeMap etc. As of Dart 3.0, the necessity for these methods is questionable, as pattern matching & sealed classes exists now. If we include it, it will definetly be an opt in feature.

BWhiteApps commented 4 months ago

I personally don't see a need for map, maybeMap, maybeWhen... freezed is already going away from those. But being able to generate sealed classes and unions with the freezed syntax would be huge.

guilhermearaujo commented 3 months ago

That example is from an older project I started working on recently, I honestly don't even know if all that generated code is really necessary or if just a piece of it should be enough.

Interesting, I was not familiar with sealed classes. That may actually work, but I need to test it.