| // 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; | |
| } | |
| '''), | |
| ); | |
| }, | |
| ); | |
| } |