Skip to content
This repository has been archived by the owner on Oct 22, 2024. It is now read-only.

Commit

Permalink
Merge the null_safety branch into master (#143)
Browse files Browse the repository at this point in the history
Migrates the package to null safety
  • Loading branch information
jakemac53 authored Jun 23, 2020
1 parent 00540dc commit 80f5b6d
Show file tree
Hide file tree
Showing 29 changed files with 533 additions and 357 deletions.
46 changes: 31 additions & 15 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,27 +1,43 @@
language: dart

dart:
- 2.3.0
- dev

dart_task:
- test

matrix:
jobs:
include:
# Only validate formatting using the dev release
- dart: dev
dart_task: dartfmt
- dart: dev
dart_task:
dartanalyzer: --fatal-infos --fatal-warnings .
- dart: 2.3.0
dart_task:
dartanalyzer: --fatal-warnings .
- stage: analyze_and_format
name: "Analyze lib/"
dart: dev
os: linux
script: dartanalyzer --fatal-warnings --fatal-infos lib/
- stage: analyze_and_format
name: "Analyze test/"
dart: dev
os: linux
script: dartanalyzer --enable-experiment=non-nullable --fatal-warnings --fatal-infos test/
- stage: analyze_and_format
name: "Format"
dart: dev
os: linux
script: dartfmt -n --set-exit-if-changed .
- stage: test
name: "Vm Tests"
dart: dev
os: linux
script: pub run --enable-experiment=non-nullable test -p vm
- stage: test
name: "Web Tests"
dart: dev
os: linux
script: pub run --enable-experiment=non-nullable test -p chrome

stages:
- analyze_and_format
- test

# Only building master means that we don't run two builds for each pull request.
branches:
only: [master]
only: [master, null_safety]

# Incremental pub cache and builds.
cache:
Expand Down
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
## 1.15.0-nnbd

Pre-release for the null safety migration of this package.

Note that `1.15.0` may not be the final stable null safety release version,
we reserve the right to release it as a `2.0.0` breaking change.

This release will be pinned to only allow pre-release sdk versions starting
from `2.9.0-dev.18.0`, which is the first version where this package will
appear in the null safety allow list.

## 1.14.13

* Deprecate `mapMap`. The Map interface has a `map` call and map literals can
Expand Down
3 changes: 3 additions & 0 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ analyzer:
unused_import: error
unused_local_variable: error
dead_code: error
enable-experiment:
- non-nullable

linter:
rules:
# Errors
Expand Down
39 changes: 20 additions & 19 deletions lib/src/algorithms.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ import 'utils.dart';
/// (`CastError` on some SDK versions).
///
/// Returns -1 if [value] is not in the list by default.
int binarySearch<T>(List<T> sortedList, T value, {int Function(T, T) compare}) {
int binarySearch<T>(List<T> sortedList, T value,
{int Function(T, T)? compare}) {
compare ??= defaultCompare<T>();
var min = 0;
var max = sortedList.length;
Expand Down Expand Up @@ -46,7 +47,7 @@ int binarySearch<T>(List<T> sortedList, T value, {int Function(T, T) compare}) {
///
/// Returns [sortedList.length] if all the items in [sortedList] compare less
/// than [value].
int lowerBound<T>(List<T> sortedList, T value, {int Function(T, T) compare}) {
int lowerBound<T>(List<T> sortedList, T value, {int Function(T, T)? compare}) {
compare ??= defaultCompare<T>();
var min = 0;
var max = sortedList.length;
Expand All @@ -66,7 +67,7 @@ int lowerBound<T>(List<T> sortedList, T value, {int Function(T, T) compare}) {
/// Shuffles a list randomly.
///
/// A sub-range of a list can be shuffled by providing [start] and [end].
void shuffle(List list, [int start = 0, int end]) {
void shuffle(List list, [int start = 0, int? end]) {
var random = math.Random();
end ??= list.length;
var length = end - start;
Expand All @@ -80,7 +81,7 @@ void shuffle(List list, [int start = 0, int end]) {
}

/// Reverses a list, or a part of a list, in-place.
void reverse(List list, [int start = 0, int end]) {
void reverse(List list, [int start = 0, int? end]) {
end ??= list.length;
_reverse(list, start, end);
}
Expand Down Expand Up @@ -111,7 +112,7 @@ void _reverse(List list, int start, int end) {
/// This insertion sort is stable: Equal elements end up in the same order
/// as they started in.
void insertionSort<T>(List<T> list,
{int Function(T, T) compare, int start = 0, int end}) {
{int Function(T, T)? compare, int start = 0, int? end}) {
// If the same method could have both positional and named optional
// parameters, this should be (list, [start, end], {compare}).
compare ??= defaultCompare<T>();
Expand Down Expand Up @@ -155,8 +156,8 @@ const int _MERGE_SORT_LIMIT = 32;
/// This merge sort is stable: Equal elements end up in the same order
/// as they started in.
void mergeSort<T>(List<T> list,
{int start = 0, int end, int Function(T, T) compare}) {
end ??= list.length;
{int start = 0, int? end, int Function(T, T)? compare}) {
end = RangeError.checkValidRange(start, end, list.length);
compare ??= defaultCompare<T>();

var length = end - start;
Expand All @@ -175,12 +176,12 @@ void mergeSort<T>(List<T> list,
var firstLength = middle - start;
var secondLength = end - middle;
// secondLength is always the same as firstLength, or one greater.
var scratchSpace = List<T>(secondLength);
_mergeSort(list, compare, middle, end, scratchSpace, 0);
var scratchSpace = List<T>.filled(secondLength, list[start]);
_mergeSort<T>(list, compare, middle, end, scratchSpace, 0);
var firstTarget = end - firstLength;
_mergeSort(list, compare, start, middle, list, firstTarget);
_merge(compare, list, firstTarget, end, scratchSpace, 0, secondLength, list,
start);
_mergeSort<T>(list, compare, start, middle, list, firstTarget);
_merge<T>(compare, list, firstTarget, end, scratchSpace, 0, secondLength,
list, start);
}

/// Performs an insertion sort into a potentially different list than the
Expand All @@ -198,7 +199,7 @@ void _movingInsertionSort<T>(List<T> list, int Function(T, T) compare,
var max = targetOffset + i;
while (min < max) {
var mid = min + ((max - min) >> 1);
if (compare(element, target[mid]) < 0) {
if (compare(element, target[mid]!) < 0) {
max = mid;
} else {
min = mid + 1;
Expand All @@ -220,7 +221,7 @@ void _mergeSort<T>(List<T> list, int Function(T, T) compare, int start, int end,
List<T> target, int targetOffset) {
var length = end - start;
if (length < _MERGE_SORT_LIMIT) {
_movingInsertionSort(list, compare, start, end, target, targetOffset);
_movingInsertionSort<T>(list, compare, start, end, target, targetOffset);
return;
}
var middle = start + (length >> 1);
Expand All @@ -229,11 +230,11 @@ void _mergeSort<T>(List<T> list, int Function(T, T) compare, int start, int end,
// Here secondLength >= firstLength (differs by at most one).
var targetMiddle = targetOffset + firstLength;
// Sort the second half into the end of the target area.
_mergeSort(list, compare, middle, end, target, targetMiddle);
_mergeSort<T>(list, compare, middle, end, target, targetMiddle);
// Sort the first half into the end of the source area.
_mergeSort(list, compare, start, middle, list, middle);
_mergeSort<T>(list, compare, start, middle, list, middle);
// Merge the two parts into the target area.
_merge(compare, list, middle, middle + firstLength, target, targetMiddle,
_merge<T>(compare, list, middle, middle + firstLength, target, targetMiddle,
targetMiddle + secondLength, target, targetOffset);
}

Expand Down Expand Up @@ -261,7 +262,7 @@ void _merge<T>(
var cursor1 = firstStart;
var cursor2 = secondStart;
var firstElement = firstList[cursor1++];
var secondElement = secondList[cursor2++];
var secondElement = secondList[cursor2++]!;
while (true) {
if (compare(firstElement, secondElement) <= 0) {
target[targetOffset++] = firstElement;
Expand All @@ -270,7 +271,7 @@ void _merge<T>(
} else {
target[targetOffset++] = secondElement;
if (cursor2 != secondEnd) {
secondElement = secondList[cursor2++];
secondElement = secondList[cursor2++]!;
continue;
}
// Second list empties first. Flushing first list here.
Expand Down
24 changes: 10 additions & 14 deletions lib/src/canonicalized_map.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,10 @@ import 'utils.dart';
/// more efficient than a [LinkedHashMap] with a custom equality operator
/// because it only canonicalizes each key once, rather than doing so for each
/// comparison.
///
/// By default, `null` is allowed as a key. It can be forbidden via the
/// `isValidKey` parameter.
class CanonicalizedMap<C, K, V> implements Map<K, V> {
final C Function(K) _canonicalize;

final bool Function(Object) _isValidKeyFn;
final bool Function(K)? _isValidKeyFn;

final _base = <C, Pair<K, V>>{};

Expand All @@ -31,7 +28,7 @@ class CanonicalizedMap<C, K, V> implements Map<K, V> {
/// methods that take arbitrary objects. It can be used to filter out keys
/// that can't be canonicalized.
CanonicalizedMap(C Function(K key) canonicalize,
{bool Function(Object key) isValidKey})
{bool Function(K key)? isValidKey})
: _canonicalize = canonicalize,
_isValidKeyFn = isValidKey;

Expand All @@ -45,14 +42,14 @@ class CanonicalizedMap<C, K, V> implements Map<K, V> {
/// methods that take arbitrary objects. It can be used to filter out keys
/// that can't be canonicalized.
CanonicalizedMap.from(Map<K, V> other, C Function(K key) canonicalize,
{bool Function(Object key) isValidKey})
{bool Function(K key)? isValidKey})
: _canonicalize = canonicalize,
_isValidKeyFn = isValidKey {
addAll(other);
}

@override
V operator [](Object key) {
V? operator [](Object? key) {
if (!_isValidKey(key)) return null;
var pair = _base[_canonicalize(key as K)];
return pair == null ? null : pair.last;
Expand Down Expand Up @@ -82,13 +79,13 @@ class CanonicalizedMap<C, K, V> implements Map<K, V> {
}

@override
bool containsKey(Object key) {
bool containsKey(Object? key) {
if (!_isValidKey(key)) return false;
return _base.containsKey(_canonicalize(key as K));
}

@override
bool containsValue(Object value) =>
bool containsValue(Object? value) =>
_base.values.any((pair) => pair.last == value);

@override
Expand Down Expand Up @@ -124,7 +121,7 @@ class CanonicalizedMap<C, K, V> implements Map<K, V> {
}

@override
V remove(Object key) {
V? remove(Object? key) {
if (!_isValidKey(key)) return null;
var pair = _base.remove(_canonicalize(key as K));
return pair == null ? null : pair.last;
Expand All @@ -138,7 +135,7 @@ class CanonicalizedMap<C, K, V> implements Map<K, V> {
Map<K2, V2> retype<K2, V2>() => cast<K2, V2>();

@override
V update(K key, V Function(V) update, {V Function() ifAbsent}) => _base
V update(K key, V Function(V) update, {V Function()? ifAbsent}) => _base
.update(_canonicalize(key), (pair) => Pair(key, update(pair.last)),
ifAbsent: ifAbsent == null ? null : () => Pair(key, ifAbsent()))
.last;
Expand Down Expand Up @@ -178,9 +175,8 @@ class CanonicalizedMap<C, K, V> implements Map<K, V> {
return result.toString();
}

bool _isValidKey(Object key) =>
(key == null || key is K) &&
(_isValidKeyFn == null || _isValidKeyFn(key));
bool _isValidKey(Object? key) =>
(key is K) && (_isValidKeyFn == null || _isValidKeyFn!(key));
}

/// A collection used to identify cyclic maps during toString() calls.
Expand Down
25 changes: 19 additions & 6 deletions lib/src/combined_wrappers/combined_iterable.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class CombinedIterableView<T> extends IterableBase<T> {
// efficient implementation instead of running through the entire iterator.

@override
bool contains(Object element) => _iterables.any((i) => i.contains(element));
bool contains(Object? element) => _iterables.any((i) => i.contains(element));

@override
bool get isEmpty => _iterables.every((i) => i.isEmpty);
Expand All @@ -45,17 +45,30 @@ class _CombinedIterator<T> implements Iterator<T> {
/// avoid instantiating unnecessary iterators.
final Iterator<Iterator<T>> _iterators;

_CombinedIterator(this._iterators);
/// The current iterator in [_iterators], or `null` if done iterating.
Iterator<T>? _currentItr;

_CombinedIterator(this._iterators) {
_advance();
}

@override
T get current => _iterators.current?.current;
T get current => _iterators.current.current;

@override
bool moveNext() {
var current = _iterators.current;
if (current != null && current.moveNext()) {
if (_currentItr == null) return false;
if (_currentItr!.moveNext()) {
return true;
} else {
_advance();
}
return _iterators.moveNext() && moveNext();
return moveNext();
}

/// Advances [_currentItr] or sets it to `null` if there are no more entries
/// in [_iterators].
void _advance() {
_currentItr = _iterators.moveNext() ? _iterators.current : null;
}
}
5 changes: 2 additions & 3 deletions lib/src/combined_wrappers/combined_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import 'dart:collection';
/// both `O(lists)` rather than `O(1)`. A [CombinedListView] is unmodifiable.
class CombinedListView<T> extends ListBase<T>
implements UnmodifiableListView<T> {
static void _throw() {
static Never _throw() {
throw UnsupportedError('Cannot modify an unmodifiable List');
}

Expand Down Expand Up @@ -57,9 +57,8 @@ class CombinedListView<T> extends ListBase<T>
}

@override
bool remove(Object element) {
bool remove(Object? element) {
_throw();
return null;
}

@override
Expand Down
4 changes: 2 additions & 2 deletions lib/src/combined_wrappers/combined_map.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class CombinedMapView<K, V> extends UnmodifiableMapBase<K, V> {
CombinedMapView(this._maps);

@override
V operator [](Object key) {
V? operator [](Object? key) {
for (var map in _maps) {
// Avoid two hash lookups on a positive hit.
var value = map[key];
Expand Down Expand Up @@ -75,7 +75,7 @@ class _DeduplicatingIterableView<T> extends IterableBase<T> {
// duplicates.

@override
bool contains(Object element) => _iterable.contains(element);
bool contains(Object? element) => _iterable.contains(element);

@override
bool get isEmpty => _iterable.isEmpty;
Expand Down
Loading

0 comments on commit 80f5b6d

Please sign in to comment.