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

Side by Side Diff: lib/src/checker/resolver.dart

Issue 1028793002: Transitive inference using SCC (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: transitive inference on Created 5 years, 9 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
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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 /// Encapsulates how to invoke the analyzer resolver and overrides how it 5 /// Encapsulates how to invoke the analyzer resolver and overrides how it
6 /// computes types on expressions to use our restricted set of types. 6 /// computes types on expressions to use our restricted set of types.
7 library dev_compiler.src.checker.resolver; 7 library dev_compiler.src.checker.resolver;
8 8
9 import 'package:analyzer/analyzer.dart'; 9 import 'package:analyzer/analyzer.dart';
10 import 'package:analyzer/src/generated/ast.dart'; 10 import 'package:analyzer/src/generated/ast.dart';
11 import 'package:analyzer/src/generated/element.dart'; 11 import 'package:analyzer/src/generated/element.dart';
12 import 'package:analyzer/src/generated/engine.dart'; 12 import 'package:analyzer/src/generated/engine.dart';
13 import 'package:analyzer/src/generated/error.dart' as analyzer; 13 import 'package:analyzer/src/generated/error.dart' as analyzer;
14 import 'package:analyzer/src/generated/java_io.dart' show JavaFile; 14 import 'package:analyzer/src/generated/java_io.dart' show JavaFile;
15 import 'package:analyzer/src/generated/resolver.dart'; 15 import 'package:analyzer/src/generated/resolver.dart';
16 import 'package:analyzer/src/generated/sdk_io.dart' show DirectoryBasedDartSdk; 16 import 'package:analyzer/src/generated/sdk_io.dart' show DirectoryBasedDartSdk;
17 import 'package:analyzer/src/generated/source.dart' show DartUriResolver; 17 import 'package:analyzer/src/generated/source.dart' show DartUriResolver;
18 import 'package:analyzer/src/generated/source.dart' show Source; 18 import 'package:analyzer/src/generated/source.dart' show Source;
19 import 'package:analyzer/src/generated/source_io.dart'; 19 import 'package:analyzer/src/generated/source_io.dart';
20 import 'package:analyzer/src/generated/static_type_analyzer.dart'; 20 import 'package:analyzer/src/generated/static_type_analyzer.dart';
21 import 'package:analyzer/src/generated/utilities_collection.dart'
22 show DirectedGraph;
21 import 'package:logging/logging.dart' as logger; 23 import 'package:logging/logging.dart' as logger;
22 24
23 import 'package:dev_compiler/src/options.dart'; 25 import 'package:dev_compiler/src/options.dart';
24 import 'package:dev_compiler/src/report.dart'; 26 import 'package:dev_compiler/src/report.dart';
25 import 'package:dev_compiler/src/utils.dart'; 27 import 'package:dev_compiler/src/utils.dart';
26 import 'dart_sdk.dart'; 28 import 'dart_sdk.dart';
27 import 'multi_package_resolver.dart'; 29 import 'multi_package_resolver.dart';
28 30
29 final _log = new logger.Logger('dev_compiler.src.resolver'); 31 final _log = new logger.Logger('dev_compiler.src.resolver');
30 32
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
82 if (message.level == logger.Level.SEVERE) failure = true; 84 if (message.level == logger.Level.SEVERE) failure = true;
83 reporter.log(message); 85 reporter.log(message);
84 } 86 }
85 } 87 }
86 return failure; 88 return failure;
87 } 89 }
88 } 90 }
89 91
90 class AnalyzerError extends Message { 92 class AnalyzerError extends Message {
91 factory AnalyzerError.from(analyzer.AnalysisError error) { 93 factory AnalyzerError.from(analyzer.AnalysisError error) {
92 var severity = error.errorCode.errorSeverity; 94 var severity = error.errorCode.type.severity;
93 var isError = severity == analyzer.ErrorSeverity.ERROR; 95 var isError = severity == analyzer.ErrorSeverity.ERROR;
94 var level = isError ? logger.Level.SEVERE : logger.Level.WARNING; 96 var level = isError ? logger.Level.SEVERE : logger.Level.WARNING;
95 int begin = error.offset; 97 int begin = error.offset;
96 int end = begin + error.length; 98 int end = begin + error.length;
97 return new AnalyzerError(error.message, level, begin, end); 99 return new AnalyzerError(error.message, level, begin, end);
98 } 100 }
99 101
100 const AnalyzerError(String message, logger.Level level, int begin, int end) 102 const AnalyzerError(String message, logger.Level level, int begin, int end)
101 : super('[from analyzer]: $message', level, begin, end); 103 : super('[from analyzer]: $message', level, begin, end);
102 } 104 }
(...skipping 15 matching lines...) Expand all
118 final ResolverOptions _options; 120 final ResolverOptions _options;
119 121
120 LibraryResolverWithInference(context, this._options) : super(context); 122 LibraryResolverWithInference(context, this._options) : super(context);
121 123
122 @override 124 @override
123 void resolveReferencesAndTypes() { 125 void resolveReferencesAndTypes() {
124 _resolveVariableReferences(); 126 _resolveVariableReferences();
125 127
126 // Run resolution in two stages, skipping method bodies first, so we can run 128 // Run resolution in two stages, skipping method bodies first, so we can run
127 // type-inference before we fully analyze methods. 129 // type-inference before we fully analyze methods.
128 _resolveReferencesAndTypes(true); 130 var visitors = _createVisitors();
129 _runInference(); 131 _resolveEverything(visitors);
130 _resolveReferencesAndTypes(false); 132 _runInference(visitors);
133
134 visitors.values.forEach((v) => v.skipMethodBodies = false);
135 _resolveEverything(visitors);
131 } 136 }
132 137
133 // Note: this was split from _resolveReferencesAndTypesInLibrary so we do it 138 // Note: this was split from _resolveReferencesAndTypesInLibrary so we do it
134 // only once. 139 // only once.
135 void _resolveVariableReferences() { 140 void _resolveVariableReferences() {
136 for (Library library in resolvedLibraries) { 141 for (Library library in resolvedLibraries) {
137 for (Source source in library.compilationUnitSources) { 142 for (Source source in library.compilationUnitSources) {
138 library.getAST(source).accept( 143 library.getAST(source).accept(
139 new VariableResolverVisitor.con1(library, source, typeProvider)); 144 new VariableResolverVisitor.con1(library, source, typeProvider));
140 } 145 }
141 } 146 }
142 } 147 }
143 148
144 // Note: this was split from _resolveReferencesAndTypesInLibrary so we can do 149 // Note: this was split from _resolveReferencesAndTypesInLibrary so we can do
145 // resolution in pieces. 150 // resolution in pieces.
146 void _resolveReferencesAndTypes(bool skipMethods) { 151 Map<Source, RestrictedResolverVisitor> _createVisitors() {
152 var visitors = <Source, RestrictedResolverVisitor>{};
147 for (Library library in resolvedLibraries) { 153 for (Library library in resolvedLibraries) {
148 for (Source source in library.compilationUnitSources) { 154 for (Source source in library.compilationUnitSources) {
149 library.getAST(source).accept(new RestrictedResolverVisitor( 155 var visitor = new RestrictedResolverVisitor(
150 library, source, typeProvider, _options, skipMethods)); 156 library, source, typeProvider, _options);
157 visitors[source] = visitor;
158 }
159 }
160 return visitors;
161 }
162
163 /// Runs the resolver on the entire library cycle.
164 void _resolveEverything(Map<Source, RestrictedResolverVisitor> visitors) {
165 for (Library library in resolvedLibraries) {
166 for (Source source in library.compilationUnitSources) {
167 library.getAST(source).accept(visitors[source]);
151 } 168 }
152 } 169 }
153 } 170 }
154 171
155 _runInference() { 172 _runInference(Map<Source, RestrictedResolverVisitor> visitors) {
156 var consts = []; 173 var globals = <VariableDeclaration>[];
vsm 2015/03/21 15:52:19 nit: maybe globals -> globalsAndStatics?
Siggi Cherem (dart-lang) 2015/03/23 20:06:31 oh funny, when I was writing this I was thinking t
157 var statics = []; 174 var classes = <ClassDeclaration>[];
158 var classes = [];
159 175
160 // Extract top-level members that are const, statics, or classes. 176 // Extract top-level members that are const, statics, or classes.
161 for (Library library in resolvedLibraries) { 177 for (Library library in resolvedLibraries) {
162 for (Source source in library.compilationUnitSources) { 178 for (Source source in library.compilationUnitSources) {
163 CompilationUnit ast = library.getAST(source); 179 CompilationUnit ast = library.getAST(source);
164 for (var declaration in ast.declarations) { 180 for (var declaration in ast.declarations) {
165 if (declaration is TopLevelVariableDeclaration) { 181 if (declaration is TopLevelVariableDeclaration) {
166 if (declaration.variables.isConst) { 182 globals.addAll(declaration.variables.variables);
167 consts.addAll(declaration.variables.variables);
168 } else {
169 statics.addAll(declaration.variables.variables);
170 }
171 } else if (declaration is ClassDeclaration) { 183 } else if (declaration is ClassDeclaration) {
172 classes.add(declaration); 184 classes.add(declaration);
173 for (var member in declaration.members) { 185 for (var member in declaration.members) {
174 if (member is! FieldDeclaration) continue; 186 if (member is FieldDeclaration &&
175 if (member.fields.isConst) { 187 (member.fields.isConst || member.isStatic)) {
176 consts.addAll(member.fields.variables); 188 globals.addAll(member.fields.variables);
177 } else if (member.isStatic) {
178 statics.addAll(member.fields.variables);
179 } 189 }
180 } 190 }
181 } 191 }
182 } 192 }
183 } 193 }
184 } 194 }
195 _inferGlobalsAndStatics(globals, visitors);
196 _inferInstanceFields(classes, visitors);
197 }
185 198
186 // TODO(sigmund): consider propagating const types after this layer of 199 _inferGlobalsAndStatics(List<VariableDeclaration> globals,
187 // inference, so their types can be used to initialize other members below. 200 Map<Source, RestrictedResolverVisitor> visitors) {
188 _inferVariableFromInitializer(consts); 201 var elementToDeclaration = {};
189 _inferVariableFromInitializer(statics); 202 for (var c in globals) {
203 elementToDeclaration[c.element] = c;
204 }
205 var constGraph = new DirectedGraph<VariableDeclaration>();
206 globals.forEach(constGraph.addNode);
207 for (var c in globals) {
208 for (var e in _VarExtractor.extract(c.initializer)) {
209 // Note: declaration is null for variables that come from other strongly
210 // connected components.
211 var declaration = elementToDeclaration[e];
212 if (declaration != null) constGraph.addEdge(c, declaration);
213 }
214 }
215
216 for (var component in constGraph.computeTopologicalSort()) {
217 if (_options.inferTransitively) {
218 component.forEach((v) => _reanalizeVar(visitors, v));
219 }
220 _inferVariableFromInitializer(component);
221 }
222 }
223
224 _inferInstanceFields(List<ClassDeclaration> classes,
225 Map<Source, RestrictedResolverVisitor> visitors) {
226 // First propagate what was inferred from globals to all instance fields.
227 if (_options.inferTransitively) {
228 // TODO(sigmund): also do a fine-grain propagation between fields. We want
229 // infer-by-override to take precedence, so we would have to include
230 // classes in the dependency graph and ensure that fields depend on their
231 // class, and classes depend on superclasses.
232 classes
233 .expand((c) => c.members.where(_isInstanceField))
234 .expand((f) => f.fields.variables)
235 .forEach((v) => _reanalizeVar(visitors, v));
236 }
190 237
191 // Track types in this strongly connected component, ensure we visit 238 // Track types in this strongly connected component, ensure we visit
192 // supertypes before subtypes. 239 // supertypes before subtypes.
193 var typeToDeclaration = <InterfaceType, ClassDeclaration>{}; 240 var typeToDeclaration = <InterfaceType, ClassDeclaration>{};
194 classes.forEach((c) => typeToDeclaration[c.element.type] = c); 241 classes.forEach((c) => typeToDeclaration[c.element.type] = c);
195 var seen = new Set<InterfaceType>(); 242 var seen = new Set<InterfaceType>();
196 visit(ClassDeclaration cls) { 243 visit(ClassDeclaration cls) {
197 var element = cls.element; 244 var element = cls.element;
198 var type = element.type; 245 var type = element.type;
199 if (seen.contains(type)) return; 246 if (seen.contains(type)) return;
200 for (var supertype in element.allSupertypes) { 247 for (var supertype in element.allSupertypes) {
201 var supertypeClass = typeToDeclaration[supertype]; 248 var supertypeClass = typeToDeclaration[supertype];
202 if (supertypeClass != null) visit(supertypeClass); 249 if (supertypeClass != null) visit(supertypeClass);
203 } 250 }
204 seen.add(type); 251 seen.add(type);
205 252
206 _isInstanceField(f) =>
207 f is FieldDeclaration && !f.isStatic && !f.fields.isConst;
208
209 if (_options.inferFromOverrides) { 253 if (_options.inferFromOverrides) {
210 // Infer field types from overrides first, otherwise from initializers. 254 // Infer field types from overrides first, otherwise from initializers.
211 var pending = new Set<VariableDeclaration>(); 255 var pending = new Set<VariableDeclaration>();
212 cls.members 256 cls.members
213 .where(_isInstanceField) 257 .where(_isInstanceField)
214 .forEach((f) => _inferFieldTypeFromOverride(f, pending)); 258 .forEach((f) => _inferFieldTypeFromOverride(f, pending));
215 if (pending.isNotEmpty) _inferVariableFromInitializer(pending); 259 if (pending.isNotEmpty) _inferVariableFromInitializer(pending);
216 260
217 // Infer return-types from overrides 261 // Infer return-types from overrides
218 cls.members 262 cls.members
219 .where((m) => m is MethodDeclaration && !m.isStatic) 263 .where((m) => m is MethodDeclaration && !m.isStatic)
220 .forEach(_inferMethodReturnTypeFromOverride); 264 .forEach(_inferMethodReturnTypeFromOverride);
221 } else { 265 } else {
222 _inferVariableFromInitializer(cls.members 266 _inferVariableFromInitializer(cls.members
223 .where(_isInstanceField) 267 .where(_isInstanceField)
224 .expand((f) => f.fields.variables)); 268 .expand((f) => f.fields.variables));
225 } 269 }
226 } 270 }
227 classes.forEach(visit); 271 classes.forEach(visit);
228 } 272 }
229 273
274 void _reanalizeVar(Map<Source, RestrictedResolverVisitor> visitors,
vsm 2015/03/21 15:52:19 _reanalize -> _reanalyze
Siggi Cherem (dart-lang) 2015/03/23 20:06:31 Done.
275 VariableDeclaration variable) {
276 if (variable.initializer == null) return;
277 var visitor = visitors[(variable.root as CompilationUnit).element.source];
278 visitor.reanalyzeInitializer(variable);
279 }
280
281 static bool _isInstanceField(f) =>
282 f is FieldDeclaration && !f.isStatic && !f.fields.isConst;
283
230 /// Attempts to infer the type on [field] from overridden fields or getters if 284 /// Attempts to infer the type on [field] from overridden fields or getters if
231 /// a type was not specified. If no type could be inferred, but it contains an 285 /// a type was not specified. If no type could be inferred, but it contains an
232 /// initializer, we add it to [pending] so we can try to infer it using the 286 /// initializer, we add it to [pending] so we can try to infer it using the
233 /// initializer type instead. 287 /// initializer type instead.
234 void _inferFieldTypeFromOverride( 288 void _inferFieldTypeFromOverride(
235 FieldDeclaration field, Set<VariableDeclaration> pending) { 289 FieldDeclaration field, Set<VariableDeclaration> pending) {
236 var variables = field.fields; 290 var variables = field.fields;
237 for (var variable in variables.variables) { 291 for (var variable in variables.variables) {
238 var varElement = variable.element; 292 var varElement = variable.element;
239 if (!varElement.type.isDynamic || variables.type != null) continue; 293 if (!varElement.type.isDynamic || variables.type != null) continue;
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
302 // ResolverVisitor. 356 // ResolverVisitor.
303 element.type = type; 357 element.type = type;
304 element.getter.returnType = type; 358 element.getter.returnType = type;
305 if (!element.isFinal && !element.isConst) { 359 if (!element.isFinal && !element.isConst) {
306 element.setter.parameters[0].type = type; 360 element.setter.parameters[0].type = type;
307 } 361 }
308 } 362 }
309 } 363 }
310 364
311 bool _canInferFrom(Expression expression) { 365 bool _canInferFrom(Expression expression) {
366 if (_options.inferTransitively) return true;
312 if (expression is Literal) return true; 367 if (expression is Literal) return true;
313 if (expression is InstanceCreationExpression) return true; 368 if (expression is InstanceCreationExpression) return true;
314 if (expression is FunctionExpression) return true; 369 if (expression is FunctionExpression) return true;
315 if (expression is AsExpression) return true; 370 if (expression is AsExpression) return true;
316 if (expression is CascadeExpression) { 371 if (expression is CascadeExpression) {
317 return _canInferFrom(expression.target); 372 return _canInferFrom(expression.target);
318 } 373 }
319 if (expression is SimpleIdentifier || expression is PropertyAccess) { 374 if (expression is SimpleIdentifier || expression is PropertyAccess) {
320 return _options.inferTransitively; 375 return false;
321 } 376 }
322 if (expression is PrefixedIdentifier) { 377 if (expression is PrefixedIdentifier) {
323 if (expression.staticElement is PropertyAccessorElement) { 378 if (expression.staticElement is PropertyAccessorElement) {
324 return _options.inferTransitively; 379 return false;
325 } 380 }
326 return _canInferFrom(expression.identifier); 381 return _canInferFrom(expression.identifier);
327 } 382 }
328 if (expression is MethodInvocation) { 383 if (expression is MethodInvocation) {
329 return _canInferFrom(expression.target); 384 return _canInferFrom(expression.target);
330 } 385 }
331 if (expression is BinaryExpression) { 386 if (expression is BinaryExpression) {
332 return _canInferFrom(expression.leftOperand); 387 return _canInferFrom(expression.leftOperand);
333 } 388 }
334 if (expression is ConditionalExpression) { 389 if (expression is ConditionalExpression) {
335 return _canInferFrom(expression.thenExpression) && 390 return _canInferFrom(expression.thenExpression) &&
336 _canInferFrom(expression.elseExpression); 391 _canInferFrom(expression.elseExpression);
337 } 392 }
338 if (expression is PrefixExpression) { 393 if (expression is PrefixExpression) {
339 return _canInferFrom(expression.operand); 394 return _canInferFrom(expression.operand);
340 } 395 }
341 if (expression is PostfixExpression) { 396 if (expression is PostfixExpression) {
342 return _canInferFrom(expression.operand); 397 return _canInferFrom(expression.operand);
343 } 398 }
344 return false; 399 return false;
345 } 400 }
346 } 401 }
347 402
403 /// Extracts the [VariableElement]s used in an initializer expression.
404 class _VarExtractor extends RecursiveAstVisitor {
405 final elements = <VariableElement>[];
406 visitSimpleIdentifier(SimpleIdentifier node) {
407 var e = node.staticElement;
408 if (e is PropertyAccessorElement) elements.add(e.variable);
409 }
410
411 static List<VariableElement> extract(Expression initializer) {
412 if (initializer == null) return const [];
413 var extractor = new _VarExtractor();
414 initializer.accept(extractor);
415 return extractor.elements;
416 }
417 }
418
348 /// Overrides the default [ResolverVisitor] to support type inference in 419 /// Overrides the default [ResolverVisitor] to support type inference in
349 /// [LibraryResolverWithInference] above. 420 /// [LibraryResolverWithInference] above.
350 /// 421 ///
351 /// Before inference, this visitor is used to resolve top-levels, classes, and 422 /// Before inference, this visitor is used to resolve top-levels, classes, and
352 /// fields, but nothing withihn method bodies. After inference, this visitor is 423 /// fields, but nothing withihn method bodies. After inference, this visitor is
353 /// used again to step into method bodies and complete resolution as a second 424 /// used again to step into method bodies and complete resolution as a second
354 /// phase. 425 /// phase.
355 class RestrictedResolverVisitor extends ResolverVisitor { 426 class RestrictedResolverVisitor extends ResolverVisitor {
356 final TypeProvider _typeProvider; 427 final TypeProvider _typeProvider;
357 428
358 /// Whether to skip resolution within method bodies. 429 /// Whether to skip resolution within method bodies.
359 final bool skipMethodBodies; 430 bool skipMethodBodies = true;
431
432 /// State of the resolver at the point a field or variable was declared.
433 final _stateAtDeclaration = <AstNode, _ResolverState>{};
434
435 /// Internal tracking of whether a node was skipped while visiting, for
436 /// example, if it contained a function expression with a function body.
437 bool _nodeWasSkipped = false;
438
439 /// Internal state, whether we are revisiting an initializer, so we minimize
440 /// the work being done elsewhere.
441 bool _revisiting = false;
442
443 /// Initializers that have been visited, reanalyzed, and for which no node was
444 /// internally skipped. These initializers are fully resolved and don't need
445 /// to be re-resolved on a sunsequent pass.
446 final _visitedInitializers = new Set<VariableDeclaration>();
360 447
361 RestrictedResolverVisitor(Library library, Source source, 448 RestrictedResolverVisitor(Library library, Source source,
362 TypeProvider typeProvider, ResolverOptions options, this.skipMethodBodies) 449 TypeProvider typeProvider, ResolverOptions options)
363 : _typeProvider = typeProvider, 450 : _typeProvider = typeProvider,
364 super.con1(library, source, typeProvider, 451 super.con1(library, source, typeProvider,
365 typeAnalyzerFactory: RestrictedStaticTypeAnalyzer.constructor); 452 typeAnalyzerFactory: RestrictedStaticTypeAnalyzer.constructor);
366 453
367 @override 454 @override
368 visitCatchClause(CatchClause node) { 455 visitCatchClause(CatchClause node) {
369 var stack = node.stackTraceParameter; 456 var stack = node.stackTraceParameter;
370 if (stack != null) { 457 if (stack != null) {
371 // TODO(jmesserly): analyzer does not correctly associate StackTrace type. 458 // TODO(jmesserly): analyzer does not correctly associate StackTrace type.
372 // It happens too late in TypeResolverVisitor visitCatchClause. 459 // It happens too late in TypeResolverVisitor visitCatchClause.
373 var element = stack.staticElement; 460 var element = stack.staticElement;
374 if (element is VariableElementImpl && element.type == null) { 461 if (element is VariableElementImpl && element.type == null) {
375 // From the language spec: 462 // From the language spec:
376 // The static type of p1 is T and the static type of p2 is StackTrace. 463 // The static type of p1 is T and the static type of p2 is StackTrace.
377 element.type = _typeProvider.stackTraceType; 464 element.type = _typeProvider.stackTraceType;
378 } 465 }
379 } 466 }
380 return super.visitCatchClause(node); 467 return super.visitCatchClause(node);
381 } 468 }
382 469
470 reanalyzeInitializer(VariableDeclaration variable) {
471 try {
472 _revisiting = true;
473 _nodeWasSkipped = false;
474 var node = variable.parent.parent;
475 var oldState;
476 var state = _stateAtDeclaration[node];
477 if (state != null) {
478 oldState = new _ResolverState(this);
479 state.restore(this);
480 if (node is FieldDeclaration) {
481 var cls = node.parent;
482 enclosingClass = cls.element;
483 }
484 }
485 visitNode(variable.initializer);
486 if (!_nodeWasSkipped) _visitedInitializers.add(variable);
487 if (oldState != null) oldState.restore(this);
488 } finally {
489 _revisiting = false;
490 }
491 }
492
493 @override
494 Object visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
495 _stateAtDeclaration[node] = new _ResolverState(this);
496 return super.visitTopLevelVariableDeclaration(node);
497 }
498
499 @override
500 Object visitFieldDeclaration(FieldDeclaration node) {
501 _stateAtDeclaration[node] = new _ResolverState(this);
502 return super.visitFieldDeclaration(node);
503 }
504
505 Object visitVariableDeclaration(VariableDeclaration node) {
506 var state = new _ResolverState(this);
507 try {
508 if (_revisiting) {
509 _stateAtDeclaration[node].restore(this);
510 } else {
511 _stateAtDeclaration[node] = state;
512 }
513 return super.visitVariableDeclaration(node);
514 } finally {
515 state.restore(this);
516 }
517 }
518
383 @override 519 @override
384 Object visitNode(AstNode node) { 520 Object visitNode(AstNode node) {
385 if (skipMethodBodies && 521 if (skipMethodBodies && node is FunctionBody) {
386 (node is FunctionBody || 522 _nodeWasSkipped = true;
387 node is FunctionExpression ||
388 node is FunctionExpressionInvocation ||
389 node is SuperConstructorInvocation ||
390 node is RedirectingConstructorInvocation ||
391 node is Annotation ||
392 node is Comment)) {
393 return null; 523 return null;
394 } 524 }
525 if (_visitedInitializers.contains(node)) return null;
395 assert(node is! Statement || !skipMethodBodies); 526 assert(node is! Statement || !skipMethodBodies);
396 return super.visitNode(node); 527 return super.visitNode(node);
397 } 528 }
398 529
399 @override 530 @override
400 Object visitMethodDeclaration(MethodDeclaration node) { 531 Object visitMethodDeclaration(MethodDeclaration node) {
401 if (skipMethodBodies) { 532 if (skipMethodBodies) {
402 node.accept(elementResolver_J2DAccessor); 533 node.accept(elementResolver_J2DAccessor);
403 node.accept(typeAnalyzer_J2DAccessor); 534 node.accept(typeAnalyzer_J2DAccessor);
404 return null; 535 return null;
(...skipping 18 matching lines...) Expand all
423 if (skipMethodBodies) { 554 if (skipMethodBodies) {
424 node.accept(elementResolver_J2DAccessor); 555 node.accept(elementResolver_J2DAccessor);
425 node.accept(typeAnalyzer_J2DAccessor); 556 node.accept(typeAnalyzer_J2DAccessor);
426 return null; 557 return null;
427 } else { 558 } else {
428 return super.visitConstructorDeclaration(node); 559 return super.visitConstructorDeclaration(node);
429 } 560 }
430 } 561 }
431 } 562 }
432 563
564 /// Internal state of the resolver, stored so we can reanalyze portions of the
565 /// AST quickly, without recomputing everything from the top.
566 class _ResolverState {
567 final TypePromotionManager_TypePromoteScope promotionScope;
568 final TypeOverrideManager_TypeOverrideScope overrideScope;
569 final Scope nameScope;
570
571 _ResolverState(ResolverVisitor visitor)
572 : promotionScope = visitor.promoteManager.currentScope,
573 overrideScope = visitor.overrideManager.currentScope,
574 nameScope = visitor.nameScope;
575
576 void restore(ResolverVisitor visitor) {
577 visitor.promoteManager.currentScope = promotionScope;
578 visitor.overrideManager.currentScope = overrideScope;
579 visitor.nameScope_J2DAccessor = nameScope;
580 }
581 }
582
433 /// Overrides the default [StaticTypeAnalyzer] to adjust rules that are stricter 583 /// Overrides the default [StaticTypeAnalyzer] to adjust rules that are stricter
434 /// in the restricted type system and to infer types for untyped local 584 /// in the restricted type system and to infer types for untyped local
435 /// variables. 585 /// variables.
436 class RestrictedStaticTypeAnalyzer extends StaticTypeAnalyzer { 586 class RestrictedStaticTypeAnalyzer extends StaticTypeAnalyzer {
437 final TypeProvider _typeProvider; 587 final TypeProvider _typeProvider;
438 588
439 RestrictedStaticTypeAnalyzer(ResolverVisitor r) 589 RestrictedStaticTypeAnalyzer(ResolverVisitor r)
440 : _typeProvider = r.typeProvider, 590 : _typeProvider = r.typeProvider,
441 super(r); 591 super(r);
442 592
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
515 } 665 }
516 } 666 }
517 667
518 // Review note: no longer need to override visitFunctionExpression, this is 668 // Review note: no longer need to override visitFunctionExpression, this is
519 // handled by the analyzer internally. 669 // handled by the analyzer internally.
520 // TODO(vsm): in visitbinaryExpression: check computeStaticReturnType result? 670 // TODO(vsm): in visitbinaryExpression: check computeStaticReturnType result?
521 // TODO(vsm): in visitFunctionDeclaration: Should we ever use the expression 671 // TODO(vsm): in visitFunctionDeclaration: Should we ever use the expression
522 // type in a (...) => expr or just the written type? 672 // type in a (...) => expr or just the written type?
523 673
524 } 674 }
OLDNEW
« no previous file with comments | « lib/runtime/dart/isolate.js ('k') | lib/src/options.dart » ('j') | lib/src/options.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698