Fix doc comment references among other new lints (#253)

Bump min SDK to 2.18
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 6f230c1..824e77b 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -46,7 +46,7 @@
       matrix:
         # Add macos-latest and/or windows-latest if relevant for this package.
         os: [ubuntu-latest]
-        sdk: [2.12.0, dev]
+        sdk: [2.18.0, dev]
     steps:
       - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8
       - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a3ce638..72eb4a8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.17.1-dev
+
+* Require Dart 2.18
+
 ## 1.17.0
 
 * Add `Iterable.elementAtOrNull` and `List.elementAtOrNull` extension methods.
diff --git a/analysis_options.yaml b/analysis_options.yaml
index a7e3292..ea2d1c4 100644
--- a/analysis_options.yaml
+++ b/analysis_options.yaml
@@ -1,14 +1,29 @@
 include: package:lints/recommended.yaml
 
+analyzer:
+  language:
+    strict-casts: true
+
 linter:
   rules:
+    - always_declare_return_types
     - avoid_dynamic_calls
-
-    # Errors
+    - 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
-
-    # Style
-    - avoid_private_typedef_functions
-    - directives_ordering
-    - only_throw_errors
+    - type_annotate_public_apis
+    - unawaited_futures
+    - unnecessary_await_in_return
+    - unnecessary_lambdas
+    - use_super_parameters
diff --git a/lib/src/algorithms.dart b/lib/src/algorithms.dart
index eb9e1de..5833bbd 100644
--- a/lib/src/algorithms.dart
+++ b/lib/src/algorithms.dart
@@ -65,8 +65,8 @@
 /// If [compare] is omitted, this defaults to calling [Comparable.compareTo] on
 /// the objects. In this case, the objects must be [Comparable].
 ///
-/// Returns [sortedList.length] if all the items in [sortedList] compare less
-/// than [value].
+/// Returns the length of [sortedList] if all the items in [sortedList] compare
+/// less than [value].
 int lowerBound<E>(List<E> sortedList, E value, {int Function(E, E)? compare}) {
   compare ??= defaultCompare;
   return lowerBoundBy<E, E>(sortedList, identity, compare, value);
@@ -76,11 +76,13 @@
 ///
 /// Uses binary search to find the location of [value].
 /// This takes on the order of `log(n)` comparisons.
-/// Elements are compared using the [compare] function of the [keyOf] property of
-/// the elements.
-/// If the list isn't sorted according to this order, the result is unpredictable.
+/// Elements are compared using the [compare] function of the [keyOf] property
+/// of the elements.
+/// If the list isn't sorted according to this order, the result is
+/// unpredictable.
 ///
-/// Returns [sortedList.length] if all the items in [sortedList] are before [value].
+/// Returns the length of [sortedList] if all the items in [sortedList] are
+/// before [value].
 ///
 /// If [start] and [end] are supplied, only that range is searched,
 /// and only that range need to be sorted.
@@ -231,12 +233,12 @@
   var secondLength = end - middle;
   // secondLength is always the same as firstLength, or one greater.
   var scratchSpace = List<E>.filled(secondLength, elements[start]);
-  E Function(E) id = identity;
-  _mergeSort(elements, id, compare, middle, end, scratchSpace, 0);
+  _mergeSort(elements, identity<E>, compare, middle, end, scratchSpace, 0);
   var firstTarget = end - firstLength;
-  _mergeSort(elements, id, compare, start, middle, elements, firstTarget);
-  _merge(id, compare, elements, firstTarget, end, scratchSpace, 0, secondLength,
-      elements, start);
+  _mergeSort(
+      elements, identity<E>, compare, start, middle, elements, firstTarget);
+  _merge(identity<E>, compare, elements, firstTarget, end, scratchSpace, 0,
+      secondLength, elements, start);
 }
 
 /// Sort [elements] using a merge-sort algorithm.
@@ -408,7 +410,7 @@
   _quickSort<E, E>(elements, identity, compare, Random(), start, end);
 }
 
-/// Sort [elements] using a quick-sort algorithm.
+/// Sort [list] using a quick-sort algorithm.
 ///
 /// The elements are compared using [compare] on the value provided by [keyOf]
 /// on the element.
diff --git a/lib/src/boollist.dart b/lib/src/boollist.dart
index 5f9dba3..3ce9cf2 100644
--- a/lib/src/boollist.dart
+++ b/lib/src/boollist.dart
@@ -74,8 +74,9 @@
 
   /// Generates a [BoolList] of values.
   ///
