Skip to content

Commit

Permalink
Fix mixin class generation for Dart 3.
Browse files Browse the repository at this point in the history
  • Loading branch information
davidmorgan committed Jun 5, 2023
1 parent a16173e commit a94145c
Show file tree
Hide file tree
Showing 7 changed files with 38 additions and 59 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

# 8.6.1

- Fix support for generating enum mixins for Dart 3. Instead of triggering
mixin generation with `abstract class TestEnumMixin = Object with
_$TestEnumMixin` it must now be triggered with `typedef TestEnumMixin =
_$TestEnumMixin`.

# 8.6.0

- Add support for value types with record fields. Serialization with records
Expand Down
36 changes: 15 additions & 21 deletions built_value_generator/lib/src/enum_source_class.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import 'package:built_value_generator/src/strings.dart';
import 'package:collection/collection.dart'
show IterableExtension, IterableNullableExtension;

import 'library_elements.dart';

part 'enum_source_class.g.dart';

abstract class EnumSourceClass
Expand All @@ -33,6 +35,14 @@ abstract class EnumSourceClass
@memoized
String get name => element.name;

/// Returns `mixin` if class modifiers are available, `abstract class`
/// otherwise.
///
/// The two are equivalent as class modifiers change the meaning of `class`.
String get _mixin => LibraryElements.areClassMixinsEnabled(element.library)
? 'mixin'
: 'abstract class';

@memoized
String get wireName => settings.wireName ?? name;

Expand Down Expand Up @@ -90,14 +100,10 @@ abstract class EnumSourceClass
}

@memoized
bool get usesMixin => element.library.getClass(name + 'Mixin') != null;

@memoized
String? get mixinDeclaration {
var mixinElement = element.library.getClass(name + 'Mixin');
if (mixinElement == null) return null;
return parsedLibrary.getElementDeclaration(mixinElement)!.node.toSource();
}
bool get usesMixin =>
element.library.getClass(name + 'Mixin') != null ||
element.library.definingCompilationUnit.typeAliases
.any((a) => a.name == name + 'Mixin');

@memoized
Iterable<String> get identifiers {
Expand All @@ -121,7 +127,6 @@ abstract class EnumSourceClass
..._checkConstructor(),
..._checkValuesGetter(),
..._checkValueOf(),
..._checkMixin(),
];
}

Expand Down Expand Up @@ -178,17 +183,6 @@ abstract class EnumSourceClass
return result;
}

Iterable<String> _checkMixin() {
if (usesMixin) {
final expectedCode =
'abstract class ${name}Mixin = Object with _\$${name}Mixin;';
if (!mixinDeclaration!.contains(expectedCode)) {
return ['Remove mixin or declare using exactly: $expectedCode'];
}
}
return [];
}

String generateCode() {
var result = StringBuffer();

Expand Down Expand Up @@ -244,7 +238,7 @@ abstract class EnumSourceClass
..writeln('$name valueOf(String name) => $valueOfIdentifier(name);')
..writeln('BuiltSet<$name> get values => $valuesIdentifier;')
..writeln('}')
..writeln('abstract class _\$${name}Mixin {')
..writeln('$_mixin _\$${name}Mixin {')
..writeln(' // ignore: non_constant_identifier_names')
..writeln('_\$${name}Meta get $name => const _\$${name}Meta();')
..writeln('}');
Expand Down
9 changes: 0 additions & 9 deletions built_value_generator/lib/src/enum_source_class.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 0 additions & 23 deletions built_value_generator/test/enum_class_generator_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -327,29 +327,6 @@ class TestEnum extends EnumClass {
1. Add method: static TestEnum valueOf(String name) => _$valueOf(name)'''));
});

test('with error on wrong mixin declaration', () async {
expect(await generate(r'''
library test_enum;
import 'package:built_value/built_value.dart';
part 'test_enum.g.dart';
class TestEnum extends EnumClass {
static const TestEnum yes = _$yes;
const TestEnum._(String name) : super(name);
static BuiltSet<TestEnum> get values => _$values;
static TestEnum valueOf(String name) => _$valueOf(name);
}
class TestEnumMixin = Object with _$TestEnumMixin;
'''), endsWith(r'''Please make the following changes to use EnumClass:
1. Remove mixin or declare using exactly: abstract class TestEnumMixin = Object with _$TestEnumMixin;'''));
});

test('with error on abstract class', () async {
expect(await generate(r'''
library test_enum;
Expand Down
4 changes: 1 addition & 3 deletions end_to_end_test/lib/enums_nnbd.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// Copyright (c) 2017, Google Inc. 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.
// @dart=2.17

library enums_nnbd;

import 'package:built_collection/built_collection.dart';
Expand All @@ -24,7 +22,7 @@ class TestEnum extends EnumClass {
static TestEnum valueOf(String name) => _$valueOf(name);
}

abstract class TestEnumMixin = Object with _$TestEnumMixin;
typedef TestEnumMixin = _$TestEnumMixin;

class SecondTestEnum extends EnumClass {
static const SecondTestEnum yes = _$ys;
Expand Down
3 changes: 1 addition & 2 deletions end_to_end_test/lib/enums_nnbd.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 14 additions & 1 deletion end_to_end_test/test/enums_nnbd_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@ import 'package:end_to_end_test/enums_nnbd.dart';
import 'package:test/test.dart';

void main() {
group('FallbackEnum', () {
group(TestEnumMixin, () {
test('mixin works as expected', () {
expect(UsesTestEnumMixin().toString(), 'yes no maybe');
});
});
group(FallbackEnum, () {
test('valueOf works for non-fallback values', () {
expect(FallbackEnum.valueOf('yes'), FallbackEnum.yes);
});
Expand All @@ -18,3 +23,11 @@ void main() {
});
});
}

class UsesTestEnumMixin with TestEnumMixin {
// Refer to the constants to check they are available via the mixin from
// another class.
@override
String toString() =>
'${this.TestEnum.yes} ${this.TestEnum.no} ${this.TestEnum.maybe}';
}

0 comments on commit a94145c

Please sign in to comment.