GithubHelp home page GithubHelp logo

xsahil03x / super_enum Goto Github PK

View Code? Open in Web Editor NEW
118.0 7.0 14.0 209 KB

Create super-powered dart enums similar to sealed classes in Kotlin

Home Page: https://pub.dev/packages/super_enum

License: MIT License

Kotlin 0.55% Swift 0.66% Objective-C 0.06% Dart 97.06% HTML 0.29% Shell 1.38%
sealed enum flutter flutter-plugin dart2 kotlin android adts code-generator build-runner dart-build-system dart annotation hacktoberfest

super_enum's Introduction

Deprecated

Super Enum is now deprecated in favor of Dart's Patterns. Read more here.

Dart CI codecov Version Version

Super-powered enums similar to sealed classes in Kotlin

Migration From v0.4.0 to v0.6.0

  • PartFile naming has been changed.

    • Should use filename.super.dart instead of filename.g.dart
  • All asyncWhenX methods have been removed as they were redundant.

    • Use regular whenX methods with async callback functions instead of them
    • asyncWhen -> when
    • asyncWhenOrElse -> whenOrElse

Migration From v0.3.0 to v0.4.0

  • DataField signature has been changed.
    • DataField(String,Type) should be replaced with DataField<Type>(String)
    • Should specify generic data types (eg: List, Map) in the following manner- DataField<List<Foo>>('foos')

Installation

Add the following to you pubspec.yaml and replace [version] with the latest version:

dependencies:
  super_enum: ^[version]

dev_dependencies:
  super_enum_generator: ^[version]
  build_runner: ^1.7.1 // Any latest version which works with your current Dart or Flutter SDK

Example

A Super Enum can be easily generated by annotating a private enum with @superEnum

import 'package:super_enum/super_enum.dart';

part "result.super.dart";

/// Generic Result Union
@superEnum
enum _Result {
  /// Success case Of the Result
  @generic
  @Data(fields: [
    DataField<Generic>('data'),
    DataField<String>('message'),
  ])
  Success,

  /// Error case Of the Result
  @object
  Error,
}

@Data() marks an enum value to be treated as a Data class.

  • One should supply a list of possible fields inside the annotation.
  • If you don't want to add fields, use @object annotation instead.
  • Fields are supplied in the form of DataField objects.
  • Each DataField must contain the name and the type of the field.
  • If you want some DataField to be optional, set required param to false.
  • If the field type needs to be generic use Generic type and annotate the enum value with @generic annotation.

@object marks an enum value to be treated as an object.

The docComments will also get copy-pasted in the generated classes.

NOTE: If you want to use existing classes directly without having them auto-generated and wrapped use @UseClass().

Run the build_runner command to generate the filename.super.dart part file.

 # Dart SDK: $pub run build_runner build
 # Flutter SDK: $flutter pub run build_runner build

Generated file

/// Generic Result Union
@immutable
abstract class Result<T> extends Equatable {
  const Result(this._type);

  /// Success case Of the Result
  factory Result.success({@required T data, @required String message}) =
      Success<T>.create;

  /// Error case Of the Result
  factory Result.error() = Error<T>.create;

  final _Result _type;

  /// The [when] method is the equivalent to pattern matching.
  /// Its prototype depends on the _Result [_type]s defined.
  R when<R extends Object>(
      {@required R Function(Success<T>) success,
      @required R Function() error}) {
    assert(() {
      if (success == null || error == null) {
        throw 'check for all possible cases';
      }
      return true;
    }());
    switch (this._type) {
      case _Result.Success:
        return success(this as Success);
      case _Result.Error:
        return error();
    }
  }