-  /// Creates a [BoolList] with [length] positions and fills it with values created by
-  /// calling [generator] for each index in the range `0` .. `length - 1` in increasing order.
+  /// Creates a [BoolList] with [length] positions and fills it with values
+  /// created by calling [generator] for each index in the range
+  /// `0` .. `length - 1` in increasing order.
   ///
   /// The created list is fixed-length unless [growable] is true.
   factory BoolList.generate(
diff --git a/lib/src/canonicalized_map.dart b/lib/src/canonicalized_map.dart
index de63908..dcb07cf 100644
--- a/lib/src/canonicalized_map.dart
+++ b/lib/src/canonicalized_map.dart
@@ -129,7 +129,7 @@
   void removeWhere(bool Function(K key, V value) test) =>
       _base.removeWhere((_, pair) => test(pair.key, pair.value));
 
-  @Deprecated("Use cast instead")
+  @Deprecated('Use cast instead')
   Map<K2, V2> retype<K2, V2>() => cast<K2, V2>();
 
   @override
diff --git a/lib/src/combined_wrappers/combined_iterable.dart b/lib/src/combined_wrappers/combined_iterable.dart
index 97d843f..281f8a2 100644
--- a/lib/src/combined_wrappers/combined_iterable.dart
+++ b/lib/src/combined_wrappers/combined_iterable.dart
@@ -17,7 +17,7 @@
   /// The iterables that this combines.
   final Iterable<Iterable<T>> _iterables;
 
-  /// Creates a combined view of [iterables].
+  /// Creates a combined view of [_iterables].
   const CombinedIterableView(this._iterables);
 
   @override
diff --git a/lib/src/combined_wrappers/combined_list.dart b/lib/src/combined_wrappers/combined_list.dart
index c9a2eb8..f0cd447 100644
--- a/lib/src/combined_wrappers/combined_list.dart
+++ b/lib/src/combined_wrappers/combined_list.dart
@@ -24,7 +24,7 @@
   /// The lists that this combines.
   final List<List<T>> _lists;
 
-  /// Creates a combined view of [lists].
+  /// Creates a combined view of [_lists].
   CombinedListView(this._lists);
 
   @override
diff --git a/lib/src/combined_wrappers/combined_map.dart b/lib/src/combined_wrappers/combined_map.dart
index ae72006..18db6e7 100644
--- a/lib/src/combined_wrappers/combined_map.dart
+++ b/lib/src/combined_wrappers/combined_map.dart
@@ -40,11 +40,11 @@
     return null;
   }
 
-  /// The keys of [this].
+  /// The keys of `this`.
   ///
   /// The returned iterable has efficient `contains` operations, assuming the
-  /// iterables returned by the wrapped maps have efficient `contains` operations
-  /// for their `keys` iterables.
+  /// iterables returned by the wrapped maps have efficient `contains`
+  /// operations for their `keys` iterables.
   ///
   /// The `length` must do deduplication and thus is not optimized.
   ///
diff --git a/lib/src/empty_unmodifiable_set.dart b/lib/src/empty_unmodifiable_set.dart
index ed442ca..12e6f4f 100644
--- a/lib/src/empty_unmodifiable_set.dart
+++ b/lib/src/empty_unmodifiable_set.dart
@@ -4,7 +4,8 @@
 
 import 'dart:collection';
 
-import 'package:collection/collection.dart';
+import 'unmodifiable_wrappers.dart';
+import 'wrappers.dart';
 
 /// An unmodifiable, empty set which can be constant.
 class EmptyUnmodifiableSet<E> extends IterableBase<E>
@@ -26,7 +27,7 @@
   Iterable<E> followedBy(Iterable<E> other) => DelegatingIterable(other);
   @override
   E? lookup(Object? element) => null;
-  @Deprecated("Use cast instead")
+  @Deprecated('Use cast instead')
   @override
   EmptyUnmodifiableSet<T> retype<T>() => EmptyUnmodifiableSet<T>();
   @override
diff --git a/lib/src/equality.dart b/lib/src/equality.dart
index a0db983..826446d 100644
--- a/lib/src/equality.dart
+++ b/lib/src/equality.dart
@@ -253,8 +253,7 @@
 /// of the other iterable, so that each pair are equal.
 class UnorderedIterableEquality<E> extends _UnorderedEquality<E, Iterable<E>> {
   const UnorderedIterableEquality(
-      [Equality<E> elementEquality = const DefaultEquality<Never>()])
-      : super(elementEquality);
+      [super.elementEquality = const DefaultEquality<Never>()]);
 
   @override
   bool isValidKey(Object? o) => o is Iterable<E>;
