Chromium Code Reviews| 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 |