| 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 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 61 test('excluded folder', () { | 61 test('excluded folder', () { |
| 62 String fileA = '/project/aaa/a.dart'; | 62 String fileA = '/project/aaa/a.dart'; |
| 63 String fileB = '/project/bbb/b.dart'; | 63 String fileB = '/project/bbb/b.dart'; |
| 64 resourceProvider.newFile(fileA, '// a'); | 64 resourceProvider.newFile(fileA, '// a'); |
| 65 resourceProvider.newFile(fileB, '// b'); | 65 resourceProvider.newFile(fileB, '// b'); |
| 66 var response = testSetAnalysisRoots(['/project'], ['/project/bbb']); | 66 var response = testSetAnalysisRoots(['/project'], ['/project/bbb']); |
| 67 var serverRef = server; | 67 var serverRef = server; |
| 68 expect(response, isResponseSuccess('0')); | 68 expect(response, isResponseSuccess('0')); |
| 69 // unit "a" is resolved eventually | 69 // unit "a" is resolved eventually |
| 70 // unit "b" is not resolved | 70 // unit "b" is not resolved |
| 71 return waitForServerOperationsPerformed(server).then((_) { | 71 return server.onAnalysisComplete.then((_) { |
| 72 expect(serverRef.getResolvedCompilationUnits(fileA), hasLength(1)); | 72 expect(serverRef.getResolvedCompilationUnits(fileA), hasLength(1)); |
| 73 expect(serverRef.getResolvedCompilationUnits(fileB), isEmpty); | 73 expect(serverRef.getResolvedCompilationUnits(fileB), isEmpty); |
| 74 }); | 74 }); |
| 75 }); | 75 }); |
| 76 }); | 76 }); |
| 77 | 77 |
| 78 group('included', () { | 78 group('included', () { |
| 79 test('new folder', () { | 79 test('new folder', () { |
| 80 String file = '/project/bin/test.dart'; | 80 String file = '/project/bin/test.dart'; |
| 81 resourceProvider.newFile('/project/pubspec.yaml', 'name: project'); | 81 resourceProvider.newFile('/project/pubspec.yaml', 'name: project'); |
| 82 resourceProvider.newFile(file, 'main() {}'); | 82 resourceProvider.newFile(file, 'main() {}'); |
| 83 var response = testSetAnalysisRoots(['/project'], []); | 83 var response = testSetAnalysisRoots(['/project'], []); |
| 84 var serverRef = server; | 84 var serverRef = server; |
| 85 expect(response, isResponseSuccess('0')); | 85 expect(response, isResponseSuccess('0')); |
| 86 // verify that unit is resolved eventually | 86 // verify that unit is resolved eventually |
| 87 return waitForServerOperationsPerformed(server).then((_) { | 87 return server.onAnalysisComplete.then((_) { |
| 88 var units = serverRef.getResolvedCompilationUnits(file); | 88 var units = serverRef.getResolvedCompilationUnits(file); |
| 89 expect(units, hasLength(1)); | 89 expect(units, hasLength(1)); |
| 90 }); | 90 }); |
| 91 }); | 91 }); |
| 92 }); | 92 }); |
| 93 }); | 93 }); |
| 94 | 94 |
| 95 group('setPriorityFiles', () { | 95 group('setPriorityFiles', () { |
| 96 test('invalid', () { | 96 test('invalid', () { |
| 97 // TODO(paulberry): under the "eventual consistency" model this request | 97 // TODO(paulberry): under the "eventual consistency" model this request |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 156 | 156 |
| 157 | 157 |
| 158 void test_setSubscriptions() { | 158 void test_setSubscriptions() { |
| 159 test('before analysis', () { | 159 test('before analysis', () { |
| 160 AnalysisTestHelper helper = new AnalysisTestHelper(); | 160 AnalysisTestHelper helper = new AnalysisTestHelper(); |
| 161 // subscribe | 161 // subscribe |
| 162 helper.addAnalysisSubscriptionHighlights(helper.testFile); | 162 helper.addAnalysisSubscriptionHighlights(helper.testFile); |
| 163 // create project | 163 // create project |
| 164 helper.createSingleFileProject('int V = 42;'); | 164 helper.createSingleFileProject('int V = 42;'); |
| 165 // wait, there are highlight regions | 165 // wait, there are highlight regions |
| 166 helper.waitForOperationsFinished().then((_) { | 166 helper.onAnalysisComplete.then((_) { |
| 167 var highlights = helper.getHighlights(helper.testFile); | 167 var highlights = helper.getHighlights(helper.testFile); |
| 168 expect(highlights, isNotEmpty); | 168 expect(highlights, isNotEmpty); |
| 169 }); | 169 }); |
| 170 }); | 170 }); |
| 171 | 171 |
| 172 test('after analysis', () { | 172 test('after analysis', () { |
| 173 AnalysisTestHelper helper = new AnalysisTestHelper(); | 173 AnalysisTestHelper helper = new AnalysisTestHelper(); |
| 174 // create project | 174 // create project |
| 175 helper.createSingleFileProject('int V = 42;'); | 175 helper.createSingleFileProject('int V = 42;'); |
| 176 // wait, no regions initially | 176 // wait, no regions initially |
| 177 return helper.waitForOperationsFinished().then((_) { | 177 return helper.onAnalysisComplete.then((_) { |
| 178 var highlights = helper.getHighlights(helper.testFile); | 178 var highlights = helper.getHighlights(helper.testFile); |
| 179 expect(highlights, isEmpty); | 179 expect(highlights, isEmpty); |
| 180 // subscribe | 180 // subscribe |
| 181 helper.addAnalysisSubscriptionHighlights(helper.testFile); | 181 helper.addAnalysisSubscriptionHighlights(helper.testFile); |
| 182 // wait, has regions | 182 // wait, has regions |
| 183 return helper.waitForOperationsFinished().then((_) { | 183 return helper.onAnalysisComplete.then((_) { |
| 184 var highlights = helper.getHighlights(helper.testFile); | 184 var highlights = helper.getHighlights(helper.testFile); |
| 185 expect(highlights, isNotEmpty); | 185 expect(highlights, isNotEmpty); |
| 186 }); | 186 }); |
| 187 }); | 187 }); |
| 188 }); | 188 }); |
| 189 | 189 |
| 190 test('after analysis, no such file', () { | 190 test('after analysis, no such file', () { |
| 191 AnalysisTestHelper helper = new AnalysisTestHelper(); | 191 AnalysisTestHelper helper = new AnalysisTestHelper(); |
| 192 helper.createSingleFileProject('int V = 42;'); | 192 helper.createSingleFileProject('int V = 42;'); |
| 193 return helper.waitForOperationsFinished().then((_) { | 193 return helper.onAnalysisComplete.then((_) { |
| 194 String noFile = '/no-such-file.dart'; | 194 String noFile = '/no-such-file.dart'; |
| 195 helper.addAnalysisSubscriptionHighlights(noFile); | 195 helper.addAnalysisSubscriptionHighlights(noFile); |
| 196 return helper.waitForOperationsFinished().then((_) { | 196 return helper.onAnalysisComplete.then((_) { |
| 197 var highlights = helper.getHighlights(noFile); | 197 var highlights = helper.getHighlights(noFile); |
| 198 expect(highlights, isEmpty); | 198 expect(highlights, isEmpty); |
| 199 }); | 199 }); |
| 200 }); | 200 }); |
| 201 }); | 201 }); |
| 202 | 202 |
| 203 test('after analysis, SDK file', () { | 203 test('after analysis, SDK file', () { |
| 204 AnalysisTestHelper helper = new AnalysisTestHelper(); | 204 AnalysisTestHelper helper = new AnalysisTestHelper(); |
| 205 helper.createSingleFileProject(''' | 205 helper.createSingleFileProject(''' |
| 206 main() { | 206 main() { |
| 207 print(42); | 207 print(42); |
| 208 } | 208 } |
| 209 '''); | 209 '''); |
| 210 return helper.waitForOperationsFinished().then((_) { | 210 return helper.onAnalysisComplete.then((_) { |
| 211 String file = '/lib/core/core.dart'; | 211 String file = '/lib/core/core.dart'; |
| 212 helper.addAnalysisSubscriptionNavigation(file); | 212 helper.addAnalysisSubscriptionNavigation(file); |
| 213 return helper.waitForOperationsFinished().then((_) { | 213 return helper.onAnalysisComplete.then((_) { |
| 214 var navigationRegions = helper.getNavigation(file); | 214 var navigationRegions = helper.getNavigation(file); |
| 215 expect(navigationRegions, isNotEmpty); | 215 expect(navigationRegions, isNotEmpty); |
| 216 }); | 216 }); |
| 217 }); | 217 }); |
| 218 }); | 218 }); |
| 219 } | 219 } |
| 220 | 220 |
| 221 | 221 |
| 222 testUpdateContent() { | 222 testUpdateContent() { |
| 223 test('bad type', () { | 223 test('bad type', () { |
| 224 AnalysisTestHelper helper = new AnalysisTestHelper(); | 224 AnalysisTestHelper helper = new AnalysisTestHelper(); |
| 225 helper.createSingleFileProject('// empty'); | 225 helper.createSingleFileProject('// empty'); |
| 226 return helper.waitForOperationsFinished().then((_) { | 226 return helper.onAnalysisComplete.then((_) { |
| 227 Request request = new Request('0', ANALYSIS_UPDATE_CONTENT, { | 227 Request request = new Request('0', ANALYSIS_UPDATE_CONTENT, { |
| 228 'files': { | 228 'files': { |
| 229 helper.testFile: { | 229 helper.testFile: { |
| 230 TYPE: 'foo', | 230 TYPE: 'foo', |
| 231 } | 231 } |
| 232 } | 232 } |
| 233 }); | 233 }); |
| 234 Response response = helper.handler.handleRequest(request); | 234 Response response = helper.handler.handleRequest(request); |
| 235 expect(response, isResponseFailure('0')); | 235 expect(response, isResponseFailure('0')); |
| 236 }); | 236 }); |
| 237 }); | 237 }); |
| 238 | 238 |
| 239 test('full content', () { | 239 test('full content', () { |
| 240 AnalysisTestHelper helper = new AnalysisTestHelper(); | 240 AnalysisTestHelper helper = new AnalysisTestHelper(); |
| 241 helper.createSingleFileProject('// empty'); | 241 helper.createSingleFileProject('// empty'); |
| 242 return helper.waitForOperationsFinished().then((_) { | 242 return helper.onAnalysisComplete.then((_) { |
| 243 // no errors initially | 243 // no errors initially |
| 244 List<AnalysisError> errors = helper.getTestErrors(); | 244 List<AnalysisError> errors = helper.getTestErrors(); |
| 245 expect(errors, isEmpty); | 245 expect(errors, isEmpty); |
| 246 // update code | 246 // update code |
| 247 helper.sendContentChange(new AddContentOverlay('library lib')); | 247 helper.sendContentChange(new AddContentOverlay('library lib')); |
| 248 // wait, there is an error | 248 // wait, there is an error |
| 249 return helper.waitForOperationsFinished().then((_) { | 249 return helper.onAnalysisComplete.then((_) { |
| 250 List<AnalysisError> errors = helper.getTestErrors(); | 250 List<AnalysisError> errors = helper.getTestErrors(); |
| 251 expect(errors, hasLength(1)); | 251 expect(errors, hasLength(1)); |
| 252 }); | 252 }); |
| 253 }); | 253 }); |
| 254 }); | 254 }); |
| 255 | 255 |
| 256 test('incremental', () { | 256 test('incremental', () { |
| 257 AnalysisTestHelper helper = new AnalysisTestHelper(); | 257 AnalysisTestHelper helper = new AnalysisTestHelper(); |
| 258 String initialContent = 'library A;'; | 258 String initialContent = 'library A;'; |
| 259 helper.createSingleFileProject(initialContent); | 259 helper.createSingleFileProject(initialContent); |
| 260 return helper.waitForOperationsFinished().then((_) { | 260 return helper.onAnalysisComplete.then((_) { |
| 261 // no errors initially | 261 // no errors initially |
| 262 List<AnalysisError> errors = helper.getTestErrors(); | 262 List<AnalysisError> errors = helper.getTestErrors(); |
| 263 expect(errors, isEmpty); | 263 expect(errors, isEmpty); |
| 264 // Add the file to the cache | 264 // Add the file to the cache |
| 265 helper.sendContentChange(new AddContentOverlay(initialContent)); | 265 helper.sendContentChange(new AddContentOverlay(initialContent)); |
| 266 // update code | 266 // update code |
| 267 helper.sendContentChange( | 267 helper.sendContentChange( |
| 268 new ChangeContentOverlay( | 268 new ChangeContentOverlay( |
| 269 [new SourceEdit('library '.length, 'A;'.length, 'lib')])); | 269 [new SourceEdit('library '.length, 'A;'.length, 'lib')])); |
| 270 // wait, there is an error | 270 // wait, there is an error |
| 271 return helper.waitForOperationsFinished().then((_) { | 271 return helper.onAnalysisComplete.then((_) { |
| 272 List<AnalysisError> errors = helper.getTestErrors(); | 272 List<AnalysisError> errors = helper.getTestErrors(); |
| 273 expect(errors, hasLength(1)); | 273 expect(errors, hasLength(1)); |
| 274 }); | 274 }); |
| 275 }); | 275 }); |
| 276 }); | 276 }); |
| 277 | 277 |
| 278 test('change on disk, normal', () { | 278 test('change on disk, normal', () { |
| 279 AnalysisTestHelper helper = new AnalysisTestHelper(); | 279 AnalysisTestHelper helper = new AnalysisTestHelper(); |
| 280 helper.createSingleFileProject('library A;'); | 280 helper.createSingleFileProject('library A;'); |
| 281 return helper.waitForOperationsFinished().then((_) { | 281 return helper.onAnalysisComplete.then((_) { |
| 282 // There should be no errors | 282 // There should be no errors |
| 283 expect(helper.getTestErrors(), hasLength(0)); | 283 expect(helper.getTestErrors(), hasLength(0)); |
| 284 // Change file on disk, adding a syntax error. | 284 // Change file on disk, adding a syntax error. |
| 285 helper.resourceProvider.modifyFile(helper.testFile, 'library lib'); | 285 helper.resourceProvider.modifyFile(helper.testFile, 'library lib'); |
| 286 // There should be errors now. | 286 // There should be errors now. |
| 287 return pumpEventQueue().then((_) { | 287 return pumpEventQueue().then((_) { |
| 288 return helper.waitForOperationsFinished().then((_) { | 288 return helper.onAnalysisComplete.then((_) { |
| 289 expect(helper.getTestErrors(), hasLength(1)); | 289 expect(helper.getTestErrors(), hasLength(1)); |
| 290 }); | 290 }); |
| 291 }); | 291 }); |
| 292 }); | 292 }); |
| 293 }); | 293 }); |
| 294 | 294 |
| 295 test('change on disk, during override', () { | 295 test('change on disk, during override', () { |
| 296 AnalysisTestHelper helper = new AnalysisTestHelper(); | 296 AnalysisTestHelper helper = new AnalysisTestHelper(); |
| 297 helper.createSingleFileProject('library A;'); | 297 helper.createSingleFileProject('library A;'); |
| 298 return helper.waitForOperationsFinished().then((_) { | 298 return helper.onAnalysisComplete.then((_) { |
| 299 // update code | 299 // update code |
| 300 helper.sendContentChange(new AddContentOverlay('library B;')); | 300 helper.sendContentChange(new AddContentOverlay('library B;')); |
| 301 // There should be no errors | 301 // There should be no errors |
| 302 return helper.waitForOperationsFinished().then((_) { | 302 return helper.onAnalysisComplete.then((_) { |
| 303 expect(helper.getTestErrors(), hasLength(0)); | 303 expect(helper.getTestErrors(), hasLength(0)); |
| 304 // Change file on disk, adding a syntax error. | 304 // Change file on disk, adding a syntax error. |
| 305 helper.resourceProvider.modifyFile(helper.testFile, 'library lib'); | 305 helper.resourceProvider.modifyFile(helper.testFile, 'library lib'); |
| 306 // There should still be no errors (file should not have been reread). | 306 // There should still be no errors (file should not have been reread). |
| 307 return helper.waitForOperationsFinished().then((_) { | 307 return helper.onAnalysisComplete.then((_) { |
| 308 expect(helper.getTestErrors(), hasLength(0)); | 308 expect(helper.getTestErrors(), hasLength(0)); |
| 309 // Send a content change with a null content param--file should be | 309 // Send a content change with a null content param--file should be |
| 310 // reread from disk. | 310 // reread from disk. |
| 311 helper.sendContentChange(new RemoveContentOverlay()); | 311 helper.sendContentChange(new RemoveContentOverlay()); |
| 312 // There should be errors now. | 312 // There should be errors now. |
| 313 return helper.waitForOperationsFinished().then((_) { | 313 return helper.onAnalysisComplete.then((_) { |
| 314 expect(helper.getTestErrors(), hasLength(1)); | 314 expect(helper.getTestErrors(), hasLength(1)); |
| 315 }); | 315 }); |
| 316 }); | 316 }); |
| 317 }); | 317 }); |
| 318 }); | 318 }); |
| 319 }); | 319 }); |
| 320 | 320 |
| 321 group('out of range', () { | 321 group('out of range', () { |
| 322 Future outOfRangeTest(SourceEdit edit) { | 322 Future outOfRangeTest(SourceEdit edit) { |
| 323 AnalysisTestHelper helper = new AnalysisTestHelper(); | 323 AnalysisTestHelper helper = new AnalysisTestHelper(); |
| 324 helper.createSingleFileProject('library A;'); | 324 helper.createSingleFileProject('library A;'); |
| 325 return helper.waitForOperationsFinished().then((_) { | 325 return helper.onAnalysisComplete.then((_) { |
| 326 helper.sendContentChange(new AddContentOverlay('library B;')); | 326 helper.sendContentChange(new AddContentOverlay('library B;')); |
| 327 return helper.waitForOperationsFinished().then((_) { | 327 return helper.onAnalysisComplete.then((_) { |
| 328 ChangeContentOverlay contentChange = new ChangeContentOverlay([edit]); | 328 ChangeContentOverlay contentChange = new ChangeContentOverlay([edit]); |
| 329 Request request = new AnalysisUpdateContentParams({ | 329 Request request = new AnalysisUpdateContentParams({ |
| 330 helper.testFile: contentChange | 330 helper.testFile: contentChange |
| 331 }).toRequest('0'); | 331 }).toRequest('0'); |
| 332 Response response = helper.handler.handleRequest(request); | 332 Response response = helper.handler.handleRequest(request); |
| 333 expect( | 333 expect( |
| 334 response, | 334 response, |
| 335 isResponseFailure('0', RequestErrorCode.INVALID_OVERLAY_CHANGE)); | 335 isResponseFailure('0', RequestErrorCode.INVALID_OVERLAY_CHANGE)); |
| 336 }); | 336 }); |
| 337 }); | 337 }); |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 466 filesHighlights[params.file] = params.regions; | 466 filesHighlights[params.file] = params.regions; |
| 467 } | 467 } |
| 468 if (notification.event == ANALYSIS_NAVIGATION) { | 468 if (notification.event == ANALYSIS_NAVIGATION) { |
| 469 var params = | 469 var params = |
| 470 new AnalysisNavigationParams.fromNotification(notification); | 470 new AnalysisNavigationParams.fromNotification(notification); |
| 471 filesNavigation[params.file] = params.regions; | 471 filesNavigation[params.file] = params.regions; |
| 472 } | 472 } |
| 473 }); | 473 }); |
| 474 } | 474 } |
| 475 | 475 |
| 476 /** |
| 477 * Returns a [Future] that completes when the server's analysis is complete. |
| 478 */ |
| 479 Future get onAnalysisComplete { |
| 480 return server.onAnalysisComplete; |
| 481 } |
| 482 |
| 476 void addAnalysisSubscription(AnalysisService service, String file) { | 483 void addAnalysisSubscription(AnalysisService service, String file) { |
| 477 // add file to subscription | 484 // add file to subscription |
| 478 var files = analysisSubscriptions[service]; | 485 var files = analysisSubscriptions[service]; |
| 479 if (files == null) { | 486 if (files == null) { |
| 480 files = <String>[]; | 487 files = <String>[]; |
| 481 analysisSubscriptions[service] = files; | 488 analysisSubscriptions[service] = files; |
| 482 } | 489 } |
| 483 files.add(file); | 490 files.add(file); |
| 484 // set subscriptions | 491 // set subscriptions |
| 485 Request request = | 492 Request request = |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 611 return path; | 618 return path; |
| 612 } | 619 } |
| 613 | 620 |
| 614 /** | 621 /** |
| 615 * Stops the associated server. | 622 * Stops the associated server. |
| 616 */ | 623 */ |
| 617 void stopServer() { | 624 void stopServer() { |
| 618 server.done(); | 625 server.done(); |
| 619 } | 626 } |
| 620 | 627 |
| 621 /** | |
| 622 * Returns a [Future] that completes when this this helper finished all its | |
| 623 * scheduled tasks. | |
| 624 */ | |
| 625 Future waitForOperationsFinished() { | |
| 626 return waitForServerOperationsPerformed(server); | |
| 627 } | |
| 628 | |
| 629 static String _getCodeString(code) { | 628 static String _getCodeString(code) { |
| 630 if (code is List<String>) { | 629 if (code is List<String>) { |
| 631 code = code.join('\n'); | 630 code = code.join('\n'); |
| 632 } | 631 } |
| 633 return code as String; | 632 return code as String; |
| 634 } | 633 } |
| 635 } | 634 } |
| OLD | NEW |