@@ -273,9 +272,7 @@
 /// even if the [isValidKey] returns `false` for `null`.
 /// The [hash] of `null` is `null.hashCode`.
 class SetEquality<E> extends _UnorderedEquality<E, Set<E>> {
-  const SetEquality(
-      [Equality<E> elementEquality = const DefaultEquality<Never>()])
-      : super(elementEquality);
+  const SetEquality([super.elementEquality = const DefaultEquality<Never>()]);
 
   @override
   bool isValidKey(Object? o) => o is Set<E>;
@@ -437,7 +434,7 @@
         _unordered = true;
 
   @override
-  bool equals(e1, e2) {
+  bool equals(Object? e1, Object? e2) {
     if (e1 is Set) {
       return e2 is Set && SetEquality(this).equals(e1, e2);
     }
diff --git a/lib/src/iterable_extensions.dart b/lib/src/iterable_extensions.dart
index 3af5124..376f450 100644
--- a/lib/src/iterable_extensions.dart
+++ b/lib/src/iterable_extensions.dart
@@ -4,10 +4,9 @@
 
 import 'dart:math' show Random;
 
-import 'package:collection/src/utils.dart';
-
 import 'algorithms.dart';
 import 'functions.dart' as functions;
+import 'utils.dart';
 
 /// Extensions that apply to all iterables.
 ///
@@ -365,18 +364,19 @@
   /// The [index] must not be negative.
   T? elementAtOrNull(int index) => skip(index).firstOrNull;
 
-  /// Associates the elements in [this] by the value returned by [key].
+  /// Associates the elements in `this` by the value returned by [key].
   ///
-  /// Returns a map from keys computed by [key] to the last value for which [key]
-  /// returns that key.
+  /// Returns a map from keys computed by [key] to the last value for which
+  /// [key] returns that key.
   Map<K, T> lastBy<K>(K Function(T) key) => functions.lastBy(this, key);
 
   /// Groups elements by [keyOf] then folds the elements in each group.
   ///
   /// A key is found for each element using [keyOf].
   /// Then the elements with the same key are all folded using [combine].
-  /// The first call to [combine] for a particular key receives [null] as
-  /// the previous value, the remaining ones receive the result of the previous call.
+  /// The first call to [combine] for a particular key receives `null` as
+  /// the previous value, the remaining ones receive the result of the previous
+  /// call.
   ///
   /// Can be used to _group_ elements into arbitrary collections.
   /// For example [groupSetsBy] could be written as:
@@ -431,7 +431,8 @@
 
   /// Splits the elements into chunks before some elements.
   ///
-  /// Each element is checked using [test] for whether it should start a new chunk.
+  /// Each element is checked using [test] for whether it should start a new
+  /// chunk.
   /// If so, the elements since the previous chunk-starting element
   /// are emitted as a list.
   /// Any final elements are emitted at the end.
@@ -504,7 +505,8 @@
   ///
   /// Example:
   /// ```dart
-  /// var parts = [1, 0, 2, 1, 5, 7, 6, 8, 9].splitAfterIndexed((i, v) => i < v);
+  /// var parts = [1, 0, 2, 1, 5, 7, 6, 8, 9]
+  ///   .splitAfterIndexed((i, v) => i < v);
   /// print(parts); // ([1, 0], [2, 1], [5, 7, 6], [8, 9])
   /// ```
   Iterable<List<T>> splitAfterIndexed(
@@ -568,10 +570,10 @@
     return true;
   }
 
-  /// Contiguous [slice]s of [this] with the given [length].
+  /// Contiguous slices of `this` with the given [length].
   ///
   /// Each slice is [length] elements long, except for the last one which may be
-  /// shorter if [this] contains too few elements. Each slice begins after the
+  /// shorter if `this` contains too few elements. Each slice begins after the
   /// last one ends. The [length] must be greater than zero.
   ///
   /// For example, `{1, 2, 3, 4, 5}.slices(2)` returns `([1, 2], [3, 4], [5])`.
diff --git a/lib/src/list_extensions.dart b/lib/src/list_extensions.dart
index 4bb719a..5ab2c8b 100644
--- a/lib/src/list_extensions.dart
+++ b/lib/src/list_extensions.dart
@@ -28,13 +28,13 @@
   ///
   /// Uses binary search to find the location of [element].
   /// This takes on the order of `log(n)` comparisons.
-  /// The list *must* be sorted according to [compare] on the [keyOf] of elements,
-  /// otherwise the result is unspecified.
+  /// The list *must* be sorted according to [compare] on the [keyOf] of
+  /// elements, otherwise the result is unspecified.
   ///
   /// Returns -1 if [element] does not occur in this list.
   ///
-  /// If [start] and [end] are supplied, only the list range from [start] to [end]
-  /// is searched, and only that range needs to be sorted.
+  /// If [start] and [end] are supplied, only the list range from [start] to
+  /// [end] is searched, and only that range needs to be sorted.
   int binarySearchByCompare<K>(
           E element, K Function(E element) keyOf, int Function(K, K) compare,
           [int start = 0, int? end]) =>
@@ -50,8 +50,8 @@
   ///
   /// Returns -1 if [element] does not occur in this list.
   ///
-  /// If [start] and [end] are supplied, only the list range from [start] to [end]
-  /// is searched, and only that range needs to be sorted.
+  /// If [start] and [end] are supplied, only the list range from [start] to
+  /// [end] is searched, and only that range needs to be sorted.
   int binarySearchBy<K extends Comparable<K>>(
           E element, K Function(E element) keyOf, [int start = 0, int? end]) =>
       algorithms.binarySearchBy<E, K>(
@@ -270,10 +270,10 @@
   /// The [index] must not be negative.
   E? elementAtOrNull(int index) => (index < length) ? this[index] : null;
 
-  /// Contiguous [slice]s of [this] with the given [length].
+  /// Contiguous [slice]s of `this` with the given [length].
   ///
   /// Each slice is a view of this list [length] elements long, except for the
-  /// last one which may be shorter if [this] contains too few elements. Each
+  /// last one which may be shorter if `this` contains too few elements. Each
   /// slice begins after the last one ends.
   ///
   /// As with [slice], these slices are backed by this list, which must not
diff --git a/lib/src/priority_queue.dart b/lib/src/priority_queue.dart
index 0a6809a..11b0348 100644
--- a/lib/src/priority_queue.dart
+++ b/lib/src/priority_queue.dart
@@ -52,7 +52,7 @@
   /// Uses the [Object.==] of elements in the queue to check
   /// for whether they are equal to [object].
   /// Equal objects objects must have the same priority
-  /// according to the [comparison] function.
+  /// according to the comparison function.
   /// That is, if `a == b` then `comparison(a, b) == 0`.
   /// If that is not the case, this check might fail to find
   /// an object.
@@ -88,7 +88,7 @@
   ///
   /// Repeatedly calling this method, without adding element in between,
   /// is guaranteed to return elements in non-decreasing order as, specified by
-  /// [comparison].
+  /// the `comparison` constructor parameter.
   ///
   /// The queue must not be empty when this method is called.
   E removeFirst();
@@ -104,7 +104,7 @@
   /// Uses the [Object.==] of elements in the queue to check
   /// for whether they are equal to [element].
   /// Equal objects objects must have the same priority
-  /// according to the [comparison] function.
+  /// according to the `comparison` function.
   /// That is, if `a == b` then `comparison(a, b) == 0`.
   /// If that is not the case, this check might fail to find
   /// an object.
diff --git a/lib/src/queue_list.dart b/lib/src/queue_list.dart
index f013723..a3eaba1 100644
--- a/lib/src/queue_list.dart
+++ b/lib/src/queue_list.dart
@@ -115,7 +115,7 @@
 
   QueueList<T> cast<T>() => QueueList._castFrom<E, T>(this);
 
-  @Deprecated("Use cast instead")
+  @Deprecated('Use cast instead')
   QueueList<T> retype<T>() => cast<T>();
 
   @override
diff --git a/lib/src/union_set.dart b/lib/src/union_set.dart
index 37aee48..a34d7ad 100644
--- a/lib/src/union_set.dart
+++ b/lib/src/union_set.dart
@@ -36,7 +36,7 @@
   /// Creates a new set that's a view of the union of all sets in [sets].
   ///
   /// If any sets in [sets] change, this [UnionSet] reflects that change.
-  /// However, unlike [new UnionSet], this creates a copy of its parameter, so
+  /// However, unlike [UnionSet.new], this creates a copy of its parameter, so
   /// changes in [sets] aren't reflected in this [UnionSet].
   ///
   /// If [disjoint] is `true`, then all component sets must be disjoint. That
diff --git a/lib/src/union_set_controller.dart b/lib/src/union_set_controller.dart
index ea3622a..498528e 100644
--- a/lib/src/union_set_controller.dart
+++ b/lib/src/union_set_controller.dart
@@ -22,7 +22,7 @@
 /// }
 /// ```
 class UnionSetController<E> {
-  /// The [UnionSet] that provides a view of the union of sets in [this].
+  /// The [UnionSet] that provides a view of the union of sets in `this`.
   final UnionSet<E> set;
 
   /// The sets whose union is exposed through [set].
@@ -32,7 +32,7 @@
   ///
   /// If [disjoint] is `true`, this assumes that all component sets are
   /// disjoint—that is, that they contain no elements in common. This makes
-  /// many operations including [length] more efficient.
+  /// many operations including `length` more efficient.
   UnionSetController({bool disjoint = false}) : this._(<Set<E>>{}, disjoint);
 
   /// Creates a controller with the provided [_sets].
@@ -49,7 +49,7 @@
 
   /// Removes the contents of [component] to [set].
   ///
-  /// If another set in [this] has overlapping elements with [component], those
+  /// If another set in `this` has overlapping elements with [component], those
   /// elements will remain in [set].
   bool remove(Set<E> component) => _sets.remove(component);
 }
diff --git a/lib/src/unmodifiable_wrappers.dart b/lib/src/unmodifiable_wrappers.dart
index c6cf2cd..4305644 100644
--- a/lib/src/unmodifiable_wrappers.dart
+++ b/lib/src/unmodifiable_wrappers.dart
@@ -20,7 +20,7 @@
 /// Permitted operations defer to the wrapped list.
 class NonGrowableListView<E> extends DelegatingList<E>
     with NonGrowableListMixin<E> {
-  NonGrowableListView(List<E> listBase) : super(listBase);
+  NonGrowableListView(super.listBase);
 }
 
 /// Mixin class that implements a throwing version of all list operations that
@@ -105,7 +105,7 @@
 /// Permitted operations defer to the wrapped set.
 class UnmodifiableSetView<E> extends DelegatingSet<E>
     with UnmodifiableSetMixin<E> {
-  UnmodifiableSetView(Set<E> setBase) : super(setBase);
+  UnmodifiableSetView(super.setBase);
 
   /// An unmodifiable empty set.
   ///
diff --git a/lib/src/wrappers.dart b/lib/src/wrappers.dart
index e380350..8b2c3d7 100644
--- a/lib/src/wrappers.dart
+++ b/lib/src/wrappers.dart
@@ -79,7 +79,7 @@
   @override
   E reduce(E Function(E value, E element) combine) => _base.reduce(combine);
 
-  @Deprecated("Use cast instead")
+  @Deprecated('Use cast instead')
   Iterable<T> retype<T>() => cast<T>();
 
   @override
@@ -137,7 +137,7 @@
   /// they're accessed. If they're not, it throws a [CastError].
   ///
   /// This forwards all operations to [base], so any changes in [base] will be
-  /// reflected in [this]. If [base] is already an `Iterable<E>`, it's returned
+  /// reflected in `this`. If [base] is already an `Iterable<E>`, it's returned
   /// unmodified.
   @Deprecated('Use iterable.cast<E> instead.')
   static Iterable<E> typed<E>(Iterable base) => base.cast<E>();
@@ -163,7 +163,7 @@
   /// collection.
   ///
   /// This forwards all operations to [base], so any changes in [base] will be
-  /// reflected in [this]. If [base] is already a `List<E>`, it's returned
+  /// reflected in `this`. If [base] is already a `List<E>`, it's returned
   /// unmodified.
   @Deprecated('Use list.cast<E> instead.')
   static List<E> typed<E>(List base) => base.cast<E>();
@@ -278,7 +278,7 @@
     _base.retainWhere(test);
   }
 
-  @Deprecated("Use cast instead")
+  @Deprecated('Use cast instead')
   @override
   List<T> retype<T>() => cast<T>();
 
@@ -328,7 +328,7 @@
   /// collection.
   ///
   /// This forwards all operations to [base], so any changes in [base] will be
-  /// reflected in [this]. If [base] is already a `Set<E>`, it's returned
+  /// reflected in `this`. If [base] is already a `Set<E>`, it's returned
   /// unmodified.
   @Deprecated('Use set.cast<E> instead.')
   static Set<E> typed<E>(Set base) => base.cast<E>();
@@ -379,7 +379,7 @@
     _base.retainAll(elements);
   }
 
-  @Deprecated("Use cast instead")
+  @Deprecated('Use cast instead')
   @override
   Set<T> retype<T>() => cast<T>();
 
@@ -416,7 +416,7 @@
   /// collection.
   ///
   /// This forwards all operations to [base], so any changes in [base] will be
-  /// reflected in [this]. If [base] is already a `Queue<E>`, it's returned
+  /// reflected in `this`. If [base] is already a `Queue<E>`, it's returned
   /// unmodified.
   @Deprecated('Use queue.cast<E> instead.')
   static Queue<E> typed<E>(Queue base) => base.cast<E>();
@@ -462,7 +462,7 @@
     _base.retainWhere(test);
   }
 
-  @Deprecated("Use cast instead")
+  @Deprecated('Use cast instead')
   @override
   Queue<T> retype<T>() => cast<T>();
 
@@ -492,7 +492,7 @@
   /// the underlying collection.
   ///
   /// This forwards all operations to [base], so any changes in [base] will be
-  /// reflected in [this]. If [base] is already a `Map<K, V>`, it's returned
+  /// reflected in `this`. If [base] is already a `Map<K, V>`, it's returned
   /// unmodified.
   @Deprecated('Use map.cast<K, V> instead.')
   static Map<K, V> typed<K, V>(Map base) => base.cast<K, V>();
@@ -563,7 +563,7 @@
   @override
   void removeWhere(bool Function(K, V) test) => _base.removeWhere(test);
 
-  @Deprecated("Use cast instead")
+  @Deprecated('Use cast instead')
   Map<K2, V2> retype<K2, V2>() => cast<K2, V2>();
 
   @override
@@ -624,24 +624,24 @@
   @override
   bool containsAll(Iterable<Object?> other) => other.every(contains);
 
-  /// Returns a new set with the the elements of [this] that are not in [other].
+  /// Returns a new set with the the elements of `this` that are not in [other].
   ///
   /// That is, the returned set contains all the elements of this [Set] that are
   /// not elements of [other] according to `other.contains`.
   ///
   /// Note that the returned set will use the default equality operation, which
-  /// may be different than the equality operation [this] uses.
+  /// may be different than the equality operation `this` uses.
   @override
   Set<E> difference(Set<Object?> other) =>
       where((element) => !other.contains(element)).toSet();
 
-  /// Returns a new set which is the intersection between [this] and [other].
+  /// Returns a new set which is the intersection between `this` and [other].
   ///
   /// That is, the returned set contains all the elements of this [Set] that are
   /// also elements of [other] according to `other.contains`.
   ///
   /// Note that the returned set will use the default equality operation, which
-  /// may be different than the equality operation [this] uses.
+  /// may be different than the equality operation `this` uses.
   @override
   Set<E> intersection(Set<Object?> other) => where(other.contains).toSet();
 
@@ -651,17 +651,17 @@
   E lookup(Object? element) =>
       throw UnsupportedError("MapKeySet doesn't support lookup().");
 
-  @Deprecated("Use cast instead")
+  @Deprecated('Use cast instead')
   @override
   Set<T> retype<T>() => Set.castFrom<E, T>(this);
 
-  /// Returns a new set which contains all the elements of [this] and [other].
+  /// Returns a new set which contains all the elements of `this` and [other].
   ///
   /// That is, the returned set contains all the elements of this [Set] and all
   /// the elements of [other].
   ///
   /// Note that the returned set will use the default equality operation, which
-  /// may be different than the equality operation [this] uses.
+  /// may be different than the equality operation `this` uses.
   @override
   Set<E> union(Set<E> other) => toSet()..addAll(other);
 }
@@ -749,24 +749,24 @@
   @override
   bool containsAll(Iterable<Object?> other) => other.every(contains);
 
-  /// Returns a new set with the the elements of [this] that are not in [other].
+  /// Returns a new set with the the elements of `this` that are not in [other].
   ///
   /// That is, the returned set contains all the elements of this [Set] that are
   /// not elements of [other] according to `other.contains`.
   ///
   /// Note that the returned set will use the default equality operation, which
-  /// may be different than the equality operation [this] uses.
+  /// may be different than the equality operation `this` uses.
   @override
   Set<V> difference(Set<Object?> other) =>
       where((element) => !other.contains(element)).toSet();
 
-  /// Returns a new set which is the intersection between [this] and [other].
+  /// Returns a new set which is the intersection between `this` and [other].
   ///
   /// That is, the returned set contains all the elements of this [Set] that are
   /// also elements of [other] according to `other.contains`.
   ///
   /// Note that the returned set will use the default equality operation, which
-  /// may be different than the equality operation [this] uses.
+  /// may be different than the equality operation `this` uses.
   @override
   Set<V> intersection(Set<Object?> other) => where(other.contains).toSet();
 
@@ -822,17 +822,17 @@
   void retainWhere(bool Function(V) test) =>
       removeWhere((element) => !test(element));
 
-  @Deprecated("Use cast instead")
+  @Deprecated('Use cast instead')
   @override
   Set<T> retype<T>() => Set.castFrom<V, T>(this);
 
-  /// Returns a new set which contains all the elements of [this] and [other].
+  /// Returns a new set which contains all the elements of `this` and [other].
   ///
   /// That is, the returned set contains all the elements of this [Set] and all
   /// the elements of [other].
   ///
   /// Note that the returned set will use the default equality operation, which
-  /// may be different than the equality operation [this] uses.
+  /// may be different than the equality operation `this` uses.
   @override
   Set<V> union(Set<V> other) => toSet()..addAll(other);
 }