  /// The [whenOrElse] method is equivalent to [when], but doesn't require
  /// all callbacks to be specified.
  ///
  /// On the other hand, it adds an extra orElse required parameter,
  /// for fallback behavior.
  R whenOrElse<R extends Object>(
      {R Function(Success<T>) success,
      R Function() error,
      @required R Function(Result<T>) orElse}) {
    assert(() {
      if (orElse == null) {
        throw 'Missing orElse case';
      }
      return true;
    }());
    switch (this._type) {
      case _Result.Success:
        if (success == null) break;
        return success(this as Success);
      case _Result.Error:
        if (error == null) break;
        return error();
    }
    return orElse(this);
  }

  /// The [whenPartial] method is equivalent to [whenOrElse],
  /// but non-exhaustive.
  void whenPartial({void Function(Success<T>) success, void Function() error}) {
    assert(() {
      if (success == null && error == null) {
        throw 'provide at least one branch';
      }
      return true;
    }());
    switch (this._type) {
      case _Result.Success:
        if (success == null) break;
        return success(this as Success);
      case _Result.Error:
        if (error == null) break;
        return error();
    }
  }

  @override
  List<Object> get props => const [];
}

/// Success case Of the Result
@immutable
abstract class Success<T> extends Result<T> {
  const Success({@required this.data, @required this.message})
      : super(_Result.Success);

  /// Success case Of the Result
  factory Success.create({@required T data, @required String message}) =
      _SuccessImpl<T>;

  final T data;

  final String message;

  /// Creates a copy of this Success but with the given fields
  /// replaced with the new values.
  Success<T> copyWith({T data, String message});
}

@immutable
class _SuccessImpl<T> extends Success<T> {
  const _SuccessImpl({@required this.data, @required this.message})
      : super(data: data, message: message);

  @override
  final T data;

  @override
  final String message;

  @override
  _SuccessImpl<T> copyWith(
          {Object data = superEnum, Object message = superEnum}) =>
      _SuccessImpl(
        data: data == superEnum ? this.data : data as T,
        message: message == superEnum ? this.message : message as String,
      );
  @override
  String toString() => 'Success(data: ${this.data}, message: ${this.message})';
  @override
  List<Object> get props => [data, message];
}

/// Error case Of the Result
@immutable
abstract class Error<T> extends Result<T> {
  const Error() : super(_Result.Error);

  /// Error case Of the Result
  factory Error.create() = _ErrorImpl<T>;
}

@immutable
class _ErrorImpl<T> extends Error<T> {
  const _ErrorImpl() : super();

  @override
  String toString() => 'Error()';
}

Usage

Below is just one of the use-case of Super Enums. It can be used wherever you want to manage state.

// Creating an StreamController of type Result<int>
final _resultController = StreamController<Result<int>>();

// Adding a success state to the stream controller
_resultController.add(Result.success(
              data: 333,
              message: 'Success',
            ));

// Adding an error state to the stream controller
_resultController.add(Result.error());

// Listening to all the possible Result states
_resultController.stream.listen((result) {
      result.when(
        onSuccess: (data) => print(data.message), // Success
        onError: () => print('Error Occurred'), // Error Occurred
      );
    });

UseClass Example

A sample UseClass() example.

class MySuccess {
  MySuccess(this.fieldA);

  final String fieldA;
}

class MyError {
  MyError(this.fieldA, this.fieldB);

  final String fieldA;
  final int fieldB;
}

@superEnum
enum _ResultUnion {
  @UseClass(MySuccess)
  Success,

  @UseClass(MyError)
  Error,
}

Getting Started

This project is a starting point for a Dart package, a library module containing code that can be shared easily across multiple Flutter or Dart projects.

For help getting started with Flutter, view our online documentation, which offers tutorials, samples, guidance on mobile development, and a full API reference.

super_enum's People

Contributors

astralstriker avatar passsy avatar xsahil03x avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

super_enum's Issues

Create a DataField with specific type of generic type

I have trouble using a specific type of generic type in DataField. Let's take List<int> for example.

@superEnum
class _Event {
    @Data(fields: [DataField('foo', List<int>)])
    Foo,
}

