diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a179b60..1ea9a34 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -19,7 +19,7 @@ jobs: - name: Run tests run: pub run test - name: Measure coverage - run: pub run test_coverage + run: pub run test_cov - name: Upload coverage uses: codecov/codecov-action@v1.0.6 with: diff --git a/lib/interval_tree.dart b/lib/interval_tree.dart index b66861e..b4d3716 100644 --- a/lib/interval_tree.dart +++ b/lib/interval_tree.dart @@ -150,7 +150,7 @@ class Interval extends Comparable { /// final b = Interval(3, 5); /// print(b.intersection(a)); // null /// - Interval intersection(Interval other) { + Interval? intersection(Interval other) { if (!intersects(other)) return null; return Interval(_max(start, other.start), _min(end, other.end)); } @@ -177,7 +177,7 @@ class Interval extends Comparable { /// print(a.difference(b)); // [[1, 2], [4, 5]] /// print(b.difference(a)); // null /// - Iterable difference(Interval other) { + Iterable? difference(Interval other) { if (other.contains(this)) return null; if (!other.intersects(this)) return [this]; if (other.start > start && other.end >= end) { @@ -324,16 +324,16 @@ class IntervalTree with IterableMixin { } /// Creates a tree from [intervals]. - factory IntervalTree.of(Iterable intervals) => + factory IntervalTree.of(Iterable intervals) => IntervalTree()..addAll(intervals); /// Adds an [interval] into this tree. - void add(dynamic interval) { - Interval iv = _asInterval(interval); + void add(dynamic? interval) { + Interval? iv = _asInterval(interval); if (iv == null) return; bool joined = false; - BidirectionalIterator it = _tree.fromIterator(iv); + BidirectionalIterator it = _tree.fromIterator(iv); while (it.movePrevious()) { final union = _tryJoin(it.current, iv); if (union == null) break; @@ -341,7 +341,7 @@ class IntervalTree with IterableMixin { joined = true; } - it = _tree.fromIterator(iv, inclusive: false); + it = _tree.fromIterator(iv!, inclusive: false); while (it.moveNext()) { final union = _tryJoin(it.current, iv); if (union == null) break; @@ -350,13 +350,12 @@ class IntervalTree with IterableMixin { } if (!joined) { - _tree.add(iv); + _tree.add(iv!); } } /// Adds all [intervals] into this tree. void addAll(Iterable intervals) { - if (intervals == null) return; for (final interval in intervals) { add(interval); } @@ -365,9 +364,8 @@ class IntervalTree with IterableMixin { /// Removes an [interval] from this tree. void remove(dynamic interval) { final iv = _asInterval(interval); - if (iv == null) return; - BidirectionalIterator it = _tree.fromIterator(iv); + BidirectionalIterator it = _tree.fromIterator(iv!); while (it.movePrevious()) { final current = it.current; if (!_trySplit(it.current, iv)) break; @@ -384,7 +382,6 @@ class IntervalTree with IterableMixin { /// Removes all [intervals] from this tree. void removeAll(Iterable intervals) { - if (intervals == null) return; for (final interval in intervals) { remove(interval); } @@ -423,15 +420,13 @@ class IntervalTree with IterableMixin { @override bool contains(dynamic interval) { final iv = _asInterval(interval); - if (iv == null) return false; - - BidirectionalIterator it = _tree.fromIterator(iv); - while (it.movePrevious() && iv.intersects(it.current)) { - if (it.current.contains(iv)) return true; + BidirectionalIterator it = _tree.fromIterator(iv!); + while (it.movePrevious() && iv.intersects(it.current!)) { + if (it.current!.contains(iv)) return true; } it = _tree.fromIterator(iv, inclusive: false); - while (it.moveNext() && it.current.intersects(iv)) { - if (it.current.contains(iv)) return true; + while (it.moveNext() && it.current!.intersects(iv)) { + if (it.current!.contains(iv)) return true; } return false; } @@ -448,11 +443,11 @@ class IntervalTree with IterableMixin { @override bool get isNotEmpty => _tree.isNotEmpty; - /// Returns the first interval in tree, or `null` if this tree is empty. + /// Returns the first interval in tree, otherwise throw StateError. @override Interval get first => _tree.first; - /// Returns the first interval in tree, or `null` if this tree is empty. + /// Returns the first interval in tree, otherwise throw StateError. @override Interval get last => _tree.last; @@ -468,17 +463,17 @@ class IntervalTree with IterableMixin { @override String toString() => 'IntervalTree' + super.toString(); - Interval _asInterval(dynamic interval) { + Interval? _asInterval(dynamic? interval) { if (interval is Iterable) { if (interval.length != 2 || interval.first is Iterable) { throw ArgumentError('$interval is not an interval'); } return Interval(interval.first, interval.last); } - return interval as Interval; + return interval; } - Interval _tryJoin(Interval a, Interval b) { + Interval? _tryJoin(Interval? a, Interval? b) { if (a == null || b == null) return null; if (a.contains(b)) return a; if (!a.intersects(b)) return null; @@ -490,7 +485,6 @@ class IntervalTree with IterableMixin { } bool _trySplit(Interval a, Interval b) { - if (a == null || b == null) return false; if (!a.intersects(b)) return false; _tree.remove(a); _tree.addAll([...?a.difference(b)]); diff --git a/pubspec.yaml b/pubspec.yaml index 4eedc24..949c128 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -9,10 +9,10 @@ repository: https://github.com/jpnurmi/interval_tree issue_tracker: https://github.com/jpnurmi/interval_tree/issues environment: - sdk: ">=2.7.0 <3.0.0" + sdk: '>=2.12.0 <3.0.0' dependencies: meta: ^1.1.8 - quiver: ^2.0.5 + quiver: ^3.0.1 dev_dependencies: test: ^1.14.2 - test_coverage: ^0.4.1 + test_cov: ^1.0.1 diff --git a/test/interval_tree_test.dart b/test/interval_tree_test.dart index 33d17e4..8a564c9 100644 --- a/test/interval_tree_test.dart +++ b/test/interval_tree_test.dart @@ -248,8 +248,8 @@ void main() { IntervalTree empty = IntervalTree(); expect(empty.isEmpty, isTrue); expect(empty.isNotEmpty, isFalse); - expect(empty.first, isNull); - expect(empty.last, isNull); + expect(() => empty.first, throwsA(isA())); + expect(() => empty.last, throwsA(isA())); expect(empty.length, 0); expect(() => empty.single, throwsStateError);