| // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| import 'package:code_builder/code_builder.dart'; |
| import 'package:test/test.dart'; |
| |
| import '../common.dart'; |
| |
| void main() { |
| useDartfmt(); |
| |
| test('should create an enum', () { |
| expect( |
| Enum((b) => b |
| ..name = 'E' |
| ..values.addAll([ |
| EnumValue((b) => b..name = 'a'), |
| EnumValue((b) => b..name = 'b'), |
| ])), |
| equalsDart(r''' |
| enum E { |
| a, |
| b |
| } |
| ''')); |
| }); |
| |
| test('should create an enum with annotations', () { |
| expect( |
| Enum((b) => b |
| ..annotations.addAll([ |
| refer('deprecated'), |
| refer('Deprecated').call([literalString('This is an old enum')]) |
| ]) |
| ..name = 'V' |
| ..values.addAll([ |
| EnumValue((b) => b..name = 'x'), |
| ])), |
| equalsDart(r''' |
| @deprecated |
| @Deprecated('This is an old enum') |
| enum V { |
| x |
| } |
| ''')); |
| }); |
| |
| test('should create an enum with annotated values', () { |
| expect( |
| Enum((b) => b |
| ..name = 'Status' |
| ..values.addAll([ |
| EnumValue((b) => b |
| ..name = 'okay' |
| ..annotations.addAll([ |
| refer('deprecated'), |
| refer('Deprecated').call([literalString('use Good instead')]), |
| ])), |
| EnumValue((b) => b |
| ..name = 'good' |
| ..annotations.addAll([ |
| refer('JsonKey').call([literalString('good')]) |
| ])), |
| ])), |
| equalsDart(r''' |
| enum Status { |
| @deprecated |
| @Deprecated('use Good instead') |
| okay, |
| @JsonKey('good') |
| good |
| } |
| ''')); |
| }); |
| |
| test('should create an enum which mixes in and implements specs', () { |
| final myEnum = Enum((b) => b |
| ..name = 'MyEnum' |
| ..implements.addAll(const [ |
| Reference('InterfaceA'), |
| Reference('InterfaceB'), |
| ]) |
| ..mixins.addAll(const [ |
| Reference('Mixin1'), |
| Reference('Mixin2'), |
| ]) |
| ..values.addAll([ |
| EnumValue((v) => v..name = 'a'), |
| EnumValue((v) => v..name = 'b'), |
| EnumValue((v) => v..name = 'c'), |
| ])); |
| expect(myEnum, equalsDart(''' |
| enum MyEnum with Mixin1, Mixin2 implements InterfaceA, InterfaceB { |
| a, |
| b, |
| c |
| } |
| ''')); |
| }); |
| |
| test('should create an enum which targets a named constructor', () { |
| final myEnum = Enum((b) => b |
| ..name = 'MyEnum' |
| ..constructors.addAll([ |
| Constructor((c) => c..constant = true), |
| Constructor((c) => c |
| ..constant = true |
| ..name = 'named'), |
| ]) |
| ..values.addAll([ |
| EnumValue((v) => v..name = 'a'), |
| EnumValue((v) => v |
| ..name = 'b' |
| ..constructorName = 'named'), |
| EnumValue((v) => v..name = 'c'), |
| ])); |
| expect(myEnum, equalsDart(''' |
| enum MyEnum { |
| a, |
| b.named(), |
| c; |
| |
| const MyEnum(); |
| |
| const MyEnum.named(); |
| } |
| ''')); |
| }); |
| |
| test('should create an enum which targets a redirecting constructor', () { |
| final myEnum = Enum((b) => b |
| ..name = 'MyEnum' |
| ..constructors.addAll([ |
| Constructor((c) => c..constant = true), |
| Constructor((c) => c |
| ..constant = true |
| ..name = 'redirect' |
| ..initializers.add( |
| refer('this').call([]).code, |
| )), |
| ]) |
| ..values.addAll([ |
| EnumValue((v) => v..name = 'a'), |
| EnumValue((v) => v |
| ..name = 'b' |
| ..constructorName = 'redirect'), |
| EnumValue((v) => v..name = 'c'), |
| ])); |
| expect(myEnum, equalsDart(''' |
| enum MyEnum { |
| a, |
| b.redirect(), |
| c; |
| |
| const MyEnum(); |
| |
| const MyEnum.redirect() : this(); |
| } |
| ''')); |
| }); |
| |
| test('should create an enum which targets a redirecting factory constructor', |
| () { |
| final myEnum = Enum((b) => b |
| ..name = 'MyEnum' |
| ..constructors.addAll([ |
| Constructor((c) => c..constant = true), |
| Constructor((c) => c |
| ..constant = true |
| ..factory = true |
| ..name = 'redirect' |
| ..redirect = refer('MyOtherEnum.named') |
| ..optionalParameters.addAll([ |
| Parameter((p) => p |
| ..type = refer('int?') |
| ..name = 'myInt'), |
| Parameter((p) => p |
| ..type = refer('String?') |
| ..name = 'myString') |
| ])) |
| ]) |
| ..values.addAll([ |
| EnumValue((v) => v..name = 'a'), |
| EnumValue((v) => v |
| ..name = 'b' |
| ..constructorName = 'redirect' |
| ..arguments.addAll([ |
| literalNum(1), |
| literalString('abc'), |
| ])), |
| EnumValue((v) => v |
| ..name = 'c' |
| ..constructorName = 'redirect'), |
| ])); |
| expect(myEnum, equalsDart(''' |
| enum MyEnum { |
| a, |
| b.redirect(1, 'abc'), |
| c.redirect(); |
| |
| const MyEnum(); |
| |
| const factory MyEnum.redirect([ |
| int? myInt, |
| String? myString, |
| ]) = MyOtherEnum.named; |
| } |
| ''')); |
| }); |
| |
| test('should create an enum which targets an unnamed constructor', () { |
| final myEnum = Enum((b) => b |
| ..name = 'MyEnum' |
| ..constructors.add(Constructor((c) => c |
| ..constant = true |
| ..optionalParameters.addAll([ |
| Parameter((p) => p |
| ..toThis = true |
| ..name = 'myInt'), |
| Parameter((p) => p |
| ..toThis = true |
| ..name = 'myString') |
| ]))) |
| ..fields.addAll([ |
| Field((f) => f |
| ..modifier = FieldModifier.final$ |
| ..type = refer('int?') |
| ..name = 'myInt'), |
| Field((f) => f |
| ..modifier = FieldModifier.final$ |
| ..type = refer('String?') |
| ..name = 'myString') |
| ]) |
| ..values.addAll([ |
| EnumValue((v) => v..name = 'a'), |
| EnumValue((v) => v |
| ..name = 'b' |
| ..arguments.addAll([ |
| literalNum(1), |
| literalString('abc'), |
| ])), |
| EnumValue((v) => v..name = 'c'), |
| ])); |
| expect(myEnum, equalsDart(''' |
| enum MyEnum { |
| a, |
| b(1, 'abc'), |
| c; |
| |
| const MyEnum([ |
| this.myInt, |
| this.myString, |
| ]); |
| |
| final int? myInt; |
| |
| final String? myString; |
| } |
| ''')); |
| }); |
| |
| test('should create an enum with generics', () { |
| final myEnum = Enum((b) => b |
| ..name = 'MyEnum' |
| ..types.add(const Reference('T')) |
| ..constructors.add(Constructor((c) => c |
| ..constant = true |
| ..requiredParameters.add(Parameter((p) => p |
| ..toThis = true |
| ..name = 'value')))) |
| ..fields.add( |
| Field((f) => f |
| ..modifier = FieldModifier.final$ |
| ..type = refer('T') |
| ..name = 'value'), |
| ) |
| ..values.addAll([ |
| EnumValue((v) => v |
| ..name = 'a' |
| ..types.add(const Reference('int')) |
| ..arguments.add(literalNum(123))), |
| EnumValue((v) => v |
| ..name = 'b' |
| ..types.add(const Reference('String')) |
| ..arguments.add(literalString('abc'))), |
| EnumValue((v) => v |
| ..name = 'c' |
| ..types.add(const Reference('MyEnum')) |
| ..arguments.add(refer('MyEnum').property('a'))), |
| ])); |
| expect(myEnum, equalsDart(''' |
| enum MyEnum<T> { |
| a<int>(123), |
| b<String>('abc'), |
| c<MyEnum>(MyEnum.a); |
| |
| const MyEnum(this.value); |
| |
| final T value; |
| } |
| ''')); |
| }); |
| |
| test('should create an enum with fields', () { |
| final myEnum = Enum((b) => b |
| ..name = 'MyEnum' |
| ..constructors.add(Constructor((c) => c |
| ..constant = true |
| ..optionalParameters.add(Parameter((p) => p |
| ..toThis = true |
| ..name = 'myInt')))) |
| ..fields.addAll([ |
| Field((f) => f |
| ..modifier = FieldModifier.final$ |
| ..type = refer('int?') |
| ..name = 'myInt'), |
| Field((f) => f |
| ..static = true |
| ..modifier = FieldModifier.constant |
| ..type = refer('String') |
| ..name = 'myString' |
| ..assignment = literalString('abc').code), |
| ]) |
| ..values.addAll([ |
| EnumValue((v) => v..name = 'a'), |
| EnumValue((v) => v..name = 'b'), |
| EnumValue((v) => v..name = 'c'), |
| ])); |
| expect(myEnum, equalsDart(''' |
| enum MyEnum { |
| a, |
| b, |
| c; |
| |
| const MyEnum([this.myInt]); |
| |
| final int? myInt; |
| |
| static const String myString = 'abc'; |
| } |
| ''')); |
| }); |
| |
| test('should create an enum with methods', () { |
| final myEnum = Enum((b) => b |
| ..name = 'MyEnum' |
| ..methods.addAll([ |
| Method((m) => m |
| ..returns = refer('int') |
| ..type = MethodType.getter |
| ..name = 'myInt' |
| ..body = literalNum(123).code), |
| Method((m) => m |
| ..returns = refer('Iterable<String>') |
| ..name = 'myStrings' |
| ..modifier = MethodModifier.syncStar |
| ..body = Block.of(const [ |
| Code("yield 'a';"), |
| Code("yield 'b';"), |
| Code("yield 'c';"), |
| ])) |
| ]) |
| ..values.addAll([ |
| EnumValue((v) => v..name = 'a'), |
| EnumValue((v) => v..name = 'b'), |
| EnumValue((v) => v..name = 'c'), |
| ])); |
| expect(myEnum, equalsDart(''' |
| enum MyEnum { |
| a, |
| b, |
| c; |
| |
| int get myInt => 123; |
| Iterable<String> myStrings() sync* { |
| yield 'a'; |
| yield 'b'; |
| yield 'c'; |
| } |
| } |
| ''')); |
| }); |
| |
| test('should create an enum which named and unnamed constructor parameters', |
| () { |
| final myEnum = Enum((b) => b |
| ..name = 'MyEnum' |
| ..constructors.add(Constructor((c) => c |
| ..constant = true |
| ..requiredParameters.addAll([ |
| Parameter((p) => p |
| ..toThis = true |
| ..name = 'myInt') |
| ]) |
| ..optionalParameters.addAll([ |
| Parameter((p) => p |
| ..toThis = true |
| ..named = true |
| ..required = true |
| ..name = 'myString') |
| ]))) |
| ..fields.addAll([ |
| Field((f) => f |
| ..modifier = FieldModifier.final$ |
| ..type = refer('int?') |
| ..name = 'myInt'), |
| Field((f) => f |
| ..modifier = FieldModifier.final$ |
| ..type = refer('String?') |
| ..name = 'myString') |
| ]) |
| ..values.addAll([ |
| EnumValue((v) => v..name = 'a'), |
| EnumValue((v) => v |
| ..name = 'b' |
| ..arguments.addAll([ |
| literalNum(1), |
| ]) |
| ..namedArguments.addAll({ |
| 'myString': literalString('abc'), |
| })), |
| EnumValue((v) => v..name = 'c'), |
| ])); |
| expect(myEnum, equalsDart(''' |
| enum MyEnum { |
| a, |
| b(1, myString: 'abc'), |
| c; |
| |
| const MyEnum( |
| this.myInt, |
| {required this.myString, } |
| ); |
| |
| final int? myInt; |
| |
| final String? myString; |
| } |
| ''')); |
| }); |
| } |