blob: 61a2cf4e655e889692048ff46a11da01b3e1ba22 [file] [log] [blame]
// 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;
}
'''),
);
},
);
}