Skip to content

Commit

Permalink
#101 Union contributor is generating fromJson as method and not factory
Browse files Browse the repository at this point in the history
- Also swapped "expected" and "actual" values in tests
  • Loading branch information
spideythewebhead committed Nov 20, 2022
1 parent 6fe4e2a commit fa21976
Show file tree
Hide file tree
Showing 9 changed files with 123 additions and 131 deletions.
92 changes: 49 additions & 43 deletions example/lib/unions/from_json.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,46 @@ import 'package:data_class_plugin/data_class_plugin.dart';
fromJson: true,
toJson: false,
)
abstract class Response {
class Response {
const Response._();

/// Creates an instance of [Response] from [json]
factory Response.fromJson(Map<dynamic, dynamic> json) {
switch (json['status']) {
case 'ok':
return ResponseOk.fromJson(json);
case 'unauthorized':
return ResponseUnauthorized.fromJson(json);
default:
return ResponseError.fromJson(json);
}
}

const factory Response.ok({
required int data,
}) = Ok;
}) = ResponseOk;

const factory Response.unauthorized() = Unauthorized;
const factory Response.unauthorized() = ResponseUnauthorized;

const factory Response.error({
required Object type,
@JsonKey(ignore: true) StackTrace? stackTrace,
}) = Error;
}) = ResponseError;

