diff --git a/super_enum/example/main.dart b/super_enum/example/main.dart index be6baf1..cf370db 100644 --- a/super_enum/example/main.dart +++ b/super_enum/example/main.dart @@ -24,21 +24,21 @@ enum _MoviesResponse { NoNetwork, /// UnexpectedException State of the MovieResponse - @Data(fields: [DataField('exception')]) + @Data(fields: [DataField('exception')]) UnexpectedException } class MoviesFetcher { http.Client client = http.Client(); - final _baseUrl = "http://api.themoviedb.org/3/movie"; final String apiKey; - MoviesFetcher({@required this.apiKey}); + MoviesFetcher({required this.apiKey}); Future fetchMovies() async { try { - final response = await client.get('$_baseUrl/popular?api_key=$apiKey'); + final response = + await client.get(Uri(scheme: 'http', host: 'api.themoviedb.org', path: '/3/movie/popular', queryParameters: {'api_key': apiKey})); if (response.statusCode == 200) { final movies = Movies.fromJson(json.decode(response.body)); return MoviesResponse.success(movies: movies); @@ -59,13 +59,12 @@ void main() async { ); final _moviesResponse = await _moviesFetcher.fetchMovies(); - _moviesResponse.when( - success: (data) => print('Total Movies: ${data.movies.totalPages}'), - unauthorized: () => print('Invalid ApiKey'), - noNetwork: () => print( + onSuccess: (data) => print('Total Movies: ${data.movies.totalPages}'), + onUnauthorized: () => print('Invalid ApiKey'), + onNoNetwork: () => print( 'No Internet, Please check your internet connection', ), - unexpectedException: (error) => print(error.exception), + onUnexpectedException: (error) => print(error.exception), ); } diff --git a/super_enum/example/main.super.dart b/super_enum/example/main.super.dart index 9211bb8..b8f5dde 100644 --- a/super_enum/example/main.super.dart +++ b/super_enum/example/main.super.dart @@ -13,7 +13,7 @@ abstract class MoviesResponse extends Equatable { const MoviesResponse(this._type); /// Success State of the MovieResponse - factory MoviesResponse.success({@required Movies movies}) = Success.create; + factory MoviesResponse.success({required Movies movies}) = Success.create; /// Unauthorized State of the MovieResponse factory MoviesResponse.unauthorized() = Unauthorized.create; @@ -22,36 +22,27 @@ abstract class MoviesResponse extends Equatable { factory MoviesResponse.noNetwork() = NoNetwork.create; /// UnexpectedException State of the MovieResponse - factory MoviesResponse.unexpectedException({@required Exception exception}) = + factory MoviesResponse.unexpectedException({required Object exception}) = UnexpectedException.create; final _MoviesResponse _type; /// The [when] method is the equivalent to pattern matching. /// Its prototype depends on the _MoviesResponse [_type]s defined. - R when( - {@required R Function(Success) success, - @required R Function() unauthorized, - @required R Function() noNetwork, - @required R Function(UnexpectedException) unexpectedException}) { - assert(() { - if (success == null || - unauthorized == null || - noNetwork == null || - unexpectedException == null) { - throw 'check for all possible cases'; - } - return true; - }()); + R when( + {required R Function(Success) onSuccess, + required R Function() onUnauthorized, + required R Function() onNoNetwork, + required R Function(UnexpectedException) onUnexpectedException}) { switch (this._type) { case _MoviesResponse.Success: - return success(this as Success); + return onSuccess(this as Success); case _MoviesResponse.Unauthorized: - return unauthorized(); + return onUnauthorized(); case _MoviesResponse.NoNetwork: - return noNetwork(); + return onNoNetwork(); case _MoviesResponse.UnexpectedException: - return unexpectedException(this as UnexpectedException); + return onUnexpectedException(this as UnexpectedException); } } @@ -60,31 +51,25 @@ abstract class MoviesResponse extends Equatable { /// /// On the other hand, it adds an extra orElse required parameter, /// for fallback behavior. - R whenOrElse( - {R Function(Success) success, - R Function() unauthorized, - R Function() noNetwork, - R Function(UnexpectedException) unexpectedException, - @required R Function(MoviesResponse) orElse}) { - assert(() { - if (orElse == null) { - throw 'Missing orElse case'; - } - return true; - }()); + R whenOrElse( + {R Function(Success)? onSuccess, + R Function()? onUnauthorized, + R Function()? onNoNetwork, + R Function(UnexpectedException)? onUnexpectedException, + required R Function(MoviesResponse) orElse}) { switch (this._type) { case _MoviesResponse.Success: - if (success == null) break; - return success(this as Success); + if (onSuccess == null) break; + return onSuccess(this as Success); case _MoviesResponse.Unauthorized: - if (unauthorized == null) break; - return unauthorized(); + if (onUnauthorized == null) break; + return onUnauthorized(); case _MoviesResponse.NoNetwork: - if (noNetwork == null) break; - return noNetwork(); + if (onNoNetwork == null) break; + return onNoNetwork(); case _MoviesResponse.UnexpectedException: - if (unexpectedException == null) break; - return unexpectedException(this as UnexpectedException); + if (onUnexpectedException == null) break; + return onUnexpectedException(this as UnexpectedException); } return orElse(this); } @@ -92,32 +77,32 @@ abstract class MoviesResponse extends Equatable { /// The [whenPartial] method is equivalent to [whenOrElse], /// but non-exhaustive. void whenPartial( - {void Function(Success) success, - void Function() unauthorized, - void Function() noNetwork, - void Function(UnexpectedException) unexpectedException}) { + {void Function(Success)? onSuccess, + void Function()? onUnauthorized, + void Function()? onNoNetwork, + void Function(UnexpectedException)? onUnexpectedException}) { assert(() { - if (success == null && - unauthorized == null && - noNetwork == null && - unexpectedException == null) { + if (onSuccess == null && + onUnauthorized == null && + onNoNetwork == null && + onUnexpectedException == null) { throw 'provide at least one branch'; } return true; }()); switch (this._type) { case _MoviesResponse.Success: - if (success == null) break; - return success(this as Success); + if (onSuccess == null) break; + return onSuccess(this as Success); case _MoviesResponse.Unauthorized: - if (unauthorized == null) break; - return unauthorized(); + if (onUnauthorized == null) break; + return onUnauthorized(); case _MoviesResponse.NoNetwork: - if (noNetwork == null) break; - return noNetwork(); + if (onNoNetwork == null) break; + return onNoNetwork(); case _MoviesResponse.UnexpectedException: - if (unexpectedException == null) break; - return unexpectedException(this as UnexpectedException); + if (onUnexpectedException == null) break; + return onUnexpectedException(this as UnexpectedException); } } @@ -128,10 +113,10 @@ abstract class MoviesResponse extends Equatable { /// Success State of the MovieResponse @immutable abstract class Success extends MoviesResponse { - const Success({@required this.movies}) : super(_MoviesResponse.Success); + const Success({required this.movies}) : super(_MoviesResponse.Success); /// Success State of the MovieResponse - factory Success.create({@required Movies movies}) = _SuccessImpl; + factory Success.create({required Movies movies}) = _SuccessImpl; final Movies movies; @@ -142,7 +127,7 @@ abstract class Success extends MoviesResponse { @immutable class _SuccessImpl extends Success { - const _SuccessImpl({@required this.movies}) : super(movies: movies); + const _SuccessImpl({required this.movies}) : super(movies: movies); @override final Movies movies; @@ -194,14 +179,14 @@ class _NoNetworkImpl extends NoNetwork { /// UnexpectedException State of the MovieResponse @immutable abstract class UnexpectedException extends MoviesResponse { - const UnexpectedException({@required this.exception}) + const UnexpectedException({required this.exception}) : super(_MoviesResponse.UnexpectedException); /// UnexpectedException State of the MovieResponse - factory UnexpectedException.create({@required Exception exception}) = + factory UnexpectedException.create({required Object exception}) = _UnexpectedExceptionImpl; - final Exception exception; + final Object exception; /// Creates a copy of this UnexpectedException but with the given fields /// replaced with the new values. @@ -210,11 +195,11 @@ abstract class UnexpectedException extends MoviesResponse { @immutable class _UnexpectedExceptionImpl extends UnexpectedException { - const _UnexpectedExceptionImpl({@required this.exception}) + const _UnexpectedExceptionImpl({required this.exception}) : super(exception: exception); @override - final Exception exception; + final Object exception; @override _UnexpectedExceptionImpl copyWith({Object exception = superEnum}) => diff --git a/super_enum/example/movies.dart b/super_enum/example/movies.dart index f3f43e6..29e2e46 100644 --- a/super_enum/example/movies.dart +++ b/super_enum/example/movies.dart @@ -4,17 +4,17 @@ class Movies extends Equatable { final int page; final int totalResults; final int totalPages; - final List results; + final List? results; - const Movies({this.page, this.totalResults, this.totalPages, this.results}); + const Movies({required this.page, required this.totalResults, required this.totalPages, this.results}); factory Movies.fromJson(Map json) => Movies( page: json['page'], totalResults: json['total_results'], totalPages: json['total_pages'], - results: (json['results'] as List) + results: (json['results'] as List?) ?.map((v) => Movie.fromJson(v)) - ?.toList() ?? + .toList() ?? [], ); @@ -24,7 +24,7 @@ class Movies extends Equatable { data['total_results'] = this.totalResults; data['total_pages'] = this.totalPages; if (this.results != null) { - data['results'] = this.results.map((v) => v.toJson()).toList(); + data['results'] = this.results!.map((v) => v.toJson()).toList(); } return data; } @@ -39,20 +39,20 @@ class Movies extends Equatable { } class Movie extends Equatable { - final int voteCount; - final int id; - final bool video; - final voteAverage; - final String title; - final double popularity; - final String posterPath; - final String originalLanguage; - final String originalTitle; - final List genreIds; - final String backdropPath; - final bool adult; - final String overview; - final String releaseDate; + final int? voteCount; + final int? id; + final bool? video; + final dynamic voteAverage; + final String? title; + final double? popularity; + final String? posterPath; + final String? originalLanguage; + final String? originalTitle; + final List? genreIds; + final String? backdropPath; + final bool? adult; + final String? overview; + final String? releaseDate; Movie( {this.voteCount, diff --git a/super_enum/lib/src/annotations.dart b/super_enum/lib/src/annotations.dart index d385c44..e3f815a 100644 --- a/super_enum/lib/src/annotations.dart +++ b/super_enum/lib/src/annotations.dart @@ -28,7 +28,7 @@ class ObjectClass { class Data { final List fields; - const Data({@required this.fields}); + const Data({required this.fields}); } /// Mark the generated type as generic. @@ -78,5 +78,5 @@ class UseClass { final Type type; final String name; - const UseClass(this.type, {this.name}); + const UseClass(this.type, {required this.name}); } diff --git a/super_enum/pubspec.yaml b/super_enum/pubspec.yaml index 4fa98d7..9e26343 100644 --- a/super_enum/pubspec.yaml +++ b/super_enum/pubspec.yaml @@ -1,20 +1,19 @@ name: super_enum description: Create super-powered enums similar to sealed classes in Kotlin. -version: 0.5.0 +version: 0.6.0 homepage: https://github.com/xsahil03x/super_enum environment: - sdk: ">=2.1.0 <3.0.0" + sdk: ">=2.12.0 <3.0.0" dependencies: meta: ^1.2.3 - equatable: ^1.2.5 + equatable: ^2.0.0 # Adding dev dependencies # just for showcasing an example dev_dependencies: - http: ^0.12.0+2 - build_runner: ^1.7.1 + http: ^0.13.0 + build_runner: ^2.0.0 super_enum_generator: path: ../super_enum_generator - diff --git a/super_enum_generator/lib/src/class_generator.dart b/super_enum_generator/lib/src/class_generator.dart index 381309b..17133e8 100644 --- a/super_enum_generator/lib/src/class_generator.dart +++ b/super_enum_generator/lib/src/class_generator.dart @@ -13,7 +13,7 @@ class ClassGenerator { ClassGenerator(this.element); - Iterable get _fields => element.fields.skip(2); + Iterable get _fields => element.fields.where((element) => element.isEnumConstant); // .sublist(0, element.fields.length - 1);//.skip(2); bool get _isNamespaceGeneric => _fields.any(type_processor.isGeneric); @@ -65,6 +65,7 @@ class ClassGenerator { final List _params = []; final StringBuffer _bodyBuffer = StringBuffer(); + /* final assertionCondition = _fields.map((f) => '${getCamelCase(f.name)} == null').join(' || '); @@ -74,6 +75,7 @@ class ClassGenerator { "return true;" "}());", ); + */ _bodyBuffer.writeln('switch(this._type){'); @@ -85,11 +87,11 @@ class ClassGenerator { _bodyBuffer.writeln('case ${element.name}.${field.name}:'); if (usedClass != null) { final wrapperName = type_processor.usedWrapperNameFromAnnotation(field); - _bodyBuffer.writeln('return ${getCamelCase(field.name)}' + _bodyBuffer.writeln('return ${getFieldFuncParamName(field.name)}' '((this as $wrapperName)' '.${getCamelCase(usedClass.toTypeValue().getDisplayString(withNullability: false))});'); } else { - _bodyBuffer.writeln('return ${getCamelCase(field.name)}' + _bodyBuffer.writeln('return ${getFieldFuncParamName(field.name)}' '${hasObjectAnnotation ? '()' : '(this as ${field.name})'};'); } @@ -98,9 +100,10 @@ class ClassGenerator { : '${field.name}'; _params.add(Parameter((p) { return p - ..name = '${getCamelCase(field.name)}' + ..name = '${getFieldFuncParamName(field.name)}' ..named = true - ..annotations.add(references.required) + ..required = true + // ..annotations.add(references.required) ..type = refer( '${references.generic_R.symbol} Function(' '${hasObjectAnnotation ? '' : '${_isNamespaceGeneric ? '$callbackArgType' : callbackArgType}'}' @@ -118,7 +121,7 @@ class ClassGenerator { type_processor.PatternMatchingMethod.when, element, )) - ..types.add(references.generic_R_extends_Object) + ..types.add(references.generic_R)//_extends_Object) ..returns = references.generic_R ..optionalParameters.addAll(_params) ..body = Code(_bodyBuffer.toString()) @@ -129,12 +132,14 @@ class ClassGenerator { final List _params = []; final StringBuffer _bodyBuffer = StringBuffer(); + /* _bodyBuffer.write( "assert(() {" "if (orElse == null) {throw 'Missing orElse case';}" "return true;" "}());", ); + */ _bodyBuffer.writeln('switch(this._type){'); @@ -144,14 +149,14 @@ class ClassGenerator { final DartObject usedClass = type_processor.usedClassFromAnnotation(field); _bodyBuffer.writeln('case ${element.name}.${field.name}:'); - _bodyBuffer.writeln('if (${getCamelCase(field.name)} == null) break;'); + _bodyBuffer.writeln('if (${getFieldFuncParamName(field.name)} == null) break;'); if (usedClass != null) { final wrapperName = type_processor.usedWrapperNameFromAnnotation(field); - _bodyBuffer.writeln('return ${getCamelCase(field.name)}' + _bodyBuffer.writeln('return ${getFieldFuncParamName(field.name)}' '((this as $wrapperName)' '.${getCamelCase(usedClass.toTypeValue().getDisplayString(withNullability: false))});'); } else { - _bodyBuffer.writeln('return ${getCamelCase(field.name)}' + _bodyBuffer.writeln('return ${getFieldFuncParamName(field.name)}' '${hasObjectAnnotation ? '()' : '(this as ${field.name})'};'); } @@ -159,12 +164,12 @@ class ClassGenerator { ? '${usedClass.toTypeValue().getDisplayString(withNullability: false)}' : '${field.name}'; _params.add(Parameter((p) => p - ..name = '${getCamelCase(field.name)}' + ..name = '${getFieldFuncParamName(field.name)}' ..named = true ..type = refer( '${references.generic_R.symbol} Function(' '${hasObjectAnnotation ? '' : '${_isNamespaceGeneric ? '$callbackArgType' : callbackArgType}'}' - ')', + ')?', ) ..build())); } @@ -172,7 +177,8 @@ class ClassGenerator { _params.add(Parameter((p) => p ..name = 'orElse' ..named = true - ..annotations.add(references.required) + ..required = true + // ..annotations.add(references.required) ..type = refer( '${references.generic_R.symbol} Function(' '${_isNamespaceGeneric ? '${element.name.replaceFirst('_', '')}' : element.name.replaceFirst('_', '')}' @@ -191,7 +197,7 @@ class ClassGenerator { type_processor.PatternMatchingMethod.whenOrElse, element, )) - ..types.add(references.generic_R_extends_Object) + ..types.add(references.generic_R)//_extends_Object) ..returns = references.generic_R ..optionalParameters.addAll(_params) ..body = Code(_bodyBuffer.toString()) @@ -203,7 +209,7 @@ class ClassGenerator { final StringBuffer _bodyBuffer = StringBuffer(); final assertionCondition = - _fields.map((f) => '${getCamelCase(f.name)} == null').join(' && '); + _fields.map((f) => '${getFieldFuncParamName(getCamelCase(f.name))} == null').join(' && '); _bodyBuffer.write( "assert(() {" @@ -220,14 +226,14 @@ class ClassGenerator { final DartObject usedClass = type_processor.usedClassFromAnnotation(field); _bodyBuffer.writeln('case ${element.name}.${field.name}:'); - _bodyBuffer.writeln('if (${getCamelCase(field.name)} == null) break;'); + _bodyBuffer.writeln('if (${getFieldFuncParamName(field.name)} == null) break;'); if (usedClass != null) { final wrapperName = type_processor.usedWrapperNameFromAnnotation(field); - _bodyBuffer.writeln('return ${getCamelCase(field.name)}' + _bodyBuffer.writeln('return ${getFieldFuncParamName(field.name)}' '((this as $wrapperName)' '.${getCamelCase(usedClass.toTypeValue().getDisplayString(withNullability: false))});'); } else { - _bodyBuffer.writeln('return ${getCamelCase(field.name)}' + _bodyBuffer.writeln('return ${getFieldFuncParamName(field.name)}' '${hasObjectAnnotation ? '()' : '(this as ${field.name})'};'); } @@ -235,12 +241,12 @@ class ClassGenerator { ? '${usedClass.toTypeValue().getDisplayString(withNullability: false)}' : '${field.name}'; _params.add(Parameter((p) => p - ..name = '${getCamelCase(field.name)}' + ..name = '${getFieldFuncParamName(field.name)}' ..named = true ..type = refer( '${references.ref_void.symbol} Function(' '${hasObjectAnnotation ? '' : '${_isNamespaceGeneric ? '$callbackArgType' : callbackArgType}'}' - ')', + ')?', ) ..build())); } @@ -303,7 +309,8 @@ class ClassGenerator { final fields = type_processor.listTypeFieldOf(element, 'fields'); return fields.map((e) => Parameter((f) { if (type_processor.dataFieldRequired(e)) { - f.annotations.add(references.required); + // f.annotations.add(references.required); + f.required = true; } return f ..name = '${type_processor.dataFieldName(e)}' @@ -502,7 +509,8 @@ class ClassGenerator { ..initializers.add(Code('super(${element.name}.${field.name})')) ..optionalParameters.addAll(_classFields.map((e) => Parameter((f) { if (type_processor.dataFieldRequired(e)) { - f.annotations.add(references.required); + // f.annotations.add(references.required); + f.required = true; } return f ..name = 'this.${type_processor.dataFieldName(e)}' @@ -516,7 +524,8 @@ class ClassGenerator { ..docs.addAll(type_processor.docCommentsOf(field)) ..optionalParameters.addAll(_classFields.map((e) => Parameter((f) { if (type_processor.dataFieldRequired(e)) { - f.annotations.add(references.required); + // f.annotations.add(references.required); + f.required = true; } return f ..name = @@ -552,7 +561,8 @@ class ClassGenerator { ..initializers.add(Code('super($values)')) ..optionalParameters.addAll(_classFields.map((e) => Parameter((f) { if (type_processor.dataFieldRequired(e)) { - f.annotations.add(references.required); + // f.annotations.add(references.required); + f.required = true; } return f ..name = 'this.${type_processor.dataFieldName(e)}' diff --git a/super_enum_generator/lib/src/extension.dart b/super_enum_generator/lib/src/extension.dart index defd5f2..0a727cb 100644 --- a/super_enum_generator/lib/src/extension.dart +++ b/super_enum_generator/lib/src/extension.dart @@ -6,6 +6,11 @@ String getCamelCase(String text, {String separator = ''}) { return words.join(separator); } +String getFieldFuncParamName(String text) { + final k = '${text.substring(0, 1).toUpperCase()}${text.substring(1)}'; + return 'on' + k; +} + String _upperCaseFirstLetter(String word) { return '${word.substring(0, 1).toUpperCase()}${word.substring(1).toLowerCase()}'; } diff --git a/super_enum_generator/pubspec.yaml b/super_enum_generator/pubspec.yaml index 01c4190..acccf9b 100644 --- a/super_enum_generator/pubspec.yaml +++ b/super_enum_generator/pubspec.yaml @@ -1,6 +1,6 @@ name: super_enum_generator description: Dev-dependency to generate sealed classes and when statements together with the super_enum.dart package. -version: 0.6.0 +version: 0.7.0 homepage: https://github.com/xsahil03x/super_enum environment: @@ -10,14 +10,14 @@ dependencies: # Specify a specific version or a version constraint # for "super_enum" before publishing the package. - super_enum: ^0.5.0 - source_gen: ^0.9.7+1 - analyzer: '>=0.40.0 <2.0.0' - build: '>=0.12.6 <2.0.0' - code_builder: ^3.5.0 - dart_style: ^1.3.7 + super_enum: ^0.6.0 + source_gen: ^1.0.0 + analyzer: ^4.6.0 + build: ^2.0.0 + code_builder: ^4.2.0 + dart_style: ^2.0.0 dev_dependencies: test: ^1.15.4 - build_runner: ^1.10.3 - source_gen_test: ^0.1.1+1 \ No newline at end of file + build_runner: ^2.0.0 + source_gen_test: ^1.0.0 \ No newline at end of file