Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Option refactoring #75

Merged
merged 5 commits into from
Nov 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/analyze.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
# - uses: subosito/flutter-action@v2
with:
channel: 'stable'
version: 3.3.10
version: 3.13.6
# - run: |
# sudo apt-get update -y
# sudo apt-get install -y ninja-build libgtk-3-dev
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/coverage.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
# - uses: subosito/flutter-action@v2
with:
channel: 'stable'
version: 3.3.10
version: 3.13.6
# - run: |
# sudo apt-get update -y
# sudo apt-get install -y ninja-build libgtk-3-dev
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
uses: flutter-actions/setup-flutter@v2
with:
channel: 'stable'
version: 3.3.10
version: 3.13.6

- name: Clearing project
run: flutter clean
Expand Down
18 changes: 0 additions & 18 deletions lib/src/core/option/none.dart

This file was deleted.

40 changes: 15 additions & 25 deletions lib/src/core/option/option.dart
Original file line number Diff line number Diff line change
@@ -1,28 +1,18 @@
part 'some.dart';
part 'none.dart';
///
/// Holds either value or nothing.
abstract class Option<T> {
///
/// Creates object that holds some [value].
const factory Option.some(T value) = Some<T>;
///
/// Creates object that holds nothing.
const factory Option.none() = None<T>;
///
/// Computes value of type [R] from provided functions
/// based on condition that object is holding some value.
///
/// Example interpetations of provided functions:
/// - [onSome] - transforms holded value to another of type [R],
/// - [onNone] - returns any default of type [R].
R fold<R>({
required R Function(T v) onSome,
required R Function() onNone,
});
sealed class Option<T> {}
///
/// [Option] that holds value.
final class Some<T> implements Option<T> {
final T value;
///
Minyewoo marked this conversation as resolved.
Show resolved Hide resolved
/// Is object holding some value?
bool get isSome;
/// Is object holding nothing?
bool get isNone;
}
/// Create [Option] object that holds [value].
const Some(this.value);
}
///
/// [Option] that holds nothing.
final class None implements Option<Never> {
///
/// Create [Option] object that holds nothing.
const None();
}
20 changes: 0 additions & 20 deletions lib/src/core/option/some.dart

This file was deleted.

2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ version: 0.0.5
homepage: https://github.com/a-givertzman/hmi_core

environment:
sdk: '>=2.18.2 <3.0.0'
sdk: '>=3.0.0 <4.0.0'
flutter: ">=1.17.0"

dependencies:
Expand Down
45 changes: 33 additions & 12 deletions test/unit/core/option/option_fold_test.dart
Original file line number Diff line number Diff line change
@@ -1,25 +1,46 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:hmi_core/hmi_core_option.dart';
import 'test_data.dart';

void main() {
group('Option fold', () {
group('Option fold strong typed', () {
test('calls onSome function if it is instance of Some', () {
for(int i=-50; i<=50; i++) {
final Option<int> option = Some(i);
final foldResult = option.fold(
onSome: (v) => '$v',
onNone: () => 'None',
);
expect(foldResult, equals('$i'));
final foldResult = switch(option) {
Some<int>(:final value) => value,
None() => null,
};
expect(foldResult, equals(i));
}
});
test('calls onNone function if it is instance of None', () {
const Option<int> option = None();
final foldResult = option.fold(
onSome: (v) => '$v',
onNone: () => 'None',
);
expect(foldResult, equals('None'));
final foldResult = switch(option) {
Some<int>(:final value) => value,
None() => null,
};
expect(foldResult, equals(null));
});
});
}
group('Option fold different types', () {
test('calls onSome function if it is instance of Some', () {
for(final value in testData) {
final Option option = Some(value);
final foldResult = switch(option) {
Some(:final value) => value,
None() => null,
};
expect(foldResult, equals(value));
}
});
test('calls onNone function if it is instance of None', () {
const Option option = None();
final foldResult = switch(option) {
Some(:final value) => value,
None() => null,
};
expect(foldResult, equals(null));
});
});
}
13 changes: 7 additions & 6 deletions test/unit/core/option/option_is_none_test.dart
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:hmi_core/hmi_core_option.dart';
import 'test_data.dart';

void main() {
group('Option isNone', () {
group('Option is None', () {
test('returns false if it is instance of Some', () {
for(int i=-50; i<=50; i++) {
final Option<int> option = Some(i);
expect(option.isNone, equals(false));
for(final value in testData) {
final Option option = Some(value);
expect(option is None, equals(false));
}
});
test('returns true if it is instance of None', () {
const Option<int> option = None();
expect(option.isNone, equals(true));
const Option option = None();
expect(option is None, equals(true));
});
});
}
13 changes: 7 additions & 6 deletions test/unit/core/option/option_is_some_test.dart
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:hmi_core/hmi_core_option.dart';
import 'test_data.dart';

void main() {
group('Option isSome', () {
group('Option is Some', () {
test('returns true if it is instance of Some', () {
for(int i=-50; i<=50; i++) {
final Option<int> option = Some(i);
expect(option.isSome, equals(true));
for(final value in testData) {
final Option option = Some(value);
expect(option is Some, equals(true));
}
});
test('returns false if it is instance of None', () {
const Option<int> option = None();
expect(option.isSome, equals(false));
const Option option = None();
expect(option is Some, equals(false));
});
});
}
20 changes: 20 additions & 0 deletions test/unit/core/option/option_none_constructor_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:hmi_core/hmi_core_option.dart';
import 'test_data.dart';

void main() {
group('Option None constructor', () {
test('creates instance of None', () {
const Option<int> option = None();
expect(option, isA<None>());
});
test('creates instance of Option of any type', () {
const none = None();
expect(none, isA<Option<int>>());
expect(none, isA<Option<bool>>());
expect(none, isA<Option<double>>());
expect(none, isA<Option<String>>());
expect(none, isA<Option<ForTestOptionOnly>>());
});
});
}
11 changes: 0 additions & 11 deletions test/unit/core/option/option_none_factory_test.dart

This file was deleted.

19 changes: 19 additions & 0 deletions test/unit/core/option/option_some_constructor_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:hmi_core/hmi_core_option.dart';
import 'test_data.dart';

void main() {
group('Option Some constructor', () {
test('creates instance of Some', () {
for(int i=-50; i<=50; i++) {
expect(Some(i), isA<Some<int>>());
expect(Some(i / 2.0), isA<Some<double>>());
expect(Some(i % 2 == 0), isA<Some<bool>>());
expect(Some('$i'), isA<Some<String>>());
expect(Some(ForTestOptionOnly('$i')), isA<Some<ForTestOptionOnly>>());
}
const userClassOption = Some(ForTestOptionOnly(''));
expect(userClassOption, isA<Some<ForTestOptionOnly>>());
});
});
}
13 changes: 0 additions & 13 deletions test/unit/core/option/option_some_factory_test.dart

This file was deleted.

27 changes: 27 additions & 0 deletions test/unit/core/option/test_data.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
final class ForTestOptionOnly {
final String value;
const ForTestOptionOnly(this.value);
}
const _maxInt64 = 0x7FFFFFFFFFFFFFFF;
const _minInt64 = -0x8000000000000000;
const testData = [
_maxInt64,
_minInt64,
0,
353465,
45,
-3456,
ForTestOptionOnly('value'),
ForTestOptionOnly(''),
ForTestOptionOnly('123'),
true,
false,
double.maxFinite,
double.minPositive
-double.maxFinite,
0.0,
1.234,
234.4,
-0.45676,
-346.786,
];
Loading