Skip to content

Commit

Permalink
feat: support for generics (#40)
Browse files Browse the repository at this point in the history
  • Loading branch information
felangel authored Oct 16, 2024
1 parent cf60442 commit 819d998
Show file tree
Hide file tree
Showing 11 changed files with 264 additions and 1 deletion.
6 changes: 5 additions & 1 deletion .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,18 @@ jobs:
runs-on: ubuntu-latest
name: ⚙️ Build

strategy:
matrix:
sdk: [stable, dev]

steps:
- name: 📚 Git Checkout
uses: actions/checkout@v4

- name: 🎯 Setup Dart
uses: dart-lang/setup-dart@v1
with:
sdk: dev
sdk: ${{ matrix.sdk }}

- name: 📦 Install Dependencies
run: dart pub get
Expand Down
18 changes: 18 additions & 0 deletions test/src/constructable_macro/generic_single_field_class_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import 'package:data_class/data_class.dart';
import 'package:test/test.dart';

@Constructable()
class GenericSingleFieldClass<T> {
final T field;
}

void main() {
group(GenericSingleFieldClass, () {
test('has a const constructor and required param', () {
expect(const GenericSingleFieldClass(field: false).field, equals(false));
expect(const GenericSingleFieldClass(field: 'field').field, equals('field'));
expect(const GenericSingleFieldClass(field: 42).field, equals(42));
expect(const GenericSingleFieldClass(field: 42.0).field, equals(42.0));
});
});
}
2 changes: 2 additions & 0 deletions test/src/constructable_macro_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import 'constructable_macro/empty_subclass_of_positional_multi_field_class_test.
import 'constructable_macro/empty_subclass_of_positional_single_field_class_test.dart'
as empty_subclass_of_positional_single_field_class_test;
import 'constructable_macro/empty_subclass_test.dart' as empty_subclass_test;
import 'constructable_macro/generic_single_field_class_test.dart' as generic_single_field_class_test;
import 'constructable_macro/nullable_single_field_class_test.dart'
as nullable_single_field_class_test;
import 'constructable_macro/single_field_class_test.dart'
Expand All @@ -41,6 +42,7 @@ void main() {
empty_subclass_of_positional_multi_field_class_test.main();
empty_subclass_of_positional_single_field_class_test.main();
empty_subclass_test.main();
generic_single_field_class_test.main();
nullable_single_field_class_test.main();
single_field_class_test.main();
single_field_nested_subclass_of_positional_single_field_class_test.main();
Expand Down
40 changes: 40 additions & 0 deletions test/src/copyable_macro/generic_single_field_class_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import 'package:data_class/data_class.dart';
import 'package:test/test.dart';

@Copyable()
class GenericSingleFieldClass<T> {
const GenericSingleFieldClass({required this.field});
final T field;
}

void main() {
group(GenericSingleFieldClass, () {
test('copyWith creates a copy when no arguments are passed', () {
final stringInstance = GenericSingleFieldClass(field: 'field');
final stringCopy = stringInstance.copyWith();
expect(stringCopy.field, equals(stringInstance.field));

final intInstance = GenericSingleFieldClass(field: 42);
final intCopy = intInstance.copyWith();
expect(intCopy.field, equals(intInstance.field));

final boolInstance = GenericSingleFieldClass(field: false);
final boolCopy = boolInstance.copyWith();
expect(boolCopy.field, equals(boolInstance.field));
});

test('copyWith creates a copy and overrides field', () {
final stringInstance = GenericSingleFieldClass(field: 'field');
final stringCopy = stringInstance.copyWith(field: 'other');
expect(stringCopy.field, equals('other'));

final intInstance = GenericSingleFieldClass(field: 42);
final intCopy = intInstance.copyWith(field: 43);
expect(intCopy.field, equals(43));

final boolInstance = GenericSingleFieldClass(field: false);
final boolCopy = boolInstance.copyWith(field: true);
expect(boolCopy.field, equals(true));
});
});
}
2 changes: 2 additions & 0 deletions test/src/copyable_macro_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import 'copyable_macro/empty_subclass_of_positional_multi_field_class_test.dart'
import 'copyable_macro/empty_subclass_of_positional_single_field_class_test.dart'
as empty_subclass_of_positional_single_field_class_test;
import 'copyable_macro/empty_subclass_test.dart' as empty_subclass_test;
import 'copyable_macro/generic_single_field_class_test.dart' as generic_single_field_class_test;
import 'copyable_macro/nullable_single_field_class_test.dart'
as nullable_single_field_class_test;
import 'copyable_macro/single_field_class_test.dart' as single_field_class_test;
Expand All @@ -39,6 +40,7 @@ void main() {
empty_subclass_of_positional_multi_field_class_test.main();
empty_subclass_of_positional_single_field_class_test.main();
empty_subclass_test.main();
generic_single_field_class_test.main();
nullable_single_field_class_test.main();
single_field_class_test.main();
single_field_nested_subclass_of_positional_single_field_class_test.main();
Expand Down
106 changes: 106 additions & 0 deletions test/src/data_macro/generic_single_field_class_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import 'package:data_class/data_class.dart';
import 'package:test/test.dart';

@Data()
class GenericSingleFieldClass<T> {
final T field;
}

void main() {
group(GenericSingleFieldClass, () {
test('has a const constructor and required param', () {
expect(const GenericSingleFieldClass(field: 'field').field, equals('field'));
expect(const GenericSingleFieldClass(field: 42).field, equals(42));
expect(const GenericSingleFieldClass(field: true).field, equals(true));
});

test('copyWith creates a copy when no arguments are passed', () {
final stringInstance = GenericSingleFieldClass(field: 'field');
final stringCopy = stringInstance.copyWith();
expect(stringCopy.field, equals(stringInstance.field));

final intInstance = GenericSingleFieldClass(field: 42);
final intCopy = intInstance.copyWith();
expect(intCopy.field, equals(intInstance.field));

final boolInstance = GenericSingleFieldClass(field: true);
final boolCopy = boolInstance.copyWith();
expect(boolCopy.field, equals(boolInstance.field));
});

test('copyWith creates a copy and overrides field', () {
final stringInstance = GenericSingleFieldClass(field: 'field');
final stringCopy = stringInstance.copyWith(field: 'other');
expect(stringCopy.field, equals('other'));

final intInstance = GenericSingleFieldClass(field: 42);
final intCopy = intInstance.copyWith(field: 43);
expect(intCopy.field, equals(43));

final boolInstance = GenericSingleFieldClass(field: false);
final boolCopy = boolInstance.copyWith(field: true);
expect(boolCopy.field, equals(true));
});

test('== is correct', () {
final stringInstanceA = GenericSingleFieldClass(field: 'field');
final stringInstanceB = GenericSingleFieldClass(field: 'field');
final stringInstanceC = GenericSingleFieldClass(field: 'other');
expect(stringInstanceA, equals(stringInstanceB));
expect(stringInstanceC, isNot(equals(stringInstanceB)));
expect(stringInstanceC, isNot(equals(stringInstanceA)));

final intInstanceA = GenericSingleFieldClass(field: 42);
final intInstanceB = GenericSingleFieldClass(field: 42);
final intInstanceC = GenericSingleFieldClass(field: 43);
expect(intInstanceA, equals(intInstanceB));
expect(intInstanceC, isNot(equals(intInstanceB)));
expect(intInstanceC, isNot(equals(intInstanceA)));

final boolInstanceA = GenericSingleFieldClass(field: false);
final boolInstanceB = GenericSingleFieldClass(field: false);
final boolInstanceC = GenericSingleFieldClass(field: true);
expect(boolInstanceA, equals(boolInstanceB));
expect(boolInstanceC, isNot(equals(boolInstanceB)));
expect(boolInstanceC, isNot(equals(boolInstanceA)));
});

test('hashCode is correct', () {
final stringInstanceA = GenericSingleFieldClass(field: 'field');
final stringInstanceB = GenericSingleFieldClass(field: 'field');
final stringInstanceC = GenericSingleFieldClass(field: 'other');
expect(stringInstanceA.hashCode, equals(stringInstanceB.hashCode));
expect(stringInstanceC.hashCode, isNot(equals(stringInstanceB.hashCode)));
expect(stringInstanceC.hashCode, isNot(equals(stringInstanceA.hashCode)));

final intInstanceA = GenericSingleFieldClass(field: 42);
final intInstanceB = GenericSingleFieldClass(field: 42);
final intInstanceC = GenericSingleFieldClass(field: 43);
expect(intInstanceA.hashCode, equals(intInstanceB.hashCode));
expect(intInstanceC.hashCode, isNot(equals(intInstanceB.hashCode)));
expect(intInstanceC.hashCode, isNot(equals(intInstanceA.hashCode)));

final boolInstanceA = GenericSingleFieldClass(field: false);
final boolInstanceB = GenericSingleFieldClass(field: false);
final boolInstanceC = GenericSingleFieldClass(field: true);
expect(boolInstanceA.hashCode, equals(boolInstanceB.hashCode));
expect(boolInstanceC.hashCode, isNot(equals(boolInstanceB.hashCode)));
expect(boolInstanceC.hashCode, isNot(equals(boolInstanceA.hashCode)));
});

test('toString is correct', () {
expect(
GenericSingleFieldClass(field: 'field').toString(),
equals('GenericSingleFieldClass(field: field)'),
);
expect(
GenericSingleFieldClass(field: 42).toString(),
equals('GenericSingleFieldClass(field: 42)'),
);
expect(
GenericSingleFieldClass(field: true).toString(),
equals('GenericSingleFieldClass(field: true)'),
);
});
});
}
2 changes: 2 additions & 0 deletions test/src/data_macro_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import 'data_macro/empty_subclass_of_positional_multi_field_class_test.dart'
import 'data_macro/empty_subclass_of_positional_single_field_class_test.dart'
as empty_subclass_of_positional_single_field_class_test;
import 'data_macro/empty_subclass_test.dart' as empty_subclass_test;
import 'data_macro/generic_single_field_class_test.dart' as generic_single_field_class_test;
import 'data_macro/nullable_single_field_class_test.dart'
as nullable_single_field_class_test;
import 'data_macro/single_field_class_test.dart' as single_field_class_test;
Expand All @@ -38,6 +39,7 @@ void main() {
empty_subclass_of_positional_multi_field_class_test.main();
empty_subclass_of_positional_single_field_class_test.main();
empty_subclass_test.main();
generic_single_field_class_test.main();
nullable_single_field_class_test.main();
single_field_class_test.main();
single_field_nested_subclass_of_positional_single_field_class_test.main();
Expand Down
58 changes: 58 additions & 0 deletions test/src/equatable_macro/generic_single_field_class_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import 'package:data_class/data_class.dart';
import 'package:test/test.dart';

@Equatable()
class GenericSingleFieldClass<T> {
GenericSingleFieldClass({required this.field});
final T field;
}

void main() {
group(GenericSingleFieldClass, () {
test('== is correct', () {
final stringInstanceA = GenericSingleFieldClass(field: 'field');
final stringInstanceB = GenericSingleFieldClass(field: 'field');
final stringInstanceC = GenericSingleFieldClass(field: 'other');
expect(stringInstanceA, equals(stringInstanceB));
expect(stringInstanceC, isNot(equals(stringInstanceB)));
expect(stringInstanceC, isNot(equals(stringInstanceA)));

final intInstanceA = GenericSingleFieldClass(field: 42);
final intInstanceB = GenericSingleFieldClass(field: 42);
final intInstanceC = GenericSingleFieldClass(field: 43);
expect(intInstanceA, equals(intInstanceB));
expect(intInstanceC, isNot(equals(intInstanceB)));
expect(intInstanceC, isNot(equals(intInstanceA)));

final boolInstanceA = GenericSingleFieldClass(field: false);
final boolInstanceB = GenericSingleFieldClass(field: false);
final boolInstanceC = GenericSingleFieldClass(field: true);
expect(boolInstanceA, equals(boolInstanceB));
expect(boolInstanceC, isNot(equals(boolInstanceB)));
expect(boolInstanceC, isNot(equals(boolInstanceA)));
});

test('hashCode is correct', () {
final stringInstanceA = GenericSingleFieldClass(field: 'field');
final stringInstanceB = GenericSingleFieldClass(field: 'field');
final stringInstanceC = GenericSingleFieldClass(field: 'other');
expect(stringInstanceA.hashCode, equals(stringInstanceB.hashCode));
expect(stringInstanceC.hashCode, isNot(equals(stringInstanceB.hashCode)));
expect(stringInstanceC.hashCode, isNot(equals(stringInstanceA.hashCode)));

final intInstanceA = GenericSingleFieldClass(field: 42);
final intInstanceB = GenericSingleFieldClass(field: 42);
final intInstanceC = GenericSingleFieldClass(field: 43);
expect(intInstanceA.hashCode, equals(intInstanceB.hashCode));
expect(intInstanceC.hashCode, isNot(equals(intInstanceB.hashCode)));
expect(intInstanceC.hashCode, isNot(equals(intInstanceA.hashCode)));

final boolInstanceA = GenericSingleFieldClass(field: false);
final boolInstanceB = GenericSingleFieldClass(field: false);
final boolInstanceC = GenericSingleFieldClass(field: true);
expect(boolInstanceA.hashCode, equals(boolInstanceB.hashCode));
expect(boolInstanceC.hashCode, isNot(equals(boolInstanceB.hashCode)));
expect(boolInstanceC.hashCode, isNot(equals(boolInstanceA.hashCode)));
});
});
}
2 changes: 2 additions & 0 deletions test/src/equatable_macro_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import 'equatable_macro/empty_subclass_of_positional_multi_field_class_test.dart
import 'equatable_macro/empty_subclass_of_positional_single_field_class_test.dart'
as empty_subclass_of_positional_single_field_class_test;
import 'equatable_macro/empty_subclass_test.dart' as empty_subclass_test;
import 'equatable_macro/generic_single_field_class_test.dart' as generic_single_field_class_test;
import 'equatable_macro/nullable_single_field_class_test.dart'
as nullable_single_field_class_test;
import 'equatable_macro/single_field_class_test.dart'
Expand All @@ -41,6 +42,7 @@ void main() {
empty_subclass_of_positional_multi_field_class_test.main();
empty_subclass_of_positional_single_field_class_test.main();
empty_subclass_test.main();
generic_single_field_class_test.main();
nullable_single_field_class_test.main();
single_field_class_test.main();
single_field_nested_subclass_of_positional_single_field_class_test.main();
Expand Down
27 changes: 27 additions & 0 deletions test/src/stringable_macro/generic_single_field_class_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import 'package:data_class/data_class.dart';
import 'package:test/test.dart';

@Stringable()
class GenericSingleFieldClass<T> {
GenericSingleFieldClass({required this.field});
final T field;
}

void main() {
group(GenericSingleFieldClass, () {
test('toString is correct', () {
expect(
GenericSingleFieldClass(field: 'field').toString(),
equals('GenericSingleFieldClass(field: field)'),
);
expect(
GenericSingleFieldClass(field: 42).toString(),
equals('GenericSingleFieldClass(field: 42)'),
);
expect(
GenericSingleFieldClass(field: true).toString(),
equals('GenericSingleFieldClass(field: true)'),
);
});
});
}
2 changes: 2 additions & 0 deletions test/src/stringable_macro_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import 'stringable_macro/empty_subclass_of_positional_multi_field_class_test.dar
import 'stringable_macro/empty_subclass_of_positional_single_field_class_test.dart'
as empty_subclass_of_positional_single_field_class_test;
import 'stringable_macro/empty_subclass_test.dart' as empty_subclass_test;
import 'stringable_macro/generic_single_field_class_test.dart' as generic_single_field_class_test;
import 'stringable_macro/nullable_single_field_class_test.dart'
as nullable_single_field_class_test;
import 'stringable_macro/single_field_class_test.dart'
Expand All @@ -41,6 +42,7 @@ void main() {
empty_subclass_of_positional_multi_field_class_test.main();
empty_subclass_of_positional_single_field_class_test.main();
empty_subclass_test.main();
generic_single_field_class_test.main();
nullable_single_field_class_test.main();
single_field_class_test.main();
single_field_nested_subclass_of_positional_single_field_class_test.main();
Expand Down

0 comments on commit 819d998

Please sign in to comment.