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'; |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 f is FieldDeclaration && !f.isStatic && !f.fields.isConst; | 191 f is FieldDeclaration && !f.isStatic && !f.fields.isConst; |
192 | 192 |
193 /// Attempts to infer the type on [field] from overridden fields or getters if | 193 /// Attempts to infer the type on [field] from overridden fields or getters if |
194 /// a type was not specified. If no type could be inferred, but it contains an | 194 /// a type was not specified. If no type could be inferred, but it contains an |
195 /// initializer, we add it to [pending] so we can try to infer it using the | 195 /// initializer, we add it to [pending] so we can try to infer it using the |
196 /// initializer type instead. | 196 /// initializer type instead. |
197 void _inferFieldTypeFromOverride( | 197 void _inferFieldTypeFromOverride( |
198 FieldDeclaration field, Set<VariableDeclaration> pending) { | 198 FieldDeclaration field, Set<VariableDeclaration> pending) { |
199 var variables = field.fields; | 199 var variables = field.fields; |
200 for (var variable in variables.variables) { | 200 for (var variable in variables.variables) { |
201 var varElement = variable.element; | 201 var varElement = variable.element as FieldElement; |
202 if (!varElement.type.isDynamic || variables.type != null) continue; | 202 if (!varElement.type.isDynamic || variables.type != null) continue; |
203 var getter = varElement.getter; | 203 var getter = varElement.getter; |
204 // Note: type will be null only when there are no overrides. When some | 204 // Note: type will be null only when there are no overrides. When some |
205 // override's type was not specified and couldn't be inferred, the type | 205 // override's type was not specified and couldn't be inferred, the type |
206 // here will be dynamic. | 206 // here will be dynamic. |
207 var type = searchTypeFor(varElement.enclosingElement.type, getter); | 207 var enclosingElement = varElement.enclosingElement; |
| 208 var type = searchTypeFor(enclosingElement.type, getter); |
208 | 209 |
209 // Infer from the RHS when there are no overrides. | 210 // Infer from the RHS when there are no overrides. |
210 if (type == null) { | 211 if (type == null) { |
211 if (variable.initializer != null) pending.add(variable); | 212 if (variable.initializer != null) pending.add(variable); |
212 continue; | 213 continue; |
213 } | 214 } |
214 | 215 |
215 // When field is final and overriden getter is dynamic, we can infer from | 216 // When field is final and overriden getter is dynamic, we can infer from |
216 // the RHS without breaking subtyping rules (return type is covariant). | 217 // the RHS without breaking subtyping rules (return type is covariant). |
217 if (type.returnType.isDynamic) { | 218 if (type.returnType.isDynamic) { |
(...skipping 10 matching lines...) Expand all Loading... |
228 if (!varElement.isFinal) varElement.setter.parameters[0].type = newType; | 229 if (!varElement.isFinal) varElement.setter.parameters[0].type = newType; |
229 } | 230 } |
230 } | 231 } |
231 | 232 |
232 void _inferMethodReturnTypeFromOverride(MethodDeclaration method) { | 233 void _inferMethodReturnTypeFromOverride(MethodDeclaration method) { |
233 var methodElement = method.element; | 234 var methodElement = method.element; |
234 if ((methodElement is MethodElement || | 235 if ((methodElement is MethodElement || |
235 methodElement is PropertyAccessorElement) && | 236 methodElement is PropertyAccessorElement) && |
236 methodElement.returnType.isDynamic && | 237 methodElement.returnType.isDynamic && |
237 method.returnType == null) { | 238 method.returnType == null) { |
238 var type = | 239 var enclosingElement = methodElement.enclosingElement as ClassElement; |
239 searchTypeFor(methodElement.enclosingElement.type, methodElement); | 240 var type = searchTypeFor(enclosingElement.type, methodElement); |
240 if (type != null && !type.returnType.isDynamic) { | 241 if (type != null && !type.returnType.isDynamic) { |
241 methodElement.returnType = type.returnType; | 242 methodElement.returnType = type.returnType; |
242 } | 243 } |
243 } | 244 } |
244 } | 245 } |
245 | 246 |
246 void _inferVariableFromInitializer(Iterable<VariableDeclaration> variables) { | 247 void _inferVariableFromInitializer(Iterable<VariableDeclaration> variables) { |
247 for (var variable in variables) { | 248 for (var variable in variables) { |
248 var declaration = variable.parent; | 249 var declaration = variable.parent as VariableDeclarationList; |
249 // Only infer on variables that don't have any declared type. | 250 // Only infer on variables that don't have any declared type. |
250 if (declaration.type != null) continue; | 251 if (declaration.type != null) continue; |
251 if (_options.onlyInferConstsAndFinalFields && | 252 if (_options.onlyInferConstsAndFinalFields && |
252 !declaration.isFinal && | 253 !declaration.isFinal && |
253 !declaration.isConst) { | 254 !declaration.isConst) { |
254 return; | 255 return; |
255 } | 256 } |
256 var initializer = variable.initializer; | 257 var initializer = variable.initializer; |
257 if (initializer == null) continue; | 258 if (initializer == null) continue; |
258 var type = initializer.staticType; | 259 var type = initializer.staticType; |
259 if (type == null || type.isDynamic || type.isBottom) continue; | 260 if (type == null || type.isDynamic || type.isBottom) continue; |
260 if (!_canInferFrom(initializer)) continue; | 261 if (!_canInferFrom(initializer)) continue; |
261 var element = variable.element; | 262 var element = variable.element as PropertyInducingElement; |
262 // Note: it's ok to update the type here, since initializer.staticType | 263 // Note: it's ok to update the type here, since initializer.staticType |
263 // is already computed for all declarations in the library cycle. The | 264 // is already computed for all declarations in the library cycle. The |
264 // new types will only be propagated on a second run of the | 265 // new types will only be propagated on a second run of the |
265 // ResolverVisitor. | 266 // ResolverVisitor. |
266 element.type = type; | 267 element.type = type; |
267 element.getter.returnType = type; | 268 element.getter.returnType = type; |
268 if (!element.isFinal && !element.isConst) { | 269 if (!element.isFinal && !element.isConst) { |
269 element.setter.parameters[0].type = type; | 270 element.setter.parameters[0].type = type; |
270 } | 271 } |
271 } | 272 } |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
364 try { | 365 try { |
365 _revisiting = true; | 366 _revisiting = true; |
366 _nodeWasSkipped = false; | 367 _nodeWasSkipped = false; |
367 var node = variable.parent.parent; | 368 var node = variable.parent.parent; |
368 var oldState; | 369 var oldState; |
369 var state = _stateAtDeclaration[node]; | 370 var state = _stateAtDeclaration[node]; |
370 if (state != null) { | 371 if (state != null) { |
371 oldState = new _ResolverState(this); | 372 oldState = new _ResolverState(this); |
372 state.restore(this); | 373 state.restore(this); |
373 if (node is FieldDeclaration) { | 374 if (node is FieldDeclaration) { |
374 var cls = node.parent; | 375 var cls = node.parent as ClassDeclaration; |
375 enclosingClass = cls.element; | 376 enclosingClass = cls.element; |
376 } | 377 } |
377 } | 378 } |
378 visitNode(variable.initializer); | 379 visitNode(variable.initializer); |
379 if (!_nodeWasSkipped) _visitedInitializers.add(variable); | 380 if (!_nodeWasSkipped) _visitedInitializers.add(variable); |
380 if (oldState != null) oldState.restore(this); | 381 if (oldState != null) oldState.restore(this); |
381 } finally { | 382 } finally { |
382 _revisiting = false; | 383 _revisiting = false; |
383 } | 384 } |
384 } | 385 } |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
540 } | 541 } |
541 | 542 |
542 return null; | 543 return null; |
543 } | 544 } |
544 | 545 |
545 @override | 546 @override |
546 visitDeclaredIdentifier(DeclaredIdentifier node) { | 547 visitDeclaredIdentifier(DeclaredIdentifier node) { |
547 super.visitDeclaredIdentifier(node); | 548 super.visitDeclaredIdentifier(node); |
548 if (node.type != null) return; | 549 if (node.type != null) return; |
549 | 550 |
550 var parent = node.parent; | 551 var parent = node.parent as ForEachStatement; |
551 assert(parent is ForEachStatement); | |
552 var expr = parent.iterable; | 552 var expr = parent.iterable; |
553 var element = node.element as LocalVariableElementImpl; | 553 var element = node.element as LocalVariableElementImpl; |
554 var exprType = expr.staticType; | 554 var exprType = expr.staticType; |
555 if (exprType is InterfaceType) { | 555 if (exprType is InterfaceType) { |
556 var iteratedType = _findIteratedType(exprType); | 556 var iteratedType = _findIteratedType(exprType); |
557 if (iteratedType != null) { | 557 if (iteratedType != null) { |
558 element.type = iteratedType; | 558 element.type = iteratedType; |
559 } | 559 } |
560 } | 560 } |
561 } | 561 } |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
599 e.library.name == '_foreign_helper' && | 599 e.library.name == '_foreign_helper' && |
600 e.name == 'JS') { | 600 e.name == 'JS') { |
601 // Fix types for JS builtin calls. | 601 // Fix types for JS builtin calls. |
602 // | 602 // |
603 // This code was taken from analyzer. It's not super sophisticated: | 603 // This code was taken from analyzer. It's not super sophisticated: |
604 // only looks for the type name in dart:core, so we just copy it here. | 604 // only looks for the type name in dart:core, so we just copy it here. |
605 // | 605 // |
606 // TODO(jmesserly): we'll likely need something that can handle a wider | 606 // TODO(jmesserly): we'll likely need something that can handle a wider |
607 // variety of types, especially when we get to JS interop. | 607 // variety of types, especially when we get to JS interop. |
608 var args = node.argumentList.arguments; | 608 var args = node.argumentList.arguments; |
609 if (args.isNotEmpty && args.first is SimpleStringLiteral) { | 609 var first = args.isNotEmpty ? args.first : null; |
| 610 if (first is SimpleStringLiteral) { |
610 var coreLib = _typeProvider.objectType.element.library; | 611 var coreLib = _typeProvider.objectType.element.library; |
611 var classElem = coreLib.getType(args.first.stringValue); | 612 var classElem = coreLib.getType(first.stringValue); |
612 if (classElem != null) node.staticType = classElem.type; | 613 if (classElem != null) node.staticType = classElem.type; |
613 } | 614 } |
614 } | 615 } |
615 } | 616 } |
616 | 617 |
617 void _inferObjectAccess( | 618 void _inferObjectAccess( |
618 Expression node, Expression target, SimpleIdentifier id) { | 619 Expression node, Expression target, SimpleIdentifier id) { |
619 // Search for Object accesses. | 620 // Search for Object accesses. |
620 var name = id.name; | 621 var name = id.name; |
621 if (node.staticType.isDynamic && | 622 if (node.staticType.isDynamic && |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
665 } | 666 } |
666 } | 667 } |
667 | 668 |
668 // Review note: no longer need to override visitFunctionExpression, this is | 669 // Review note: no longer need to override visitFunctionExpression, this is |
669 // handled by the analyzer internally. | 670 // handled by the analyzer internally. |
670 // TODO(vsm): in visitbinaryExpression: check computeStaticReturnType result? | 671 // TODO(vsm): in visitbinaryExpression: check computeStaticReturnType result? |
671 // TODO(vsm): in visitFunctionDeclaration: Should we ever use the expression | 672 // TODO(vsm): in visitFunctionDeclaration: Should we ever use the expression |
672 // type in a (...) => expr or just the written type? | 673 // type in a (...) => expr or just the written type? |
673 | 674 |
674 } | 675 } |
OLD | NEW |