| Index: pkg/analyzer/lib/src/generated/static_type_analyzer.dart
|
| diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
|
| index af157bbbc2701b4d804c8f2b9afefb29ebe60d92..79481baa2099c29eb08c7ac1aaf7384c89b50f16 100644
|
| --- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
|
| +++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
|
| @@ -6,6 +6,8 @@ library engine.resolver.static_type_analyzer;
|
|
|
| import 'dart:collection';
|
|
|
| +import 'package:analyzer/src/generated/scanner.dart';
|
| +
|
| import 'ast.dart';
|
| import 'element.dart';
|
| import 'java_engine.dart';
|
| @@ -230,6 +232,14 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
|
| */
|
| @override
|
| Object visitBinaryExpression(BinaryExpression node) {
|
| + if (node.operator.type == TokenType.QUESTION_QUESTION) {
|
| + // Evaluation of an if-null expresion e of the form e1 ?? e2 is
|
| + // equivalent to the evaluation of the expression
|
| + // ((x) => x == null ? e2 : x)(e1). The static type of e is the least
|
| + // upper bound of the static type of e1 and the static type of e2.
|
| + _analyzeLeastUpperBound(node, node.leftOperand, node.rightOperand);
|
| + return null;
|
| + }
|
| ExecutableElement staticMethodElement = node.staticElement;
|
| DartType staticType = _computeStaticReturnType(staticMethodElement);
|
| staticType = _refineBinaryExpressionType(node, staticType);
|
| @@ -276,34 +286,7 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
|
| */
|
| @override
|
| Object visitConditionalExpression(ConditionalExpression node) {
|
| - DartType staticThenType = _getStaticType(node.thenExpression);
|
| - DartType staticElseType = _getStaticType(node.elseExpression);
|
| - if (staticThenType == null) {
|
| - // TODO(brianwilkerson) Determine whether this can still happen.
|
| - staticThenType = _dynamicType;
|
| - }
|
| - if (staticElseType == null) {
|
| - // TODO(brianwilkerson) Determine whether this can still happen.
|
| - staticElseType = _dynamicType;
|
| - }
|
| - DartType staticType = staticThenType.getLeastUpperBound(staticElseType);
|
| - if (staticType == null) {
|
| - staticType = _dynamicType;
|
| - }
|
| - _recordStaticType(node, staticType);
|
| - DartType propagatedThenType = node.thenExpression.propagatedType;
|
| - DartType propagatedElseType = node.elseExpression.propagatedType;
|
| - if (propagatedThenType != null || propagatedElseType != null) {
|
| - if (propagatedThenType == null) {
|
| - propagatedThenType = staticThenType;
|
| - }
|
| - if (propagatedElseType == null) {
|
| - propagatedElseType = staticElseType;
|
| - }
|
| - DartType propagatedType =
|
| - propagatedThenType.getLeastUpperBound(propagatedElseType);
|
| - _recordPropagatedTypeIfBetter(node, propagatedType);
|
| - }
|
| + _analyzeLeastUpperBound(node, node.thenExpression, node.elseExpression);
|
| return null;
|
| }
|
|
|
| @@ -1198,6 +1181,42 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
|
| }
|
|
|
| /**
|
| + * Set the static (propagated) type of [node] to be the least upper bound
|
| + * of the static (propagated) types of subexpressions [expr1] and [expr2].
|
| + */
|
| + void _analyzeLeastUpperBound(
|
| + Expression node, Expression expr1, Expression expr2) {
|
| + DartType staticType1 = _getStaticType(expr1);
|
| + DartType staticType2 = _getStaticType(expr2);
|
| + if (staticType1 == null) {
|
| + // TODO(brianwilkerson) Determine whether this can still happen.
|
| + staticType1 = _dynamicType;
|
| + }
|
| + if (staticType2 == null) {
|
| + // TODO(brianwilkerson) Determine whether this can still happen.
|
| + staticType2 = _dynamicType;
|
| + }
|
| + DartType staticType = staticType1.getLeastUpperBound(staticType2);
|
| + if (staticType == null) {
|
| + staticType = _dynamicType;
|
| + }
|
| + _recordStaticType(node, staticType);
|
| + DartType propagatedType1 = expr1.propagatedType;
|
| + DartType propagatedType2 = expr2.propagatedType;
|
| + if (propagatedType1 != null || propagatedType2 != null) {
|
| + if (propagatedType1 == null) {
|
| + propagatedType1 = staticType1;
|
| + }
|
| + if (propagatedType2 == null) {
|
| + propagatedType2 = staticType2;
|
| + }
|
| + DartType propagatedType =
|
| + propagatedType1.getLeastUpperBound(propagatedType2);
|
| + _recordPropagatedTypeIfBetter(node, propagatedType);
|
| + }
|
| + }
|
| +
|
| + /**
|
| * Record that the static type of the given node is the type of the second argument to the method
|
| * represented by the given element.
|
| *
|
|
|