blob: 6824c5ba9eeff19da81a33010142948544744960 [file] [log] [blame]
kevmoo@google.comf9c77422014-03-21 23:50:50 +00001// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
kevmoo@google.com94a9bcf2014-06-05 17:11:03 +00005library matcher.operator_matchers;
kevmoo@google.comf9c77422014-03-21 23:50:50 +00006
kevmoo@google.com94a9bcf2014-06-05 17:11:03 +00007import 'interfaces.dart';
kevmoo@google.come0d6dfd2014-07-31 22:50:50 +00008import 'util.dart';
kevmoo@google.com94a9bcf2014-06-05 17:11:03 +00009
10/// This returns a matcher that inverts [matcher] to its logical negation.
kevmoo@google.comf9c77422014-03-21 23:50:50 +000011Matcher isNot(matcher) => new _IsNot(wrapMatcher(matcher));
12
13class _IsNot extends Matcher {
14 final Matcher _matcher;
15
kevmoo@google.come0d6dfd2014-07-31 22:50:50 +000016 const _IsNot(this._matcher);
kevmoo@google.comf9c77422014-03-21 23:50:50 +000017
18 bool matches(item, Map matchState) => !_matcher.matches(item, matchState);
19
20 Description describe(Description description) =>
Kevin Moore0d23f152015-01-14 14:28:53 -080021 description.add('not ').addDescriptionOf(_matcher);
kevmoo@google.comf9c77422014-03-21 23:50:50 +000022}
23
kevmoo@google.com94a9bcf2014-06-05 17:11:03 +000024/// This returns a matcher that matches if all of the matchers passed as
srawlins@google.com3bec76d2014-10-06 16:23:04 +000025/// arguments (up to 7) match.
26///
27/// Instead of passing the matchers separately they can be passed as a single
28/// List argument. Any argument that is not a matcher is implicitly wrapped in a
kevmoo@google.com94a9bcf2014-06-05 17:11:03 +000029/// Matcher to check for equality.
Kevin Moore0d23f152015-01-14 14:28:53 -080030Matcher allOf(arg0, [arg1, arg2, arg3, arg4, arg5, arg6]) {
kevmoo@google.com94a9bcf2014-06-05 17:11:03 +000031 return new _AllOf(_wrapArgs(arg0, arg1, arg2, arg3, arg4, arg5, arg6));
kevmoo@google.comf9c77422014-03-21 23:50:50 +000032}
33
34class _AllOf extends Matcher {
kevmoo@google.com94a9bcf2014-06-05 17:11:03 +000035 final List<Matcher> _matchers;
kevmoo@google.comf9c77422014-03-21 23:50:50 +000036
37 const _AllOf(this._matchers);
38
39 bool matches(item, Map matchState) {
Kevin Moore0d23f152015-01-14 14:28:53 -080040 for (var matcher in _matchers) {
41 if (!matcher.matches(item, matchState)) {
kevmoo@google.comf9c77422014-03-21 23:50:50 +000042 addStateInfo(matchState, {'matcher': matcher});
Kevin Moore0d23f152015-01-14 14:28:53 -080043 return false;
44 }
45 }
46 return true;
kevmoo@google.comf9c77422014-03-21 23:50:50 +000047 }
48
Kevin Moore0d23f152015-01-14 14:28:53 -080049 Description describeMismatch(
50 item, Description mismatchDescription, Map matchState, bool verbose) {
kevmoo@google.comf9c77422014-03-21 23:50:50 +000051 var matcher = matchState['matcher'];
Kevin Moore0d23f152015-01-14 14:28:53 -080052 matcher.describeMismatch(
53 item, mismatchDescription, matchState['state'], verbose);
kevmoo@google.comf9c77422014-03-21 23:50:50 +000054 return mismatchDescription;
55 }
56
57 Description describe(Description description) =>
58 description.addAll('(', ' and ', ')', _matchers);
59}
60
srawlins@google.com3bec76d2014-10-06 16:23:04 +000061/// Matches if any of the given matchers evaluate to true.
62///
63/// The arguments can be a set of matchers as separate parameters
kevmoo@google.com94a9bcf2014-06-05 17:11:03 +000064/// (up to 7), or a List of matchers.
65///
66/// The matchers are evaluated from left to right using short-circuit
67/// evaluation, so evaluation stops as soon as a matcher returns true.
68///
69/// Any argument that is not a matcher is implicitly wrapped in a
70/// Matcher to check for equality.
Kevin Moore0d23f152015-01-14 14:28:53 -080071Matcher anyOf(arg0, [arg1, arg2, arg3, arg4, arg5, arg6]) {
kevmoo@google.com94a9bcf2014-06-05 17:11:03 +000072 return new _AnyOf(_wrapArgs(arg0, arg1, arg2, arg3, arg4, arg5, arg6));
kevmoo@google.com27da56e2014-06-02 16:54:44 +000073}
kevmoo@google.com1495cd12014-06-03 07:10:01 +000074
75class _AnyOf extends Matcher {
kevmoo@google.com94a9bcf2014-06-05 17:11:03 +000076 final List<Matcher> _matchers;
kevmoo@google.com1495cd12014-06-03 07:10:01 +000077
78 const _AnyOf(this._matchers);
79
80 bool matches(item, Map matchState) {
kevmoo@google.com94a9bcf2014-06-05 17:11:03 +000081 for (var matcher in _matchers) {
82 if (matcher.matches(item, matchState)) {
83 return true;
84 }
85 }
86 return false;
kevmoo@google.com1495cd12014-06-03 07:10:01 +000087 }
88
89 Description describe(Description description) =>
Kevin Moore0d23f152015-01-14 14:28:53 -080090 description.addAll('(', ' or ', ')', _matchers);
kevmoo@google.com1495cd12014-06-03 07:10:01 +000091}
92
kevmoo@google.com94a9bcf2014-06-05 17:11:03 +000093List<Matcher> _wrapArgs(arg0, arg1, arg2, arg3, arg4, arg5, arg6) {
kevmoo@google.come0d6dfd2014-07-31 22:50:50 +000094 Iterable<Matcher> matchers;
kevmoo@google.com94a9bcf2014-06-05 17:11:03 +000095 if (arg0 is List) {
Kevin Moore0d23f152015-01-14 14:28:53 -080096 if (arg1 != null ||
97 arg2 != null ||
98 arg3 != null ||
99 arg4 != null ||
100 arg5 != null ||
101 arg6 != null) {
kevmoo@google.come0d6dfd2014-07-31 22:50:50 +0000102 throw new ArgumentError('If arg0 is a List, all other arguments must be'
103 ' null.');
104 }
kevmoo@google.com94a9bcf2014-06-05 17:11:03 +0000105
kevmoo@google.come0d6dfd2014-07-31 22:50:50 +0000106 matchers = arg0;
107 } else {
Kevin Moore0d23f152015-01-14 14:28:53 -0800108 matchers =
109 [arg0, arg1, arg2, arg3, arg4, arg5, arg6].where((e) => e != null);
kevmoo@google.com94a9bcf2014-06-05 17:11:03 +0000110 }
111
Kevin Moore0d23f152015-01-14 14:28:53 -0800112 return matchers.map((e) => wrapMatcher(e)).toList();
kevmoo@google.com94a9bcf2014-06-05 17:11:03 +0000113}