| 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.domain.analysis; | 5 library test.domain.analysis; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 | 8 |
| 9 import 'package:analysis_server/src/analysis_server.dart'; | 9 import 'package:analysis_server/src/analysis_server.dart'; |
| 10 import 'package:analysis_server/src/constants.dart'; | 10 import 'package:analysis_server/src/constants.dart'; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 runReflectiveTests(AnalysisDomainTest); | 26 runReflectiveTests(AnalysisDomainTest); |
| 27 | 27 |
| 28 MockServerChannel serverChannel; | 28 MockServerChannel serverChannel; |
| 29 MemoryResourceProvider resourceProvider; | 29 MemoryResourceProvider resourceProvider; |
| 30 AnalysisServer server; | 30 AnalysisServer server; |
| 31 AnalysisDomainHandler handler; | 31 AnalysisDomainHandler handler; |
| 32 | 32 |
| 33 setUp(() { | 33 setUp(() { |
| 34 serverChannel = new MockServerChannel(); | 34 serverChannel = new MockServerChannel(); |
| 35 resourceProvider = new MemoryResourceProvider(); | 35 resourceProvider = new MemoryResourceProvider(); |
| 36 server = new AnalysisServer( | 36 server = new AnalysisServer(serverChannel, resourceProvider, |
| 37 serverChannel, resourceProvider, new MockPackageMapProvider(), null); | 37 new MockPackageMapProvider(), null); |
| 38 server.defaultSdk = new MockSdk(); | 38 server.defaultSdk = new MockSdk(); |
| 39 handler = new AnalysisDomainHandler(server); | 39 handler = new AnalysisDomainHandler(server); |
| 40 }); | 40 }); |
| 41 | 41 |
| 42 group('notification.errors', testNotificationErrors); | 42 group('notification.errors', testNotificationErrors); |
| 43 group('updateContent', testUpdateContent); | 43 group('updateContent', testUpdateContent); |
| 44 group('setSubscriptions', test_setSubscriptions); | 44 group('setSubscriptions', test_setSubscriptions); |
| 45 | 45 |
| 46 group('AnalysisDomainHandler', () { | 46 group('AnalysisDomainHandler', () { |
| 47 group('setAnalysisRoots', () { | 47 group('setAnalysisRoots', () { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 58 // TODO(scheglov) implement | 58 // TODO(scheglov) implement |
| 59 var response = handler.handleRequest(request); | 59 var response = handler.handleRequest(request); |
| 60 expect(response, isResponseFailure('0')); | 60 expect(response, isResponseFailure('0')); |
| 61 }); | 61 }); |
| 62 | 62 |
| 63 group('included', () { | 63 group('included', () { |
| 64 test('new folder', () { | 64 test('new folder', () { |
| 65 resourceProvider.newFolder('/project'); | 65 resourceProvider.newFolder('/project'); |
| 66 resourceProvider.newFile('/project/pubspec.yaml', 'name: project'); | 66 resourceProvider.newFile('/project/pubspec.yaml', 'name: project'); |
| 67 resourceProvider.newFile('/project/bin/test.dart', 'main() {}'); | 67 resourceProvider.newFile('/project/bin/test.dart', 'main() {}'); |
| 68 request.setParameter( | 68 request.setParameter(INCLUDED, ['/project']); |
| 69 INCLUDED, | |
| 70 ['/project']); | |
| 71 var response = handler.handleRequest(request); | 69 var response = handler.handleRequest(request); |
| 72 var serverRef = server; | 70 var serverRef = server; |
| 73 expect(response, isResponseSuccess('0')); | 71 expect(response, isResponseSuccess('0')); |
| 74 // verify that unit is resolved eventually | 72 // verify that unit is resolved eventually |
| 75 return waitForServerOperationsPerformed(server).then((_) { | 73 return waitForServerOperationsPerformed(server).then((_) { |
| 76 var unit = serverRef.test_getResolvedCompilationUnit('/project/bin/t
est.dart'); | 74 var unit = serverRef.test_getResolvedCompilationUnit( |
| 75 '/project/bin/test.dart'); |
| 77 expect(unit, isNotNull); | 76 expect(unit, isNotNull); |
| 78 }); | 77 }); |
| 79 }); | 78 }); |
| 80 }); | 79 }); |
| 81 }); | 80 }); |
| 82 | 81 |
| 83 group('setPriorityFiles', () { | 82 group('setPriorityFiles', () { |
| 84 test('invalid', () { | 83 test('invalid', () { |
| 85 var request = new Request('0', ANALYSIS_SET_PRIORITY_FILES); | 84 var request = new Request('0', ANALYSIS_SET_PRIORITY_FILES); |
| 86 request.setParameter(FILES, ['/project/lib.dart']); | 85 request.setParameter(FILES, ['/project/lib.dart']); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 113 | 112 |
| 114 setPriorityFiles(['/p1/a.dart', '/p2/b.dart']); | 113 setPriorityFiles(['/p1/a.dart', '/p2/b.dart']); |
| 115 setPriorityFiles(['/p2/b.dart', '/p2/c.dart']); | 114 setPriorityFiles(['/p2/b.dart', '/p2/c.dart']); |
| 116 setPriorityFiles([]); | 115 setPriorityFiles([]); |
| 117 }); | 116 }); |
| 118 }); | 117 }); |
| 119 | 118 |
| 120 group('updateOptions', () { | 119 group('updateOptions', () { |
| 121 test('invalid', () { | 120 test('invalid', () { |
| 122 var request = new Request('0', ANALYSIS_UPDATE_OPTIONS); | 121 var request = new Request('0', ANALYSIS_UPDATE_OPTIONS); |
| 123 request.setParameter(OPTIONS, {'not-an-option' : true}); | 122 request.setParameter(OPTIONS, { |
| 123 'not-an-option': true |
| 124 }); |
| 124 var response = handler.handleRequest(request); | 125 var response = handler.handleRequest(request); |
| 125 expect(response, isResponseFailure('0')); | 126 expect(response, isResponseFailure('0')); |
| 126 }); | 127 }); |
| 127 | 128 |
| 128 test('valid', () { | 129 test('valid', () { |
| 129 AnalysisOptions options = server.contextDirectoryManager.defaultOptions; | 130 AnalysisOptions options = server.contextDirectoryManager.defaultOptions; |
| 130 bool analyzeAngular = !options.analyzeAngular; | 131 bool analyzeAngular = !options.analyzeAngular; |
| 131 bool enableDeferredLoading = options.enableDeferredLoading; | 132 bool enableDeferredLoading = options.enableDeferredLoading; |
| 132 var request = new Request('0', ANALYSIS_UPDATE_OPTIONS); | 133 var request = new Request('0', ANALYSIS_UPDATE_OPTIONS); |
| 133 request.setParameter( | 134 request.setParameter(OPTIONS, { |
| 134 OPTIONS, | 135 'analyzeAngular': analyzeAngular, |
| 135 { | 136 'enableDeferredLoading': enableDeferredLoading, |
| 136 'analyzeAngular' : analyzeAngular, | 137 'enableEnums': false |
| 137 'enableDeferredLoading': enableDeferredLoading, | 138 }); |
| 138 'enableEnums': false | |
| 139 }); | |
| 140 var response = handler.handleRequest(request); | 139 var response = handler.handleRequest(request); |
| 141 expect(response, isResponseSuccess('0')); | 140 expect(response, isResponseSuccess('0')); |
| 142 expect(options.analyzeAngular, equals(analyzeAngular)); | 141 expect(options.analyzeAngular, equals(analyzeAngular)); |
| 143 expect(options.enableDeferredLoading, equals(enableDeferredLoading)); | 142 expect(options.enableDeferredLoading, equals(enableDeferredLoading)); |
| 144 }); | 143 }); |
| 145 }); | 144 }); |
| 146 | 145 |
| 147 test('updateSdks', () { | 146 test('updateSdks', () { |
| 148 var request = new Request('0', ANALYSIS_UPDATE_SDKS); | 147 var request = new Request('0', ANALYSIS_UPDATE_SDKS); |
| 149 request.setParameter( | 148 request.setParameter(ADDED, ['/dart/sdk-1.3', '/dart/sdk-1.4']); |
| 150 ADDED, | 149 request.setParameter(REMOVED, ['/dart/sdk-1.2']); |
| 151 ['/dart/sdk-1.3', '/dart/sdk-1.4']); | |
| 152 request.setParameter( | |
| 153 REMOVED, | |
| 154 ['/dart/sdk-1.2']); | |
| 155 request.setParameter(DEFAULT, '/dart/sdk-1.4'); | 150 request.setParameter(DEFAULT, '/dart/sdk-1.4'); |
| 156 var response = handler.handleRequest(request); | 151 var response = handler.handleRequest(request); |
| 157 // TODO(scheglov) implement | 152 // TODO(scheglov) implement |
| 158 expect(response, isNull); | 153 expect(response, isNull); |
| 159 }); | 154 }); |
| 160 }); | 155 }); |
| 161 } | 156 } |
| 162 | 157 |
| 163 | 158 |
| 164 class AnalysisError { | 159 class AnalysisError { |
| 165 final String file; | |
| 166 final String errorCode; | 160 final String errorCode; |
| 167 final int offset; | 161 final String severity; |
| 168 final int length; | 162 final String type; |
| 163 final Location location; |
| 169 final String message; | 164 final String message; |
| 170 final String correction; | 165 final String correction; |
| 171 AnalysisError(this.file, this.errorCode, this.offset, this.length, | 166 AnalysisError(this.errorCode, this.severity, this.type, this.location, |
| 172 this.message, this.correction); | 167 this.message, this.correction); |
| 173 | 168 |
| 174 @override | 169 @override |
| 175 String toString() { | 170 String toString() { |
| 176 return 'NotificationError(file=$file; errorCode=$errorCode; ' | 171 return 'AnalysisError(location=$location message=$message); ' |
| 177 'offset=$offset; length=$length; message=$message)'; | 172 'errorCode=$errorCode; severity=$separator type=$type'; |
| 173 } |
| 174 } |
| 175 |
| 176 |
| 177 class Location { |
| 178 final String file; |
| 179 final int offset; |
| 180 final int length; |
| 181 final int startLine; |
| 182 final int startColumn; |
| 183 Location(this.file, this.offset, this.length, this.startLine, |
| 184 this.startColumn); |
| 185 |
| 186 @override |
| 187 String toString() { |
| 188 return 'Location(file=$file; offset=$offset; length=$length; ' |
| 189 'startLine=$startLine; startColumn=$startColumn)'; |
| 178 } | 190 } |
| 179 } | 191 } |
| 180 | 192 |
| 181 | 193 |
| 182 AnalysisError jsonToAnalysisError(Map<String, Object> json) { | 194 AnalysisError jsonToAnalysisError(Map<String, Object> json) { |
| 183 return new AnalysisError( | 195 Map<String, Object> jsonLocation = json[LOCATION]; |
| 184 json['file'], | 196 Location location = new Location(jsonLocation[FILE], _getSafeInt(jsonLocation, |
| 185 json['errorCode'], | 197 OFFSET, -1), _getSafeInt(jsonLocation, LENGTH, -1), _getSafeInt(jsonLocati
on, |
| 186 json['offset'], | 198 START_LINE, -1), _getSafeInt(jsonLocation, START_COLUMN, -1)); |
| 187 json['length'], | 199 return new AnalysisError(json[ERROR_CODE], json[SEVERITY], json[TYPE], locatio
n, |
| 188 json['message'], | 200 json['message'], json['correction']); |
| 189 json['correction']); | |
| 190 } | 201 } |
| 191 | 202 |
| 192 | 203 |
| 204 int _getSafeInt(Map<String, Object> json, String key, int defaultValue) { |
| 205 Object value = json[key]; |
| 206 if (value is int) { |
| 207 return value; |
| 208 } |
| 209 return defaultValue; |
| 210 } |
| 211 |
| 212 |
| 193 /** | 213 /** |
| 194 * A helper to test 'analysis.*' requests. | 214 * A helper to test 'analysis.*' requests. |
| 195 */ | 215 */ |
| 196 class AnalysisTestHelper { | 216 class AnalysisTestHelper { |
| 197 MockServerChannel serverChannel; | 217 MockServerChannel serverChannel; |
| 198 MemoryResourceProvider resourceProvider; | 218 MemoryResourceProvider resourceProvider; |
| 199 AnalysisServer server; | 219 AnalysisServer server; |
| 200 AnalysisDomainHandler handler; | 220 AnalysisDomainHandler handler; |
| 201 | 221 |
| 202 Map<String, List<String>> analysisSubscriptions = {}; | 222 Map<String, List<String>> analysisSubscriptions = {}; |
| 203 | 223 |
| 204 Map<String, List<AnalysisError>> filesErrors = {}; | 224 Map<String, List<AnalysisError>> filesErrors = {}; |
| 205 Map<String, List<Map<String, Object>>> filesHighlights = {}; | 225 Map<String, List<Map<String, Object>>> filesHighlights = {}; |
| 206 Map<String, List<Map<String, Object>>> filesNavigation = {}; | 226 Map<String, List<Map<String, Object>>> filesNavigation = {}; |
| 207 | 227 |
| 208 String testFile = '/project/bin/test.dart'; | 228 String testFile = '/project/bin/test.dart'; |
| 209 String testCode; | 229 String testCode; |
| 210 | 230 |
| 211 AnalysisTestHelper() { | 231 AnalysisTestHelper() { |
| 212 serverChannel = new MockServerChannel(); | 232 serverChannel = new MockServerChannel(); |
| 213 resourceProvider = new MemoryResourceProvider(); | 233 resourceProvider = new MemoryResourceProvider(); |
| 214 server = new AnalysisServer( | 234 server = new AnalysisServer(serverChannel, resourceProvider, |
| 215 serverChannel, resourceProvider, new MockPackageMapProvider(), null); | 235 new MockPackageMapProvider(), null); |
| 216 server.defaultSdk = new MockSdk(); | 236 server.defaultSdk = new MockSdk(); |
| 217 handler = new AnalysisDomainHandler(server); | 237 handler = new AnalysisDomainHandler(server); |
| 218 // listen for notifications | 238 // listen for notifications |
| 219 Stream<Notification> notificationStream = serverChannel.notificationControll
er.stream; | 239 Stream<Notification> notificationStream = |
| 240 serverChannel.notificationController.stream; |
| 220 notificationStream.listen((Notification notification) { | 241 notificationStream.listen((Notification notification) { |
| 221 if (notification.event == ANALYSIS_ERRORS) { | 242 if (notification.event == ANALYSIS_ERRORS) { |
| 222 String file = notification.getParameter(FILE); | 243 String file = notification.getParameter(FILE); |
| 223 List<Map<String, Object>> errorMaps = notification.getParameter(ERRORS); | 244 List<Map<String, Object>> errorMaps = notification.getParameter(ERRORS); |
| 224 filesErrors[file] = errorMaps.map(jsonToAnalysisError).toList(); | 245 filesErrors[file] = errorMaps.map(jsonToAnalysisError).toList(); |
| 225 } | 246 } |
| 226 if (notification.event == ANALYSIS_HIGHLIGHTS) { | 247 if (notification.event == ANALYSIS_HIGHLIGHTS) { |
| 227 String file = notification.getParameter(FILE); | 248 String file = notification.getParameter(FILE); |
| 228 filesHighlights[file] = notification.getParameter(REGIONS); | 249 filesHighlights[file] = notification.getParameter(REGIONS); |
| 229 } | 250 } |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 405 setUp(() { | 426 setUp(() { |
| 406 helper = new AnalysisTestHelper(); | 427 helper = new AnalysisTestHelper(); |
| 407 }); | 428 }); |
| 408 | 429 |
| 409 test('ParserErrorCode', () { | 430 test('ParserErrorCode', () { |
| 410 helper.createSingleFileProject('library lib'); | 431 helper.createSingleFileProject('library lib'); |
| 411 return helper.waitForOperationsFinished().then((_) { | 432 return helper.waitForOperationsFinished().then((_) { |
| 412 List<AnalysisError> errors = helper.getTestErrors(); | 433 List<AnalysisError> errors = helper.getTestErrors(); |
| 413 expect(errors, hasLength(1)); | 434 expect(errors, hasLength(1)); |
| 414 AnalysisError error = errors[0]; | 435 AnalysisError error = errors[0]; |
| 415 expect(error.file, '/project/bin/test.dart'); | 436 expect(error.location.file, '/project/bin/test.dart'); |
| 437 expect(error.location.offset, isPositive); |
| 438 expect(error.location.length, isNonNegative); |
| 416 expect(error.errorCode, 'ParserErrorCode.EXPECTED_TOKEN'); | 439 expect(error.errorCode, 'ParserErrorCode.EXPECTED_TOKEN'); |
| 417 expect(error.offset, isPositive); | 440 expect(error.severity, 'ERROR'); |
| 418 expect(error.length, isNonNegative); | 441 expect(error.type, 'SYNTACTIC_ERROR'); |
| 419 expect(error.message, isNotNull); | 442 expect(error.message, isNotNull); |
| 420 }); | 443 }); |
| 421 }); | 444 }); |
| 422 | 445 |
| 423 test('StaticWarningCode', () { | 446 test('StaticWarningCode', () { |
| 424 helper.createSingleFileProject([ | 447 helper.createSingleFileProject(['main() {', ' print(unknown);', '}']); |
| 425 'main() {', | |
| 426 ' print(unknown);', | |
| 427 '}']); | |
| 428 return helper.waitForOperationsFinished().then((_) { | 448 return helper.waitForOperationsFinished().then((_) { |
| 429 List<AnalysisError> errors = helper.getTestErrors(); | 449 List<AnalysisError> errors = helper.getTestErrors(); |
| 430 expect(errors, hasLength(1)); | 450 expect(errors, hasLength(1)); |
| 431 AnalysisError error = errors[0]; | 451 AnalysisError error = errors[0]; |
| 432 expect(error.errorCode, 'StaticWarningCode.UNDEFINED_IDENTIFIER'); | 452 expect(error.errorCode, 'StaticWarningCode.UNDEFINED_IDENTIFIER'); |
| 433 }); | 453 }); |
| 434 }); | 454 }); |
| 435 } | 455 } |
| 436 | 456 |
| 437 | 457 |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 571 } | 591 } |
| 572 } | 592 } |
| 573 | 593 |
| 574 test_setRoots_packages() { | 594 test_setRoots_packages() { |
| 575 // prepare package | 595 // prepare package |
| 576 String pkgFile = '/packages/pkgA/libA.dart'; | 596 String pkgFile = '/packages/pkgA/libA.dart'; |
| 577 resourceProvider.newFile(pkgFile, ''' | 597 resourceProvider.newFile(pkgFile, ''' |
| 578 library lib_a; | 598 library lib_a; |
| 579 class A {} | 599 class A {} |
| 580 '''); | 600 '''); |
| 581 packageMapProvider.packageMap['pkgA'] = | 601 packageMapProvider.packageMap['pkgA'] = [resourceProvider.getResource( |
| 582 [resourceProvider.getResource('/packages/pkgA')]; | 602 '/packages/pkgA')]; |
| 583 addTestFile(''' | 603 addTestFile(''' |
| 584 import 'package:pkgA/libA.dart'; | 604 import 'package:pkgA/libA.dart'; |
| 585 main(A a) { | 605 main(A a) { |
| 586 } | 606 } |
| 587 '''); | 607 '''); |
| 588 // create project and wait for analysis | 608 // create project and wait for analysis |
| 589 createProject(); | 609 createProject(); |
| 590 return waitForTasksFinished().then((_) { | 610 return waitForTasksFinished().then((_) { |
| 591 // if 'package:pkgA/libA.dart' was resolved, then there are no errors | 611 // if 'package:pkgA/libA.dart' was resolved, then there are no errors |
| 592 expect(filesErrors[testFile], isEmpty); | 612 expect(filesErrors[testFile], isEmpty); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 610 '''); | 630 '''); |
| 611 String pkgDependency = posix.join(projectPath, 'package_dep'); | 631 String pkgDependency = posix.join(projectPath, 'package_dep'); |
| 612 resourceProvider.newFile(pkgDependency, 'contents'); | 632 resourceProvider.newFile(pkgDependency, 'contents'); |
| 613 packageMapProvider.dependencies.add(pkgDependency); | 633 packageMapProvider.dependencies.add(pkgDependency); |
| 614 // Create project and wait for analysis | 634 // Create project and wait for analysis |
| 615 createProject(); | 635 createProject(); |
| 616 return waitForTasksFinished().then((_) { | 636 return waitForTasksFinished().then((_) { |
| 617 expect(filesErrors[testFile], isNot(isEmpty)); | 637 expect(filesErrors[testFile], isNot(isEmpty)); |
| 618 // Add the package to the package map and tickle the package dependency. | 638 // Add the package to the package map and tickle the package dependency. |
| 619 packageMapProvider.packageMap = { | 639 packageMapProvider.packageMap = { |
| 620 'pkgA': [resourceProvider.getResource('/packages/pkgA')] }; | 640 'pkgA': [resourceProvider.getResource('/packages/pkgA')] |
| 641 }; |
| 621 resourceProvider.modifyFile(pkgDependency, 'new contents'); | 642 resourceProvider.modifyFile(pkgDependency, 'new contents'); |
| 622 // Let the server time to notice the file has changed, then let | 643 // Let the server time to notice the file has changed, then let |
| 623 // analysis omplete. There should now be no error. | 644 // analysis omplete. There should now be no error. |
| 624 return pumpEventQueue().then((_) => waitForTasksFinished()).then((_) { | 645 return pumpEventQueue().then((_) => waitForTasksFinished()).then((_) { |
| 625 expect(filesErrors[testFile], isEmpty); | 646 expect(filesErrors[testFile], isEmpty); |
| 626 }); | 647 }); |
| 627 }); | 648 }); |
| 628 } | 649 } |
| 629 } | 650 } |
| OLD | NEW |