The above code won't compile, with following error message:

  error • In constant expressions, operands of this operator must be of type 'num' •
  error • The operator '<' isn't defined for the class 'Type' •
  error • A comparison expression can't be an operand of another comparison expression •
  error • Arguments of a constant creation must be constant expressions •
...

Seems like dart compiler takes <> as two separate part. With some hard trying, I changed the code to

@superEnum
enum _Event {
  @Data(fields: [DataField('foo', <int>[].runtimeType)])
  Foo,
}

That was much better, with the following error message though:

  error • Arguments of a constant creation must be constant expressions •
  error • The values in a const list literal must be constants •

BTW, the following code do compile without using super_enum:

class Data {
  final List<DataField> fields;

  const Data({this.fields});
}

class DataField {
  final String name;
  final Type type;

  const DataField(this.name, this.type);
}

void main() {
  print(Data(fields: [DataField('scanResult', <String>[].runtimeType)]));
}

Can you please make a release?

Thanks for this great work. I'm looking forward to using the required property on DataFields, but I see that's not released on DartPub yet.

Enum as data field in another enum

I'm trying to do this:

@superEnum
enum _SelectedContact {
  @Data(fields: [DataField('user', User)])
  InternalUser,

  @Data(fields: [DataField('contact', Contact)])
  AddressBook,
}

Where Contact is another super enum defined in a different file. When building this, the generated file only contains the following comment, and no code:

/*FormatException: Not an instance of Type.*/

Is reusing enums in other enums not allowed?

Optional fields

Currently the generator adds "@required" to all DataField objects.

We should have a parameter to indicate if this is really required parameter, like:

    DataField<String>("errorMessage", required: false),

This way, the library will be 100% ready for the NNBD next release of Dart language:
dart-lang/language#110

Why renaming enum fields?

Why does the generator rename enum fields? For example, if I define the following enum

@superEnum
enum _Result {
  @object
  Success,

  @object
  Error
}

...Success becomes success and Error becomes error. Is there a reason for this? I think it would be better to keep the original names to avoid confusion.

WhenPartial breaks when updraging from 0.3.0 to 0.4.2

so i'm getting these weird errors because i use whenPartial in my bloc's mapEventToState.

yield* event.whenPartial(
  someEvent: (_) async* {
     // some logic
     return State.someState();
  }
);

not sure why it's not working anymore

How can I convert a String to a Enum Type

I would like to generate a super enum Type from a String.
I would expect something like:

MyEnum enum = MyEnum.fromString(String Name);

Actually, support for the roundtrip String conversion should be supported from and to String.

Version compatibility issues (`analyzer`, `super_enum`, `json_serializable`)

I'm running on a project that uses super_enum, along with other codegen packages.

Relevant portion of my pubspec.yaml:

environment:
  sdk: ">=2.5.0 <3.0.0"

dependencies:
  flutter:
    sdk: flutter  
  json_annotation: any
  provider: any
  http: any
  logger: any
  intl: any
  super_enum: any
  cupertino_icons: ^0.1.2

dev_dependencies:
  flutter_test:
    sdk: flutter
  build_runner: any
  json_serializable: any
  super_enum_generator: any

Output of flutter packages get:

[weather_app_flutter] flutter packages get
Running "flutter pub get" in weather_app_flutter...             
The current Dart SDK version is 2.5.0.



Because json_serializable >=2.0.1 <2.0.2 depends on analyzer >=0.32.2 <0.35.0 and json_serializable >=1.5.1 <2.0.1 depends on analyzer >=0.32.2 <0.34.0, json_serializable >=1.5.1 <2.0.2 requires analyzer >=0.32.2 <0.35.0.

And because json_serializable >=1.0.0 <1.5.1 depends on analyzer ^0.32.2 and json_serializable >=0.5.8+1 <1.4.0 depends on build ^0.12.6, json_serializable >=0.5.8+1 <2.0.2 requires analyzer >=0.32.2 <0.35.0 or build ^0.12.6.