diff --git a/pubspec.yaml b/pubspec.yaml
index 50c30bf..14ab46d 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,11 +1,11 @@
 name: collection
-version: 1.17.0
+version: 1.17.1-dev
 description: Collections and utilities functions and classes related to collections.
 repository: https://github.com/dart-lang/collection
 
 environment:
-  sdk: ">=2.12.0 <3.0.0"
+  sdk: ">=2.18.0 <3.0.0"
 
 dev_dependencies:
-  lints: ^1.0.0
+  lints: ^2.0.0
   test: ^1.16.0
diff --git a/test/algorithms_test.dart b/test/algorithms_test.dart
index 0c60463..c2ffb7f 100644
--- a/test/algorithms_test.dart
+++ b/test/algorithms_test.dart
@@ -32,7 +32,7 @@
     var l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
     var c = l.toList();
     var count = 0;
-    do {
+    for (;;) {
       shuffle(l);
       if (!const ListEquality().equals(c, l)) return;
       // Odds of not changing the order should be one in ~ 16! ~= 2e+13.
@@ -42,7 +42,7 @@
       // If this happens even once, it's ok to report it.
       print('Failed shuffle $count times');
       if (count == 10) fail("Shuffle didn't change order.");
-    } while (true);
+    }
   });
   test('Shuffle sublist', () {
     var l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
diff --git a/test/boollist_test.dart b/test/boollist_test.dart
index 0027ba7..aa9e398 100644
--- a/test/boollist_test.dart
+++ b/test/boollist_test.dart
@@ -111,7 +111,8 @@
       );
 
       expect(
-        // BoolList.filled constructor isn't used due internal usage of fillRange
+        // BoolList.filled constructor isn't used due internal usage of
+        // fillRange
         BoolList.generate(1024, (i) => true)..fillRange(32, 64, false),
         List.filled(1024, true)..fillRange(32, 64, false),
       );
@@ -124,7 +125,8 @@
       );
 
       expect(
-        // BoolList.filled constructor isn't used due internal usage of fillRange
+        // BoolList.filled constructor isn't used due internal usage of
+        // fillRange
         BoolList.generate(1024, (i) => true)..fillRange(32, 128, false),
         List.filled(1024, true)..fillRange(32, 128, false),
       );
