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 |