Skip to content

Commit

Permalink
Use dart_flutter_team_lints for matcher (#2426)
Browse files Browse the repository at this point in the history
Change the dependency and analysis options include to the stricter team
configuration.

Fix newly surfaced diagnostics. Most code changes are related to the
strict modes that are enabled by the team config.
Fix most implicit casts with explicit casts, but fix some arguments in
`typedMatches` implementation so they don't unnecessarily widen the type
back to `dynamic` before using the value.

Bump to Dart 3.5 The min SDK for the test runner is already at 3.5.0 and
matcher is only usable with the latest version of the test runner.
  • Loading branch information
natebosch authored Dec 13, 2024
1 parent dc0f8ea commit 6719bc6
Show file tree
Hide file tree
Showing 35 changed files with 188 additions and 237 deletions.
234 changes: 86 additions & 148 deletions .github/workflows/dart.yml

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions pkgs/matcher/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
## 0.12.18-wip

* Remove some dynamic invocations.
* Add explicit casts from `dynamic` values.
* Require Dart 3.5

## 0.12.17

Expand Down
2 changes: 1 addition & 1 deletion pkgs/matcher/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
include: package:lints/recommended.yaml
include: package:dart_flutter_team_lints/analysis_options.yaml

linter:
rules:
Expand Down
8 changes: 4 additions & 4 deletions pkgs/matcher/lib/expect.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,14 @@ export 'src/expect/prints_matcher.dart' show prints;
export 'src/expect/stream_matcher.dart' show StreamMatcher;
export 'src/expect/stream_matchers.dart'
show
emitsDone,
emits,
emitsError,
mayEmit,
emitsAnyOf,
emitsInOrder,
emitsDone,
emitsError,
emitsInAnyOrder,
emitsInOrder,
emitsThrough,
mayEmit,
mayEmitMultiple,
neverEmits;
export 'src/expect/throws_matcher.dart' show Throws, throws, throwsA;
Expand Down
2 changes: 1 addition & 1 deletion pkgs/matcher/lib/mirror_matchers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class _HasProperty extends Matcher {
.add('has property "$_name" with value ')
.addDescriptionOf(matchState['value']);
var innerDescription = StringDescription();
matchState['state'] ??= {};
matchState['state'] ??= <Object?, Object?>{};
_matcher?.describeMismatch(matchState['value'], innerDescription,
matchState['state'] as Map, verbose);
if (innerDescription.length > 0) {
Expand Down
6 changes: 4 additions & 2 deletions pkgs/matcher/lib/src/core_matchers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ class _Empty extends Matcher {
const _Empty();

@override
bool matches(Object? item, Map matchState) => (item as dynamic).isEmpty;
bool matches(Object? item, Map matchState) =>
(item as dynamic).isEmpty as bool;

@override
Description describe(Description description) => description.add('empty');
Expand All @@ -27,7 +28,8 @@ class _NotEmpty extends Matcher {
const _NotEmpty();

@override
bool matches(Object? item, Map matchState) => (item as dynamic).isNotEmpty;
bool matches(Object? item, Map matchState) =>
(item as dynamic).isNotEmpty as bool;

@override
Description describe(Description description) => description.add('non-empty');
Expand Down
2 changes: 1 addition & 1 deletion pkgs/matcher/lib/src/equals_matcher.dart
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ class _DeepMatcher extends Matcher {
Object? expected, Object? actual, String location, int depth) {
// If the expected value is a matcher, try to match it.
if (expected is Matcher) {
var matchState = {};
var matchState = <Object?, Object?>{};
if (expected.matches(actual, matchState)) return null;
return _Mismatch(location, actual, (description, verbose) {
var oldLength = description.length;
Expand Down
7 changes: 5 additions & 2 deletions pkgs/matcher/lib/src/expect/expect.dart
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,10 @@ Future expectLater(dynamic actual, dynamic matcher,

/// The implementation of [expect] and [expectLater].
Future _expect(Object? actual, Object? matcher,
{String? reason, skip, bool verbose = false, ErrorFormatter? formatter}) {
{String? reason,
Object? skip,
bool verbose = false,
ErrorFormatter? formatter}) {
final test = TestHandle.current;
formatter ??= (actual, matcher, reason, matchState, verbose) {
var mismatchDescription = StringDescription();
Expand Down Expand Up @@ -133,7 +136,7 @@ Future _expect(Object? actual, Object? matcher,
return Future.sync(() {});
}

var matchState = {};
var matchState = <Object?, Object?>{};
try {
if ((matcher as Matcher).matches(actual, matchState)) {
return Future.sync(() {});
Expand Down
22 changes: 13 additions & 9 deletions pkgs/matcher/lib/src/expect/expect_async.dart
Original file line number Diff line number Diff line change
Expand Up @@ -124,15 +124,17 @@ class _ExpectedFunction<T> {
/// Returns a function that has the same number of positional arguments as the
/// wrapped function (up to a total of 6).
Function get func {
if (_callback is Function(Never, Never, Never, Never, Never, Never)) {
if (_callback is void Function(Never, Never, Never, Never, Never, Never)) {
return max6;
}
if (_callback is Function(Never, Never, Never, Never, Never)) return max5;
if (_callback is Function(Never, Never, Never, Never)) return max4;
if (_callback is Function(Never, Never, Never)) return max3;
if (_callback is Function(Never, Never)) return max2;
if (_callback is Function(Never)) return max1;
if (_callback is Function()) return max0;
if (_callback is void Function(Never, Never, Never, Never, Never)) {
return max5;
}
if (_callback is void Function(Never, Never, Never, Never)) return max4;
if (_callback is void Function(Never, Never, Never)) return max3;
if (_callback is void Function(Never, Never)) return max2;
if (_callback is void Function(Never)) return max1;
if (_callback is void Function()) return max0;

_outstandingWork?.complete();
throw ArgumentError(
Expand Down Expand Up @@ -219,7 +221,8 @@ class _ExpectedFunction<T> {
@Deprecated('Will be removed in 0.13.0')
Function expectAsync(Function callback,
{int count = 1, int max = 0, String? id, String? reason}) =>
_ExpectedFunction(callback, count, max, id: id, reason: reason).func;
_ExpectedFunction<Object?>(callback, count, max, id: id, reason: reason)
.func;

/// Informs the framework that the given [callback] of arity 0 is expected to be
/// called [count] number of times (by default 1).
Expand Down Expand Up @@ -415,7 +418,8 @@ Func6<T, A, B, C, D, E, F> expectAsync6<T, A, B, C, D, E, F>(
@Deprecated('Will be removed in 0.13.0')
Function expectAsyncUntil(Function callback, bool Function() isDone,
{String? id, String? reason}) =>
_ExpectedFunction(callback, 0, -1, id: id, reason: reason, isDone: isDone)
_ExpectedFunction<Object?>(callback, 0, -1,
id: id, reason: reason, isDone: isDone)
.func;

/// Informs the framework that the given [callback] of arity 0 is expected to be
Expand Down
2 changes: 1 addition & 1 deletion pkgs/matcher/lib/src/expect/future_matchers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class _Completes extends AsyncMatcher {
result = await _matcher.matchAsync(value) as String?;
if (result == null) return null;
} else {
var matchState = {};
var matchState = <Object?, Object?>{};
if (_matcher.matches(value, matchState)) return null;
result = _matcher
.describeMismatch(value, StringDescription(), matchState, false)
Expand Down
4 changes: 2 additions & 2 deletions pkgs/matcher/lib/src/expect/prints_matcher.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class _Prints extends AsyncMatcher {
// synchronous.
@override
dynamic /*FutureOr<String>*/ matchAsync(Object? item) {
if (item is! Function()) return 'was not a unary Function';
if (item is! Object? Function()) return 'was not a unary Function';

var buffer = StringBuffer();
var result = runZoned(item,
Expand All @@ -53,7 +53,7 @@ class _Prints extends AsyncMatcher {
/// Verifies that [actual] matches [_matcher] and returns a [String]
/// description of the failure if it doesn't.
String? _check(String actual) {
var matchState = {};
var matchState = <Object?, Object?>{};
if (_matcher.matches(actual, matchState)) return null;

var result = _matcher
Expand Down
2 changes: 1 addition & 1 deletion pkgs/matcher/lib/src/expect/stream_matcher.dart
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ class _StreamMatcher extends AsyncMatcher implements StreamMatcher {
.listen(events.add, onDone: () => events.add(null));

// Wait on a timer tick so all buffered events are emitted.
await Future.delayed(Duration.zero);
await Future<void>.delayed(Duration.zero);
_unawaited(subscription.cancel());

var eventsString = events.map((event) {
Expand Down
8 changes: 5 additions & 3 deletions pkgs/matcher/lib/src/expect/stream_matchers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ StreamMatcher emits(Object? matcher) {
return StreamMatcher((queue) async {
if (!await queue.hasNext) return '';

var matchState = {};
var matchState = <Object?, Object?>{};
var actual = await queue.next;
if (wrapped.matches(actual, matchState)) return null;

Expand Down Expand Up @@ -138,7 +138,7 @@ StreamMatcher emitsAnyOf(Iterable matchers) {
if (consumedMost == null) {
transaction.reject();
if (firstError != null) {
await Future.error(firstError!, firstStackTrace);
await Future<Never>.error(firstError!, firstStackTrace);
}

var failureMessages = <String>[];
Expand Down Expand Up @@ -368,7 +368,9 @@ Future<bool> _tryInAnyOrder(

if (consumedMost == null) {
transaction.reject();
if (firstError != null) await Future.error(firstError!, firstStackTrace);
if (firstError != null) {
await Future<Never>.error(firstError!, firstStackTrace);
}
return false;
} else {
transaction.commit(consumedMost!);
Expand Down
4 changes: 2 additions & 2 deletions pkgs/matcher/lib/src/expect/throws_matcher.dart
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,10 @@ class Throws extends AsyncMatcher {

/// Verifies that [error] matches [_matcher] and returns a [String]
/// description of the failure if it doesn't.
String? _check(error, StackTrace? trace) {
String? _check(Object error, StackTrace? trace) {
if (_matcher == null) return null;

var matchState = {};
var matchState = <Object?, Object?>{};
if (_matcher.matches(error, matchState)) return null;

var result = _matcher
Expand Down
4 changes: 2 additions & 2 deletions pkgs/matcher/lib/src/map_matchers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class _ContainsValue extends Matcher {
@override
bool matches(Object? item, Map matchState) =>
// ignore: avoid_dynamic_calls
(item as dynamic).containsValue(_value);
(item as dynamic).containsValue(_value) as bool;
@override
Description describe(Description description) =>
description.add('contains value ').addDescriptionOf(_value);
Expand All @@ -36,7 +36,7 @@ class _ContainsMapping extends Matcher {
@override
bool matches(Object? item, Map matchState) =>
// ignore: avoid_dynamic_calls
(item as dynamic).containsKey(_key) &&
((item as dynamic).containsKey(_key) as bool) &&
_valueMatcher.matches((item as dynamic)[_key], matchState);

@override
Expand Down
2 changes: 1 addition & 1 deletion pkgs/matcher/lib/src/operator_matchers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class _AllOf extends Matcher {
Map matchState, bool verbose) {
var matcher = matchState['matcher'] as Matcher;
matcher.describeMismatch(
item, mismatchDescription, matchState['state'], verbose);
item, mismatchDescription, matchState['state'] as Map, verbose);
return mismatchDescription;
}

Expand Down
4 changes: 2 additions & 2 deletions pkgs/matcher/lib/src/order_matchers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,9 @@ class _OrderingMatcher extends Matcher {
bool matches(Object? item, Map matchState) {
if (item == _value) {
return _equalValue;
} else if ((item as dynamic) < _value) {
} else if ((item as dynamic) < _value as bool) {
return _lessThanValue;
} else if ((item as dynamic) > _value) {
} else if ((item as dynamic) > _value as bool) {
return _greaterThanValue;
} else {
return false;
Expand Down
4 changes: 2 additions & 2 deletions pkgs/matcher/lib/src/string_matchers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class _IsEqualIgnoringWhitespace extends FeatureMatcher<String> {
description.addDescriptionOf(_matchValue).add(' ignoring whitespace');

@override
Description describeTypedMismatch(dynamic item,
Description describeTypedMismatch(String item,
Description mismatchDescription, Map matchState, bool verbose) {
return mismatchDescription
.add('is ')
Expand Down Expand Up @@ -152,7 +152,7 @@ class _MatchesRegExp extends FeatureMatcher<String> {
: throw ArgumentError('matches requires a regexp or string');

@override
bool typedMatches(dynamic item, Map matchState) => _regexp.hasMatch(item);
bool typedMatches(String item, Map matchState) => _regexp.hasMatch(item);

@override
Description describe(Description description) =>
Expand Down
3 changes: 1 addition & 2 deletions pkgs/matcher/lib/src/util.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,7 @@ Matcher wrapMatcher(Object? valueOrMatcher) {
} else if (valueOrMatcher is bool Function(Never)) {
// unary predicate, but expects a specific type
// so wrap it.
// ignore: unnecessary_lambdas
return predicate((a) => (valueOrMatcher as dynamic)(a));
return predicate((a) => (valueOrMatcher as dynamic)(a) as bool);
} else {
return equals(valueOrMatcher);
}
Expand Down
4 changes: 2 additions & 2 deletions pkgs/matcher/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ description: >-
repository: https://github.com/dart-lang/test/tree/master/pkgs/matcher

environment:
sdk: ^3.4.0
sdk: ^3.5.0

dependencies:
async: ^2.10.0
Expand All @@ -16,8 +16,8 @@ dependencies:
test_api: ">=0.5.0 <0.8.0"

dev_dependencies:
dart_flutter_team_lints: ^3.2.0
fake_async: ^1.3.0
lints: ^3.0.0
test: ^1.23.0

dependency_overrides:
Expand Down
26 changes: 13 additions & 13 deletions pkgs/matcher/test/core_matchers_test.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.

import 'package:matcher/matcher.dart';
import 'package:test/test.dart' show test, group;
import 'package:test/test.dart' show group, test;

import 'test_utils.dart';

Expand Down Expand Up @@ -42,22 +42,22 @@ void main() {
});

test('same', () {
var a = {};
var b = {};
var a = <Object?, Object?>{};
var b = <Object?, Object?>{};
shouldPass(a, same(a));
shouldFail(b, same(a), 'Expected: same instance as {} Actual: {}');
});

test('equals', () {
var a = {};
var b = {};
var a = <Object?, Object?>{};
var b = <Object?, Object?>{};
shouldPass(a, equals(a));
shouldPass(a, equals(b));
});

test('equals with null', () {
Object? a; // null
var b = {};
var b = <Object?, Object?>{};
shouldPass(a, equals(a));
shouldFail(
a, equals(b), 'Expected: {} Actual: <null> Which: expected a map');
Expand Down Expand Up @@ -87,7 +87,7 @@ void main() {
});

test('anything', () {
var a = {};
var a = <Object?, Object?>{};
shouldPass(0, anything);
shouldPass(null, anything);
shouldPass(a, anything);
Expand All @@ -107,8 +107,8 @@ void main() {
});

test('hasLength', () {
var a = {};
var b = [];
var a = <Object?, Object?>{};
var b = <Object?>[];
shouldPass(a, hasLength(0));
shouldPass(b, hasLength(0));
shouldPass('a', hasLength(1));
Expand Down Expand Up @@ -173,13 +173,13 @@ void main() {
['foo', 'bar'],
['foo'],
3,
[]
<Object?>[]
];
var expected1 = [
['foo', 'bar'],
['foo'],
4,
[]
<Object?>[]
];
var reason1 = "Expected: [['foo', 'bar'], ['foo'], 4, []] "
"Actual: [['foo', 'bar'], ['foo'], 3, []] "
Expand All @@ -189,13 +189,13 @@ void main() {
['foo', 'barry'],
['foo'],
4,
[]
<Object?>[]
];
var expected2 = [
['foo', 'bar'],
['foo'],
4,
[]
<Object?>[]
];
var reason2 = "Expected: [['foo', 'bar'], ['foo'], 4, []] "
"Actual: [['foo', 'barry'], ['foo'], 4, []] "
Expand Down
2 changes: 1 addition & 1 deletion pkgs/matcher/test/expect_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ void main() {
});

test('contains an async error', () {
expect(expectLater(Future.error('oh no'), completion(isFalse)),
expect(expectLater(Future<Never>.error('oh no'), completion(isFalse)),
throwsA('oh no'));
});
});
Expand Down
Loading

0 comments on commit 6719bc6

Please sign in to comment.