diff --git a/test/equality_test.dart b/test/equality_test.dart
index d75a177..4786b40 100644
--- a/test/equality_test.dart
+++ b/test/equality_test.dart
@@ -168,8 +168,7 @@
       test('with identical collection types', () {
         expect(colleq.equals(l1, l1.toList()), isTrue);
         expect(colleq.equals(s1, s1.toSet()), isTrue);
-        expect(
-            colleq.equals(map1b, map1b.map((k, v) => MapEntry(k, v))), isTrue);
+        expect(colleq.equals(map1b, map1b.map(MapEntry.new)), isTrue);
         expect(colleq.equals(i1, i1.map((i) => i)), isTrue);
         expect(colleq.equals(map1a, map2a), isFalse);
         expect(colleq.equals(map1b, map2b), isFalse);
@@ -279,5 +278,5 @@
   @override
   bool operator ==(Object other) => other is Element && id == other.id;
   @override
-  int compareTo(other) => id.compareTo(other.id);
+  int compareTo(Element other) => id.compareTo(other.id);
 }
diff --git a/test/functions_test.dart b/test/functions_test.dart
index 9d41625..359265c 100644
--- a/test/functions_test.dart
+++ b/test/functions_test.dart
@@ -82,7 +82,7 @@
   group('lastBy()', () {
     test('returns an empty map for an empty iterable', () {
       expect(
-        lastBy([], (_) => fail("Must not be called for empty input")),
+        lastBy([], (_) => fail('Must not be called for empty input')),
         isEmpty,
       );
     });
@@ -280,25 +280,26 @@
 
     test('returns individual vertices for a tree', () {
       expect(
-          stronglyConnectedComponents({
-            'foo': ['bar'],
-            'bar': ['baz', 'bang'],
-            'baz': ['qux'],
-            'bang': ['zap'],
-            'qux': [],
-            'zap': []
-          }),
-          equals([
-            // This is expected to return *a* topological ordering, but this isn't
-            // the only valid one. If the function implementation changes in the
-            // future, this test may need to be updated.
-            {'foo'},
-            {'bar'},
-            {'bang'},
-            {'zap'},
-            {'baz'},
-            {'qux'}
-          ]));
+        stronglyConnectedComponents({
+          'foo': ['bar'],
+          'bar': ['baz', 'bang'],
+          'baz': ['qux'],
+          'bang': ['zap'],
+          'qux': [],
+          'zap': []
+        }),
+        equals([
+          // This is expected to return *a* topological ordering, but this isn't
+          // the only valid one. If the function implementation changes in the
+          // future, this test may need to be updated.
+          {'foo'},
+          {'bar'},
+          {'bang'},
+          {'zap'},
+          {'baz'},
+          {'qux'}
+        ]),
+      );
     });
 
     test('returns a single set for a fully cyclic graph', () {
@@ -317,47 +318,49 @@
     test('returns separate sets for each strongly connected component', () {
       // https://en.wikipedia.org/wiki/Strongly_connected_component#/media/File:Scc.png
       expect(
-          stronglyConnectedComponents({
-            'a': ['b'],
-            'b': ['c', 'e', 'f'],
-            'c': ['d', 'g'],
-            'd': ['c', 'h'],
-            'e': ['a', 'f'],
-            'f': ['g'],
-            'g': ['f'],
-            'h': ['g', 'd']
-          }),
-          equals([
-            // This is expected to return *a* topological ordering, but this isn't
-            // the only valid one. If the function implementation changes in the
-            // future, this test may need to be updated.
-            {'a', 'b', 'e'},
-            {'c', 'd', 'h'},
-            {'f', 'g'},
-          ]));
+        stronglyConnectedComponents({
+          'a': ['b'],
+          'b': ['c', 'e', 'f'],
+          'c': ['d', 'g'],
+          'd': ['c', 'h'],
+          'e': ['a', 'f'],
+          'f': ['g'],
+          'g': ['f'],
+          'h': ['g', 'd']
+        }),
+        equals([
+          // This is expected to return *a* topological ordering, but this isn't
+          // the only valid one. If the function implementation changes in the
+          // future, this test may need to be updated.
+          {'a', 'b', 'e'},
+          {'c', 'd', 'h'},
+          {'f', 'g'},
+        ]),
+      );
     });
 
     test('always returns components in topological order', () {
       expect(
-          stronglyConnectedComponents({
-            'bar': ['baz', 'bang'],
-            'zap': [],
-            'baz': ['qux'],
-            'qux': [],
-            'foo': ['bar'],
-            'bang': ['zap']
-          }),
-          equals([
-            // This is expected to return *a* topological ordering, but this isn't
-            // the only valid one. If the function implementation changes in the
-            // future, this test may need to be updated.
-            {'foo'},
-            {'bar'},
-            {'bang'},
-            {'zap'},
-            {'baz'},
-            {'qux'}
-          ]));
+        stronglyConnectedComponents({
+          'bar': ['baz', 'bang'],
+          'zap': [],
+          'baz': ['qux'],
+          'qux': [],
+          'foo': ['bar'],
+          'bang': ['zap']
+        }),
+        equals([
+          // This is expected to return *a* topological ordering, but this isn't
+          // the only valid one. If the function implementation changes in the
+          // future, this test may need to be updated.
+          {'foo'},
+          {'bar'},
+          {'bang'},
+          {'zap'},
+          {'baz'},
+          {'qux'}
+        ]),
+      );
     });
   });
 }
