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/src/generated/ast.dart'; | 9 import 'package:analyzer/src/generated/ast.dart'; |
10 import 'package:analyzer/src/generated/element.dart'; | 10 import 'package:analyzer/src/generated/element.dart'; |
11 import 'package:analyzer/src/generated/engine.dart'; | |
12 import 'package:analyzer/src/generated/java_engine.dart'; | |
13 import 'package:analyzer/src/generated/resolver.dart'; | 11 import 'package:analyzer/src/generated/resolver.dart'; |
14 import 'package:analyzer/src/generated/utilities_dart.dart'; | 12 import 'package:analyzer/src/generated/utilities_dart.dart'; |
15 | 13 |
16 /** | 14 /** |
15 * Set the type of the sole parameter of the given [element] to the given [type] . | |
16 */ | |
17 void setParameterType(PropertyAccessorElement element, DartType type) { | |
18 if (element is PropertyAccessorElementImpl) { | |
Paul Berry
2015/08/29 01:14:55
I realize this is just code motion, so feel free t
Brian Wilkerson
2015/08/31 15:08:52
Each of the 'if' statements in these methods is th
Paul Berry
2015/08/31 15:50:59
I understand that. I am not suggesting replacing
Brian Wilkerson
2015/08/31 18:35:38
While I understand the testing value, I really don
| |
19 ParameterElement parameter = _getParameter(element); | |
20 if (parameter is ParameterElementImpl) { | |
21 // | |
22 // Update the type of the parameter. | |
23 // | |
24 parameter.type = type; | |
25 // | |
26 // Update the type of the setter to reflect the new parameter type. | |
27 // | |
28 FunctionType functionType = element.type; | |
29 if (functionType is FunctionTypeImpl) { | |
30 element.type = | |
31 new FunctionTypeImpl(element, functionType.prunedTypedefs); | |
32 } | |
33 } | |
34 } | |
35 } | |
36 | |
37 /** | |
38 * Set the return type of the given [element] to the given [type]. | |
39 */ | |
40 void setReturnType(ExecutableElement element, DartType type) { | |
41 if (element is ExecutableElementImpl) { | |
Paul Berry
2015/08/29 01:14:55
Similar concerns in this function.
| |
42 // | |
43 // Update the return type of the element, which is stored in two places: | |
44 // directly in the element and indirectly in the type of the element. | |
45 // | |
46 element.returnType = type; | |
47 FunctionType functionType = element.type; | |
48 if (functionType is FunctionTypeImpl) { | |
49 element.type = new FunctionTypeImpl(element, functionType.prunedTypedefs); | |
50 } | |
51 } | |
52 } | |
53 | |
54 /** | |
55 * Return the element for the single parameter of the given [setter], or `null` | |
56 * if the executable element is not a setter or does not have a single | |
57 * parameter. | |
58 */ | |
59 ParameterElement _getParameter(ExecutableElement setter) { | |
60 if (setter is PropertyAccessorElement && setter.isSetter) { | |
61 List<ParameterElement> parameters = setter.parameters; | |
62 if (parameters.length == 1) { | |
63 return parameters[0]; | |
64 } | |
65 } | |
66 return null; | |
67 } | |
68 | |
69 /** | |
17 * A function that returns `true` if the given [variable] passes the filter. | 70 * A function that returns `true` if the given [variable] passes the filter. |
18 */ | 71 */ |
19 typedef bool VariableFilter(VariableElement element); | 72 typedef bool VariableFilter(VariableElement element); |
20 | 73 |
21 /** | 74 /** |
22 * An object used to find static variables whose types should be inferred and | 75 * An object used to find static variables whose types should be inferred and |
23 * classes whose members should have types inferred. Clients are expected to | 76 * classes whose members should have types inferred. Clients are expected to |
24 * visit a [CompilationUnit]. | 77 * visit a [CompilationUnit]. |
25 */ | 78 */ |
26 class InferrenceFinder extends SimpleAstVisitor { | 79 class InferrenceFinder extends SimpleAstVisitor { |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
186 DartType type = _getReturnType(overriddenMethods[i]); | 239 DartType type = _getReturnType(overriddenMethods[i]); |
187 if (returnType == null) { | 240 if (returnType == null) { |
188 returnType = type; | 241 returnType = type; |
189 } else if (returnType != type) { | 242 } else if (returnType != type) { |
190 return typeProvider.dynamicType; | 243 return typeProvider.dynamicType; |
191 } | 244 } |
192 } | 245 } |
193 return returnType == null ? typeProvider.dynamicType : returnType; | 246 return returnType == null ? typeProvider.dynamicType : returnType; |
194 } | 247 } |
195 | 248 |
196 /** | |
197 * Return the element for the single parameter of the given [setter], or | |
198 * `null` if the executable element is not a setter or does not have a single | |
199 * parameter. | |
200 */ | |
201 ParameterElement _getParameter(ExecutableElement setter) { | |
202 if (setter is PropertyAccessorElement && setter.isSetter) { | |
203 List<ParameterElement> parameters = setter.parameters; | |
204 if (parameters.length == 1) { | |
205 return parameters[0]; | |
206 } | |
207 } | |
208 return null; | |
209 } | |
210 | |
211 DartType _getReturnType(ExecutableElement element) { | 249 DartType _getReturnType(ExecutableElement element) { |
212 DartType returnType = element.returnType; | 250 DartType returnType = element.returnType; |
213 if (returnType == null) { | 251 if (returnType == null) { |
214 return typeProvider.dynamicType; | 252 return typeProvider.dynamicType; |
215 } | 253 } |
216 return returnType; | 254 return returnType; |
217 } | 255 } |
218 | 256 |
219 /** | 257 /** |
220 * Given a [method], return the type of the parameter in the method that | 258 * Given a [method], return the type of the parameter in the method that |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
277 .lookupOverrides( | 315 .lookupOverrides( |
278 accessorElement.enclosingElement, accessorElement.name + '='); | 316 accessorElement.enclosingElement, accessorElement.name + '='); |
279 PropertyAccessorElement setter = (accessorElement.enclosingElement | 317 PropertyAccessorElement setter = (accessorElement.enclosingElement |
280 as ClassElement).getSetter(accessorElement.name); | 318 as ClassElement).getSetter(accessorElement.name); |
281 if (setter != null) { | 319 if (setter != null) { |
282 overriddenSetters.add(setter); | 320 overriddenSetters.add(setter); |
283 } | 321 } |
284 if (!_isCompatible(newType, overriddenSetters)) { | 322 if (!_isCompatible(newType, overriddenSetters)) { |
285 newType = typeProvider.dynamicType; | 323 newType = typeProvider.dynamicType; |
286 } | 324 } |
287 _setReturnType(accessorElement, newType); | 325 setReturnType(accessorElement, newType); |
288 (accessorElement.variable as FieldElementImpl).type = newType; | 326 (accessorElement.variable as FieldElementImpl).type = newType; |
289 } | 327 } |
290 } | 328 } |
291 } | 329 } |
292 | 330 |
293 /** | 331 /** |
294 * Infer type information for all of the instance members in the given | 332 * Infer type information for all of the instance members in the given |
295 * [classElement]. | 333 * [classElement]. |
296 */ | 334 */ |
297 void _inferClass(ClassElement classElement) { | 335 void _inferClass(ClassElement classElement) { |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
358 if (newType == null) { | 396 if (newType == null) { |
359 if (fieldElement.initializer != null && | 397 if (fieldElement.initializer != null && |
360 (fieldElement.isFinal || overriddenGetters.isEmpty)) { | 398 (fieldElement.isFinal || overriddenGetters.isEmpty)) { |
361 newType = fieldElement.initializer.returnType; | 399 newType = fieldElement.initializer.returnType; |
362 } | 400 } |
363 } | 401 } |
364 if (newType == null || newType.isBottom) { | 402 if (newType == null || newType.isBottom) { |
365 newType = typeProvider.dynamicType; | 403 newType = typeProvider.dynamicType; |
366 } | 404 } |
367 (fieldElement as FieldElementImpl).type = newType; | 405 (fieldElement as FieldElementImpl).type = newType; |
368 _setReturnType(fieldElement.getter, newType); | 406 setReturnType(fieldElement.getter, newType); |
369 _setParameterType(fieldElement.setter, newType); | 407 setParameterType(fieldElement.setter, newType); |
370 } | 408 } |
371 } | 409 } |
372 | 410 |
373 /** | 411 /** |
374 * If the given [methodElement] represents a non-synthetic instance method | 412 * If the given [methodElement] represents a non-synthetic instance method |
375 * for which no return type was provided, infer the return type of the method. | 413 * for which no return type was provided, infer the return type of the method. |
376 */ | 414 */ |
377 void _inferMethod(MethodElement methodElement) { | 415 void _inferMethod(MethodElement methodElement) { |
378 if (methodElement.isSynthetic || methodElement.isStatic) { | 416 if (methodElement.isSynthetic || methodElement.isStatic) { |
379 return; | 417 return; |
380 } | 418 } |
381 List<ExecutableElement> overriddenMethods = null; | 419 List<ExecutableElement> overriddenMethods = null; |
382 // | 420 // |
383 // Infer the return type. | 421 // Infer the return type. |
384 // | 422 // |
385 if (methodElement.hasImplicitReturnType) { | 423 if (methodElement.hasImplicitReturnType) { |
386 overriddenMethods = inheritanceManager.lookupOverrides( | 424 overriddenMethods = inheritanceManager.lookupOverrides( |
387 methodElement.enclosingElement, methodElement.name); | 425 methodElement.enclosingElement, methodElement.name); |
388 if (overriddenMethods.isEmpty || !_onlyMethods(overriddenMethods)) { | 426 if (overriddenMethods.isEmpty || !_onlyMethods(overriddenMethods)) { |
389 return; | 427 return; |
390 } | 428 } |
391 MethodElementImpl element = methodElement as MethodElementImpl; | 429 MethodElementImpl element = methodElement as MethodElementImpl; |
392 _setReturnType(element, _computeReturnType(overriddenMethods)); | 430 setReturnType(element, _computeReturnType(overriddenMethods)); |
393 } | 431 } |
394 // | 432 // |
395 // Infer the parameter types. | 433 // Infer the parameter types. |
396 // | 434 // |
397 List<ParameterElement> parameters = methodElement.parameters; | 435 List<ParameterElement> parameters = methodElement.parameters; |
398 var length = parameters.length; | 436 var length = parameters.length; |
399 for (int i = 0; i < length; ++i) { | 437 for (int i = 0; i < length; ++i) { |
400 ParameterElement parameter = parameters[i]; | 438 ParameterElement parameter = parameters[i]; |
401 if (parameter is ParameterElementImpl && parameter.hasImplicitType) { | 439 if (parameter is ParameterElementImpl && parameter.hasImplicitType) { |
402 overriddenMethods = overriddenMethods ?? | 440 overriddenMethods = overriddenMethods ?? |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
453 * Return `true` if the list of [elements] contains only methods. | 491 * Return `true` if the list of [elements] contains only methods. |
454 */ | 492 */ |
455 bool _onlyMethods(List<ExecutableElement> elements) { | 493 bool _onlyMethods(List<ExecutableElement> elements) { |
456 for (ExecutableElement element in elements) { | 494 for (ExecutableElement element in elements) { |
457 if (element is! MethodElement) { | 495 if (element is! MethodElement) { |
458 return false; | 496 return false; |
459 } | 497 } |
460 } | 498 } |
461 return true; | 499 return true; |
462 } | 500 } |
463 | |
464 /** | |
465 * Set the type of the sole parameter of the given [element] to the given [typ e]. | |
466 */ | |
467 void _setParameterType(PropertyAccessorElement element, DartType type) { | |
468 if (element is PropertyAccessorElementImpl) { | |
469 ParameterElement parameter = _getParameter(element); | |
470 if (parameter is ParameterElementImpl) { | |
471 // | |
472 // Update the type of the parameter. | |
473 // | |
474 parameter.type = type; | |
475 // | |
476 // Update the type of the setter to reflect the new parameter type. | |
477 // | |
478 FunctionType functionType = element.type; | |
479 if (functionType is FunctionTypeImpl) { | |
480 element.type = | |
481 new FunctionTypeImpl(element, functionType.prunedTypedefs); | |
482 } | |
483 } | |
484 } | |
485 } | |
486 | |
487 /** | |
488 * Set the return type of the given [element] to the given [type]. | |
489 */ | |
490 void _setReturnType(ExecutableElement element, DartType type) { | |
491 if (element is ExecutableElementImpl) { | |
492 // | |
493 // Update the return type of the element, which is stored in two places: | |
494 // directly in the element and indirectly in the type of the element. | |
495 // | |
496 element.returnType = type; | |
497 FunctionType functionType = element.type; | |
498 if (functionType is FunctionTypeImpl) { | |
499 element.type = | |
500 new FunctionTypeImpl(element, functionType.prunedTypedefs); | |
501 } | |
502 } | |
503 } | |
504 } | 501 } |
505 | 502 |
506 /** | 503 /** |
507 * A visitor that will gather all of the variables referenced within a given | 504 * A visitor that will gather all of the variables referenced within a given |
508 * AST structure. The collection can be restricted to contain only those | 505 * AST structure. The collection can be restricted to contain only those |
509 * variables that pass a specified filter. | 506 * variables that pass a specified filter. |
510 */ | 507 */ |
511 class VariableGatherer extends RecursiveAstVisitor { | 508 class VariableGatherer extends RecursiveAstVisitor { |
512 /** | 509 /** |
513 * The filter used to limit which variables are gathered, or `null` if no | 510 * The filter used to limit which variables are gathered, or `null` if no |
(...skipping 23 matching lines...) Expand all Loading... | |
537 results.add(element); | 534 results.add(element); |
538 } | 535 } |
539 } | 536 } |
540 } | 537 } |
541 } | 538 } |
542 | 539 |
543 /** | 540 /** |
544 * A class of exception that is not used anywhere else. | 541 * A class of exception that is not used anywhere else. |
545 */ | 542 */ |
546 class _CycleException implements Exception {} | 543 class _CycleException implements Exception {} |
OLD | NEW |