// 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 implements TypeMatcher { final TypeMatcher _parent; final List<_FunctionMatcher> _functionMatchers; HavingMatcher( this._parent, String description, Object? Function(T) feature, dynamic matcher, ) : _functionMatchers = [_FunctionMatcher(description, feature, matcher)]; HavingMatcher._fromExisting( this._parent, String description, Object? Function(T) feature, dynamic matcher, Iterable<_FunctionMatcher>? existing, ) : _functionMatchers = [ ...?existing, _FunctionMatcher(description, feature, matcher), ]; @override TypeMatcher 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 [_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 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); }