| OLD | NEW |
| (Empty) | |
| 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 |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 library analyzer.test.generated.incremental_resolver_test; |
| 6 |
| 7 import 'package:analyzer/dart/ast/ast.dart'; |
| 8 import 'package:analyzer/dart/ast/token.dart'; |
| 9 import 'package:analyzer/dart/element/element.dart'; |
| 10 import 'package:analyzer/error/error.dart'; |
| 11 import 'package:analyzer/error/listener.dart'; |
| 12 import 'package:analyzer/exception/exception.dart'; |
| 13 import 'package:analyzer/src/context/cache.dart'; |
| 14 import 'package:analyzer/src/dart/ast/utilities.dart'; |
| 15 import 'package:analyzer/src/dart/element/element.dart'; |
| 16 import 'package:analyzer/src/dart/scanner/reader.dart'; |
| 17 import 'package:analyzer/src/dart/scanner/scanner.dart'; |
| 18 import 'package:analyzer/src/generated/engine.dart'; |
| 19 import 'package:analyzer/src/generated/incremental_logger.dart' as logging; |
| 20 import 'package:analyzer/src/generated/incremental_resolution_validator.dart'; |
| 21 import 'package:analyzer/src/generated/incremental_resolver.dart'; |
| 22 import 'package:analyzer/src/generated/java_engine.dart'; |
| 23 import 'package:analyzer/src/generated/parser.dart'; |
| 24 import 'package:analyzer/src/generated/resolver.dart'; |
| 25 import 'package:analyzer/src/generated/source_io.dart'; |
| 26 import 'package:analyzer/src/generated/testing/ast_test_factory.dart'; |
| 27 import 'package:analyzer/src/generated/testing/element_factory.dart'; |
| 28 import 'package:analyzer/src/generated/utilities_collection.dart'; |
| 29 import 'package:analyzer/src/task/dart.dart'; |
| 30 import 'package:analyzer/task/dart.dart'; |
| 31 import 'package:analyzer/task/model.dart'; |
| 32 import 'package:test/test.dart'; |
| 33 import 'package:test_reflective_loader/test_reflective_loader.dart'; |
| 34 |
| 35 import 'analysis_context_factory.dart'; |
| 36 import 'resolver_test_case.dart'; |
| 37 import 'test_support.dart'; |
| 38 |
| 39 main() { |
| 40 initializeTestEnvironment(); |
| 41 defineReflectiveSuite(() { |
| 42 defineReflectiveTests(IncrementalResolverTest); |
| 43 defineReflectiveTests(PoorMansIncrementalResolutionTest); |
| 44 defineReflectiveTests(ResolutionContextBuilderTest); |
| 45 }); |
| 46 } |
| 47 |
| 48 void initializeTestEnvironment() {} |
| 49 |
| 50 void _assertEqualError(AnalysisError incError, AnalysisError fullError) { |
| 51 if (incError.errorCode != fullError.errorCode || |
| 52 incError.source != fullError.source || |
| 53 incError.offset != fullError.offset || |
| 54 incError.length != fullError.length || |
| 55 incError.message != fullError.message) { |
| 56 StringBuffer buffer = new StringBuffer(); |
| 57 buffer.writeln('Found error does not match expected error:'); |
| 58 if (incError.errorCode == fullError.errorCode) { |
| 59 buffer.write(' errorCode = '); |
| 60 buffer.write(fullError.errorCode.uniqueName); |
| 61 } else { |
| 62 buffer.write(' Expected errorCode = '); |
| 63 buffer.write(fullError.errorCode.uniqueName); |
| 64 buffer.write(' found '); |
| 65 buffer.write(incError.errorCode.uniqueName); |
| 66 } |
| 67 buffer.writeln(); |
| 68 if (incError.source == fullError.source) { |
| 69 buffer.write(' source = '); |
| 70 buffer.write(fullError.source); |
| 71 } else { |
| 72 buffer.write(' Expected source = '); |
| 73 buffer.write(fullError.source); |
| 74 buffer.write(' found '); |
| 75 buffer.write(incError.source); |
| 76 } |
| 77 buffer.writeln(); |
| 78 if (incError.offset == fullError.offset) { |
| 79 buffer.write(' offset = '); |
| 80 buffer.write(fullError.offset); |
| 81 } else { |
| 82 buffer.write(' Expected offset = '); |
| 83 buffer.write(fullError.offset); |
| 84 buffer.write(' found '); |
| 85 buffer.write(incError.offset); |
| 86 } |
| 87 buffer.writeln(); |
| 88 if (incError.length == fullError.length) { |
| 89 buffer.write(' length = '); |
| 90 buffer.write(fullError.length); |
| 91 } else { |
| 92 buffer.write(' Expected length = '); |
| 93 buffer.write(fullError.length); |
| 94 buffer.write(' found '); |
| 95 buffer.write(incError.length); |
| 96 } |
| 97 buffer.writeln(); |
| 98 if (incError.message == fullError.message) { |
| 99 buffer.write(' message = '); |
| 100 buffer.write(fullError.message); |
| 101 } else { |
| 102 buffer.write(' Expected message = '); |
| 103 buffer.write(fullError.message); |
| 104 buffer.write(' found '); |
| 105 buffer.write(incError.message); |
| 106 } |
| 107 fail(buffer.toString()); |
| 108 } |
| 109 } |
| 110 |
| 111 void _assertEqualErrors( |
| 112 List<AnalysisError> incErrors, List<AnalysisError> fullErrors) { |
| 113 expect(incErrors, hasLength(fullErrors.length)); |
| 114 if (incErrors.isNotEmpty) { |
| 115 incErrors.sort((a, b) => a.offset - b.offset); |
| 116 } |
| 117 if (fullErrors.isNotEmpty) { |
| 118 fullErrors.sort((a, b) => a.offset - b.offset); |
| 119 } |
| 120 int length = incErrors.length; |
| 121 for (int i = 0; i < length; i++) { |
| 122 AnalysisError incError = incErrors[i]; |
| 123 AnalysisError fullError = fullErrors[i]; |
| 124 _assertEqualError(incError, fullError); |
| 125 } |
| 126 } |
| 127 |
| 128 void _checkCacheEntries(AnalysisCache cache) { |
| 129 Set seen = new Set(); |
| 130 MapIterator<AnalysisTarget, CacheEntry> it = cache.iterator(); |
| 131 while (it.moveNext()) { |
| 132 AnalysisTarget key = it.key; |
| 133 if (cache.get(key) == null) { |
| 134 fail("cache corrupted: value of $key changed to null"); |
| 135 } |
| 136 if (!seen.add(key)) { |
| 137 fail("cache corrupted: $key appears more than once"); |
| 138 } |
| 139 } |
| 140 } |
| 141 |
| 142 @reflectiveTest |
| 143 class IncrementalResolverTest extends ResolverTestCase { |
| 144 Source source; |
| 145 String code; |
| 146 LibraryElement library; |
| 147 CompilationUnit unit; |
| 148 |
| 149 void setUp() { |
| 150 super.setUp(); |
| 151 logging.logger = logging.NULL_LOGGER; |
| 152 } |
| 153 |
| 154 void test_classMemberAccessor_body() { |
| 155 _resolveUnit(r''' |
| 156 class A { |
| 157 int get test { |
| 158 return 1 + 2; |
| 159 } |
| 160 }'''); |
| 161 _resolve(_editString('+', '*'), _isFunctionBody); |
| 162 } |
| 163 |
| 164 void test_computeConstants_offsetChanged() { |
| 165 _resolveUnit(r''' |
| 166 int f() => 0; |
| 167 main() { |
| 168 const x1 = f(); |
| 169 const x2 = f(); |
| 170 const x3 = f(); |
| 171 const x4 = f(); |
| 172 const x5 = f(); |
| 173 print(x1 + x2 + x3 + x4 + x5 + 1); |
| 174 } |
| 175 '''); |
| 176 _resolve(_editString('x1', ' x1'), _isFunctionBody); |
| 177 } |
| 178 |
| 179 void test_constructor_body() { |
| 180 _resolveUnit(r''' |
| 181 class A { |
| 182 int f; |
| 183 A(int a, int b) { |
| 184 f = a + b; |
| 185 } |
| 186 }'''); |
| 187 _resolve(_editString('+', '*'), _isFunctionBody); |
| 188 } |
| 189 |
| 190 void test_constructor_label_add() { |
| 191 _resolveUnit(r''' |
| 192 class A { |
| 193 A() { |
| 194 return 42; |
| 195 } |
| 196 } |
| 197 '''); |
| 198 _resolve(_editString('return', 'label: return'), _isBlock); |
| 199 } |
| 200 |
| 201 void test_constructor_localVariable_add() { |
| 202 _resolveUnit(r''' |
| 203 class A { |
| 204 A() { |
| 205 42; |
| 206 } |
| 207 } |
| 208 '''); |
| 209 _resolve(_editString('42;', 'var res = 42;'), _isBlock); |
| 210 } |
| 211 |
| 212 void test_function_localFunction_add() { |
| 213 _resolveUnit(r''' |
| 214 int main() { |
| 215 return 0; |
| 216 } |
| 217 callIt(f) {} |
| 218 '''); |
| 219 _resolve(_editString('return 0;', 'callIt((p) {});'), _isBlock); |
| 220 } |
| 221 |
| 222 void test_functionBody_body() { |
| 223 _resolveUnit(r''' |
| 224 main(int a, int b) { |
| 225 return a + b; |
| 226 }'''); |
| 227 _resolve(_editString('+', '*'), _isFunctionBody); |
| 228 } |
| 229 |
| 230 void test_functionBody_statement() { |
| 231 _resolveUnit(r''' |
| 232 main(int a, int b) { |
| 233 return a + b; |
| 234 }'''); |
| 235 _resolve(_editString('+', '*'), _isStatement); |
| 236 } |
| 237 |
| 238 void test_method_body() { |
| 239 _resolveUnit(r''' |
| 240 class A { |
| 241 m(int a, int b) { |
| 242 return a + b; |
| 243 } |
| 244 }'''); |
| 245 _resolve(_editString('+', '*'), _isFunctionBody); |
| 246 } |
| 247 |
| 248 void test_method_label_add() { |
| 249 _resolveUnit(r''' |
| 250 class A { |
| 251 int m(int a, int b) { |
| 252 return a + b; |
| 253 } |
| 254 } |
| 255 '''); |
| 256 _resolve(_editString('return', 'label: return'), _isBlock); |
| 257 } |
| 258 |
| 259 void test_method_localFunction_add() { |
| 260 _resolveUnit(r''' |
| 261 class A { |
| 262 int m() { |
| 263 return 0; |
| 264 } |
| 265 } |
| 266 callIt(f) {} |
| 267 '''); |
| 268 _resolve(_editString('return 0;', 'callIt((p) {});'), _isBlock); |
| 269 } |
| 270 |
| 271 void test_method_localVariable_add() { |
| 272 _resolveUnit(r''' |
| 273 class A { |
| 274 int m(int a, int b) { |
| 275 return a + b; |
| 276 } |
| 277 } |
| 278 '''); |
| 279 _resolve( |
| 280 _editString( |
| 281 ' return a + b;', |
| 282 r''' |
| 283 int res = a + b; |
| 284 return res; |
| 285 '''), |
| 286 _isBlock); |
| 287 } |
| 288 |
| 289 void test_superInvocation() { |
| 290 _resolveUnit(r''' |
| 291 class A { |
| 292 foo(p) {} |
| 293 } |
| 294 class B extends A { |
| 295 bar() { |
| 296 super.foo(1 + 2); |
| 297 } |
| 298 }'''); |
| 299 _resolve(_editString('+', '*'), _isFunctionBody); |
| 300 } |
| 301 |
| 302 void test_topLevelAccessor_body() { |
| 303 _resolveUnit(r''' |
| 304 int get test { |
| 305 return 1 + 2; |
| 306 }'''); |
| 307 _resolve(_editString('+', '*'), _isFunctionBody); |
| 308 } |
| 309 |
| 310 void test_topLevelFunction_label_add() { |
| 311 _resolveUnit(r''' |
| 312 int main(int a, int b) { |
| 313 return a + b; |
| 314 } |
| 315 '''); |
| 316 _resolve(_editString(' return', 'label: return a + b;'), _isBlock); |
| 317 } |
| 318 |
| 319 void test_topLevelFunction_label_remove() { |
| 320 _resolveUnit(r''' |
| 321 int main(int a, int b) { |
| 322 label: return a + b; |
| 323 } |
| 324 '''); |
| 325 _resolve(_editString('label: ', ''), _isBlock); |
| 326 } |
| 327 |
| 328 void test_topLevelFunction_localVariable_add() { |
| 329 _resolveUnit(r''' |
| 330 int main(int a, int b) { |
| 331 return a + b; |
| 332 } |
| 333 '''); |
| 334 _resolve( |
| 335 _editString( |
| 336 ' return a + b;', |
| 337 r''' |
| 338 int res = a + b; |
| 339 return res; |
| 340 '''), |
| 341 _isBlock); |
| 342 } |
| 343 |
| 344 void test_topLevelFunction_localVariable_remove() { |
| 345 _resolveUnit(r''' |
| 346 int main(int a, int b) { |
| 347 int res = a * b; |
| 348 return a + b; |
| 349 } |
| 350 '''); |
| 351 _resolve(_editString('int res = a * b;', ''), _isBlock); |
| 352 } |
| 353 |
| 354 void test_updateElementOffset() { |
| 355 _resolveUnit(r''' |
| 356 class A { |
| 357 int am(String ap) { |
| 358 int av = 1; |
| 359 return av; |
| 360 } |
| 361 } |
| 362 main(int a, int b) { |
| 363 return a + b; |
| 364 } |
| 365 class B { |
| 366 int bm(String bp) { |
| 367 int bv = 1; |
| 368 return bv; |
| 369 } |
| 370 } |
| 371 '''); |
| 372 _resolve(_editString('+', ' + '), _isStatement); |
| 373 } |
| 374 |
| 375 _Edit _editString(String search, String replacement, [int length]) { |
| 376 int offset = code.indexOf(search); |
| 377 expect(offset, isNot(-1)); |
| 378 if (length == null) { |
| 379 length = search.length; |
| 380 } |
| 381 return new _Edit(offset, length, replacement); |
| 382 } |
| 383 |
| 384 /** |
| 385 * Applies [edit] to [code], find the [AstNode] specified by [predicate] |
| 386 * and incrementally resolves it. |
| 387 * |
| 388 * Then resolves the new code from scratch and validates that results of |
| 389 * the incremental resolution and non-incremental resolutions are the same. |
| 390 */ |
| 391 void _resolve(_Edit edit, Predicate<AstNode> predicate) { |
| 392 int offset = edit.offset; |
| 393 // parse "newCode" |
| 394 String newCode = code.substring(0, offset) + |
| 395 edit.replacement + |
| 396 code.substring(offset + edit.length); |
| 397 CompilationUnit newUnit = _parseUnit(newCode); |
| 398 AnalysisCache cache = analysisContext2.analysisCache; |
| 399 _checkCacheEntries(cache); |
| 400 |
| 401 // replace the node |
| 402 AstNode oldNode = _findNodeAt(unit, offset, predicate); |
| 403 AstNode newNode = _findNodeAt(newUnit, offset, predicate); |
| 404 { |
| 405 bool success = NodeReplacer.replace(oldNode, newNode); |
| 406 expect(success, isTrue); |
| 407 } |
| 408 // update tokens |
| 409 { |
| 410 int delta = edit.replacement.length - edit.length; |
| 411 _shiftTokens(unit.beginToken, offset, delta); |
| 412 Token oldBeginToken = oldNode.beginToken; |
| 413 Token oldEndTokenNext = oldNode.endToken.next; |
| 414 oldBeginToken.previous.setNext(newNode.beginToken); |
| 415 newNode.endToken.setNext(oldEndTokenNext); |
| 416 } |
| 417 // do incremental resolution |
| 418 int updateOffset = edit.offset; |
| 419 int updateEndOld = updateOffset + edit.length; |
| 420 int updateOldNew = updateOffset + edit.replacement.length; |
| 421 IncrementalResolver resolver; |
| 422 LibrarySpecificUnit lsu = new LibrarySpecificUnit(source, source); |
| 423 resolver = new IncrementalResolver(cache, cache.get(source), cache.get(lsu), |
| 424 unit.element, updateOffset, updateEndOld, updateOldNew); |
| 425 |
| 426 BlockFunctionBody body = newNode.getAncestor((n) => n is BlockFunctionBody); |
| 427 expect(body, isNotNull); |
| 428 |
| 429 resolver.resolve(body); |
| 430 _checkCacheEntries(cache); |
| 431 |
| 432 List<AnalysisError> newErrors = analysisContext.computeErrors(source); |
| 433 // resolve "newCode" from scratch |
| 434 CompilationUnit fullNewUnit; |
| 435 { |
| 436 source = addSource(newCode); |
| 437 _runTasks(); |
| 438 LibraryElement library = resolve2(source); |
| 439 fullNewUnit = resolveCompilationUnit(source, library); |
| 440 } |
| 441 _checkCacheEntries(cache); |
| 442 |
| 443 assertSameResolution(unit, fullNewUnit); |
| 444 // errors |
| 445 List<AnalysisError> newFullErrors = |
| 446 analysisContext.getErrors(source).errors; |
| 447 _assertEqualErrors(newErrors, newFullErrors); |
| 448 // prepare for the next cycle |
| 449 code = newCode; |
| 450 } |
| 451 |
| 452 void _resolveUnit(String code) { |
| 453 this.code = code; |
| 454 source = addSource(code); |
| 455 library = resolve2(source); |
| 456 unit = resolveCompilationUnit(source, library); |
| 457 _runTasks(); |
| 458 _checkCacheEntries(analysisContext2.analysisCache); |
| 459 } |
| 460 |
| 461 void _runTasks() { |
| 462 AnalysisResult result = analysisContext.performAnalysisTask(); |
| 463 while (result.changeNotices != null) { |
| 464 result = analysisContext.performAnalysisTask(); |
| 465 } |
| 466 } |
| 467 |
| 468 static AstNode _findNodeAt( |
| 469 CompilationUnit oldUnit, int offset, Predicate<AstNode> predicate) { |
| 470 NodeLocator locator = new NodeLocator(offset); |
| 471 AstNode node = locator.searchWithin(oldUnit); |
| 472 return node.getAncestor(predicate); |
| 473 } |
| 474 |
| 475 static bool _isBlock(AstNode node) => node is Block; |
| 476 |
| 477 static bool _isFunctionBody(AstNode node) => node is FunctionBody; |
| 478 |
| 479 static bool _isStatement(AstNode node) => node is Statement; |
| 480 |
| 481 static CompilationUnit _parseUnit(String code) { |
| 482 var errorListener = new BooleanErrorListener(); |
| 483 var reader = new CharSequenceReader(code); |
| 484 var scanner = new Scanner(null, reader, errorListener); |
| 485 var token = scanner.tokenize(); |
| 486 var parser = new Parser(null, errorListener); |
| 487 return parser.parseCompilationUnit(token); |
| 488 } |
| 489 |
| 490 static void _shiftTokens(Token token, int afterOffset, int delta) { |
| 491 while (true) { |
| 492 if (token.offset > afterOffset) { |
| 493 token.applyDelta(delta); |
| 494 } |
| 495 if (token.type == TokenType.EOF) { |
| 496 break; |
| 497 } |
| 498 token = token.next; |
| 499 } |
| 500 } |
| 501 } |
| 502 |
| 503 /** |
| 504 * The test for [poorMansIncrementalResolution] function and its integration |
| 505 * into [AnalysisContext]. |
| 506 */ |
| 507 @reflectiveTest |
| 508 class PoorMansIncrementalResolutionTest extends ResolverTestCase { |
| 509 final _TestLogger logger = new _TestLogger(); |
| 510 |
| 511 Source source; |
| 512 String code; |
| 513 LibraryElement oldLibrary; |
| 514 CompilationUnit oldUnit; |
| 515 CompilationUnitElement oldUnitElement; |
| 516 |
| 517 @override |
| 518 void setUp() { |
| 519 super.setUp(); |
| 520 _resetWithIncremental(true); |
| 521 } |
| 522 |
| 523 void test_computeConstants() { |
| 524 _resolveUnit(r''' |
| 525 int f() => 0; |
| 526 main() { |
| 527 const x = f(); |
| 528 print(x + 1); |
| 529 } |
| 530 '''); |
| 531 _updateAndValidate( |
| 532 r''' |
| 533 int f() => 0; |
| 534 main() { |
| 535 const x = f(); |
| 536 print(x + 2); |
| 537 } |
| 538 ''', |
| 539 expectCachePostConstantsValid: false); |
| 540 } |
| 541 |
| 542 void test_dartDoc_beforeField() { |
| 543 _resolveUnit(r''' |
| 544 class A { |
| 545 /** |
| 546 * A field [field] of type [int] in class [A]. |
| 547 */ |
| 548 int field; |
| 549 } |
| 550 '''); |
| 551 _updateAndValidate(r''' |
| 552 class A { |
| 553 /** |
| 554 * A field [field] of the type [int] in the class [A]. |
| 555 * Updated, with a reference to the [String] type. |
| 556 */ |
| 557 int field; |
| 558 } |
| 559 '''); |
| 560 } |
| 561 |
| 562 void test_dartDoc_beforeTopLevelVariable() { |
| 563 _resolveUnit(r''' |
| 564 /** |
| 565 * Variables [V1] and [V2] of type [int]. |
| 566 */ |
| 567 int V1, V2; |
| 568 '''); |
| 569 _updateAndValidate(r''' |
| 570 /** |
| 571 * Variables [V1] and [V2] of type [int]. |
| 572 * Updated, with a reference to the [String] type. |
| 573 */ |
| 574 int V1, V2; |
| 575 '''); |
| 576 } |
| 577 |
| 578 void test_dartDoc_clumsy_addReference() { |
| 579 _resolveUnit(r''' |
| 580 /** |
| 581 * aaa bbbb |
| 582 */ |
| 583 main() { |
| 584 } |
| 585 '''); |
| 586 _updateAndValidate(r''' |
| 587 /** |
| 588 * aaa [main] bbbb |
| 589 */ |
| 590 main() { |
| 591 } |
| 592 '''); |
| 593 } |
| 594 |
| 595 void test_dartDoc_clumsy_removeReference() { |
| 596 _resolveUnit(r''' |
| 597 /** |
| 598 * aaa [main] bbbb |
| 599 */ |
| 600 main() { |
| 601 } |
| 602 '''); |
| 603 _updateAndValidate(r''' |
| 604 /** |
| 605 * aaa bbbb |
| 606 */ |
| 607 main() { |
| 608 } |
| 609 '''); |
| 610 } |
| 611 |
| 612 void test_dartDoc_clumsy_updateText_beforeKeywordToken() { |
| 613 _resolveUnit(r''' |
| 614 /** |
| 615 * A comment with the [int] type reference. |
| 616 */ |
| 617 class A {} |
| 618 '''); |
| 619 _updateAndValidate(r''' |
| 620 /** |
| 621 * A comment with the [int] type reference. |
| 622 * Plus reference to [A] itself. |
| 623 */ |
| 624 class A {} |
| 625 '''); |
| 626 } |
| 627 |
| 628 void test_dartDoc_clumsy_updateText_insert() { |
| 629 _resolveUnit(r''' |
| 630 /** |
| 631 * A function [main] with a parameter [p] of type [int]. |
| 632 */ |
| 633 main(int p) { |
| 634 unresolvedFunctionProblem(); |
| 635 } |
| 636 /** |
| 637 * Other comment with [int] reference. |
| 638 */ |
| 639 foo() {} |
| 640 '''); |
| 641 _updateAndValidate(r''' |
| 642 /** |
| 643 * A function [main] with a parameter [p] of type [int]. |
| 644 * Inserted text with [String] reference. |
| 645 */ |
| 646 main(int p) { |
| 647 unresolvedFunctionProblem(); |
| 648 } |
| 649 /** |
| 650 * Other comment with [int] reference. |
| 651 */ |
| 652 foo() {} |
| 653 '''); |
| 654 } |
| 655 |
| 656 void test_dartDoc_clumsy_updateText_remove() { |
| 657 _resolveUnit(r''' |
| 658 /** |
| 659 * A function [main] with a parameter [p] of type [int]. |
| 660 * Some text with [String] reference to remove. |
| 661 */ |
| 662 main(int p) { |
| 663 } |
| 664 /** |
| 665 * Other comment with [int] reference. |
| 666 */ |
| 667 foo() {} |
| 668 '''); |
| 669 _updateAndValidate(r''' |
| 670 /** |
| 671 * A function [main] with a parameter [p] of type [int]. |
| 672 */ |
| 673 main(int p) { |
| 674 } |
| 675 /** |
| 676 * Other comment with [int] reference. |
| 677 */ |
| 678 foo() {} |
| 679 '''); |
| 680 } |
| 681 |
| 682 void test_dartDoc_elegant_addReference() { |
| 683 _resolveUnit(r''' |
| 684 /// aaa bbb |
| 685 main() { |
| 686 return 1; |
| 687 } |
| 688 '''); |
| 689 _updateAndValidate(r''' |
| 690 /// aaa [main] bbb |
| 691 /// ccc [int] ddd |
| 692 main() { |
| 693 return 1; |
| 694 } |
| 695 '''); |
| 696 } |
| 697 |
| 698 void test_dartDoc_elegant_removeReference() { |
| 699 _resolveUnit(r''' |
| 700 /// aaa [main] bbb |
| 701 /// ccc [int] ddd |
| 702 main() { |
| 703 return 1; |
| 704 } |
| 705 '''); |
| 706 _updateAndValidate(r''' |
| 707 /// aaa bbb |
| 708 main() { |
| 709 return 1; |
| 710 } |
| 711 '''); |
| 712 } |
| 713 |
| 714 void test_dartDoc_elegant_updateText_insertToken() { |
| 715 _resolveUnit(r''' |
| 716 /// A |
| 717 /// [int] |
| 718 class Test { |
| 719 } |
| 720 '''); |
| 721 _updateAndValidate(r''' |
| 722 /// A |
| 723 /// |
| 724 /// [int] |
| 725 class Test { |
| 726 } |
| 727 '''); |
| 728 } |
| 729 |
| 730 void test_dartDoc_elegant_updateText_removeToken() { |
| 731 _resolveUnit(r''' |
| 732 /// A |
| 733 /// |
| 734 /// [int] |
| 735 class Test { |
| 736 } |
| 737 '''); |
| 738 _updateAndValidate(r''' |
| 739 /// A |
| 740 /// [int] |
| 741 class Test { |
| 742 } |
| 743 '''); |
| 744 } |
| 745 |
| 746 void test_endOfLineComment_add_beforeKeywordToken() { |
| 747 _resolveUnit(r''' |
| 748 main() { |
| 749 var v = 42; |
| 750 } |
| 751 '''); |
| 752 _updateAndValidate(r''' |
| 753 main() { |
| 754 // some comment |
| 755 var v = 42; |
| 756 } |
| 757 '''); |
| 758 } |
| 759 |
| 760 void test_endOfLineComment_add_beforeStringToken() { |
| 761 _resolveUnit(r''' |
| 762 main() { |
| 763 print(0); |
| 764 } |
| 765 '''); |
| 766 _updateAndValidate(r''' |
| 767 main() { |
| 768 // some comment |
| 769 print(0); |
| 770 } |
| 771 '''); |
| 772 } |
| 773 |
| 774 void test_endOfLineComment_edit() { |
| 775 _resolveUnit(r''' |
| 776 main() { |
| 777 // some comment |
| 778 print(0); |
| 779 } |
| 780 '''); |
| 781 _updateAndValidate(r''' |
| 782 main() { |
| 783 // edited comment text |
| 784 print(0); |
| 785 } |
| 786 '''); |
| 787 } |
| 788 |
| 789 void test_endOfLineComment_outBody_add() { |
| 790 _resolveUnit(r''' |
| 791 main() { |
| 792 Object x; |
| 793 x.foo(); |
| 794 } |
| 795 '''); |
| 796 _updateAndValidate( |
| 797 r''' |
| 798 // 000 |
| 799 main() { |
| 800 Object x; |
| 801 x.foo(); |
| 802 } |
| 803 ''', |
| 804 expectedSuccess: false); |
| 805 } |
| 806 |
| 807 void test_endOfLineComment_outBody_remove() { |
| 808 _resolveUnit(r''' |
| 809 // 000 |
| 810 main() { |
| 811 Object x; |
| 812 x.foo(); |
| 813 } |
| 814 '''); |
| 815 _updateAndValidate( |
| 816 r''' |
| 817 main() { |
| 818 Object x; |
| 819 x.foo(); |
| 820 } |
| 821 ''', |
| 822 expectedSuccess: false); |
| 823 } |
| 824 |
| 825 void test_endOfLineComment_outBody_update() { |
| 826 _resolveUnit(r''' |
| 827 // 000 |
| 828 main() { |
| 829 Object x; |
| 830 x.foo(); |
| 831 } |
| 832 '''); |
| 833 _updateAndValidate( |
| 834 r''' |
| 835 // 10 |
| 836 main() { |
| 837 Object x; |
| 838 x.foo(); |
| 839 } |
| 840 ''', |
| 841 expectedSuccess: false); |
| 842 } |
| 843 |
| 844 void test_endOfLineComment_remove() { |
| 845 _resolveUnit(r''' |
| 846 main() { |
| 847 // some comment |
| 848 print(0); |
| 849 } |
| 850 '''); |
| 851 _updateAndValidate(r''' |
| 852 main() { |
| 853 print(0); |
| 854 } |
| 855 '''); |
| 856 } |
| 857 |
| 858 void test_endOfLineComment_toDartDoc() { |
| 859 _resolveUnit(r''' |
| 860 class A { |
| 861 // text |
| 862 main() { |
| 863 print(42); |
| 864 } |
| 865 }'''); |
| 866 _updateAndValidate( |
| 867 r''' |
| 868 class A { |
| 869 /// text |
| 870 main() { |
| 871 print(42); |
| 872 } |
| 873 }''', |
| 874 expectedSuccess: false); |
| 875 } |
| 876 |
| 877 void test_false_constConstructor_initializer() { |
| 878 _resolveUnit(r''' |
| 879 class C { |
| 880 final int x; |
| 881 const C(this.x); |
| 882 const C.foo() : x = 0; |
| 883 } |
| 884 main() { |
| 885 const {const C(0): 0, const C.foo(): 1}; |
| 886 } |
| 887 '''); |
| 888 _updateAndValidate( |
| 889 r''' |
| 890 class C { |
| 891 final int x; |
| 892 const C(this.x); |
| 893 const C.foo() : x = 1; |
| 894 } |
| 895 main() { |
| 896 const {const C(0): 0, const C.foo(): 1}; |
| 897 } |
| 898 ''', |
| 899 expectedSuccess: false); |
| 900 } |
| 901 |
| 902 void test_false_constructor_initializer_damage() { |
| 903 _resolveUnit(r''' |
| 904 class Problem { |
| 905 final Map location; |
| 906 final String message; |
| 907 |
| 908 Problem(Map json) |
| 909 : location = json["location"], |
| 910 message = json["message"]; |
| 911 }'''); |
| 912 _updateAndValidate( |
| 913 r''' |
| 914 class Problem { |
| 915 final Map location; |
| 916 final String message; |
| 917 |
| 918 Problem(Map json) |
| 919 : location = json["location], |
| 920 message = json["message"]; |
| 921 }''', |
| 922 expectedSuccess: false); |
| 923 } |
| 924 |
| 925 void test_false_constructor_initializer_remove() { |
| 926 _resolveUnit(r''' |
| 927 class Problem { |
| 928 final String severity; |
| 929 final Map location; |
| 930 final String message; |
| 931 |
| 932 Problem(Map json) |
| 933 : severity = json["severity"], |
| 934 location = json["location"], |
| 935 message = json["message"]; |
| 936 }'''); |
| 937 _updateAndValidate( |
| 938 r''' |
| 939 class Problem { |
| 940 final String severity; |
| 941 final Map location; |
| 942 final String message; |
| 943 |
| 944 Problem(Map json) |
| 945 : severity = json["severity"], |
| 946 message = json["message"]; |
| 947 }''', |
| 948 expectedSuccess: false); |
| 949 } |
| 950 |
| 951 void test_false_endOfLineComment_localFunction_inTopLevelVariable() { |
| 952 _resolveUnit(r''' |
| 953 typedef int Binary(one, two, three); |
| 954 |
| 955 int Global = f((a, b, c) { |
| 956 return 0; // Some comment |
| 957 }); |
| 958 '''); |
| 959 _updateAndValidate( |
| 960 r''' |
| 961 typedef int Binary(one, two, three); |
| 962 |
| 963 int Global = f((a, b, c) { |
| 964 return 0; // Some comment |
| 965 }); |
| 966 ''', |
| 967 expectedSuccess: false); |
| 968 } |
| 969 |
| 970 void test_false_expressionBody() { |
| 971 _resolveUnit(r''' |
| 972 class A { |
| 973 final f = (() => 1)(); |
| 974 } |
| 975 '''); |
| 976 _updateAndValidate( |
| 977 r''' |
| 978 class A { |
| 979 final f = (() => 2)(); |
| 980 } |
| 981 ''', |
| 982 expectedSuccess: false); |
| 983 } |
| 984 |
| 985 void test_false_expressionBody2() { |
| 986 _resolveUnit(r''' |
| 987 class A { |
| 988 int m() => 10 * 10; |
| 989 } |
| 990 '''); |
| 991 _updateAndValidate( |
| 992 r''' |
| 993 class A { |
| 994 int m() => 10 * 100; |
| 995 } |
| 996 ''', |
| 997 expectedSuccess: false); |
| 998 } |
| 999 |
| 1000 void test_false_inBody_addAsync() { |
| 1001 _resolveUnit(r''' |
| 1002 class C { |
| 1003 test() {} |
| 1004 } |
| 1005 '''); |
| 1006 _updateAndValidate( |
| 1007 r''' |
| 1008 class C { |
| 1009 test() async {} |
| 1010 } |
| 1011 ''', |
| 1012 expectedSuccess: false); |
| 1013 } |
| 1014 |
| 1015 void test_false_inBody_async_addStar() { |
| 1016 _resolveUnit(r''' |
| 1017 import 'dart:async'; |
| 1018 class C { |
| 1019 Stream test() async {} |
| 1020 } |
| 1021 '''); |
| 1022 _updateAndValidate( |
| 1023 r''' |
| 1024 import 'dart:async'; |
| 1025 class C { |
| 1026 Stream test() async* {} |
| 1027 } |
| 1028 ''', |
| 1029 expectedSuccess: false); |
| 1030 } |
| 1031 |
| 1032 void test_false_inBody_async_removeStar() { |
| 1033 _resolveUnit(r''' |
| 1034 import 'dart:async'; |
| 1035 class C { |
| 1036 Stream test() async* {} |
| 1037 } |
| 1038 '''); |
| 1039 _updateAndValidate( |
| 1040 r''' |
| 1041 import 'dart:async'; |
| 1042 class C { |
| 1043 Stream test() async {} |
| 1044 } |
| 1045 ''', |
| 1046 expectedSuccess: false); |
| 1047 } |
| 1048 |
| 1049 void test_false_inBody_functionExpression() { |
| 1050 _resolveUnit(r''' |
| 1051 class C extends D { |
| 1052 static final f = () { |
| 1053 var x = 0; |
| 1054 }(); |
| 1055 } |
| 1056 |
| 1057 class D {} |
| 1058 '''); |
| 1059 _updateAndValidate( |
| 1060 r''' |
| 1061 class C extends D { |
| 1062 static final f = () { |
| 1063 var x = 01; |
| 1064 }(); |
| 1065 } |
| 1066 |
| 1067 class D {} |
| 1068 ''', |
| 1069 expectedSuccess: false); |
| 1070 } |
| 1071 |
| 1072 void test_false_inBody_removeAsync() { |
| 1073 _resolveUnit(r''' |
| 1074 class C { |
| 1075 test() async {} |
| 1076 } |
| 1077 '''); |
| 1078 _updateAndValidate( |
| 1079 r''' |
| 1080 class C { |
| 1081 test() {} |
| 1082 } |
| 1083 ''', |
| 1084 expectedSuccess: false); |
| 1085 } |
| 1086 |
| 1087 void test_false_inBody_sync_addStar() { |
| 1088 _resolveUnit(r''' |
| 1089 class C { |
| 1090 test() {} |
| 1091 } |
| 1092 '''); |
| 1093 _updateAndValidate( |
| 1094 r''' |
| 1095 class C { |
| 1096 test() sync* {} |
| 1097 } |
| 1098 ''', |
| 1099 expectedSuccess: false); |
| 1100 } |
| 1101 |
| 1102 void test_false_topLevelFunction_name() { |
| 1103 _resolveUnit(r''' |
| 1104 a() {} |
| 1105 b() {} |
| 1106 '''); |
| 1107 _updateAndValidate( |
| 1108 r''' |
| 1109 a() {} |
| 1110 bb() {} |
| 1111 ''', |
| 1112 expectedSuccess: false); |
| 1113 } |
| 1114 |
| 1115 void test_false_unbalancedCurlyBrackets_inNew() { |
| 1116 _resolveUnit(r''' |
| 1117 class A { |
| 1118 aaa() { |
| 1119 if (true) { |
| 1120 1; |
| 1121 } |
| 1122 } |
| 1123 |
| 1124 bbb() { |
| 1125 print(0123456789); |
| 1126 } |
| 1127 }'''); |
| 1128 _updateAndValidate( |
| 1129 r''' |
| 1130 class A { |
| 1131 aaa() { |
| 1132 1; |
| 1133 } |
| 1134 } |
| 1135 |
| 1136 bbb() { |
| 1137 print(0123456789); |
| 1138 } |
| 1139 }''', |
| 1140 expectedSuccess: false); |
| 1141 } |
| 1142 |
| 1143 void test_false_unbalancedCurlyBrackets_inOld() { |
| 1144 _resolveUnit(r''' |
| 1145 class A { |
| 1146 aaa() { |
| 1147 1; |
| 1148 } |
| 1149 } |
| 1150 |
| 1151 bbb() { |
| 1152 print(0123456789); |
| 1153 } |
| 1154 }'''); |
| 1155 _updateAndValidate( |
| 1156 r''' |
| 1157 class A { |
| 1158 aaa() { |
| 1159 if (true) { |
| 1160 1; |
| 1161 } |
| 1162 } |
| 1163 |
| 1164 bbb() { |
| 1165 print(0123456789); |
| 1166 } |
| 1167 }''', |
| 1168 expectedSuccess: false); |
| 1169 } |
| 1170 |
| 1171 void test_false_wholeConstructor() { |
| 1172 _resolveUnit(r''' |
| 1173 class A { |
| 1174 A(int a) { |
| 1175 print(a); |
| 1176 } |
| 1177 } |
| 1178 '''); |
| 1179 _updateAndValidate( |
| 1180 r''' |
| 1181 class A { |
| 1182 A(int b) { |
| 1183 print(b); |
| 1184 } |
| 1185 } |
| 1186 ''', |
| 1187 expectedSuccess: false); |
| 1188 } |
| 1189 |
| 1190 void test_false_wholeConstructor_addInitializer() { |
| 1191 _resolveUnit(r''' |
| 1192 class A { |
| 1193 int field; |
| 1194 A(); |
| 1195 } |
| 1196 '''); |
| 1197 _updateAndValidate( |
| 1198 r''' |
| 1199 class A { |
| 1200 int field; |
| 1201 A() : field = 5; |
| 1202 } |
| 1203 ''', |
| 1204 expectedSuccess: false); |
| 1205 } |
| 1206 |
| 1207 void test_false_wholeFunction() { |
| 1208 _resolveUnit(r''' |
| 1209 foo() {} |
| 1210 main(int a) { |
| 1211 print(a); |
| 1212 } |
| 1213 '''); |
| 1214 _updateAndValidate( |
| 1215 r''' |
| 1216 foo() {} |
| 1217 main(int b) { |
| 1218 print(b); |
| 1219 } |
| 1220 ''', |
| 1221 expectedSuccess: false); |
| 1222 } |
| 1223 |
| 1224 void test_false_wholeMethod() { |
| 1225 _resolveUnit(r''' |
| 1226 class A { |
| 1227 main(int a) { |
| 1228 print(a); |
| 1229 } |
| 1230 } |
| 1231 '''); |
| 1232 _updateAndValidate( |
| 1233 r''' |
| 1234 class A { |
| 1235 main(int b) { |
| 1236 print(b); |
| 1237 } |
| 1238 } |
| 1239 ''', |
| 1240 expectedSuccess: false); |
| 1241 } |
| 1242 |
| 1243 void test_fieldClassField_propagatedType() { |
| 1244 _resolveUnit(r''' |
| 1245 class A { |
| 1246 static const A b = const B(); |
| 1247 const A(); |
| 1248 } |
| 1249 |
| 1250 class B extends A { |
| 1251 const B(); |
| 1252 } |
| 1253 |
| 1254 main() { |
| 1255 print(12); |
| 1256 A.b; |
| 1257 } |
| 1258 '''); |
| 1259 _updateAndValidate(r''' |
| 1260 class A { |
| 1261 static const A b = const B(); |
| 1262 const A(); |
| 1263 } |
| 1264 |
| 1265 class B extends A { |
| 1266 const B(); |
| 1267 } |
| 1268 |
| 1269 main() { |
| 1270 print(123); |
| 1271 A.b; |
| 1272 } |
| 1273 '''); |
| 1274 } |
| 1275 |
| 1276 void test_hasElementAfter_defaultParameter() { |
| 1277 _resolveUnit(r''' |
| 1278 main() { |
| 1279 print(1); |
| 1280 } |
| 1281 otherFunction([p = 0]) {} |
| 1282 '''); |
| 1283 _updateAndValidate(r''' |
| 1284 main() { |
| 1285 print(2); |
| 1286 } |
| 1287 otherFunction([p = 0]) {} |
| 1288 '''); |
| 1289 } |
| 1290 |
| 1291 void test_inBody_expression() { |
| 1292 _resolveUnit(r''' |
| 1293 class A { |
| 1294 m() { |
| 1295 print(1); |
| 1296 } |
| 1297 } |
| 1298 '''); |
| 1299 _updateAndValidate(r''' |
| 1300 class A { |
| 1301 m() { |
| 1302 print(2 + 3); |
| 1303 } |
| 1304 } |
| 1305 '''); |
| 1306 } |
| 1307 |
| 1308 void test_inBody_insertStatement() { |
| 1309 _resolveUnit(r''' |
| 1310 main() { |
| 1311 print(1); |
| 1312 } |
| 1313 '''); |
| 1314 _updateAndValidate(r''' |
| 1315 main() { |
| 1316 print(0); |
| 1317 print(1); |
| 1318 } |
| 1319 '''); |
| 1320 } |
| 1321 |
| 1322 void test_inBody_tokenToNode() { |
| 1323 _resolveUnit(r''' |
| 1324 main() { |
| 1325 var v = 42; |
| 1326 print(v); |
| 1327 } |
| 1328 '''); |
| 1329 _updateAndValidate(r''' |
| 1330 main() { |
| 1331 int v = 42; |
| 1332 print(v); |
| 1333 } |
| 1334 '''); |
| 1335 } |
| 1336 |
| 1337 void test_multiple_emptyLine() { |
| 1338 _resolveUnit(r''' |
| 1339 class A { |
| 1340 m() { |
| 1341 return true; |
| 1342 } |
| 1343 }'''); |
| 1344 for (int i = 0; i < 6; i++) { |
| 1345 if (i.isEven) { |
| 1346 _updateAndValidate( |
| 1347 r''' |
| 1348 class A { |
| 1349 m() { |
| 1350 return true; |
| 1351 |
| 1352 } |
| 1353 }''', |
| 1354 compareWithFull: false); |
| 1355 } else { |
| 1356 _updateAndValidate( |
| 1357 r''' |
| 1358 class A { |
| 1359 m() { |
| 1360 return true; |
| 1361 } |
| 1362 }''', |
| 1363 compareWithFull: false); |
| 1364 } |
| 1365 } |
| 1366 } |
| 1367 |
| 1368 void test_multiple_expression() { |
| 1369 _resolveUnit(r''' |
| 1370 main() { |
| 1371 print(1); |
| 1372 }'''); |
| 1373 for (int i = 0; i < 6; i++) { |
| 1374 if (i.isEven) { |
| 1375 _updateAndValidate( |
| 1376 r''' |
| 1377 main() { |
| 1378 print(12); |
| 1379 }''', |
| 1380 compareWithFull: false); |
| 1381 } else { |
| 1382 _updateAndValidate( |
| 1383 r''' |
| 1384 main() { |
| 1385 print(1); |
| 1386 }''', |
| 1387 compareWithFull: false); |
| 1388 } |
| 1389 } |
| 1390 } |
| 1391 |
| 1392 void test_strongMode_typeComments_insertWhitespace() { |
| 1393 _resolveUnit(r''' |
| 1394 import 'dart:async'; |
| 1395 |
| 1396 void fadeIn(int milliseconds) { |
| 1397 Future<String> f; |
| 1398 f.then/*<String>*/((e) {print("hello");}); |
| 1399 } |
| 1400 '''); |
| 1401 _updateAndValidate(r''' |
| 1402 import 'dart:async'; |
| 1403 |
| 1404 void fadeIn(int milliseconds) { |
| 1405 Future<String> f; |
| 1406 f.then/*<String>*/((e) {print("hello") ;}); |
| 1407 } |
| 1408 '''); |
| 1409 } |
| 1410 |
| 1411 void test_true_emptyLine_betweenClassMembers_insert() { |
| 1412 _resolveUnit(r''' |
| 1413 class A { |
| 1414 a() {} |
| 1415 b() {} |
| 1416 } |
| 1417 '''); |
| 1418 _updateAndValidate(r''' |
| 1419 class A { |
| 1420 a() {} |
| 1421 |
| 1422 b() {} |
| 1423 } |
| 1424 '''); |
| 1425 } |
| 1426 |
| 1427 void test_true_emptyLine_betweenClassMembers_insert_beforeComment() { |
| 1428 _resolveUnit(r''' |
| 1429 class A { |
| 1430 a() {} |
| 1431 /// BBB |
| 1432 b() {} |
| 1433 } |
| 1434 '''); |
| 1435 _updateAndValidate(r''' |
| 1436 class A { |
| 1437 a() {} |
| 1438 |
| 1439 /// BBB |
| 1440 b() {} |
| 1441 } |
| 1442 '''); |
| 1443 } |
| 1444 |
| 1445 void test_true_emptyLine_betweenClassMembers_remove() { |
| 1446 _resolveUnit(r''' |
| 1447 class A { |
| 1448 a() {} |
| 1449 |
| 1450 b() {} |
| 1451 } |
| 1452 '''); |
| 1453 _updateAndValidate(r''' |
| 1454 class A { |
| 1455 a() {} |
| 1456 b() {} |
| 1457 } |
| 1458 '''); |
| 1459 } |
| 1460 |
| 1461 void test_true_emptyLine_betweenClassMembers_remove_beforeComment() { |
| 1462 _resolveUnit(r''' |
| 1463 class A { |
| 1464 a() {} |
| 1465 |
| 1466 /// BBB |
| 1467 b() {} |
| 1468 } |
| 1469 '''); |
| 1470 _updateAndValidate(r''' |
| 1471 class A { |
| 1472 a() {} |
| 1473 /// BBB |
| 1474 b() {} |
| 1475 } |
| 1476 '''); |
| 1477 } |
| 1478 |
| 1479 void test_true_emptyLine_betweenUnitMembers_insert() { |
| 1480 _resolveUnit(r''' |
| 1481 a() {} |
| 1482 b() {} |
| 1483 '''); |
| 1484 _updateAndValidate(r''' |
| 1485 a() {} |
| 1486 |
| 1487 b() {} |
| 1488 '''); |
| 1489 } |
| 1490 |
| 1491 void test_true_emptyLine_betweenUnitMembers_insert_beforeComment() { |
| 1492 _resolveUnit(r''' |
| 1493 a() {} |
| 1494 |
| 1495 // BBB |
| 1496 b() {} |
| 1497 '''); |
| 1498 _updateAndValidate(r''' |
| 1499 a() {} |
| 1500 |
| 1501 |
| 1502 // BBB |
| 1503 b() {} |
| 1504 '''); |
| 1505 } |
| 1506 |
| 1507 void test_true_emptyLine_betweenUnitMembers_remove() { |
| 1508 _resolveUnit(r''' |
| 1509 a() { |
| 1510 print(1) |
| 1511 } |
| 1512 |
| 1513 b() { |
| 1514 foo(42); |
| 1515 } |
| 1516 foo(String p) {} |
| 1517 '''); |
| 1518 _updateAndValidate(r''' |
| 1519 a() { |
| 1520 print(1) |
| 1521 } |
| 1522 b() { |
| 1523 foo(42); |
| 1524 } |
| 1525 foo(String p) {} |
| 1526 '''); |
| 1527 } |
| 1528 |
| 1529 void test_true_emptyLine_betweenUnitMembers_remove_beforeComment() { |
| 1530 _resolveUnit(r''' |
| 1531 a() {} |
| 1532 |
| 1533 // BBB |
| 1534 b() {} |
| 1535 '''); |
| 1536 _updateAndValidate(r''' |
| 1537 a() {} |
| 1538 // BBB |
| 1539 b() {} |
| 1540 '''); |
| 1541 } |
| 1542 |
| 1543 void test_true_todoHint() { |
| 1544 _resolveUnit(r''' |
| 1545 main() { |
| 1546 print(1); |
| 1547 } |
| 1548 foo() { |
| 1549 // TODO |
| 1550 } |
| 1551 '''); |
| 1552 List<AnalysisError> oldErrors = analysisContext.computeErrors(source); |
| 1553 _updateAndValidate(r''' |
| 1554 main() { |
| 1555 print(2); |
| 1556 } |
| 1557 foo() { |
| 1558 // TODO |
| 1559 } |
| 1560 '''); |
| 1561 List<AnalysisError> newErrors = analysisContext.computeErrors(source); |
| 1562 _assertEqualErrors(newErrors, oldErrors); |
| 1563 } |
| 1564 |
| 1565 void test_unusedHint_add_wasUsedOnlyInPart() { |
| 1566 Source partSource = addNamedSource( |
| 1567 '/my_unit.dart', |
| 1568 r''' |
| 1569 part of lib; |
| 1570 |
| 1571 f(A a) { |
| 1572 a._foo(); |
| 1573 } |
| 1574 '''); |
| 1575 _resolveUnit(r''' |
| 1576 library lib; |
| 1577 part 'my_unit.dart'; |
| 1578 class A { |
| 1579 _foo() { |
| 1580 print(1); |
| 1581 } |
| 1582 } |
| 1583 '''); |
| 1584 _runTasks(); |
| 1585 // perform incremental resolution |
| 1586 _resetWithIncremental(true); |
| 1587 analysisContext2.setContents( |
| 1588 partSource, |
| 1589 r''' |
| 1590 part of lib; |
| 1591 |
| 1592 f(A a) { |
| 1593 // a._foo(); |
| 1594 } |
| 1595 '''); |
| 1596 // no hints right now, because we delay hints computing |
| 1597 { |
| 1598 List<AnalysisError> errors = analysisContext.getErrors(source).errors; |
| 1599 expect(errors, isEmpty); |
| 1600 } |
| 1601 // a new hint should be added |
| 1602 List<AnalysisError> errors = analysisContext.computeErrors(source); |
| 1603 expect(errors, hasLength(1)); |
| 1604 expect(errors[0].errorCode.type, ErrorType.HINT); |
| 1605 // the same hint should be reported using a ChangeNotice |
| 1606 bool noticeFound = false; |
| 1607 AnalysisResult result = analysisContext2.performAnalysisTask(); |
| 1608 for (ChangeNotice notice in result.changeNotices) { |
| 1609 if (notice.source == source) { |
| 1610 expect(notice.errors, contains(errors[0])); |
| 1611 noticeFound = true; |
| 1612 } |
| 1613 } |
| 1614 expect(noticeFound, isTrue); |
| 1615 } |
| 1616 |
| 1617 void test_unusedHint_false_stillUsedInPart() { |
| 1618 addNamedSource( |
| 1619 '/my_unit.dart', |
| 1620 r''' |
| 1621 part of lib; |
| 1622 |
| 1623 f(A a) { |
| 1624 a._foo(); |
| 1625 } |
| 1626 '''); |
| 1627 _resolveUnit(r''' |
| 1628 library lib; |
| 1629 part 'my_unit.dart'; |
| 1630 class A { |
| 1631 _foo() { |
| 1632 print(1); |
| 1633 } |
| 1634 } |
| 1635 '''); |
| 1636 // perform incremental resolution |
| 1637 _resetWithIncremental(true); |
| 1638 analysisContext2.setContents( |
| 1639 source, |
| 1640 r''' |
| 1641 library lib; |
| 1642 part 'my_unit.dart'; |
| 1643 class A { |
| 1644 _foo() { |
| 1645 print(12); |
| 1646 } |
| 1647 } |
| 1648 '''); |
| 1649 // no hints |
| 1650 List<AnalysisError> errors = analysisContext.getErrors(source).errors; |
| 1651 expect(errors, isEmpty); |
| 1652 } |
| 1653 |
| 1654 void test_updateConstantInitializer() { |
| 1655 _resolveUnit(r''' |
| 1656 main() { |
| 1657 const v = const [Unknown]; |
| 1658 } |
| 1659 '''); |
| 1660 _updateAndValidate( |
| 1661 r''' |
| 1662 main() { |
| 1663 const v = const [Unknown]; |
| 1664 } |
| 1665 ''', |
| 1666 expectCachePostConstantsValid: false); |
| 1667 } |
| 1668 |
| 1669 void test_updateErrors_addNew_hint1() { |
| 1670 _resolveUnit(r''' |
| 1671 int main() { |
| 1672 return 42; |
| 1673 } |
| 1674 '''); |
| 1675 _updateAndValidate(r''' |
| 1676 int main() { |
| 1677 } |
| 1678 '''); |
| 1679 } |
| 1680 |
| 1681 void test_updateErrors_addNew_hint2() { |
| 1682 _resolveUnit(r''' |
| 1683 main() { |
| 1684 int v = 0; |
| 1685 print(v); |
| 1686 } |
| 1687 '''); |
| 1688 _updateAndValidate(r''' |
| 1689 main() { |
| 1690 int v = 0; |
| 1691 } |
| 1692 '''); |
| 1693 } |
| 1694 |
| 1695 void test_updateErrors_addNew_parse() { |
| 1696 _resolveUnit(r''' |
| 1697 main() { |
| 1698 print(42); |
| 1699 } |
| 1700 '''); |
| 1701 _updateAndValidate(r''' |
| 1702 main() { |
| 1703 print(42) |
| 1704 } |
| 1705 '''); |
| 1706 } |
| 1707 |
| 1708 void test_updateErrors_addNew_resolve() { |
| 1709 _resolveUnit(r''' |
| 1710 main() { |
| 1711 foo(); |
| 1712 } |
| 1713 foo() {} |
| 1714 '''); |
| 1715 _updateAndValidate(r''' |
| 1716 main() { |
| 1717 bar(); |
| 1718 } |
| 1719 foo() {} |
| 1720 '''); |
| 1721 } |
| 1722 |
| 1723 void test_updateErrors_addNew_resolve2() { |
| 1724 _resolveUnit(r''' |
| 1725 // this comment is important to reproduce the problem |
| 1726 main() { |
| 1727 int vvv = 42; |
| 1728 print(vvv); |
| 1729 } |
| 1730 '''); |
| 1731 _updateAndValidate(r''' |
| 1732 // this comment is important to reproduce the problem |
| 1733 main() { |
| 1734 int vvv = 42; |
| 1735 print(vvv2); |
| 1736 } |
| 1737 '''); |
| 1738 } |
| 1739 |
| 1740 void test_updateErrors_addNew_scan() { |
| 1741 _resolveUnit(r''' |
| 1742 main() { |
| 1743 1; |
| 1744 } |
| 1745 '''); |
| 1746 _updateAndValidate(r''' |
| 1747 main() { |
| 1748 1e; |
| 1749 } |
| 1750 '''); |
| 1751 } |
| 1752 |
| 1753 void test_updateErrors_addNew_verify() { |
| 1754 _resolveUnit(r''' |
| 1755 main() { |
| 1756 foo(0); |
| 1757 } |
| 1758 foo(int p) {} |
| 1759 '''); |
| 1760 _updateAndValidate(r''' |
| 1761 main() { |
| 1762 foo('abc'); |
| 1763 } |
| 1764 foo(int p) {} |
| 1765 '''); |
| 1766 } |
| 1767 |
| 1768 void test_updateErrors_invalidVerifyErrors() { |
| 1769 _resolveUnit(r''' |
| 1770 main() { |
| 1771 foo('aaa'); |
| 1772 } |
| 1773 main2() { |
| 1774 foo('bbb'); |
| 1775 } |
| 1776 foo(int p) {} |
| 1777 '''); |
| 1778 // Complete analysis, e.g. compute VERIFY_ERRORS. |
| 1779 _runTasks(); |
| 1780 // Invalidate VERIFY_ERRORS. |
| 1781 AnalysisCache cache = analysisContext2.analysisCache; |
| 1782 LibrarySpecificUnit target = new LibrarySpecificUnit(source, source); |
| 1783 CacheEntry cacheEntry = cache.get(target); |
| 1784 expect(cacheEntry.getValue(VERIFY_ERRORS), hasLength(2)); |
| 1785 cacheEntry.setState(VERIFY_ERRORS, CacheState.INVALID); |
| 1786 // Perform incremental resolution. |
| 1787 _resetWithIncremental(true); |
| 1788 analysisContext2.setContents( |
| 1789 source, |
| 1790 r''' |
| 1791 main() { |
| 1792 foo(0); |
| 1793 } |
| 1794 main2() { |
| 1795 foo('bbb'); |
| 1796 } |
| 1797 foo(int p) {} |
| 1798 '''); |
| 1799 // VERIFY_ERRORS is still invalid. |
| 1800 expect(cacheEntry.getState(VERIFY_ERRORS), CacheState.INVALID); |
| 1801 // Continue analysis - run tasks, so recompute VERIFY_ERRORS. |
| 1802 _runTasks(); |
| 1803 expect(cacheEntry.getState(VERIFY_ERRORS), CacheState.VALID); |
| 1804 expect(cacheEntry.getValue(VERIFY_ERRORS), hasLength(1)); |
| 1805 } |
| 1806 |
| 1807 void test_updateErrors_removeExisting_hint() { |
| 1808 _resolveUnit(r''' |
| 1809 int main() { |
| 1810 } |
| 1811 '''); |
| 1812 _updateAndValidate(r''' |
| 1813 int main() { |
| 1814 return 42; |
| 1815 } |
| 1816 '''); |
| 1817 } |
| 1818 |
| 1819 void test_updateErrors_removeExisting_verify() { |
| 1820 _resolveUnit(r''' |
| 1821 f1() { |
| 1822 print(1) |
| 1823 } |
| 1824 f2() { |
| 1825 print(22) |
| 1826 } |
| 1827 f3() { |
| 1828 print(333) |
| 1829 } |
| 1830 '''); |
| 1831 _updateAndValidate(r''' |
| 1832 f1() { |
| 1833 print(1) |
| 1834 } |
| 1835 f2() { |
| 1836 print(22); |
| 1837 } |
| 1838 f3() { |
| 1839 print(333) |
| 1840 } |
| 1841 '''); |
| 1842 } |
| 1843 |
| 1844 void test_updateErrors_shiftExisting() { |
| 1845 _resolveUnit(r''' |
| 1846 f1() { |
| 1847 print(1) |
| 1848 } |
| 1849 f2() { |
| 1850 print(2); |
| 1851 } |
| 1852 f3() { |
| 1853 print(333) |
| 1854 } |
| 1855 '''); |
| 1856 _updateAndValidate(r''' |
| 1857 f1() { |
| 1858 print(1) |
| 1859 } |
| 1860 f2() { |
| 1861 print(22); |
| 1862 } |
| 1863 f3() { |
| 1864 print(333) |
| 1865 } |
| 1866 '''); |
| 1867 } |
| 1868 |
| 1869 void test_updateFunctionToForLoop() { |
| 1870 _resolveUnit(r''' |
| 1871 class PlayDrag { |
| 1872 final List<num> times = new List<num>(); |
| 1873 |
| 1874 PlayDrag.start() {} |
| 1875 |
| 1876 void update(num pos) { |
| 1877 fo (int i = times.length - 2; i >= 0; i--) {} |
| 1878 } |
| 1879 } |
| 1880 '''); |
| 1881 |
| 1882 _updateAndValidate( |
| 1883 r''' |
| 1884 class PlayDrag { |
| 1885 final List<num> times = new List<num>(); |
| 1886 |
| 1887 PlayDrag.start() {} |
| 1888 |
| 1889 void update(num pos) { |
| 1890 for (int i = times.length - 2; i >= 0; i--) {} |
| 1891 } |
| 1892 } |
| 1893 ''', |
| 1894 expectLibraryUnchanged: false); |
| 1895 } |
| 1896 |
| 1897 void test_visibleRange() { |
| 1898 _resolveUnit(r''' |
| 1899 class Test { |
| 1900 method1(p1) { |
| 1901 var v1; |
| 1902 f1() {} |
| 1903 return 1; |
| 1904 } |
| 1905 method2(p2) { |
| 1906 var v2; |
| 1907 f2() {} |
| 1908 return 2; |
| 1909 } |
| 1910 method3(p3) { |
| 1911 var v3; |
| 1912 f3() {} |
| 1913 return 3; |
| 1914 } |
| 1915 } |
| 1916 '''); |
| 1917 _updateAndValidate(r''' |
| 1918 class Test { |
| 1919 method1(p1) { |
| 1920 var v1; |
| 1921 f1() {} |
| 1922 return 1; |
| 1923 } |
| 1924 method2(p2) { |
| 1925 var v2; |
| 1926 f2() {} |
| 1927 return 2222; |
| 1928 } |
| 1929 method3(p3) { |
| 1930 var v3; |
| 1931 f3() {} |
| 1932 return 3; |
| 1933 } |
| 1934 } |
| 1935 '''); |
| 1936 } |
| 1937 |
| 1938 void test_whitespace_getElementAt() { |
| 1939 _resolveUnit(r''' |
| 1940 class A {} |
| 1941 class B extends A {} |
| 1942 '''); |
| 1943 { |
| 1944 ClassElement typeA = oldUnitElement.getType('A'); |
| 1945 expect(oldUnitElement.getElementAt(typeA.nameOffset), typeA); |
| 1946 } |
| 1947 { |
| 1948 ClassElement typeB = oldUnitElement.getType('B'); |
| 1949 expect(oldUnitElement.getElementAt(typeB.nameOffset), typeB); |
| 1950 } |
| 1951 _updateAndValidate(r''' |
| 1952 class A {} |
| 1953 |
| 1954 class B extends A {} |
| 1955 '''); |
| 1956 // getElementAt() caches results, it should be notified when offset |
| 1957 // are changed. |
| 1958 { |
| 1959 ClassElement typeA = oldUnitElement.getType('A'); |
| 1960 expect(oldUnitElement.getElementAt(typeA.nameOffset), typeA); |
| 1961 } |
| 1962 { |
| 1963 ClassElement typeB = oldUnitElement.getType('B'); |
| 1964 expect(oldUnitElement.getElementAt(typeB.nameOffset), typeB); |
| 1965 } |
| 1966 } |
| 1967 |
| 1968 void _assertCacheResults( |
| 1969 {bool expectLibraryUnchanged: true, |
| 1970 bool expectCachePostConstantsValid: true}) { |
| 1971 _assertCacheSourceResult(TOKEN_STREAM); |
| 1972 _assertCacheSourceResult(SCAN_ERRORS); |
| 1973 _assertCacheSourceResult(PARSED_UNIT); |
| 1974 _assertCacheSourceResult(PARSE_ERRORS); |
| 1975 if (!expectLibraryUnchanged) { |
| 1976 return; |
| 1977 } |
| 1978 _assertCacheSourceResult(LIBRARY_ELEMENT1); |
| 1979 _assertCacheSourceResult(LIBRARY_ELEMENT2); |
| 1980 _assertCacheSourceResult(LIBRARY_ELEMENT3); |
| 1981 _assertCacheSourceResult(LIBRARY_ELEMENT4); |
| 1982 _assertCacheSourceResult(LIBRARY_ELEMENT5); |
| 1983 _assertCacheSourceResult(LIBRARY_ELEMENT6); |
| 1984 _assertCacheSourceResult(LIBRARY_ELEMENT7); |
| 1985 _assertCacheSourceResult(LIBRARY_ELEMENT8); |
| 1986 _assertCacheSourceResult(LIBRARY_ELEMENT9); |
| 1987 if (expectCachePostConstantsValid) { |
| 1988 _assertCacheSourceResult(LIBRARY_ELEMENT); |
| 1989 } |
| 1990 _assertCacheUnitResult(RESOLVED_UNIT1); |
| 1991 _assertCacheUnitResult(RESOLVED_UNIT2); |
| 1992 _assertCacheUnitResult(RESOLVED_UNIT3); |
| 1993 _assertCacheUnitResult(RESOLVED_UNIT4); |
| 1994 _assertCacheUnitResult(RESOLVED_UNIT5); |
| 1995 _assertCacheUnitResult(RESOLVED_UNIT6); |
| 1996 _assertCacheUnitResult(RESOLVED_UNIT7); |
| 1997 _assertCacheUnitResult(RESOLVED_UNIT8); |
| 1998 _assertCacheUnitResult(RESOLVED_UNIT9); |
| 1999 _assertCacheUnitResult(RESOLVED_UNIT10); |
| 2000 _assertCacheUnitResult(RESOLVED_UNIT11); |
| 2001 if (expectCachePostConstantsValid) { |
| 2002 _assertCacheUnitResult(RESOLVED_UNIT12); |
| 2003 _assertCacheUnitResult(RESOLVED_UNIT); |
| 2004 } |
| 2005 } |
| 2006 |
| 2007 /** |
| 2008 * Assert that the [result] of [source] is not INVALID. |
| 2009 */ |
| 2010 void _assertCacheSourceResult(ResultDescriptor result) { |
| 2011 AnalysisCache cache = analysisContext2.analysisCache; |
| 2012 CacheState state = cache.getState(source, result); |
| 2013 expect(state, isNot(CacheState.INVALID), reason: result.toString()); |
| 2014 } |
| 2015 |
| 2016 /** |
| 2017 * Assert that the [result] of the defining unit [source] is not INVALID. |
| 2018 */ |
| 2019 void _assertCacheUnitResult(ResultDescriptor result) { |
| 2020 AnalysisCache cache = analysisContext2.analysisCache; |
| 2021 LibrarySpecificUnit target = new LibrarySpecificUnit(source, source); |
| 2022 CacheState state = cache.getState(target, result); |
| 2023 expect(state, isNot(CacheState.INVALID), reason: result.toString()); |
| 2024 } |
| 2025 |
| 2026 void _assertEqualLineInfo(LineInfo incLineInfo, LineInfo fullLineInfo) { |
| 2027 for (int offset = 0; offset < 1000; offset++) { |
| 2028 LineInfo_Location incLocation = incLineInfo.getLocation(offset); |
| 2029 LineInfo_Location fullLocation = fullLineInfo.getLocation(offset); |
| 2030 if (incLocation.lineNumber != fullLocation.lineNumber || |
| 2031 incLocation.columnNumber != fullLocation.columnNumber) { |
| 2032 fail('At offset $offset ' + |
| 2033 '(${incLocation.lineNumber}, ${incLocation.columnNumber})' + |
| 2034 ' != ' + |
| 2035 '(${fullLocation.lineNumber}, ${fullLocation.columnNumber})'); |
| 2036 } |
| 2037 } |
| 2038 } |
| 2039 |
| 2040 /** |
| 2041 * Reset the analysis context to have the 'incremental' option set to the |
| 2042 * given value. |
| 2043 */ |
| 2044 void _resetWithIncremental(bool enable) { |
| 2045 AnalysisOptionsImpl analysisOptions = new AnalysisOptionsImpl(); |
| 2046 analysisOptions.strongMode = true; |
| 2047 analysisOptions.incremental = enable; |
| 2048 analysisOptions.incrementalApi = enable; |
| 2049 logging.logger = logger; |
| 2050 analysisContext2.analysisOptions = analysisOptions; |
| 2051 } |
| 2052 |
| 2053 void _resolveUnit(String code) { |
| 2054 this.code = code; |
| 2055 source = addSource(code); |
| 2056 oldLibrary = resolve2(source); |
| 2057 oldUnit = resolveCompilationUnit(source, oldLibrary); |
| 2058 oldUnitElement = oldUnit.element; |
| 2059 } |
| 2060 |
| 2061 void _runTasks() { |
| 2062 AnalysisResult result = analysisContext.performAnalysisTask(); |
| 2063 while (result.changeNotices != null) { |
| 2064 result = analysisContext.performAnalysisTask(); |
| 2065 } |
| 2066 } |
| 2067 |
| 2068 void _updateAndValidate(String newCode, |
| 2069 {bool expectedSuccess: true, |
| 2070 bool expectLibraryUnchanged: true, |
| 2071 bool expectCachePostConstantsValid: true, |
| 2072 bool compareWithFull: true, |
| 2073 bool runTasksBeforeIncremental: true}) { |
| 2074 // Run any pending tasks tasks. |
| 2075 if (runTasksBeforeIncremental) { |
| 2076 _runTasks(); |
| 2077 } |
| 2078 // Update the source - currently this may cause incremental resolution. |
| 2079 // Then request the updated resolved unit. |
| 2080 _resetWithIncremental(true); |
| 2081 analysisContext2.setContents(source, newCode); |
| 2082 CompilationUnit newUnit = resolveCompilationUnit(source, oldLibrary); |
| 2083 logger.expectNoErrors(); |
| 2084 List<AnalysisError> newErrors = analysisContext.computeErrors(source); |
| 2085 LineInfo newLineInfo = analysisContext.getLineInfo(source); |
| 2086 // check for expected failure |
| 2087 if (!expectedSuccess) { |
| 2088 expect(newUnit.element, isNot(same(oldUnitElement))); |
| 2089 return; |
| 2090 } |
| 2091 // The cache must still have enough results to make the incremental |
| 2092 // resolution useful. |
| 2093 _assertCacheResults( |
| 2094 expectLibraryUnchanged: expectLibraryUnchanged, |
| 2095 expectCachePostConstantsValid: expectCachePostConstantsValid); |
| 2096 // The existing CompilationUnit[Element] should be updated. |
| 2097 expect(newUnit, same(oldUnit)); |
| 2098 expect(newUnit.element, same(oldUnitElement)); |
| 2099 expect(analysisContext.getResolvedCompilationUnit(source, oldLibrary), |
| 2100 same(oldUnit)); |
| 2101 // The only expected pending task should return the same resolved |
| 2102 // "newUnit", so all clients will get it using the usual way. |
| 2103 AnalysisResult analysisResult = analysisContext.performAnalysisTask(); |
| 2104 ChangeNotice notice = analysisResult.changeNotices[0]; |
| 2105 expect(notice.resolvedDartUnit, same(newUnit)); |
| 2106 // Resolve "newCode" from scratch. |
| 2107 if (compareWithFull) { |
| 2108 _resetWithIncremental(false); |
| 2109 changeSource(source, ''); |
| 2110 changeSource(source, newCode); |
| 2111 _runTasks(); |
| 2112 LibraryElement library = resolve2(source); |
| 2113 CompilationUnit fullNewUnit = resolveCompilationUnit(source, library); |
| 2114 // Validate tokens. |
| 2115 _assertEqualTokens(newUnit, fullNewUnit); |
| 2116 // Validate LineInfo |
| 2117 _assertEqualLineInfo(newLineInfo, analysisContext.getLineInfo(source)); |
| 2118 // Validate that "incremental" and "full" units have the same resolution. |
| 2119 try { |
| 2120 assertSameResolution(newUnit, fullNewUnit, validateTypes: true); |
| 2121 } on IncrementalResolutionMismatch catch (mismatch) { |
| 2122 fail(mismatch.message); |
| 2123 } |
| 2124 List<AnalysisError> newFullErrors = |
| 2125 analysisContext.getErrors(source).errors; |
| 2126 _assertEqualErrors(newErrors, newFullErrors); |
| 2127 } |
| 2128 _checkCacheEntries(analysisContext2.analysisCache); |
| 2129 } |
| 2130 |
| 2131 static void _assertEqualToken(Token incToken, Token fullToken) { |
| 2132 // print('[${incToken.offset}] |$incToken| vs. [${fullToken.offset}] |$fullTo
ken|'); |
| 2133 expect(incToken.type, fullToken.type); |
| 2134 expect(incToken.offset, fullToken.offset); |
| 2135 expect(incToken.length, fullToken.length); |
| 2136 expect(incToken.lexeme, fullToken.lexeme); |
| 2137 } |
| 2138 |
| 2139 static void _assertEqualTokens( |
| 2140 CompilationUnit incUnit, CompilationUnit fullUnit) { |
| 2141 Token incToken = incUnit.beginToken; |
| 2142 Token fullToken = fullUnit.beginToken; |
| 2143 while (incToken.type != TokenType.EOF && fullToken.type != TokenType.EOF) { |
| 2144 _assertEqualToken(incToken, fullToken); |
| 2145 // comments |
| 2146 { |
| 2147 Token incComment = incToken.precedingComments; |
| 2148 Token fullComment = fullToken.precedingComments; |
| 2149 while (true) { |
| 2150 if (fullComment == null) { |
| 2151 expect(incComment, isNull); |
| 2152 break; |
| 2153 } |
| 2154 expect(incComment, isNotNull); |
| 2155 _assertEqualToken(incComment, fullComment); |
| 2156 incComment = incComment.next; |
| 2157 fullComment = fullComment.next; |
| 2158 } |
| 2159 } |
| 2160 // next tokens |
| 2161 incToken = incToken.next; |
| 2162 fullToken = fullToken.next; |
| 2163 } |
| 2164 } |
| 2165 } |
| 2166 |
| 2167 @reflectiveTest |
| 2168 class ResolutionContextBuilderTest extends EngineTestCase { |
| 2169 void test_scopeFor_ClassDeclaration() { |
| 2170 Scope scope = _scopeFor(_createResolvedClassDeclaration()); |
| 2171 EngineTestCase.assertInstanceOf( |
| 2172 (obj) => obj is LibraryScope, LibraryScope, scope); |
| 2173 } |
| 2174 |
| 2175 void test_scopeFor_ClassTypeAlias() { |
| 2176 Scope scope = _scopeFor(_createResolvedClassTypeAlias()); |
| 2177 EngineTestCase.assertInstanceOf( |
| 2178 (obj) => obj is LibraryScope, LibraryScope, scope); |
| 2179 } |
| 2180 |
| 2181 void test_scopeFor_CompilationUnit() { |
| 2182 Scope scope = _scopeFor(_createResolvedCompilationUnit()); |
| 2183 EngineTestCase.assertInstanceOf( |
| 2184 (obj) => obj is LibraryScope, LibraryScope, scope); |
| 2185 } |
| 2186 |
| 2187 void test_scopeFor_ConstructorDeclaration() { |
| 2188 Scope scope = _scopeFor(_createResolvedConstructorDeclaration()); |
| 2189 EngineTestCase.assertInstanceOf( |
| 2190 (obj) => obj is ClassScope, ClassScope, scope); |
| 2191 } |
| 2192 |
| 2193 void test_scopeFor_ConstructorDeclaration_parameters() { |
| 2194 Scope scope = _scopeFor(_createResolvedConstructorDeclaration().parameters); |
| 2195 EngineTestCase.assertInstanceOf( |
| 2196 (obj) => obj is FunctionScope, FunctionScope, scope); |
| 2197 } |
| 2198 |
| 2199 void test_scopeFor_FunctionDeclaration() { |
| 2200 Scope scope = _scopeFor(_createResolvedFunctionDeclaration()); |
| 2201 EngineTestCase.assertInstanceOf( |
| 2202 (obj) => obj is LibraryScope, LibraryScope, scope); |
| 2203 } |
| 2204 |
| 2205 void test_scopeFor_FunctionDeclaration_parameters() { |
| 2206 Scope scope = _scopeFor( |
| 2207 _createResolvedFunctionDeclaration().functionExpression.parameters); |
| 2208 EngineTestCase.assertInstanceOf( |
| 2209 (obj) => obj is FunctionScope, FunctionScope, scope); |
| 2210 } |
| 2211 |
| 2212 void test_scopeFor_FunctionTypeAlias() { |
| 2213 Scope scope = _scopeFor(_createResolvedFunctionTypeAlias()); |
| 2214 EngineTestCase.assertInstanceOf( |
| 2215 (obj) => obj is LibraryScope, LibraryScope, scope); |
| 2216 } |
| 2217 |
| 2218 void test_scopeFor_FunctionTypeAlias_parameters() { |
| 2219 Scope scope = _scopeFor(_createResolvedFunctionTypeAlias().parameters); |
| 2220 EngineTestCase.assertInstanceOf( |
| 2221 (obj) => obj is FunctionTypeScope, FunctionTypeScope, scope); |
| 2222 } |
| 2223 |
| 2224 void test_scopeFor_MethodDeclaration() { |
| 2225 Scope scope = _scopeFor(_createResolvedMethodDeclaration()); |
| 2226 EngineTestCase.assertInstanceOf( |
| 2227 (obj) => obj is ClassScope, ClassScope, scope); |
| 2228 } |
| 2229 |
| 2230 void test_scopeFor_MethodDeclaration_body() { |
| 2231 Scope scope = _scopeFor(_createResolvedMethodDeclaration().body); |
| 2232 EngineTestCase.assertInstanceOf( |
| 2233 (obj) => obj is FunctionScope, FunctionScope, scope); |
| 2234 } |
| 2235 |
| 2236 void test_scopeFor_notInCompilationUnit() { |
| 2237 try { |
| 2238 _scopeFor(AstTestFactory.identifier3("x")); |
| 2239 fail("Expected AnalysisException"); |
| 2240 } on AnalysisException { |
| 2241 // Expected |
| 2242 } |
| 2243 } |
| 2244 |
| 2245 void test_scopeFor_null() { |
| 2246 try { |
| 2247 _scopeFor(null); |
| 2248 fail("Expected AnalysisException"); |
| 2249 } on AnalysisException { |
| 2250 // Expected |
| 2251 } |
| 2252 } |
| 2253 |
| 2254 void test_scopeFor_unresolved() { |
| 2255 try { |
| 2256 _scopeFor(AstTestFactory.compilationUnit()); |
| 2257 fail("Expected AnalysisException"); |
| 2258 } on AnalysisException { |
| 2259 // Expected |
| 2260 } |
| 2261 } |
| 2262 |
| 2263 ClassDeclaration _createResolvedClassDeclaration() { |
| 2264 CompilationUnit unit = _createResolvedCompilationUnit(); |
| 2265 String className = "C"; |
| 2266 ClassDeclaration classNode = AstTestFactory.classDeclaration( |
| 2267 null, className, AstTestFactory.typeParameterList(), null, null, null); |
| 2268 unit.declarations.add(classNode); |
| 2269 ClassElement classElement = ElementFactory.classElement2(className); |
| 2270 classNode.name.staticElement = classElement; |
| 2271 (unit.element as CompilationUnitElementImpl).types = <ClassElement>[ |
| 2272 classElement |
| 2273 ]; |
| 2274 return classNode; |
| 2275 } |
| 2276 |
| 2277 ClassTypeAlias _createResolvedClassTypeAlias() { |
| 2278 CompilationUnit unit = _createResolvedCompilationUnit(); |
| 2279 String className = "C"; |
| 2280 ClassTypeAlias classNode = AstTestFactory.classTypeAlias( |
| 2281 className, AstTestFactory.typeParameterList(), null, null, null, null); |
| 2282 unit.declarations.add(classNode); |
| 2283 ClassElement classElement = ElementFactory.classElement2(className); |
| 2284 classNode.name.staticElement = classElement; |
| 2285 (unit.element as CompilationUnitElementImpl).types = <ClassElement>[ |
| 2286 classElement |
| 2287 ]; |
| 2288 return classNode; |
| 2289 } |
| 2290 |
| 2291 CompilationUnit _createResolvedCompilationUnit() { |
| 2292 CompilationUnit unit = AstTestFactory.compilationUnit(); |
| 2293 LibraryElementImpl library = |
| 2294 ElementFactory.library(AnalysisContextFactory.contextWithCore(), "lib"); |
| 2295 unit.element = library.definingCompilationUnit; |
| 2296 return unit; |
| 2297 } |
| 2298 |
| 2299 ConstructorDeclaration _createResolvedConstructorDeclaration() { |
| 2300 ClassDeclaration classNode = _createResolvedClassDeclaration(); |
| 2301 String constructorName = "f"; |
| 2302 ConstructorDeclaration constructorNode = |
| 2303 AstTestFactory.constructorDeclaration( |
| 2304 AstTestFactory.identifier3(constructorName), |
| 2305 null, |
| 2306 AstTestFactory.formalParameterList(), |
| 2307 null); |
| 2308 classNode.members.add(constructorNode); |
| 2309 ConstructorElement constructorElement = |
| 2310 ElementFactory.constructorElement2(classNode.element, null); |
| 2311 constructorNode.element = constructorElement; |
| 2312 (classNode.element as ClassElementImpl).constructors = <ConstructorElement>[ |
| 2313 constructorElement |
| 2314 ]; |
| 2315 return constructorNode; |
| 2316 } |
| 2317 |
| 2318 FunctionDeclaration _createResolvedFunctionDeclaration() { |
| 2319 CompilationUnit unit = _createResolvedCompilationUnit(); |
| 2320 String functionName = "f"; |
| 2321 FunctionDeclaration functionNode = AstTestFactory.functionDeclaration( |
| 2322 null, null, functionName, AstTestFactory.functionExpression()); |
| 2323 unit.declarations.add(functionNode); |
| 2324 FunctionElement functionElement = |
| 2325 ElementFactory.functionElement(functionName); |
| 2326 functionNode.name.staticElement = functionElement; |
| 2327 (unit.element as CompilationUnitElementImpl).functions = <FunctionElement>[ |
| 2328 functionElement |
| 2329 ]; |
| 2330 return functionNode; |
| 2331 } |
| 2332 |
| 2333 FunctionTypeAlias _createResolvedFunctionTypeAlias() { |
| 2334 CompilationUnit unit = _createResolvedCompilationUnit(); |
| 2335 FunctionTypeAlias aliasNode = AstTestFactory.typeAlias( |
| 2336 AstTestFactory.typeName4("A"), |
| 2337 "F", |
| 2338 AstTestFactory.typeParameterList(), |
| 2339 AstTestFactory.formalParameterList()); |
| 2340 unit.declarations.add(aliasNode); |
| 2341 SimpleIdentifier aliasName = aliasNode.name; |
| 2342 FunctionTypeAliasElement aliasElement = |
| 2343 new FunctionTypeAliasElementImpl.forNode(aliasName); |
| 2344 aliasName.staticElement = aliasElement; |
| 2345 (unit.element as CompilationUnitElementImpl).typeAliases = |
| 2346 <FunctionTypeAliasElement>[aliasElement]; |
| 2347 return aliasNode; |
| 2348 } |
| 2349 |
| 2350 MethodDeclaration _createResolvedMethodDeclaration() { |
| 2351 ClassDeclaration classNode = _createResolvedClassDeclaration(); |
| 2352 String methodName = "f"; |
| 2353 MethodDeclaration methodNode = AstTestFactory.methodDeclaration( |
| 2354 null, |
| 2355 null, |
| 2356 null, |
| 2357 null, |
| 2358 AstTestFactory.identifier3(methodName), |
| 2359 AstTestFactory.formalParameterList()); |
| 2360 classNode.members.add(methodNode); |
| 2361 MethodElement methodElement = |
| 2362 ElementFactory.methodElement(methodName, null); |
| 2363 methodNode.name.staticElement = methodElement; |
| 2364 (classNode.element as ClassElementImpl).methods = <MethodElement>[ |
| 2365 methodElement |
| 2366 ]; |
| 2367 return methodNode; |
| 2368 } |
| 2369 |
| 2370 Scope _scopeFor(AstNode node) { |
| 2371 return ResolutionContextBuilder.contextFor(node).scope; |
| 2372 } |
| 2373 } |
| 2374 |
| 2375 class _Edit { |
| 2376 final int offset; |
| 2377 final int length; |
| 2378 final String replacement; |
| 2379 _Edit(this.offset, this.length, this.replacement); |
| 2380 } |
| 2381 |
| 2382 class _TestLogger implements logging.Logger { |
| 2383 Object lastException; |
| 2384 Object lastStackTrace; |
| 2385 |
| 2386 @override |
| 2387 void enter(String name) {} |
| 2388 |
| 2389 @override |
| 2390 void exit() {} |
| 2391 |
| 2392 void expectNoErrors() { |
| 2393 if (lastException != null) { |
| 2394 fail("logged an exception:\n$lastException\n$lastStackTrace\n"); |
| 2395 } |
| 2396 } |
| 2397 |
| 2398 @override |
| 2399 void log(Object obj) {} |
| 2400 |
| 2401 @override |
| 2402 void logException(Object exception, [Object stackTrace]) { |
| 2403 lastException = exception; |
| 2404 lastStackTrace = stackTrace; |
| 2405 } |
| 2406 |
| 2407 @override |
| 2408 logging.LoggingTimer startTimer() { |
| 2409 return new logging.LoggingTimer(this); |
| 2410 } |
| 2411 } |
| OLD | NEW |