blob: 9cb31318c264441f6f9ef2fa661915f9868e4a2f [file] [log] [blame]
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'custom_matcher.dart';
import 'interfaces.dart';
import 'type_matcher.dart';
import 'util.dart';
/// A package-private [TypeMatcher] implementation that handles is returned
/// by calls to [TypeMatcher.having].
class HavingMatcher<T> implements TypeMatcher<T> {
final TypeMatcher<T> _parent;
final List<_FunctionMatcher<T>> _functionMatchers;
HavingMatcher(
this._parent,
String description,
Object? Function(T) feature,
dynamic matcher,
) : _functionMatchers = [_FunctionMatcher<T>(description, feature, matcher)];
HavingMatcher._fromExisting(
this._parent,
String description,
Object? Function(T) feature,
dynamic matcher,
Iterable<_FunctionMatcher<T>>? existing,
) : _functionMatchers = [
...?existing,
_FunctionMatcher<T>(description, feature, matcher),
];
@override
TypeMatcher<T> having(
Object? Function(T) feature,
String description,
dynamic matcher,
) => HavingMatcher._fromExisting(
_parent,
description,
feature,
matcher,
_functionMatchers,
);
@override
bool matches(dynamic item, Map matchState) {
for (var matcher in <Matcher>[_parent].followedBy(_functionMatchers)) {
if (!matcher.matches(item, matchState)) {
addStateInfo(matchState, {'matcher': matcher});
return false;
}
}
return true;
}
@override
Description describeMismatch(
Object? item,
Description mismatchDescription,
Map matchState,
bool verbose,
) {
var matcher = matchState['matcher'] as Matcher;
matcher.describeMismatch(
item,
mismatchDescription,
matchState['state'] as Map,
verbose,
);
return mismatchDescription;
}
@override
Description describe(Description description) => description
.add('')
.addDescriptionOf(_parent)
.add(' with ')
.addAll('', ' and ', '', _functionMatchers);
}
class _FunctionMatcher<T> extends CustomMatcher {
final Object? Function(T value) _feature;
_FunctionMatcher(String name, this._feature, Object? matcher)
: super('`$name`:', '`$name`', matcher);
@override
Object? featureValueOf(covariant T actual) => _feature(actual);
}