And because every version of super_enum_generator depends on build ^1.2.1 and json_serializable >=3.2.1 <3.2.3 depends on analyzer >=0.33.3 <0.39.0, if super_enum_generator any and json_serializable >=0.5.8+1 <2.0.2-∞ or >=3.2.1 <3.2.3-∞ then analyzer >=0.32.2 <0.39.0.

And because json_serializable >=3.1.0 <3.2.1 depends on analyzer >=0.33.3 <0.38.0 and json_serializable >=2.1.1 <3.1.0 depends on analyzer >=0.33.3 <0.37.0, if super_enum_generator any and json_serializable >=0.5.8+1 <2.0.2-∞ or >=2.1.1 <3.2.3-∞ then analyzer >=0.32.2 <0.39.0.

And because json_serializable >=2.0.2 <2.1.1 depends on analyzer >=0.33.3 <0.36.0 and json_serializable <=0.5.8 requires SDK version >=1.22.1 <2.0.0-∞, if super_enum_generator any and json_serializable <3.2.3 then analyzer >=0.32.2 <0.39.0.

And because no versions of json_serializable match >3.2.3 and every version of super_enum_generator depends on analyzer ^0.39.1, super_enum_generator is incompatible with json_serializable.

So, because weather_app_flutter depends on both json_serializable any and super_enum_generator any, version solving failed.
pub get failed (1)
exit code 1

Output of flutter doctor:

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, v1.9.1+hotfix.4, on Mac OS X 10.14.4 18E226, locale en-GB)
 
[!] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
    ! Some Android licenses not accepted.  To resolve this, run: flutter doctor --android-licenses
[✓] Xcode - develop for iOS and macOS (Xcode 11.1)
[✓] Android Studio (version 3.5)
[✓] VS Code (version 1.40.2)
[✓] Connected device (1 available)

! Doctor found issues in 1 category.

Any guidance on how to solve the incompatibilities issues?

DataFields with a name including 'T' break code generation

Latest update (0.4.0, released several hours ago) has a very bad bug.

Any data field with a capital 'T' in the name appears to break code generation, yielding the standard comment header and the single line:
/*State must be annotated with @generic*/

To reproduce:

The following works properly -- exactly as you would expect:

import 'package:super_enum/super_enum.dart';

part 'super_enum_sample.g.dart';

class SomeVee {
  String data;
}

@superEnum
enum _StatesGood {
  @Data(fields: [
    DataField<SomeVee>('fieldName'),
  ])
  State
}

The following fails, and is the same other than the type of field, now being SomeTee instead of SomeVee (T in the name vs no T in the name).

import 'package:super_enum/super_enum.dart';

part 'super_enum_sample.g.dart';

class SomeTee {
  String data;
}

@superEnum
enum _StatesBad {
  @Data(fields: [
    DataField<SomeTee>('fieldName'),
  ])
  State
}

The problem stems from line 377 of class_generator.dart

    if (_classFields
        .any((e) => type_processor.dataFieldType(e).contains('T'))) {
      if (!isGeneric) {
        throw InvalidGenerationSourceError(
            '${field.name} must be annotated with @generic');
      }
    }