/// Executes one of the provided callbacks based on a type match
R when<R>({
required R Function(Ok value) ok,
required R Function(Unauthorized value) unauthorized,
required R Function(Error value) error,
required R Function(ResponseOk value) ok,
required R Function(ResponseUnauthorized value) unauthorized,
required R Function(ResponseError value) error,
}) {
if (this is Ok) {
return ok(this as Ok);
if (this is ResponseOk) {
return ok(this as ResponseOk);
}
if (this is Unauthorized) {
return unauthorized(this as Unauthorized);
if (this is ResponseUnauthorized) {
return unauthorized(this as ResponseUnauthorized);
}
if (this is Error) {
return error(this as Error);
if (this is ResponseError) {
return error(this as ResponseError);
}
throw UnimplementedError('Unknown instance of $this used in when(..)');
}
Expand All @@ -41,66 +53,60 @@ abstract class Response {
///
/// If no match is found [orElse] is executed
R maybeWhen<R>({
R Function(Ok value)? ok,
R Function(Unauthorized value)? unauthorized,
R Function(Error value)? error,
R Function(ResponseOk value)? ok,
R Function(ResponseUnauthorized value)? unauthorized,
R Function(ResponseError value)? error,
required R Function() orElse,
}) {
if (this is Ok) {
return ok?.call(this as Ok) ?? orElse();
if (this is ResponseOk) {
return ok?.call(this as ResponseOk) ?? orElse();
}
if (this is Unauthorized) {
return unauthorized?.call(this as Unauthorized) ?? orElse();
if (this is ResponseUnauthorized) {
return unauthorized?.call(this as ResponseUnauthorized) ?? orElse();
}
if (this is Error) {
return error?.call(this as Error) ?? orElse();
if (this is ResponseError) {
return error?.call(this as ResponseError) ?? orElse();
}
throw UnimplementedError('Unknown instance of $this used in maybeWhen(..)');
}

/// Creates an instance of [Response] from [json]
Response fromJson(Map<dynamic, dynamic> json) {
// TODO: Implement
throw UnimplementedError();
}
}

class Ok extends Response {
const Ok({
class ResponseOk extends Response {
const ResponseOk({
required this.data,
}) : super._();

final int data;

/// Creates an instance of [Ok] from [json]
factory Ok.fromJson(Map<dynamic, dynamic> json) {
return Ok(
/// Creates an instance of [ResponseOk] from [json]
factory ResponseOk.fromJson(Map<dynamic, dynamic> json) {
return ResponseOk(
data: json['data'] as int,
);
}
}

class Unauthorized extends Response {
const Unauthorized() : super._();
class ResponseUnauthorized extends Response {
const ResponseUnauthorized() : super._();

/// Creates an instance of [Unauthorized] from [json]
factory Unauthorized.fromJson(Map<dynamic, dynamic> json) {
return Unauthorized();
/// Creates an instance of [ResponseUnauthorized] from [json]
factory ResponseUnauthorized.fromJson(Map<dynamic, dynamic> json) {
return ResponseUnauthorized();
}
}

class Error extends Response {
const Error({
class ResponseError extends Response {
const ResponseError({
required this.type,
this.stackTrace,
}) : super._();

final Object type;
final StackTrace? stackTrace;

/// Creates an instance of [Error] from [json]
factory Error.fromJson(Map<dynamic, dynamic> json) {
return Error(
/// Creates an instance of [ResponseError] from [json]
factory ResponseError.fromJson(Map<dynamic, dynamic> json) {
return ResponseError(
type: jsonConverterRegistrant.find(Object).fromJson(json['type']) as Object,
);
}
Expand Down
3 changes: 2 additions & 1 deletion lib/src/contributors/class/shorthand_constructor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ class ShorthandConstructorAssistContributor extends Object
if (classNode == null ||
classNode.members.isEmpty ||
classNode.declaredElement == null ||
classNode.declaredElement!.hasDataClassAnnotation) {
classNode.declaredElement!.hasDataClassAnnotation ||
classNode.declaredElement!.hasUnionAnnotation) {
return;
}

Expand Down
21 changes: 10 additions & 11 deletions lib/src/contributors/class/union_assist_contributor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,12 @@ class UnionAssistContributor extends Object
fileEditBuilder: fileEditBuilder,
);

_generateGenerativeConstructor(
classNode: classNode,
classElement: classElement,
fileEditBuilder: fileEditBuilder,
);

if (unionInternalAnnotation.fromJson) {
_generateFromJsonFunction(
classNode: classNode,
Expand All @@ -109,12 +115,6 @@ class UnionAssistContributor extends Object
unionInternalAnnotation: unionInternalAnnotation,
);

_generateGenerativeConstructor(
classNode: classNode,
classElement: classElement,
fileEditBuilder: fileEditBuilder,
);

fileEditBuilder.format(SourceRange(classNode.offset, classNode.length));
},
);
Expand Down Expand Up @@ -189,7 +189,7 @@ class UnionAssistContributor extends Object
required final UnionInternal unionInternalAnnotation,
}) {
for (final ConstructorElement ctor in classElement.constructors.reversed) {
if (!ctor.isFactory || ctor.name.isEmpty) {
if (!ctor.isFactory || ctor.name.isEmpty || ctor.name == 'fromJson') {
continue;
}

Expand Down Expand Up @@ -264,11 +264,11 @@ class UnionAssistContributor extends Object
required final ClassElement classElement,
required final DartFileEditBuilder fileEditBuilder,
}) {
final SourceRange? sourceRange = classNode.members.getSourceRangeForMethod('fromJson');
final SourceRange? sourceRange = classNode.members.getSourceRangeForConstructor('fromJson');

if (sourceRange == null) {
fileEditBuilder.addInsertion(
classNode.rightBracket.offset,
1 + classNode.leftBracket.offset,
(DartEditBuilder builder) =>
_writeFromJsonFunction(classElement: classElement, builder: builder),
);
Expand Down Expand Up @@ -598,8 +598,7 @@ class UnionAssistContributor extends Object
}) {
builder
..writeln('/// Creates an instance of [${classElement.name}] from [json]')
..writeln('${classElement.thisType} fromJson(Map<dynamic, dynamic> json) {')
..writeln('// TODO: Implement')
..writeln('factory ${classElement.name}.fromJson(Map<dynamic, dynamic> json) {')
..writeln('throw UnimplementedError();')
..writeln('}');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import 'package:data_class_plugin/data_class_plugin.dart';
toJson: false,
)
class AsyncResult<T> {
const AsyncResult._();

const factory AsyncResult.data({
required T data,
}) = AsyncResultData<T>;
Expand Down
20 changes: 9 additions & 11 deletions test/contributors/annotations/union/test_files/in_from_json.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,15 @@ import 'package:data_class_plugin/data_class_plugin.dart';
fromJson: true,
toJson: false,
)
class AsyncResult<T> {
const AsyncResult._();
class Response {
const factory Response.ok({
required int data,
}) = ResponseOk;

const factory AsyncResult.data({
required T data,
}) = AsyncResultData<T>;
const factory Response.unauthorized() = ResponseUnauthorized;

const factory AsyncResult.loading() = AsyncResultLoading<T>;

const factory AsyncResult.error({
required Object error,
StackTrace? stackTrace,
}) = AsyncResultError<T>;
const factory Response.error({
required Object type,
@JsonKey(ignore: true) StackTrace? stackTrace,
}) = ResponseError;
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import 'package:data_class_plugin/data_class_plugin.dart';
toJson: false,
)
abstract class User {
const User._();

const factory User.normal({
required String id,
required String username,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import 'package:data_class_plugin/data_class_plugin.dart';
toJson: true,
)
class AsyncResult<T> {
const AsyncResult._();

const factory AsyncResult.data({
required T data,
}) = AsyncResultData<T>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ class User {
toJson: false,
)
class UnionWithDefaultValues {
const UnionWithDefaultValues._();

const factory UnionWithDefaultValues.impl({
@UnionFieldValue<User>(User.none) User value,
@UnionFieldValue<String>('') String value2,
Expand Down

0 comments on commit fa21976

Please sign in to comment.