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

Latest lints, require Dart 3.1, use mixin #322

Merged
merged 2 commits into from
Nov 8, 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/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;
kevmoo marked this conversation as resolved.
Show resolved Hide resolved

/// 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