(Hairy debug session to find this... 'my T' was in a complex type using built values and I had a lot of suspicions to track down before I got to "does it include a capital T' ;-)

Love all the new features, thanks for all your hard work!

Unhandled Exception when using Generics

When using generics, I am getting a type casting exceptions given the following example

@superEnum
enum _ModelState {
  @generic
  @Data(fields: [DataField('data', Generic)])
  Success,

  @object
  Error,

  @object
  Loading,

  @object
  Empty,
}

//Somewhere else in code
Stream<ModelState<int>> getSomething() {
  return Stream.fromFuture(Future.value(1))
      .publishReplay(maxSize: 1)
      .refCount()
      .map((data) => ModelState.loading());
}

The error:

Unhandled Exception: type 'Loading<dynamic>' is not a subtype of type 'Loading<int>'

Environment:

Flutter 1.12.13+hotfix.6
Framework • revision 18cd7a3601 (7 days ago) • 2019-12-11 06:35:39 -0800
Engine • revision 2994f7e1e6
Tools • Dart 2.7.0

Dependencies:

dependencies:
  super_enum: ^0.2.0

dev_dependencies:
  super_enum_generator: ^0.2.0+1
  build_runner: ^1.7.1

@UseClass generating Error

Hey guys,

I just ran into another code generation error.
When using the same Class in @useClass() the build_runner generates the wrapper twice.

For example this:

@superEnum
enum _RevenueState {
  @object
  Empty,
  @UseClass(RevenueLoaded)
  YearLoaded,
  @UseClass(RevenueLoaded)
  MonthLoaded,
  @Data(fields: [DataField<String>('message')])
  Error,
}
class RevenueLoaded {
  final Revenue revenue;
  const RevenueLoaded({
    @required this.revenue,
  });
}

Generates the RevenueLoadedwWrapper twice

Have a nice day !

VS Studio can not find the build task

VS Studio for some reason is not detecting the build task runner. Could be something wrong with the library or my version of VS Studio(I updated to the latest version)?

Ability to specify generated class names.

Would like the ability to specify the name to use when computing sealed class. This would remove collisions when creating similarly named classes. See the following example taken from sealed_unions_generator

@Seal('WeatherState')
abstract class WeatherModel {
  @Sealed()
  void initial();
  @Sealed()
  void loading();
  @Sealed()
  void loaded(int temperature);
}

// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'weather_model.dart';

// **************************************************************************
// SealedUnionsGenerator
// **************************************************************************

class WeatherState extends Union3Impl<WeatherStateInitial, WeatherStateLoading,
    WeatherStateLoaded> {
  static final Triplet<WeatherStateInitial, WeatherStateLoading,
          WeatherStateLoaded> _factory =
      const Triplet<WeatherStateInitial, WeatherStateLoading,
          WeatherStateLoaded>();

  WeatherState._(
      Union3<WeatherStateInitial, WeatherStateLoading, WeatherStateLoaded>
          union)
      : super(union);

  factory WeatherState.initial() =>
      WeatherState._(_factory.first(WeatherStateInitial()));

  factory WeatherState.loading() =>
      WeatherState._(_factory.second(WeatherStateLoading()));

  factory WeatherState.loaded(int temperature) =>
      WeatherState._(_factory.third(WeatherStateLoaded(temperature)));
}

class WeatherStateInitial {
  WeatherStateInitial();
}

class WeatherStateLoading {
  WeatherStateLoading();
}

class WeatherStateLoaded {
  final int temperature;

  WeatherStateLoaded(this.temperature);
}

use const constructor

Hey,

I really love your package ! Thanks a lot for putting so much effort into it !

I only have a super small suggestion for improvement:
You have const constructors but you don't use them in the factorys (for @object's).
For example:

@immutable
class Empty extends ExampleState {
  const Empty._() : super(ExampleState .Empty);

  factory Empty() {
    _instance ??= Empty._(); // -> _instance ??= const Empty._()
    return _instance;
  }

  static Empty _instance;
}

There is no problem in that, but my linting settings mark this as an warning :)

Add factory constructors for derived classes to mimic enums

eg :

abstract class LoginResponse {
  // Not necessary when case classes are public, 
  // but I usually put factories and constants on the base class.
  
  factory LoginResponse.success(authToken) = LoginSuccess;
  static const invalidCredentials = const InvalidLoginCredentials();
  static const noNetwork = const NoNetworkForLogin();
  factory LoginResponse.unexpectedException(Exception exception) = UnexpectedLoginException;
}

Linter Warnings: DO use curly braces for all flow control structures

The generated code sometimes provokes the analyzer (under pedantic settings) to issue the warning: "DO use curly braces for all flow control structures".

It can be fixed either by generating braces when you have an if with a single line body (these single line bodies currently appear when you throw).

Or faster, you could take the approach that built_value does and just suppress warnings at the file level by generating the following line at the bottom of each .g.dart file:

