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

Commit

Permalink
Latest lints, require Dart 3.1, use mixin (#322)
Browse files Browse the repository at this point in the history
  • Loading branch information
kevmoo authored Nov 8, 2023
1 parent e8d7e92 commit f309148
Show file tree
Hide file tree
Showing 26 changed files with 143 additions and 180 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ jobs:
matrix:
# Add macos-latest and/or windows-latest if relevant for this package.
os: [ubuntu-latest]
sdk: [2.18.0, dev]
sdk: [3.1.0, dev]
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
- uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

- Adds `shuffled` to `IterableExtension`.
- Shuffle `IterableExtension.sample` results.
- Require Dart `^3.1.0`
- Mark "mixin" classes as `mixin`.

## 1.18.0

Expand Down
15 changes: 1 addition & 14 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -1,29 +1,16 @@
include: package:lints/recommended.yaml
include: package:dart_flutter_team_lints/analysis_options.yaml

analyzer:
language:
strict-casts: true

linter:
rules:
- always_declare_return_types
- avoid_dynamic_calls
- avoid_unused_constructor_parameters
- cancel_subscriptions
- directives_ordering
- lines_longer_than_80_chars
- literal_only_boolean_expressions
- missing_whitespace_between_adjacent_strings
- no_adjacent_strings_in_list
- no_runtimeType_toString
- omit_local_variable_types
- package_api_docs
- prefer_relative_imports
- prefer_single_quotes
- test_types_in_equals
- throw_in_finally
- type_annotate_public_apis
- unawaited_futures
- unnecessary_await_in_return
- unnecessary_lambdas
- use_super_parameters
2 changes: 1 addition & 1 deletion lib/algorithms.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@
library dart.pkg.collection.algorithms;

export 'src/algorithms.dart'
show binarySearch, insertionSort, lowerBound, mergeSort, shuffle, reverse;
show binarySearch, insertionSort, lowerBound, mergeSort, reverse, shuffle;
2 changes: 1 addition & 1 deletion lib/collection.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// BSD-style license that can be found in the LICENSE file.

export 'src/algorithms.dart'
show binarySearch, insertionSort, lowerBound, mergeSort, shuffle, reverse;
show binarySearch, insertionSort, lowerBound, mergeSort, reverse, shuffle;
export 'src/boollist.dart';
export 'src/canonicalized_map.dart';
export 'src/combined_wrappers/combined_iterable.dart';
Expand Down
2 changes: 1 addition & 1 deletion lib/src/comparators.dart
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ int compareAsciiUpperCase(String a, String b) {
bUpperCase -= _asciiCaseBit;
}
if (aUpperCase != bUpperCase) return (aUpperCase - bUpperCase).sign;
if (defaultResult == 0) defaultResult = (aChar - bChar);
if (defaultResult == 0) defaultResult = aChar - bChar;
}
if (b.length > a.length) return -1;
return defaultResult.sign;
Expand Down
2 changes: 1 addition & 1 deletion lib/src/empty_unmodifiable_set.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class EmptyUnmodifiableSet<E> extends IterableBase<E>
E singleWhere(bool Function(E) test, {E Function()? orElse}) =>
orElse != null ? orElse() : throw StateError('No element');
@override
Iterable<T> whereType<T>() => Iterable.empty();
Iterable<T> whereType<T>() => Iterable<T>.empty();
@override
Set<E> toSet() => {};
@override
Expand Down
12 changes: 6 additions & 6 deletions lib/src/equality.dart
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,10 @@ class IterableEquality<E> implements Equality<Iterable<E>> {
var c = _elementEquality.hash(element);
hash = (hash + c) & _hashMask;
hash = (hash + (hash << 10)) & _hashMask;
hash ^= (hash >> 6);
hash ^= hash >> 6;
}
hash = (hash + (hash << 3)) & _hashMask;
hash ^= (hash >> 11);
hash ^= hash >> 11;
hash = (hash + (hash << 15)) & _hashMask;
return hash;
}
Expand Down Expand Up @@ -190,10 +190,10 @@ class ListEquality<E> implements Equality<List<E>> {
var c = _elementEquality.hash(list[i]);
hash = (hash + c) & _hashMask;
hash = (hash + (hash << 10)) & _hashMask;
hash ^= (hash >> 6);
hash ^= hash >> 6;
}
hash = (hash + (hash << 3)) & _hashMask;
hash ^= (hash >> 11);
hash ^= hash >> 11;
hash = (hash + (hash << 15)) & _hashMask;
return hash;
}
Expand Down Expand Up @@ -240,7 +240,7 @@ abstract class _UnorderedEquality<E, T extends Iterable<E>>
hash = (hash + c) & _hashMask;
}
hash = (hash + (hash << 3)) & _hashMask;
hash ^= (hash >> 11);
hash ^= hash >> 11;
hash = (hash + (hash << 15)) & _hashMask;
return hash;
}
Expand Down Expand Up @@ -349,7 +349,7 @@ class MapEquality<K, V> implements Equality<Map<K, V>> {
hash = (hash + 3 * keyHash + 7 * valueHash) & _hashMask;
}
hash = (hash + (hash << 3)) & _hashMask;
hash ^= (hash >> 11);
hash ^= hash >> 11;
hash = (hash + (hash << 15)) & _hashMask;
return hash;
}
Expand Down
6 changes: 3 additions & 3 deletions lib/src/unmodifiable_wrappers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class NonGrowableListView<E> extends DelegatingList<E>

/// Mixin class that implements a throwing version of all list operations that
/// change the List's length.
abstract class NonGrowableListMixin<E> implements List<E> {
abstract mixin class NonGrowableListMixin<E> implements List<E> {
static Never _throw() {
throw UnsupportedError('Cannot change the length of a fixed-length list');
}
Expand Down Expand Up @@ -116,7 +116,7 @@ class UnmodifiableSetView<E> extends DelegatingSet<E>

/// Mixin class that implements a throwing version of all set operations that
/// change the Set.
abstract /*mixin*/ class UnmodifiableSetMixin<E> implements Set<E> {
abstract mixin class UnmodifiableSetMixin<E> implements Set<E> {
static Never _throw() {
throw UnsupportedError('Cannot modify an unmodifiable Set');
}
Expand Down Expand Up @@ -164,7 +164,7 @@ abstract /*mixin*/ class UnmodifiableSetMixin<E> implements Set<E> {

/// Mixin class that implements a throwing version of all map operations that
/// change the Map.
abstract /*mixin*/ class UnmodifiableMapMixin<K, V> implements Map<K, V> {
abstract mixin class UnmodifiableMapMixin<K, V> implements Map<K, V> {
static Never _throw() {
throw UnsupportedError('Cannot modify an unmodifiable Map');
}
Expand Down
4 changes: 2 additions & 2 deletions lib/src/wrappers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -793,7 +793,7 @@ class MapValueSet<K, V> extends _DelegatingIterableBase<V> implements Set<V> {

@override
void removeWhere(bool Function(V) test) {
var toRemove = [];
var toRemove = <K>[];
_baseMap.forEach((key, value) {
if (test(value)) toRemove.add(key);
});
Expand All @@ -811,7 +811,7 @@ class MapValueSet<K, V> extends _DelegatingIterableBase<V> implements Set<V> {
valuesToRetain.add(_baseMap[key] ?? null as V);
}

var keysToRemove = [];
var keysToRemove = <K>[];
_baseMap.forEach((k, v) {
if (!valuesToRetain.contains(v)) keysToRemove.add(k);
});
Expand Down
4 changes: 2 additions & 2 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ topics:
- collections

environment:
sdk: ">=2.18.0 <4.0.0"
sdk: ^3.1.0

dev_dependencies:
lints: ^2.0.1
dart_flutter_team_lints: ^2.0.0
test: ^1.16.0
26 changes: 13 additions & 13 deletions test/algorithms_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
// BSD-style license that can be found in the LICENSE file.

/// Tests algorithm utilities.
library;

import 'dart:math';

import 'package:collection/collection.dart';
Expand All @@ -13,7 +15,7 @@ void main() {
void testShuffle(List list) {
var copy = list.toList();
shuffle(list);
expect(UnorderedIterableEquality().equals(list, copy), isTrue);
expect(const UnorderedIterableEquality().equals(list, copy), isTrue);
}

test('Shuffle 0', () {
Expand Down Expand Up @@ -270,34 +272,34 @@ void main() {
test('$name2: Same #$n', () {
var list = List<OC>.generate(n, (i) => OC(i, 0));
// Should succeed. Bad implementations of, e.g., quicksort can diverge.
sort(list, ocOrder, compareInt);
sort(list, _ocOrder, _compareInt);
});
test('$name: Pre-sorted #$n', () {
var list = List<OC>.generate(n, (i) => OC(-i, i));
var expected = list.toList();
sort(list, ocOrder, compareInt);
sort(list, _ocOrder, _compareInt);
// Elements have not moved.
expect(list, expected);
});
test('$name: Reverse-sorted #$n', () {
var list = List<OC>.generate(n, (i) => OC(i, -i));
sort(list, ocOrder, compareInt);
expectSorted(list, ocOrder, compareInt);
sort(list, _ocOrder, _compareInt);
expectSorted(list, _ocOrder, _compareInt);
});
test('$name: Random #$n', () {
var random = Random();
var list = List<OC>.generate(n, (i) => OC(i, random.nextInt(n)));
sort(list, ocOrder, compareInt);
expectSorted(list, ocOrder, compareInt);
sort(list, _ocOrder, _compareInt);
expectSorted(list, _ocOrder, _compareInt);
});
test('$name: Sublist #$n', () {
var random = Random();
var list = List<OC>.generate(n, (i) => OC(i, random.nextInt(n)));
var original = list.toList();
var start = n ~/ 4;
var end = start * 3;
sort(list, ocOrder, compareInt, start, end);
expectSorted(list, ocOrder, compareInt, start, end);
sort(list, _ocOrder, _compareInt, start, end);
expectSorted(list, _ocOrder, _compareInt, start, end);
expect(list.sublist(0, start), original.sublist(0, start));
expect(list.sublist(end), original.sublist(end));
});
Expand Down Expand Up @@ -374,7 +376,6 @@ class C {
}

int compareC(C one, C other) => one.id - other.id;
int cId(C c) => c.id;

/// Class naturally ordered by its first constructor argument.
class OC implements Comparable<OC> {
Expand All @@ -389,10 +390,9 @@ class OC implements Comparable<OC> {
String toString() => 'OC[$id,$order]';
}

int ocId(OC oc) => oc.id;
int ocOrder(OC oc) => oc.order;
int _ocOrder(OC oc) => oc.order;

int compareInt(int a, int b) => a - b;
int _compareInt(int a, int b) => a - b;

/// Check that a list is sorted according to [compare] of [keyOf] of elements.
void expectSorted<T, K>(
Expand Down
2 changes: 2 additions & 0 deletions test/analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ include: ../analysis_options.yaml
analyzer:
errors:
avoid_dynamic_calls: ignore
inference_failure_on_collection_literal: ignore
inference_failure_on_instance_creation: ignore
2 changes: 2 additions & 0 deletions test/boollist_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,12 @@ void main() {
var b = BoolList(1024, fill: false);

expect(() {
// ignore: unnecessary_statements
b[-1];
}, throwsRangeError);

expect(() {
// ignore: unnecessary_statements
b[1024];
}, throwsRangeError);
});
Expand Down
6 changes: 3 additions & 3 deletions test/canonicalized_map_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,9 @@ void main() {

test('addEntries adds key-value pairs to the map', () {
map.addEntries([
MapEntry('1', 'value 1'),
MapEntry('01', 'value 01'),
MapEntry('2', 'value 2'),
const MapEntry('1', 'value 1'),
const MapEntry('01', 'value 01'),
const MapEntry('2', 'value 2'),
]);
expect(map, {'01': 'value 01', '2': 'value 2'});
});
Expand Down
4 changes: 2 additions & 2 deletions test/combined_wrapper/iterable_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ void main() {
});

test('should function as an empty iterable when no iterables are passed', () {
var empty = CombinedIterableView([]);
var empty = const CombinedIterableView([]);
expect(empty, isEmpty);
});

test('should function as an empty iterable with all empty iterables', () {
var empty = CombinedIterableView([[], [], []]);
var empty = const CombinedIterableView([[], [], []]);
expect(empty, isEmpty);
});

Expand Down
55 changes: 51 additions & 4 deletions test/combined_wrapper/map_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ import 'dart:collection';
import 'package:collection/collection.dart';
import 'package:test/test.dart';

import '../unmodifiable_collection_test.dart' as common;

void main() {
var map1 = const {1: 1, 2: 2, 3: 3};
var map2 = const {4: 4, 5: 5, 6: 6};
Expand All @@ -24,10 +22,10 @@ void main() {
..addAll(map3);

// In every way possible this should test the same as an UnmodifiableMapView.
common.testReadMap(
_testReadMap(
concat, CombinedMapView([map1, map2, map3, map4]), 'CombinedMapView');

common.testReadMap(
_testReadMap(
concat,
CombinedMapView([map1, {}, map2, {}, map3, {}, map4, {}]),
'CombinedMapView (some empty)');
Expand Down Expand Up @@ -69,3 +67,52 @@ void main() {
expect(keys.toList(), keys.toList());
});
}

void _testReadMap(Map<int, int> original, Map<int, int> wrapped, String name) {
test('$name length', () {
expect(wrapped.length, equals(original.length));
});

test('$name isEmpty', () {
expect(wrapped.isEmpty, equals(original.isEmpty));
});

test('$name isNotEmpty', () {
expect(wrapped.isNotEmpty, equals(original.isNotEmpty));
});

test('$name operator[]', () {
expect(wrapped[0], equals(original[0]));
expect(wrapped[999], equals(original[999]));
});

test('$name containsKey', () {
expect(wrapped.containsKey(0), equals(original.containsKey(0)));
expect(wrapped.containsKey(999), equals(original.containsKey(999)));
});

test('$name containsValue', () {
expect(wrapped.containsValue(0), equals(original.containsValue(0)));
expect(wrapped.containsValue(999), equals(original.containsValue(999)));
});

test('$name forEach', () {
var origCnt = 0;
var wrapCnt = 0;
wrapped.forEach((k, v) {
wrapCnt += 1 << k + 3 * v;
});
original.forEach((k, v) {
origCnt += 1 << k + 3 * v;
});
expect(wrapCnt, equals(origCnt));
});

test('$name keys', () {
expect(wrapped.keys, orderedEquals(original.keys));
});

test('$name values', () {
expect(wrapped.values, orderedEquals(original.values));
});
}
Loading

0 comments on commit f309148

Please sign in to comment.