| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 globalsAndStatics = <VariableDeclaration>[]; |
| 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 globalsAndStatics.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 globalsAndStatics.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(globalsAndStatics, visitors); |
| 196 _inferInstanceFields(classes, visitors); |
| 197 } |
| 185 | 198 |
| 186 // TODO(sigmund): consider propagating const types after this layer of | 199 _inferGlobalsAndStatics(List<VariableDeclaration> globalsAndStatics, |
| 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 globalsAndStatics) { |
| 203 elementToDeclaration[c.element] = c; |
| 204 } |
| 205 var constGraph = new DirectedGraph<VariableDeclaration>(); |
| 206 globalsAndStatics.forEach(constGraph.addNode); |
| 207 for (var c in globalsAndStatics) { |
| 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) => _reanalyzeVar(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) => _reanalyzeVar(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 _reanalyzeVar(Map<Source, RestrictedResolverVisitor> visitors, |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |