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