| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 test.integration.analysis; | 5 library test.integration.analysis; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:collection'; | 8 import 'dart:collection'; |
| 9 import 'dart:convert'; | 9 import 'dart:convert'; |
| 10 import 'dart:io'; | 10 import 'dart:io'; |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 135 return server.kill().then((_) { | 135 return server.kill().then((_) { |
| 136 sourceDirectory.deleteSync(recursive: true); | 136 sourceDirectory.deleteSync(recursive: true); |
| 137 }); | 137 }); |
| 138 } | 138 } |
| 139 } | 139 } |
| 140 | 140 |
| 141 // Matchers for data types defined in the analysis server API | 141 // Matchers for data types defined in the analysis server API |
| 142 // ========================================================== | 142 // ========================================================== |
| 143 // TODO(paulberry): add more matchers. | 143 // TODO(paulberry): add more matchers. |
| 144 | 144 |
| 145 const Matcher isString = const isInstanceOf<String>('String'); | 145 // Matchers common to all domains |
| 146 | 146 // ------------------------------ |
| 147 const Matcher isInt = const isInstanceOf<int>('int'); | |
| 148 | |
| 149 const Matcher isBool = const isInstanceOf<bool>('bool'); | |
| 150 | 147 |
| 151 const Matcher isResultResponse = const MatchesJsonObject('result response', | 148 const Matcher isResultResponse = const MatchesJsonObject('result response', |
| 152 const { | 149 const { |
| 153 'id': isString | 150 'id': isString |
| 154 }, optionalFields: const { | 151 }, optionalFields: const { |
| 155 'result': anything | 152 'result': anything |
| 156 }); | 153 }); |
| 157 | 154 |
| 158 const Matcher isError = const MatchesJsonObject('Error', const { | 155 const Matcher isError = const MatchesJsonObject('Error', const { |
| 159 // TODO(paulberry): once we decide what the set of permitted error codes are, | 156 // TODO(paulberry): once we decide what the set of permitted error codes are, |
| (...skipping 13 matching lines...) Expand all Loading... |
| 173 'id': isString, | 170 'id': isString, |
| 174 'error': isError | 171 'error': isError |
| 175 }); | 172 }); |
| 176 | 173 |
| 177 const Matcher isNotification = const MatchesJsonObject('notification', const { | 174 const Matcher isNotification = const MatchesJsonObject('notification', const { |
| 178 'event': isString | 175 'event': isString |
| 179 }, optionalFields: const { | 176 }, optionalFields: const { |
| 180 'params': isMap | 177 'params': isMap |
| 181 }); | 178 }); |
| 182 | 179 |
| 180 // Matchers for specific responses and notifications |
| 181 // ------------------------------------------------- |
| 182 |
| 183 // server.getVersion |
| 183 const Matcher isServerGetVersionResult = const MatchesJsonObject( | 184 const Matcher isServerGetVersionResult = const MatchesJsonObject( |
| 184 'server.getVersion result', const { | 185 'server.getVersion result', const { |
| 185 'version': isString | 186 'version': isString |
| 186 }); | 187 }); |
| 187 | 188 |
| 189 // server.status |
| 188 const Matcher isServerStatusParams = const MatchesJsonObject( | 190 const Matcher isServerStatusParams = const MatchesJsonObject( |
| 189 'server.status params', null, optionalFields: const { | 191 'server.status params', null, optionalFields: const { |
| 190 'analysis': isAnalysisStatus | 192 'analysis': isAnalysisStatus |
| 191 }); | 193 }); |
| 192 | 194 |
| 193 final Matcher isErrorSeverity = isIn(['INFO', 'WARNING', 'ERROR']); | 195 // analysis.getHover |
| 194 | 196 final Matcher isAnalysisGetHoverResult = new MatchesJsonObject( |
| 195 final Matcher isErrorType = isIn(['COMPILE_TIME_ERROR', 'HINT', | 197 'analysis.getHover result', { |
| 196 'STATIC_TYPE_WARNING', 'STATIC_WARNING', 'SYNTACTIC_ERROR', 'TODO']); | 198 'hovers': isListOf(isHoverInformation) |
| 197 | |
| 198 const Matcher isLocation = const MatchesJsonObject('Location', const { | |
| 199 'file': isString, | |
| 200 'offset': isInt, | |
| 201 'length': isInt, | |
| 202 'startLine': isInt, | |
| 203 'startColumn': isInt | |
| 204 }); | 199 }); |
| 205 | 200 |
| 201 // Matchers for data types used in responses and notifications |
| 202 // ----------------------------------------------------------- |
| 203 |
| 204 const Matcher isString = const isInstanceOf<String>('String'); |
| 205 |
| 206 const Matcher isInt = const isInstanceOf<int>('int'); |
| 207 |
| 208 const Matcher isBool = const isInstanceOf<bool>('bool'); |
| 209 |
| 210 // AnalysisError |
| 206 final Matcher isAnalysisError = new MatchesJsonObject('AnalysisError', { | 211 final Matcher isAnalysisError = new MatchesJsonObject('AnalysisError', { |
| 207 'severity': isErrorSeverity, | 212 'severity': isErrorSeverity, |
| 208 'type': isErrorType, | 213 'type': isErrorType, |
| 209 'location': isLocation, | 214 'location': isLocation, |
| 210 'message': isString, | 215 'message': isString, |
| 211 }, optionalFields: { | 216 }, optionalFields: { |
| 212 'correction': isString | 217 'correction': isString |
| 213 }); | 218 }); |
| 214 | 219 |
| 220 // AnalysisStatus |
| 215 const Matcher isAnalysisStatus = const MatchesJsonObject('AnalysisStatus', const | 221 const Matcher isAnalysisStatus = const MatchesJsonObject('AnalysisStatus', const |
| 216 { | 222 { |
| 217 'analyzing': isBool | 223 'analyzing': isBool |
| 218 }, optionalFields: const { | 224 }, optionalFields: const { |
| 219 'analysisTarget': isString | 225 'analysisTarget': isString |
| 220 }); | 226 }); |
| 221 | 227 |
| 228 // ErrorSeverity |
| 229 final Matcher isErrorSeverity = isIn(['INFO', 'WARNING', 'ERROR']); |
| 230 |
| 231 // ErrorType |
| 232 final Matcher isErrorType = isIn(['COMPILE_TIME_ERROR', 'HINT', |
| 233 'STATIC_TYPE_WARNING', 'STATIC_WARNING', 'SYNTACTIC_ERROR', 'TODO']); |
| 234 |
| 235 // HoverInformation |
| 236 const Matcher isHoverInformation = const MatchesJsonObject('HoverInformation', |
| 237 const { |
| 238 'offset': isInt, |
| 239 'length': isInt |
| 240 }, optionalFields: const { |
| 241 'containingLibraryPath': isString, |
| 242 'containingLibraryName': isString, |
| 243 'dartdoc': isString, |
| 244 'elementDescription': isString, |
| 245 'elementKind': isString, |
| 246 'parameter': isString, |
| 247 'propagatedType': isString, |
| 248 'staticType': isString |
| 249 }); |
| 250 |
| 251 // Location |
| 252 const Matcher isLocation = const MatchesJsonObject('Location', const { |
| 253 'file': isString, |
| 254 'offset': isInt, |
| 255 'length': isInt, |
| 256 'startLine': isInt, |
| 257 'startColumn': isInt |
| 258 }); |
| 259 |
| 222 | 260 |
| 223 /** | 261 /** |
| 224 * Type of closures used by MatchesJsonObject to record field mismatches. | 262 * Type of closures used by MatchesJsonObject to record field mismatches. |
| 225 */ | 263 */ |
| 226 typedef Description MismatchDescriber(Description mismatchDescription, bool | 264 typedef Description MismatchDescriber(Description mismatchDescription, bool |
| 227 verbose); | 265 verbose); |
| 228 | 266 |
| 229 /** | 267 /** |
| 230 * Matcher that matches a JSON object, with a given set of required and | 268 * Matcher that matches a JSON object, with a given set of required and |
| 231 * optional fields, and their associated types (expressed as [Matcher]s). | 269 * optional fields, and their associated types (expressed as [Matcher]s). |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 336 mismatchDescription = mismatchDescription.add('; ').add(subDescription | 374 mismatchDescription = mismatchDescription.add('; ').add(subDescription |
| 337 ); | 375 ); |
| 338 } | 376 } |
| 339 return mismatchDescription.add(')'); | 377 return mismatchDescription.add(')'); |
| 340 }); | 378 }); |
| 341 } | 379 } |
| 342 } | 380 } |
| 343 } | 381 } |
| 344 | 382 |
| 345 /** | 383 /** |
| 384 * Matcher that matches a list of objects, each of which satisfies the given |
| 385 * matcher. |
| 386 */ |
| 387 class _ListOf extends Matcher { |
| 388 /** |
| 389 * Matcher which every element of the list must satisfy. |
| 390 */ |
| 391 final Matcher elementMatcher; |
| 392 |
| 393 /** |
| 394 * Iterable matcher which we use to test the contents of the list. |
| 395 */ |
| 396 final Matcher iterableMatcher; |
| 397 |
| 398 _ListOf(elementMatcher) |
| 399 : elementMatcher = elementMatcher, |
| 400 iterableMatcher = everyElement(elementMatcher); |
| 401 |
| 402 @override |
| 403 bool matches(item, Map matchState) { |
| 404 if (item is! List) { |
| 405 return false; |
| 406 } |
| 407 return iterableMatcher.matches(item, matchState); |
| 408 } |
| 409 |
| 410 @override |
| 411 Description describe(Description description) => description.add('List of ' |
| 412 ).addDescriptionOf(elementMatcher); |
| 413 |
| 414 @override |
| 415 Description describeMismatch(item, Description mismatchDescription, Map |
| 416 matchState, bool verbose) { |
| 417 if (item is! List) { |
| 418 return super.describeMismatch(item, mismatchDescription, matchState, |
| 419 verbose); |
| 420 } else { |
| 421 return iterableMatcher.describeMismatch(item, mismatchDescription, |
| 422 matchState, verbose); |
| 423 } |
| 424 } |
| 425 } |
| 426 |
| 427 Matcher isListOf(Matcher elementMatcher) => new _ListOf(elementMatcher); |
| 428 |
| 429 /** |
| 346 * Instances of the class [Server] manage a connection to a server process, and | 430 * Instances of the class [Server] manage a connection to a server process, and |
| 347 * facilitate communication to and from the server. | 431 * facilitate communication to and from the server. |
| 348 */ | 432 */ |
| 349 class Server { | 433 class Server { |
| 350 /** | 434 /** |
| 351 * Server process object. | 435 * Server process object. |
| 352 */ | 436 */ |
| 353 Process _process; | 437 Process _process; |
| 354 | 438 |
| 355 /** | 439 /** |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 530 * Record a message that was exchanged with the server, and print it out if | 614 * Record a message that was exchanged with the server, and print it out if |
| 531 * [debugStdio] has been called. | 615 * [debugStdio] has been called. |
| 532 */ | 616 */ |
| 533 void _recordStdio(String line) { | 617 void _recordStdio(String line) { |
| 534 if (_debuggingStdio) { | 618 if (_debuggingStdio) { |
| 535 print(line); | 619 print(line); |
| 536 } | 620 } |
| 537 _recordedStdio.add(line); | 621 _recordedStdio.add(line); |
| 538 } | 622 } |
| 539 } | 623 } |
| OLD | NEW |