// ignore_for_file: curly_braces_in_flow_control_structures

Details:
It happens sometimes where the generated code includes throws clauses that aren't surrounded by braces, e.g.:

//ignore: missing_return
  FutureOr<R> when<R>(
      {@required FutureOr<R> Function(UpdateFilter) updateFilter,
      @required FutureOr<R> Function(UpdateFeatures) updateFeatures}) {
    assert(() {
      if (updateFilter == null || updateFeatures == null)
        throw 'check for all possible cases';
      return true;
    }());
    ....

Here, it happens because throw 'check for all possible cases'; is formatted alone on a line.

It only causes linter warnings sometimes, because oddly, if the formatter keeps the throw on the same line as the if or an || as shown below, there is no linter warning.

      if (updateFilter == null || ... || ...
          || updateFeatures == null) throw 'check for all possible cases';

@object enum values generated as: List get props =>null

A consequence of generating List get props => null; is that (with the current Equatable package: equatable 1.0.1), calling hashCode on a generated @object throws NoSuchMethodError.

To reproduce:

import 'package:super_enum/super_enum.dart';
part "my_state.g.dart";

@superEnum
enum _MyState {
  @object
  Success,
  @object
  Error,
}
  • flutter pub run build_runner build
...
  // any running code
  var success = MyState.success();
  success.hashCode;

BOOM!
NoSuchMethodError: The method 'fold' was called on null.
Receiver: null
Tried calling: fold(0, Closure: (int, dynamic) => i

I got bit pretty hard by this tonight, in test code checking emitsInOrder on a StreamController, but hashCode is called in plenty of situations.

The bug arises because the generator produces

List get props => null;

Instead the generator needs to produce:

List get props => const [];

I see you have an outstanding pull request on an unrelated issue that silently fixes this: #23

(small nit: that fix assigns props [] and not const []).

Not knowing the timeline for that PR, I wanted to raise this as a separate (and urgent) issue.

Add more whenX clauses

For example if you have enums like [Success, Error] and you only want to do something if it is an [Error], you have to use when and leave the success empty which can get ugly when there are many enums.
I think it would be good to generate functions like whenSuccess, whenError to deal with that, instead of having to import generated files.

analyzer version compatibility issues when used with built_value_generator

After upgrading packages, built_value_generator ^7.0.8 and super_enum_generator ^0.3.0 are conflicting on analyzer version:

Because super_enum_generator >=0.2.0+1 depends on analyzer >=0.37.1 <0.39.1 and
built_value_generator >=7.0.8 depends on analyzer ^0.39.3, super_enum_generator >=0.2.0+1 
is incompatible with built_value_generator >=7.0.8.

pub upgrade failed (1; So, because ___ depends on both built_value_generator ^7.0.8 
and super_enum_generator ^0.3.0, version solving failed.)

Enums with Value

the "extension"s has been added since Dart 2.6 so it would be great if we have Enums with default values. for example:

enum Country {
  UnitedArabEmirates,
  Argentina,
  Austria,
  Australia,
  Belgium,
  Bulgaria,
  Brazil,
}

extension CountryExtension on Country {
  String getValue() {
    switch (this) {
      case Country.UnitedArabEmirates:
        return "ae";
      case Country.Argentina:
        return "ar";
      case Country.Austria:
        return "at";
      case Country.Australia:
        return "au";
      case Country.Belgium:
        return "be";
      case Country.Bulgaria:
        return "bg";
      case Country.Brazil:
        return "br";
      default:
        return "COUNTRY NOT FOUND";
    }
  }
}

main(){
	var au = Country.Australia;
	print('the country code of Australia is ${au}');
}

as I represented, we can do it our selves but it would be nice if we can define that like this:

@superEnum
enum Country {
  @object(value: "ae")
  UnitedArabEmirates,
  @object(value: "ar")
  Argentina,
  @object(value: "at")
  Austria,
  @object(value: "au")
  Australia,
  @object(value: "be")
  Belgium,
  @object(value: "bg")
  Bulgaria,
  @object(value: "br")
  Brazil,
}

main(){
	var au = Country.Australia;
	print('the country code of Australia is ${au.value}');
}

Thnaks,

whenXXX methods return FutureOr

The update to 0.3 modified when() and its new sibling methods to return FutureOr.

The Effective Dart advice is to use FutureOr as a parameter, but not to return it. They advise instead to just return Future, as it will be more clear to users (who need to await the result either way).

https://dart.dev/guides/language/effective-dart/design#avoid-using-futureort-as-a-return-type

So the generator would produce

  Future<R> when<R>(
      {@required FutureOr<R> Function(Success) success,
      @required FutureOr<R> Function(Error) error}) async {
}

with Future / async instead of FutureOr

  FutureOr<R> when<R>(
      {@required FutureOr<R> Function(Success) success,
      @required FutureOr<R> Function(Error) error}) {
}

(That may also save you from having to document how to use the return types, as many of your users won't have experience dealing with a FutureOr return.)

Thanks for the new whenXXX methods, and for fixing the generation of null props for @objects!

Copy comments to generated file

It would be very helpful when comments on the enum values would also be rendered to the generated source

@superEnum
enum _Result {
  /// Comment #1
  @generic
  @Data(fields: [
    DataField('data', Generic),
    DataField('message', String),
  ])
  Success,

  @object
  Error,
}
abstract class Result<T> extends Equatable {
  const Result(this._type);

   /// Comment #1
  factory Result.success({@required T data, @required String message}) =
      Success<T>;

  // ...
}

/// Comment #1
class Success<T> extends Result<T> {
  /// Comment #1
  const Success({@required this.data, @required this.message})
      : super(_Result.Success);
  

Generics support?

This is more of a question than anything else.

It would be really cool if we could define generic types like so:

@superEnum
enum _Result<T> {
  @object
  NotLoaded,

  @object
  Loading,

  @object
  Error,

  @Data(fields: [
    DataField('data', T),
  ])
  Loaded,
}

This would be extremely useful as we could use the same _Result type to handle multiple model classes.

However I assume this can't be done as Dart doesn't support enums with generics?

Would this be achievable by using standard classes?

Great library btw!

Linter Error with super_enum_generator 0.4.2

I do get a linter error 'return_of_invalid_type' in the generated R when<R>, R whenOrElse<R> etc. methods. you are returning a FutureOr and not R.
(Flutter (Channel beta, v1.14.6, on Mac OS X 10.15.3 19D76, locale de-DE))

Use external class directly without wrapping

Sometimes I share classes between multiple superEnums. This is currently only possible by wrapping them each time I use them.

class ApiError { /*...*/ }

@superEnum
enum _ResultA {
  @Data(fields: [
    DataField('error', ApiError),
  ])
  Error,
}

@superEnum
enum _ResultB {
  @Data(fields: [
    DataField('error', ApiError),
  ])
  Error,
}

I'd prefer to use some classes directly without having them auto-generated and wrapped.

class ApiError { /*...*/ }

@superEnum
enum _ResultA {
  @UserClass(ApiError)
  Error,
}

@superEnum
enum _ResultB {
  @UserClass(ApiError)
  Error,
}

emit `when` method arguments for "empty" actions

Given I have a super_enum definition like this:

@superEnum
enum _ContactUsAction {
  CallPhone,
  StartLiveChat
}

Then the generated when method looks like this:

  R when<R>(
      {@required
          FutureOr<R> Function(CallPhone) callPhone,
      @required
          FutureOr<R> Function(StartLiveChat) startLiveChat}) {

...

could this possibly be simplified to:

  R when<R>(
      {@required
          FutureOr<R> Function() callPhone,
      @required
          FutureOr<R> Function() startLiveChat}) {

...

As from my point of view, the event has no associated values and thus does not need to be passed into the when method.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.