| 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 |