diff --git a/test/priority_queue_test.dart b/test/priority_queue_test.dart
index ce0f88e..96e2c15 100644
--- a/test/priority_queue_test.dart
+++ b/test/priority_queue_test.dart
@@ -8,8 +8,8 @@
 
 void main() {
   testDefault();
-  testInt(() => HeapPriorityQueue<int>());
-  testCustom((comparator) => HeapPriorityQueue<C>(comparator));
+  testInt(HeapPriorityQueue<int>.new);
+  testCustom(HeapPriorityQueue<C>.new);
   testDuplicates();
   testNullable();
   testConcurrentModification();
@@ -19,8 +19,8 @@
   test('PriorityQueue() returns a HeapPriorityQueue', () {
     expect(PriorityQueue<int>(), TypeMatcher<HeapPriorityQueue<int>>());
   });
-  testInt(() => PriorityQueue<int>());
-  testCustom((comparator) => PriorityQueue<C>(comparator));
+  testInt(PriorityQueue<int>.new);
+  testCustom(PriorityQueue<C>.new);
 }
 
 void testInt(PriorityQueue<int> Function() create) {
@@ -33,9 +33,9 @@
     PriorityQueue<C> Function(int Function(C, C)? comparator) create) {
   for (var count in [1, 5, 127, 128]) {
     testQueue('Custom:$count/null', () => create(null),
-        List<C>.generate(count, (x) => C(x)), C(count));
+        List<C>.generate(count, C.new), C(count));
     testQueue('Custom:$count/compare', () => create(compare),
-        List<C>.generate(count, (x) => C(x)), C(count));
+        List<C>.generate(count, C.new), C(count));
     testQueue('Custom:$count/compareNeg', () => create(compareNeg),
         List<C>.generate(count, (x) => C(count - x)), C(0));
   }
