OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library matcher.string_matchers; | 5 library matcher.string_matchers; |
6 | 6 |
7 import 'interfaces.dart'; | 7 import 'interfaces.dart'; |
8 | 8 |
9 /// Returns a matcher which matches if the match argument is a string and | 9 /// Returns a matcher which matches if the match argument is a string and |
10 /// is equal to [value] when compared case-insensitively. | 10 /// is equal to [value] when compared case-insensitively. |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
50 final String _matchValue; | 50 final String _matchValue; |
51 | 51 |
52 _IsEqualIgnoringWhitespace(String value) | 52 _IsEqualIgnoringWhitespace(String value) |
53 : _value = value, | 53 : _value = value, |
54 _matchValue = collapseWhitespace(value); | 54 _matchValue = collapseWhitespace(value); |
55 | 55 |
56 bool matches(item, Map matchState) => | 56 bool matches(item, Map matchState) => |
57 item is String && _matchValue == collapseWhitespace(item); | 57 item is String && _matchValue == collapseWhitespace(item); |
58 | 58 |
59 Description describe(Description description) => | 59 Description describe(Description description) => |
60 description.addDescriptionOf(_matchValue).add(' ignoring whitespace'); | 60 description.addDescriptionOf(_matchValue).add(' ignoring whitespace'); |
61 | 61 |
62 Description describeMismatch(item, Description mismatchDescription, | 62 Description describeMismatch( |
63 Map matchState, bool verbose) { | 63 item, Description mismatchDescription, Map matchState, bool verbose) { |
64 if (item is String) { | 64 if (item is String) { |
65 return mismatchDescription.add('is '). | 65 return mismatchDescription |
66 addDescriptionOf(collapseWhitespace(item)). | 66 .add('is ') |
67 add(' with whitespace compressed'); | 67 .addDescriptionOf(collapseWhitespace(item)) |
| 68 .add(' with whitespace compressed'); |
68 } else { | 69 } else { |
69 return super.describeMismatch(item, mismatchDescription, | 70 return super.describeMismatch( |
70 matchState, verbose); | 71 item, mismatchDescription, matchState, verbose); |
71 } | 72 } |
72 } | 73 } |
73 } | 74 } |
74 | 75 |
75 /// Returns a matcher that matches if the match argument is a string and | 76 /// Returns a matcher that matches if the match argument is a string and |
76 /// starts with [prefixString]. | 77 /// starts with [prefixString]. |
77 Matcher startsWith(String prefixString) => new _StringStartsWith(prefixString); | 78 Matcher startsWith(String prefixString) => new _StringStartsWith(prefixString); |
78 | 79 |
79 class _StringStartsWith extends _StringMatcher { | 80 class _StringStartsWith extends _StringMatcher { |
80 final String _prefix; | 81 final String _prefix; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
123 return false; | 124 return false; |
124 } | 125 } |
125 var from_index = 0; | 126 var from_index = 0; |
126 for (var s in _substrings) { | 127 for (var s in _substrings) { |
127 from_index = item.indexOf(s, from_index); | 128 from_index = item.indexOf(s, from_index); |
128 if (from_index < 0) return false; | 129 if (from_index < 0) return false; |
129 } | 130 } |
130 return true; | 131 return true; |
131 } | 132 } |
132 | 133 |
133 Description describe(Description description) => | 134 Description describe(Description description) => description.addAll( |
134 description.addAll('a string containing ', ', ', ' in order', | 135 'a string containing ', ', ', ' in order', _substrings); |
135 _substrings); | |
136 } | 136 } |
137 | 137 |
138 /// Returns a matcher that matches if the match argument is a string and | 138 /// Returns a matcher that matches if the match argument is a string and |
139 /// matches the regular expression given by [re]. | 139 /// matches the regular expression given by [re]. |
140 /// | 140 /// |
141 /// [re] can be a [RegExp] instance or a [String]; in the latter case it will be | 141 /// [re] can be a [RegExp] instance or a [String]; in the latter case it will be |
142 /// used to create a RegExp instance. | 142 /// used to create a RegExp instance. |
143 Matcher matches(re) => new _MatchesRegExp(re); | 143 Matcher matches(re) => new _MatchesRegExp(re); |
144 | 144 |
145 class _MatchesRegExp extends _StringMatcher { | 145 class _MatchesRegExp extends _StringMatcher { |
146 RegExp _regexp; | 146 RegExp _regexp; |
147 | 147 |
148 _MatchesRegExp(re) { | 148 _MatchesRegExp(re) { |
149 if (re is String) { | 149 if (re is String) { |
150 _regexp = new RegExp(re); | 150 _regexp = new RegExp(re); |
151 } else if (re is RegExp) { | 151 } else if (re is RegExp) { |
152 _regexp = re; | 152 _regexp = re; |
153 } else { | 153 } else { |
154 throw new ArgumentError('matches requires a regexp or string'); | 154 throw new ArgumentError('matches requires a regexp or string'); |
155 } | 155 } |
156 } | 156 } |
157 | 157 |
158 bool matches(item, Map matchState) => | 158 bool matches(item, Map matchState) => |
159 item is String ? _regexp.hasMatch(item) : false; | 159 item is String ? _regexp.hasMatch(item) : false; |
160 | 160 |
161 Description describe(Description description) => | 161 Description describe(Description description) => |
162 description.add("match '${_regexp.pattern}'"); | 162 description.add("match '${_regexp.pattern}'"); |
163 } | 163 } |
164 | 164 |
165 // String matchers match against a string. We add this intermediate | 165 // String matchers match against a string. We add this intermediate |
166 // class to give better mismatch error messages than the base Matcher class. | 166 // class to give better mismatch error messages than the base Matcher class. |
167 abstract class _StringMatcher extends Matcher { | 167 abstract class _StringMatcher extends Matcher { |
168 const _StringMatcher(); | 168 const _StringMatcher(); |
169 Description describeMismatch(item, Description mismatchDescription, | 169 Description describeMismatch( |
170 Map matchState, bool verbose) { | 170 item, Description mismatchDescription, Map matchState, bool verbose) { |
171 if (!(item is String)) { | 171 if (!(item is String)) { |
172 return mismatchDescription. | 172 return mismatchDescription.addDescriptionOf(item).add(' not a string'); |
173 addDescriptionOf(item). | |
174 add(' not a string'); | |
175 } else { | 173 } else { |
176 return super.describeMismatch(item, mismatchDescription, | 174 return super.describeMismatch( |
177 matchState, verbose); | 175 item, mismatchDescription, matchState, verbose); |
178 } | 176 } |
179 } | 177 } |
180 } | 178 } |
181 | 179 |
182 /// Utility function to collapse whitespace runs to single spaces | 180 /// Utility function to collapse whitespace runs to single spaces |
183 /// and strip leading/trailing whitespace. | 181 /// and strip leading/trailing whitespace. |
184 String collapseWhitespace(String string) { | 182 String collapseWhitespace(String string) { |
185 var result = new StringBuffer(); | 183 var result = new StringBuffer(); |
186 var skipSpace = true; | 184 var skipSpace = true; |
187 for (var i = 0; i < string.length; i++) { | 185 for (var i = 0; i < string.length; i++) { |
188 var character = string[i]; | 186 var character = string[i]; |
189 if (_isWhitespace(character)) { | 187 if (_isWhitespace(character)) { |
190 if (!skipSpace) { | 188 if (!skipSpace) { |
191 result.write(' '); | 189 result.write(' '); |
192 skipSpace = true; | 190 skipSpace = true; |
193 } | 191 } |
194 } else { | 192 } else { |
195 result.write(character); | 193 result.write(character); |
196 skipSpace = false; | 194 skipSpace = false; |
197 } | 195 } |
198 } | 196 } |
199 return result.toString().trim(); | 197 return result.toString().trim(); |
200 } | 198 } |
201 | 199 |
202 bool _isWhitespace(String ch) => | 200 bool _isWhitespace(String ch) => |
203 ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t'; | 201 ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t'; |
OLD | NEW |