| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 engine.resolver; | 5 library engine.resolver; |
| 6 | 6 |
| 7 import "dart:math" as math; | 7 import "dart:math" as math; |
| 8 import 'dart:collection'; | 8 import 'dart:collection'; |
| 9 | 9 |
| 10 import 'package:analyzer/src/generated/utilities_collection.dart'; | 10 import 'package:analyzer/src/generated/utilities_collection.dart'; |
| (...skipping 10317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10328 * | 10328 * |
| 10329 * @param expression the expression used to access the static and propagated e
lements whose types | 10329 * @param expression the expression used to access the static and propagated e
lements whose types |
| 10330 * might be overridden | 10330 * might be overridden |
| 10331 * @param potentialType the potential type of the elements | 10331 * @param potentialType the potential type of the elements |
| 10332 * @param allowPrecisionLoss see @{code overrideVariable} docs | 10332 * @param allowPrecisionLoss see @{code overrideVariable} docs |
| 10333 */ | 10333 */ |
| 10334 void overrideExpression( | 10334 void overrideExpression( |
| 10335 Expression expression, DartType potentialType, bool allowPrecisionLoss) { | 10335 Expression expression, DartType potentialType, bool allowPrecisionLoss) { |
| 10336 VariableElement element = getOverridableStaticElement(expression); | 10336 VariableElement element = getOverridableStaticElement(expression); |
| 10337 if (element != null) { | 10337 if (element != null) { |
| 10338 overrideVariable(element, potentialType, allowPrecisionLoss); | 10338 DartType newBestType = |
| 10339 overrideVariable(element, potentialType, allowPrecisionLoss); |
| 10340 recordPropagatedTypeIfBetter(expression, newBestType); |
| 10339 } | 10341 } |
| 10340 element = getOverridablePropagatedElement(expression); | 10342 element = getOverridablePropagatedElement(expression); |
| 10341 if (element != null) { | 10343 if (element != null) { |
| 10342 overrideVariable(element, potentialType, allowPrecisionLoss); | 10344 overrideVariable(element, potentialType, allowPrecisionLoss); |
| 10343 } | 10345 } |
| 10344 } | 10346 } |
| 10345 | 10347 |
| 10346 /** | 10348 /** |
| 10347 * If it is appropriate to do so, override the current type of the given eleme
nt with the given | 10349 * If it is appropriate to do so, override the current type of the given eleme
nt with the given |
| 10348 * type. | 10350 * type. |
| 10349 * | 10351 * |
| 10350 * @param element the element whose type might be overridden | 10352 * @param element the element whose type might be overridden |
| 10351 * @param potentialType the potential type of the element | 10353 * @param potentialType the potential type of the element |
| 10352 * @param allowPrecisionLoss true if `potentialType` is allowed to be less pre
cise than the | 10354 * @param allowPrecisionLoss true if `potentialType` is allowed to be less pre
cise than the |
| 10353 * current best type | 10355 * current best type |
| 10356 * |
| 10357 * Return a new better [DartType], or `null` if [potentialType] is not better |
| 10358 * than the current [element] type. |
| 10354 */ | 10359 */ |
| 10355 void overrideVariable(VariableElement element, DartType potentialType, | 10360 DartType overrideVariable(VariableElement element, DartType potentialType, |
| 10356 bool allowPrecisionLoss) { | 10361 bool allowPrecisionLoss) { |
| 10357 if (potentialType == null || potentialType.isBottom) { | 10362 if (potentialType == null || potentialType.isBottom) { |
| 10358 return; | 10363 return null; |
| 10359 } | 10364 } |
| 10360 DartType currentType = _overrideManager.getBestType(element); | 10365 DartType currentType = _overrideManager.getBestType(element); |
| 10361 | 10366 |
| 10362 if (potentialType == currentType) { | 10367 if (potentialType == currentType) { |
| 10363 return; | 10368 return null; |
| 10364 } | 10369 } |
| 10365 | 10370 |
| 10366 // If we aren't allowing precision loss then the third and fourth conditions | 10371 // If we aren't allowing precision loss then the third and fourth conditions |
| 10367 // check that we aren't losing precision. | 10372 // check that we aren't losing precision. |
| 10368 // | 10373 // |
| 10369 // Let [C] be the current type and [P] be the potential type. When we | 10374 // Let [C] be the current type and [P] be the potential type. When we |
| 10370 // aren't allowing precision loss -- which is the case for is-checks -- we | 10375 // aren't allowing precision loss -- which is the case for is-checks -- we |
| 10371 // check that [! (C << P)] or [P << C]. The second check, that [P << C], is | 10376 // check that [! (C << P)] or [P << C]. The second check, that [P << C], is |
| 10372 // analogous to part of the Dart Language Spec rule for type promotion under | 10377 // analogous to part of the Dart Language Spec rule for type promotion under |
| 10373 // is-checks (in the analogy [T] is [P] and [S] is [C]): | 10378 // is-checks (in the analogy [T] is [P] and [S] is [C]): |
| (...skipping 18 matching lines...) Expand all Loading... |
| 10392 // the client before the field, then propagated type is not set yet. | 10397 // the client before the field, then propagated type is not set yet. |
| 10393 // if (element is PropertyInducingElement) { | 10398 // if (element is PropertyInducingElement) { |
| 10394 // PropertyInducingElement variable = element; | 10399 // PropertyInducingElement variable = element; |
| 10395 // if (!variable.isConst && !variable.isFinal) { | 10400 // if (!variable.isConst && !variable.isFinal) { |
| 10396 // return; | 10401 // return; |
| 10397 // } | 10402 // } |
| 10398 // (variable as PropertyInducingElementImpl).propagatedType = | 10403 // (variable as PropertyInducingElementImpl).propagatedType = |
| 10399 // potentialType; | 10404 // potentialType; |
| 10400 // } | 10405 // } |
| 10401 _overrideManager.setType(element, potentialType); | 10406 _overrideManager.setType(element, potentialType); |
| 10407 return potentialType; |
| 10402 } | 10408 } |
| 10409 return null; |
| 10410 } |
| 10411 |
| 10412 /** |
| 10413 * If the given [type] is valid, strongly more specific than the |
| 10414 * existing static type of the given [expression], record it as a propagated |
| 10415 * type of the given [expression]. Otherwise, reset it to `null`. |
| 10416 * |
| 10417 * If [hasOldPropagatedType] is `true` then the existing propagated type |
| 10418 * should also is checked. |
| 10419 */ |
| 10420 void recordPropagatedTypeIfBetter(Expression expression, DartType type, |
| 10421 [bool hasOldPropagatedType = false]) { |
| 10422 // Ensure that propagated type invalid. |
| 10423 if (type == null || type.isDynamic || type.isBottom) { |
| 10424 if (!hasOldPropagatedType) { |
| 10425 expression.propagatedType = null; |
| 10426 } |
| 10427 return; |
| 10428 } |
| 10429 // Ensure that propagated type is more specific than the static type. |
| 10430 DartType staticType = expression.staticType; |
| 10431 if (type == staticType || !type.isMoreSpecificThan(staticType)) { |
| 10432 expression.propagatedType = null; |
| 10433 return; |
| 10434 } |
| 10435 // Ensure that the new propagated type is more specific than the old one. |
| 10436 if (hasOldPropagatedType) { |
| 10437 DartType oldPropagatedType = expression.propagatedType; |
| 10438 if (oldPropagatedType != null && |
| 10439 !type.isMoreSpecificThan(oldPropagatedType)) { |
| 10440 return; |
| 10441 } |
| 10442 } |
| 10443 // OK |
| 10444 expression.propagatedType = type; |
| 10403 } | 10445 } |
| 10404 | 10446 |
| 10405 @override | 10447 @override |
| 10406 Object visitAnnotation(Annotation node) { | 10448 Object visitAnnotation(Annotation node) { |
| 10407 AstNode parent = node.parent; | 10449 AstNode parent = node.parent; |
| 10408 if (identical(parent, _enclosingClassDeclaration) || | 10450 if (identical(parent, _enclosingClassDeclaration) || |
| 10409 identical(parent, _enclosingFunctionTypeAlias)) { | 10451 identical(parent, _enclosingFunctionTypeAlias)) { |
| 10410 return null; | 10452 return null; |
| 10411 } | 10453 } |
| 10412 return super.visitAnnotation(node); | 10454 return super.visitAnnotation(node); |
| (...skipping 4992 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15405 } | 15447 } |
| 15406 | 15448 |
| 15407 bool isCatchException(LocalVariableElement element) { | 15449 bool isCatchException(LocalVariableElement element) { |
| 15408 return catchExceptionElements.contains(element); | 15450 return catchExceptionElements.contains(element); |
| 15409 } | 15451 } |
| 15410 | 15452 |
| 15411 bool isCatchStackTrace(LocalVariableElement element) { | 15453 bool isCatchStackTrace(LocalVariableElement element) { |
| 15412 return catchStackTraceElements.contains(element); | 15454 return catchStackTraceElements.contains(element); |
| 15413 } | 15455 } |
| 15414 } | 15456 } |
| OLD | NEW |