Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(825)

Side by Side Diff: pkg/analyzer/test/generated/incremental_resolver_test.dart

Issue 1650873002: Fix memory leak in incremental resolver (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: simplify and improve tests Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « pkg/analyzer/lib/src/generated/incremental_resolver.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library analyzer.test.generated.incremental_resolver_test; 5 library analyzer.test.generated.incremental_resolver_test;
6 6
7 import 'package:analyzer/dart/ast/ast.dart'; 7 import 'package:analyzer/dart/ast/ast.dart';
8 import 'package:analyzer/dart/element/element.dart'; 8 import 'package:analyzer/dart/element/element.dart';
9 import 'package:analyzer/src/context/cache.dart'; 9 import 'package:analyzer/src/context/cache.dart';
10 import 'package:analyzer/src/dart/ast/utilities.dart'; 10 import 'package:analyzer/src/dart/ast/utilities.dart';
11 import 'package:analyzer/src/dart/element/builder.dart'; 11 import 'package:analyzer/src/dart/element/builder.dart';
12 import 'package:analyzer/src/dart/element/element.dart'; 12 import 'package:analyzer/src/dart/element/element.dart';
13 import 'package:analyzer/src/generated/engine.dart'; 13 import 'package:analyzer/src/generated/engine.dart';
14 import 'package:analyzer/src/generated/error.dart'; 14 import 'package:analyzer/src/generated/error.dart';
15 import 'package:analyzer/src/generated/incremental_logger.dart' as logging; 15 import 'package:analyzer/src/generated/incremental_logger.dart' as logging;
16 import 'package:analyzer/src/generated/incremental_resolution_validator.dart'; 16 import 'package:analyzer/src/generated/incremental_resolution_validator.dart';
17 import 'package:analyzer/src/generated/incremental_resolver.dart'; 17 import 'package:analyzer/src/generated/incremental_resolver.dart';
18 import 'package:analyzer/src/generated/java_engine.dart'; 18 import 'package:analyzer/src/generated/java_engine.dart';
19 import 'package:analyzer/src/generated/parser.dart'; 19 import 'package:analyzer/src/generated/parser.dart';
20 import 'package:analyzer/src/generated/resolver.dart'; 20 import 'package:analyzer/src/generated/resolver.dart';
21 import 'package:analyzer/src/generated/scanner.dart'; 21 import 'package:analyzer/src/generated/scanner.dart';
22 import 'package:analyzer/src/generated/source_io.dart'; 22 import 'package:analyzer/src/generated/source_io.dart';
23 import 'package:analyzer/src/generated/testing/ast_factory.dart'; 23 import 'package:analyzer/src/generated/testing/ast_factory.dart';
24 import 'package:analyzer/src/generated/testing/element_factory.dart'; 24 import 'package:analyzer/src/generated/testing/element_factory.dart';
25 import 'package:analyzer/src/generated/utilities_collection.dart';
25 import 'package:analyzer/src/task/dart.dart'; 26 import 'package:analyzer/src/task/dart.dart';
26 import 'package:analyzer/task/dart.dart'; 27 import 'package:analyzer/task/dart.dart';
28 import 'package:analyzer/task/model.dart';
27 import 'package:unittest/unittest.dart'; 29 import 'package:unittest/unittest.dart';
28 30
29 import '../reflective_tests.dart'; 31 import '../reflective_tests.dart';
30 import 'resolver_test.dart'; 32 import 'resolver_test.dart';
31 import 'test_support.dart'; 33 import 'test_support.dart';
32 34
33 main() { 35 main() {
34 initializeTestEnvironment(); 36 initializeTestEnvironment();
35 runReflectiveTests(DeclarationMatcherTest); 37 runReflectiveTests(DeclarationMatcherTest);
36 runReflectiveTests(IncrementalResolverTest); 38 runReflectiveTests(IncrementalResolverTest);
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 fullErrors.sort((a, b) => a.offset - b.offset); 113 fullErrors.sort((a, b) => a.offset - b.offset);
112 } 114 }
113 int length = incrErrors.length; 115 int length = incrErrors.length;
114 for (int i = 0; i < length; i++) { 116 for (int i = 0; i < length; i++) {
115 AnalysisError incrError = incrErrors[i]; 117 AnalysisError incrError = incrErrors[i];
116 AnalysisError fullError = fullErrors[i]; 118 AnalysisError fullError = fullErrors[i];
117 _assertEqualError(incrError, fullError); 119 _assertEqualError(incrError, fullError);
118 } 120 }
119 } 121 }
120 122
123 void _checkCacheEntries(AnalysisCache cache) {
124 Set seen = new Set();
125 MapIterator<AnalysisTarget, CacheEntry> it = cache.iterator();
126 while (it.moveNext()) {
127 AnalysisTarget key = it.key;
128 if (cache.get(key) == null) {
Brian Wilkerson 2016/02/02 22:51:14 Would the test cache.get(key) != it.value be b
scheglov 2016/02/02 23:04:25 `it.value` works mostly as `cache.get(key)`. So, i
skybrian 2016/02/02 23:27:02 Yes, the old value is (usually) no longer accessib
129 fail("cache corrupted: value of $key changed to null");
130 }
131 if (seen.contains(key)) {
Brian Wilkerson 2016/02/02 22:51:14 nit: just use "!seen.add(key)" here and remove lin
skybrian 2016/02/02 23:27:02 Done.
132 fail("cache corrupted: $key appears more than once");
133 }
134 seen.add(key);
135 }
136 }
137
121 @reflectiveTest 138 @reflectiveTest
122 class DeclarationMatcherTest extends ResolverTestCase { 139 class DeclarationMatcherTest extends ResolverTestCase {
123 void setUp() { 140 void setUp() {
124 super.setUp(); 141 super.setUp();
125 test_resolveApiChanges = true; 142 test_resolveApiChanges = true;
126 } 143 }
127 144
128 void test_false_class_annotation_accessor_edit() { 145 void test_false_class_annotation_accessor_edit() {
129 _assertDoesNotMatch( 146 _assertDoesNotMatch(
130 r''' 147 r'''
(...skipping 2983 matching lines...) Expand 10 before | Expand all | Expand 10 after
3114 void test_classMemberAccessor_body() { 3131 void test_classMemberAccessor_body() {
3115 _resolveUnit(r''' 3132 _resolveUnit(r'''
3116 class A { 3133 class A {
3117 int get test { 3134 int get test {
3118 return 1 + 2; 3135 return 1 + 2;
3119 } 3136 }
3120 }'''); 3137 }''');
3121 _resolve(_editString('+', '*'), _isFunctionBody); 3138 _resolve(_editString('+', '*'), _isFunctionBody);
3122 } 3139 }
3123 3140
3141 void test_computeConstants_offsetChanged() {
3142 _resolveUnit(r'''
3143 int f() => 0;
3144 main() {
3145 const x1 = f();
3146 const x2 = f();
3147 const x3 = f();
3148 const x4 = f();
3149 const x5 = f();
3150 print(x1 + x2 + x3 + x4 + x5 + 1);
3151 }
3152 ''');
3153 _resolve(_editString('x1', ' x1'), _isFunctionBody);
3154 }
3155
3124 void test_constructor_body() { 3156 void test_constructor_body() {
3125 _resolveUnit(r''' 3157 _resolveUnit(r'''
3126 class A { 3158 class A {
3127 int f; 3159 int f;
3128 A(int a, int b) { 3160 A(int a, int b) {
3129 f = a + b; 3161 f = a + b;
3130 } 3162 }
3131 }'''); 3163 }''');
3132 _resolve(_editString('+', '*'), _isFunctionBody); 3164 _resolve(_editString('+', '*'), _isFunctionBody);
3133 } 3165 }
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after
3419 * Then resolves the new code from scratch and validates that results of 3451 * Then resolves the new code from scratch and validates that results of
3420 * the incremental resolution and non-incremental resolutions are the same. 3452 * the incremental resolution and non-incremental resolutions are the same.
3421 */ 3453 */
3422 void _resolve(_Edit edit, Predicate<AstNode> predicate) { 3454 void _resolve(_Edit edit, Predicate<AstNode> predicate) {
3423 int offset = edit.offset; 3455 int offset = edit.offset;
3424 // parse "newCode" 3456 // parse "newCode"
3425 String newCode = code.substring(0, offset) + 3457 String newCode = code.substring(0, offset) +
3426 edit.replacement + 3458 edit.replacement +
3427 code.substring(offset + edit.length); 3459 code.substring(offset + edit.length);
3428 CompilationUnit newUnit = _parseUnit(newCode); 3460 CompilationUnit newUnit = _parseUnit(newCode);
3461 AnalysisCache cache = analysisContext2.analysisCache;
3462 _checkCacheEntries(cache);
3463
3429 // replace the node 3464 // replace the node
3430 AstNode oldNode = _findNodeAt(unit, offset, predicate); 3465 AstNode oldNode = _findNodeAt(unit, offset, predicate);
3431 AstNode newNode = _findNodeAt(newUnit, offset, predicate); 3466 AstNode newNode = _findNodeAt(newUnit, offset, predicate);
3432 { 3467 {
3433 bool success = NodeReplacer.replace(oldNode, newNode); 3468 bool success = NodeReplacer.replace(oldNode, newNode);
3434 expect(success, isTrue); 3469 expect(success, isTrue);
3435 } 3470 }
3436 // update tokens 3471 // update tokens
3437 { 3472 {
3438 int delta = edit.replacement.length - edit.length; 3473 int delta = edit.replacement.length - edit.length;
3439 _shiftTokens(unit.beginToken, offset, delta); 3474 _shiftTokens(unit.beginToken, offset, delta);
3440 } 3475 }
3441 // do incremental resolution 3476 // do incremental resolution
3442 int updateOffset = edit.offset; 3477 int updateOffset = edit.offset;
3443 int updateEndOld = updateOffset + edit.length; 3478 int updateEndOld = updateOffset + edit.length;
3444 int updateOldNew = updateOffset + edit.replacement.length; 3479 int updateOldNew = updateOffset + edit.replacement.length;
3445 IncrementalResolver resolver; 3480 IncrementalResolver resolver;
3446 LibrarySpecificUnit lsu = new LibrarySpecificUnit(source, source); 3481 LibrarySpecificUnit lsu = new LibrarySpecificUnit(source, source);
3447 AnalysisCache cache = analysisContext2.analysisCache; 3482 resolver = new IncrementalResolver(cache, cache.get(source), cache.get(lsu),
3448 resolver = new IncrementalResolver(cache.get(source), cache.get(lsu),
3449 unit.element, updateOffset, updateEndOld, updateOldNew); 3483 unit.element, updateOffset, updateEndOld, updateOldNew);
3450 bool success = resolver.resolve(newNode); 3484 bool success = resolver.resolve(newNode);
3451 expect(success, isTrue); 3485 expect(success, isTrue);
3486 _checkCacheEntries(cache);
3487
3452 List<AnalysisError> newErrors = analysisContext.computeErrors(source); 3488 List<AnalysisError> newErrors = analysisContext.computeErrors(source);
3453 // resolve "newCode" from scratch 3489 // resolve "newCode" from scratch
3454 CompilationUnit fullNewUnit; 3490 CompilationUnit fullNewUnit;
3455 { 3491 {
3456 source = addSource(newCode); 3492 source = addSource(newCode);
3457 _runTasks(); 3493 _runTasks();
3458 LibraryElement library = resolve2(source); 3494 LibraryElement library = resolve2(source);
3459 fullNewUnit = resolveCompilationUnit(source, library); 3495 fullNewUnit = resolveCompilationUnit(source, library);
3460 } 3496 }
3497 _checkCacheEntries(cache);
3498
3461 try { 3499 try {
3462 assertSameResolution(unit, fullNewUnit); 3500 assertSameResolution(unit, fullNewUnit);
3463 } on IncrementalResolutionMismatch catch (mismatch) { 3501 } on IncrementalResolutionMismatch catch (mismatch) {
3464 fail(mismatch.message); 3502 fail(mismatch.message);
3465 } 3503 }
3466 // errors 3504 // errors
3467 List<AnalysisError> newFullErrors = 3505 List<AnalysisError> newFullErrors =
3468 analysisContext.getErrors(source).errors; 3506 analysisContext.getErrors(source).errors;
3469 _assertEqualErrors(newErrors, newFullErrors); 3507 _assertEqualErrors(newErrors, newFullErrors);
3470 // prepare for the next cycle 3508 // prepare for the next cycle
3471 code = newCode; 3509 code = newCode;
3472 } 3510 }
3473 3511
3474 void _resolveUnit(String code) { 3512 void _resolveUnit(String code) {
3475 this.code = code; 3513 this.code = code;
3476 source = addSource(code); 3514 source = addSource(code);
3477 library = resolve2(source); 3515 library = resolve2(source);
3478 unit = resolveCompilationUnit(source, library); 3516 unit = resolveCompilationUnit(source, library);
3479 _runTasks(); 3517 _runTasks();
3518 _checkCacheEntries(analysisContext2.analysisCache);
3480 } 3519 }
3481 3520
3482 void _runTasks() { 3521 void _runTasks() {
3483 AnalysisResult result = analysisContext.performAnalysisTask(); 3522 AnalysisResult result = analysisContext.performAnalysisTask();
3484 while (result.changeNotices != null) { 3523 while (result.changeNotices != null) {
3485 result = analysisContext.performAnalysisTask(); 3524 result = analysisContext.performAnalysisTask();
3486 } 3525 }
3487 } 3526 }
3488 3527
3489 static AstNode _findNodeAt( 3528 static AstNode _findNodeAt(
(...skipping 1370 matching lines...) Expand 10 before | Expand all | Expand 10 after
4860 // Validate that "incremental" and "full" units have the same resolution. 4899 // Validate that "incremental" and "full" units have the same resolution.
4861 try { 4900 try {
4862 assertSameResolution(newUnit, fullNewUnit, validateTypes: true); 4901 assertSameResolution(newUnit, fullNewUnit, validateTypes: true);
4863 } on IncrementalResolutionMismatch catch (mismatch) { 4902 } on IncrementalResolutionMismatch catch (mismatch) {
4864 fail(mismatch.message); 4903 fail(mismatch.message);
4865 } 4904 }
4866 List<AnalysisError> newFullErrors = 4905 List<AnalysisError> newFullErrors =
4867 analysisContext.getErrors(source).errors; 4906 analysisContext.getErrors(source).errors;
4868 _assertEqualErrors(newErrors, newFullErrors); 4907 _assertEqualErrors(newErrors, newFullErrors);
4869 } 4908 }
4909 _checkCacheEntries(analysisContext2.analysisCache);
4870 } 4910 }
4871 4911
4872 static void _assertEqualToken(Token incrToken, Token fullToken) { 4912 static void _assertEqualToken(Token incrToken, Token fullToken) {
4873 // print('[${incrToken.offset}] |$incrToken| vs. [${fullToken.offset}] |$full Token|'); 4913 // print('[${incrToken.offset}] |$incrToken| vs. [${fullToken.offset}] |$full Token|');
4874 expect(incrToken.type, fullToken.type); 4914 expect(incrToken.type, fullToken.type);
4875 expect(incrToken.offset, fullToken.offset); 4915 expect(incrToken.offset, fullToken.offset);
4876 expect(incrToken.length, fullToken.length); 4916 expect(incrToken.length, fullToken.length);
4877 expect(incrToken.lexeme, fullToken.lexeme); 4917 expect(incrToken.lexeme, fullToken.lexeme);
4878 } 4918 }
4879 4919
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after
5136 @override 5176 @override
5137 void logException(Object exception, [Object stackTrace]) { 5177 void logException(Object exception, [Object stackTrace]) {
5138 hasError = true; 5178 hasError = true;
5139 } 5179 }
5140 5180
5141 @override 5181 @override
5142 logging.LoggingTimer startTimer() { 5182 logging.LoggingTimer startTimer() {
5143 return new logging.LoggingTimer(this); 5183 return new logging.LoggingTimer(this);
5144 } 5184 }
5145 } 5185 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/generated/incremental_resolver.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698