| 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 library analyzer.src.task.strong_mode; | 5 library analyzer.src.task.strong_mode; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 | 8 |
| 9 import 'package:analyzer/dart/ast/ast.dart'; | 9 import 'package:analyzer/dart/ast/ast.dart'; |
| 10 import 'package:analyzer/dart/ast/visitor.dart'; | 10 import 'package:analyzer/dart/ast/visitor.dart'; |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 114 * At the moment, this method will only return a type other than 'dynamic' if | 114 * At the moment, this method will only return a type other than 'dynamic' if |
| 115 * the types of all of the parameters are the same. In the future we might | 115 * the types of all of the parameters are the same. In the future we might |
| 116 * want to be smarter about it, such as by returning the least upper bound of | 116 * want to be smarter about it, such as by returning the least upper bound of |
| 117 * the parameter types. | 117 * the parameter types. |
| 118 */ | 118 */ |
| 119 DartType _computeParameterType(ParameterElement parameter, int index, | 119 DartType _computeParameterType(ParameterElement parameter, int index, |
| 120 List<FunctionType> overriddenTypes) { | 120 List<FunctionType> overriddenTypes) { |
| 121 DartType parameterType = null; | 121 DartType parameterType = null; |
| 122 int length = overriddenTypes.length; | 122 int length = overriddenTypes.length; |
| 123 for (int i = 0; i < length; i++) { | 123 for (int i = 0; i < length; i++) { |
| 124 DartType type = _getTypeOfCorrespondingParameter( | 124 ParameterElement matchingParam = _getCorrespondingParameter( |
| 125 parameter, index, overriddenTypes[i].parameters); | 125 parameter, index, overriddenTypes[i].parameters); |
| 126 var type = matchingParam?.type ?? typeProvider.dynamicType; |
| 126 if (parameterType == null) { | 127 if (parameterType == null) { |
| 127 parameterType = type; | 128 parameterType = type; |
| 128 } else if (parameterType != type) { | 129 } else if (parameterType != type) { |
| 129 return typeProvider.dynamicType; | 130 return typeProvider.dynamicType; |
| 130 } | 131 } |
| 131 } | 132 } |
| 132 return parameterType ?? typeProvider.dynamicType; | 133 return parameterType ?? typeProvider.dynamicType; |
| 133 } | 134 } |
| 134 | 135 |
| 135 /** | 136 /** |
| (...skipping 13 matching lines...) Expand all Loading... |
| 149 if (returnType == null) { | 150 if (returnType == null) { |
| 150 returnType = type; | 151 returnType = type; |
| 151 } else if (returnType != type) { | 152 } else if (returnType != type) { |
| 152 return typeProvider.dynamicType; | 153 return typeProvider.dynamicType; |
| 153 } | 154 } |
| 154 } | 155 } |
| 155 return returnType ?? typeProvider.dynamicType; | 156 return returnType ?? typeProvider.dynamicType; |
| 156 } | 157 } |
| 157 | 158 |
| 158 /** | 159 /** |
| 159 * Given a method, return the type of the parameter in the method that | 160 * Given a method, return the parameter in the method that corresponds to the |
| 160 * corresponds to the given [parameter]. If the parameter is positional, then | 161 * given [parameter]. If the parameter is positional, then |
| 161 * it appears at the given [index] in its enclosing element's list of | 162 * it appears at the given [index] in its enclosing element's list of |
| 162 * parameters. | 163 * parameters. |
| 163 */ | 164 */ |
| 164 DartType _getTypeOfCorrespondingParameter(ParameterElement parameter, | 165 ParameterElement _getCorrespondingParameter(ParameterElement parameter, |
| 165 int index, List<ParameterElement> methodParameters) { | 166 int index, List<ParameterElement> methodParameters) { |
| 166 // | 167 // |
| 167 // Find the corresponding parameter. | 168 // Find the corresponding parameter. |
| 168 // | 169 // |
| 169 ParameterElement matchingParameter = null; | |
| 170 if (parameter.parameterKind == ParameterKind.NAMED) { | 170 if (parameter.parameterKind == ParameterKind.NAMED) { |
| 171 // | 171 // |
| 172 // If we're looking for a named parameter, only a named parameter with | 172 // If we're looking for a named parameter, only a named parameter with |
| 173 // the same name will be matched. | 173 // the same name will be matched. |
| 174 // | 174 // |
| 175 matchingParameter = methodParameters.lastWhere( | 175 return methodParameters.lastWhere( |
| 176 (ParameterElement methodParameter) => | 176 (ParameterElement methodParameter) => |
| 177 methodParameter.parameterKind == ParameterKind.NAMED && | 177 methodParameter.parameterKind == ParameterKind.NAMED && |
| 178 methodParameter.name == parameter.name, | 178 methodParameter.name == parameter.name, |
| 179 orElse: () => null); | 179 orElse: () => null); |
| 180 } else { | 180 } |
| 181 // | 181 // |
| 182 // If we're looking for a positional parameter we ignore the difference | 182 // If we're looking for a positional parameter we ignore the difference |
| 183 // between required and optional parameters. | 183 // between required and optional parameters. |
| 184 // | 184 // |
| 185 if (index < methodParameters.length) { | 185 if (index < methodParameters.length) { |
| 186 matchingParameter = methodParameters[index]; | 186 var matchingParameter = methodParameters[index]; |
| 187 if (matchingParameter.parameterKind == ParameterKind.NAMED) { | 187 if (matchingParameter.parameterKind != ParameterKind.NAMED) { |
| 188 matchingParameter = null; | 188 return matchingParameter; |
| 189 } | |
| 190 } | 189 } |
| 191 } | 190 } |
| 192 // | 191 return null; |
| 193 // Then return the type of the parameter. | |
| 194 // | |
| 195 return matchingParameter == null | |
| 196 ? typeProvider.dynamicType | |
| 197 : matchingParameter.type; | |
| 198 } | 192 } |
| 199 | 193 |
| 200 /** | 194 /** |
| 201 * Infer type information for all of the instance members in the given | 195 * Infer type information for all of the instance members in the given |
| 202 * [classElement]. | 196 * [classElement]. |
| 203 */ | 197 */ |
| 204 void _inferClass(ClassElement classElement) { | 198 void _inferClass(ClassElement classElement) { |
| 205 if (classElement is ClassElementImpl) { | 199 if (classElement is ClassElementImpl) { |
| 206 if (classElement.hasBeenInferred) { | 200 if (classElement.hasBeenInferred) { |
| 207 return; | 201 return; |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 304 _updateSyntheticVariableType(element); | 298 _updateSyntheticVariableType(element); |
| 305 } | 299 } |
| 306 } | 300 } |
| 307 // | 301 // |
| 308 // Infer the parameter types. | 302 // Infer the parameter types. |
| 309 // | 303 // |
| 310 List<ParameterElement> parameters = element.parameters; | 304 List<ParameterElement> parameters = element.parameters; |
| 311 int length = parameters.length; | 305 int length = parameters.length; |
| 312 for (int i = 0; i < length; ++i) { | 306 for (int i = 0; i < length; ++i) { |
| 313 ParameterElement parameter = parameters[i]; | 307 ParameterElement parameter = parameters[i]; |
| 314 if (parameter is ParameterElementImpl && parameter.hasImplicitType) { | 308 if (parameter is ParameterElementImpl) { |
| 315 parameter.type = _computeParameterType(parameter, i, overriddenTypes); | 309 // If a parameter is covariant, any parameters that override it are too. |
| 316 if (element is PropertyAccessorElement) { | 310 parameter.inheritsCovariant = overriddenTypes.any((f) { |
| 317 _updateSyntheticVariableType(element); | 311 var param = _getCorrespondingParameter(parameter, i, f.parameters); |
| 312 return param != null && param.isCovariant; |
| 313 }); |
| 314 |
| 315 if (parameter.hasImplicitType) { |
| 316 parameter.type = _computeParameterType(parameter, i, overriddenTypes); |
| 317 if (element is PropertyAccessorElement) { |
| 318 _updateSyntheticVariableType(element); |
| 319 } |
| 318 } | 320 } |
| 319 } | 321 } |
| 320 } | 322 } |
| 321 } | 323 } |
| 322 | 324 |
| 323 /** | 325 /** |
| 324 * If the given [fieldElement] represents a non-synthetic instance field for | 326 * If the given [fieldElement] represents a non-synthetic instance field for |
| 325 * which no type was provided, infer the type of the field. | 327 * which no type was provided, infer the type of the field. |
| 326 */ | 328 */ |
| 327 void _inferField(FieldElement fieldElement) { | 329 void _inferField(FieldElement fieldElement) { |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 478 results.add(element); | 480 results.add(element); |
| 479 } | 481 } |
| 480 } | 482 } |
| 481 } | 483 } |
| 482 } | 484 } |
| 483 | 485 |
| 484 /** | 486 /** |
| 485 * A class of exception that is not used anywhere else. | 487 * A class of exception that is not used anywhere else. |
| 486 */ | 488 */ |
| 487 class _CycleException implements Exception {} | 489 class _CycleException implements Exception {} |
| OLD | NEW |