@@ -44,13 +44,17 @@
 /// Test that a queue behaves correctly.
 ///
 /// The elements must be in priority order, from highest to lowest.
-void testQueue(
-    String name, PriorityQueue Function() create, List elements, notElement) {
+void testQueue<T>(
+  String name,
+  PriorityQueue<T> Function() create,
+  List<T> elements,
+  T notElement,
+) {
   test(name, () => testQueueBody(create, elements, notElement));
 }
 
 void testQueueBody<T>(
-    PriorityQueue<T> Function() create, List<T> elements, notElement) {
+    PriorityQueue<T> Function() create, List<T> elements, T notElement) {
   var q = create();
   expect(q.isEmpty, isTrue);
   expect(q, hasLength(0));
diff --git a/test/wrapper_test.dart b/test/wrapper_test.dart
index 5f03ae6..c9785e8 100644
--- a/test/wrapper_test.dart
+++ b/test/wrapper_test.dart
@@ -84,29 +84,24 @@
 // argument to DelegatingIterable/Set/List/Queue.
 class IterableInvocationChecker<T> extends InvocationChecker
     implements Iterable<T> {
-  IterableInvocationChecker(Invocation expected, InstanceMirror mirror)
-      : super(expected, mirror);
+  IterableInvocationChecker(super.expected, super.mirror);
 }
 
 class ListInvocationChecker<T> extends InvocationChecker implements List<T> {
-  ListInvocationChecker(Invocation expected, InstanceMirror mirror)
-      : super(expected, mirror);
+  ListInvocationChecker(super.expected, super.mirror);
 }
 
 class SetInvocationChecker<T> extends InvocationChecker implements Set<T> {
-  SetInvocationChecker(Invocation expected, InstanceMirror mirror)
-      : super(expected, mirror);
+  SetInvocationChecker(super.expected, super.mirror);
 }
 
 class QueueInvocationChecker<T> extends InvocationChecker implements Queue<T> {
-  QueueInvocationChecker(Invocation expected, InstanceMirror mirror)
-      : super(expected, mirror);
+  QueueInvocationChecker(super.expected, super.mirror);
 }
 
 class MapInvocationChecker<K, V> extends InvocationChecker
     implements Map<K, V> {
-  MapInvocationChecker(Invocation expected, InstanceMirror mirror)
-      : super(expected, mirror);
+  MapInvocationChecker(super.expected, super.mirror);
 }
 
 // Expector that wraps in DelegatingIterable.
@@ -123,7 +118,7 @@
 
 // Expector that wraps in DelegatingList.
 class ListExpector<T> extends IterableExpector<T> implements List<T> {
-  ListExpector(List<T> realInstance) : super(realInstance);
+  ListExpector(List<T> super.realInstance);
 
   @override
   dynamic wrappedChecker(Invocation i) =>
@@ -132,7 +127,7 @@
 
 // Expector that wraps in DelegatingSet.
 class SetExpector<T> extends IterableExpector<T> implements Set<T> {
-  SetExpector(Set<T> realInstance) : super(realInstance);
+  SetExpector(Set<T> super.realInstance);
 
   @override
   dynamic wrappedChecker(Invocation i) =>
@@ -141,7 +136,7 @@
 
 // Expector that wraps in DelegatingSet.
 class QueueExpector<T> extends IterableExpector<T> implements Queue<T> {
-  QueueExpector(Queue<T> realInstance) : super(realInstance);
+  QueueExpector(Queue<T> super.realInstance);
 
   @override
   dynamic wrappedChecker(Invocation i) =>
@@ -169,7 +164,7 @@
 Iterable<dynamic> expandFunc(dynamic x) => [x];
 dynamic foldFunc(dynamic previous, dynamic next) => previous;
 int compareFunc(dynamic x, dynamic y) => 0;
-var val = 10;
+int val = 10;
 
 void main() {
   void testIterable(IterableExpector expect) {