| 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 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 161 } | 161 } |
| 162 | 162 |
| 163 if (_options.inferFromOverrides) { | 163 if (_options.inferFromOverrides) { |
| 164 // Infer field types from overrides first, otherwise from initializers. | 164 // Infer field types from overrides first, otherwise from initializers. |
| 165 var pending = new Set<VariableDeclaration>(); | 165 var pending = new Set<VariableDeclaration>(); |
| 166 cls.members | 166 cls.members |
| 167 .where(_isInstanceField) | 167 .where(_isInstanceField) |
| 168 .forEach((f) => _inferFieldTypeFromOverride(f, pending)); | 168 .forEach((f) => _inferFieldTypeFromOverride(f, pending)); |
| 169 if (pending.isNotEmpty) _inferVariableFromInitializer(pending); | 169 if (pending.isNotEmpty) _inferVariableFromInitializer(pending); |
| 170 | 170 |
| 171 // Infer return-types from overrides | 171 // Infer return-types and param-types from overrides |
| 172 cls.members | 172 cls.members |
| 173 .where((m) => m is MethodDeclaration && !m.isStatic) | 173 .where((m) => m is MethodDeclaration && !m.isStatic) |
| 174 .forEach(_inferMethodReturnTypeFromOverride); | 174 .forEach(_inferMethodTypesFromOverride); |
| 175 } else { | 175 } else { |
| 176 _inferVariableFromInitializer(cls.members | 176 _inferVariableFromInitializer(cls.members |
| 177 .where(_isInstanceField) | 177 .where(_isInstanceField) |
| 178 .expand((f) => f.fields.variables)); | 178 .expand((f) => f.fields.variables)); |
| 179 } | 179 } |
| 180 } | 180 } |
| 181 classes.forEach(visit); | 181 classes.forEach(visit); |
| 182 } | 182 } |
| 183 | 183 |
| 184 void _reanalyzeVar(Map<Source, RestrictedResolverVisitor> visitors, | 184 void _reanalyzeVar(Map<Source, RestrictedResolverVisitor> visitors, |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 224 } | 224 } |
| 225 | 225 |
| 226 // Use type from the override. | 226 // Use type from the override. |
| 227 var newType = type.returnType; | 227 var newType = type.returnType; |
| 228 varElement.type = newType; | 228 varElement.type = newType; |
| 229 varElement.getter.returnType = newType; | 229 varElement.getter.returnType = newType; |
| 230 if (!varElement.isFinal) varElement.setter.parameters[0].type = newType; | 230 if (!varElement.isFinal) varElement.setter.parameters[0].type = newType; |
| 231 } | 231 } |
| 232 } | 232 } |
| 233 | 233 |
| 234 void _inferMethodReturnTypeFromOverride(MethodDeclaration method) { | 234 void _inferMethodTypesFromOverride(MethodDeclaration method) { |
| 235 var methodElement = method.element; | 235 var methodElement = method.element; |
| 236 if ((methodElement is MethodElement || | 236 if (methodElement is! MethodElement && |
| 237 methodElement is PropertyAccessorElement) && | 237 methodElement is! PropertyAccessorElement) return; |
| 238 methodElement.returnType.isDynamic && | 238 |
| 239 method.returnType == null) { | 239 var enclosingElement = methodElement.enclosingElement as ClassElement; |
| 240 var enclosingElement = methodElement.enclosingElement as ClassElement; | 240 FunctionType type = null; |
| 241 var type = searchTypeFor(enclosingElement.type, methodElement); | 241 |
| 242 if (type != null && !type.returnType.isDynamic) { | 242 // Infer the return type if omitted |
| 243 if (methodElement.returnType.isDynamic && method.returnType == null) { |
| 244 type = searchTypeFor(enclosingElement.type, methodElement); |
| 245 if (type == null) return; |
| 246 if (!type.returnType.isDynamic) { |
| 243 methodElement.returnType = type.returnType; | 247 methodElement.returnType = type.returnType; |
| 244 } | 248 } |
| 245 } | 249 } |
| 250 |
| 251 // Infer parameter types if omitted |
| 252 if (method.parameters == null) return; |
| 253 var parameters = method.parameters.parameters; |
| 254 var length = parameters.length; |
| 255 for (int i = 0; i < length; ++i) { |
| 256 var parameter = parameters[i]; |
| 257 if (parameter is DefaultFormalParameter) parameter = parameter.parameter; |
| 258 if (parameter is SimpleFormalParameter && parameter.type == null) { |
| 259 type = type ?? searchTypeFor(enclosingElement.type, methodElement); |
| 260 if (type == null) return; |
| 261 if (type.parameters.length > i && !type.parameters[i].type.isDynamic) { |
| 262 parameter.element.type = type.parameters[i].type; |
| 263 } |
| 264 } |
| 265 } |
| 246 } | 266 } |
| 247 | 267 |
| 248 void _inferVariableFromInitializer(Iterable<VariableDeclaration> variables) { | 268 void _inferVariableFromInitializer(Iterable<VariableDeclaration> variables) { |
| 249 for (var variable in variables) { | 269 for (var variable in variables) { |
| 250 var declaration = variable.parent as VariableDeclarationList; | 270 var declaration = variable.parent as VariableDeclarationList; |
| 251 // Only infer on variables that don't have any declared type. | 271 // Only infer on variables that don't have any declared type. |
| 252 if (declaration.type != null) continue; | 272 if (declaration.type != null) continue; |
| 253 if (_options.onlyInferConstsAndFinalFields && | 273 if (_options.onlyInferConstsAndFinalFields && |
| 254 !declaration.isFinal && | 274 !declaration.isFinal && |
| 255 !declaration.isConst) { | 275 !declaration.isConst) { |
| (...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 716 } | 736 } |
| 717 } | 737 } |
| 718 | 738 |
| 719 // Review note: no longer need to override visitFunctionExpression, this is | 739 // Review note: no longer need to override visitFunctionExpression, this is |
| 720 // handled by the analyzer internally. | 740 // handled by the analyzer internally. |
| 721 // TODO(vsm): in visitbinaryExpression: check computeStaticReturnType result? | 741 // TODO(vsm): in visitbinaryExpression: check computeStaticReturnType result? |
| 722 // TODO(vsm): in visitFunctionDeclaration: Should we ever use the expression | 742 // TODO(vsm): in visitFunctionDeclaration: Should we ever use the expression |
| 723 // type in a (...) => expr or just the written type? | 743 // type in a (...) => expr or just the written type? |
| 724 | 744 |
| 725 } | 745 } |
| OLD | NEW |