| Index: dart/compiler/java/com/google/dart/compiler/resolver/CompileTimeConstantAnalyzer.java
|
| diff --git a/dart/compiler/java/com/google/dart/compiler/resolver/CompileTimeConstantAnalyzer.java b/dart/compiler/java/com/google/dart/compiler/resolver/CompileTimeConstantAnalyzer.java
|
| deleted file mode 100644
|
| index f0dc599147742f5e557a13f3b3f4d7eff4ae25f8..0000000000000000000000000000000000000000
|
| --- a/dart/compiler/java/com/google/dart/compiler/resolver/CompileTimeConstantAnalyzer.java
|
| +++ /dev/null
|
| @@ -1,822 +0,0 @@
|
| -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
|
| -// for details. All rights reserved. Use of this source code is governed by a
|
| -// BSD-style license that can be found in the LICENSE file.
|
| -
|
| -package com.google.dart.compiler.resolver;
|
| -
|
| -import com.google.common.collect.Maps;
|
| -import com.google.common.collect.Sets;
|
| -import com.google.dart.compiler.DartCompilationError;
|
| -import com.google.dart.compiler.DartCompilationPhase;
|
| -import com.google.dart.compiler.DartCompilerContext;
|
| -import com.google.dart.compiler.ast.ASTVisitor;
|
| -import com.google.dart.compiler.ast.DartArrayLiteral;
|
| -import com.google.dart.compiler.ast.DartBinaryExpression;
|
| -import com.google.dart.compiler.ast.DartBooleanLiteral;
|
| -import com.google.dart.compiler.ast.DartCase;
|
| -import com.google.dart.compiler.ast.DartClass;
|
| -import com.google.dart.compiler.ast.DartConditional;
|
| -import com.google.dart.compiler.ast.DartDeclaration;
|
| -import com.google.dart.compiler.ast.DartDoubleLiteral;
|
| -import com.google.dart.compiler.ast.DartExpression;
|
| -import com.google.dart.compiler.ast.DartField;
|
| -import com.google.dart.compiler.ast.DartFunction;
|
| -import com.google.dart.compiler.ast.DartFunctionObjectInvocation;
|
| -import com.google.dart.compiler.ast.DartIdentifier;
|
| -import com.google.dart.compiler.ast.DartInitializer;
|
| -import com.google.dart.compiler.ast.DartIntegerLiteral;
|
| -import com.google.dart.compiler.ast.DartInvocation;
|
| -import com.google.dart.compiler.ast.DartMapLiteral;
|
| -import com.google.dart.compiler.ast.DartMapLiteralEntry;
|
| -import com.google.dart.compiler.ast.DartMethodDefinition;
|
| -import com.google.dart.compiler.ast.DartMethodInvocation;
|
| -import com.google.dart.compiler.ast.DartNamedExpression;
|
| -import com.google.dart.compiler.ast.DartNewExpression;
|
| -import com.google.dart.compiler.ast.DartNode;
|
| -import com.google.dart.compiler.ast.DartNullLiteral;
|
| -import com.google.dart.compiler.ast.DartParameter;
|
| -import com.google.dart.compiler.ast.DartParenthesizedExpression;
|
| -import com.google.dart.compiler.ast.DartPropertyAccess;
|
| -import com.google.dart.compiler.ast.DartRedirectConstructorInvocation;
|
| -import com.google.dart.compiler.ast.DartStringInterpolation;
|
| -import com.google.dart.compiler.ast.DartStringLiteral;
|
| -import com.google.dart.compiler.ast.DartSuperConstructorInvocation;
|
| -import com.google.dart.compiler.ast.DartSuperExpression;
|
| -import com.google.dart.compiler.ast.DartThisExpression;
|
| -import com.google.dart.compiler.ast.DartUnaryExpression;
|
| -import com.google.dart.compiler.ast.DartUnit;
|
| -import com.google.dart.compiler.ast.DartUnqualifiedInvocation;
|
| -import com.google.dart.compiler.ast.DartVariable;
|
| -import com.google.dart.compiler.ast.DartVariableStatement;
|
| -import com.google.dart.compiler.ast.Modifiers;
|
| -import com.google.dart.compiler.common.HasSourceInfo;
|
| -import com.google.dart.compiler.type.Type;
|
| -import com.google.dart.compiler.type.TypeKind;
|
| -
|
| -import java.math.BigInteger;
|
| -import java.util.List;
|
| -import java.util.Map;
|
| -import java.util.Set;
|
| -
|
| -/**
|
| - * Given an tree, finds all compile-time constant expressions, and determines if
|
| - * each expression matches all the rules for a compile-time constant. Emits a
|
| - * resolution error if not.
|
| - *
|
| - * This script doesn't just resolve expressions, it also sets types to the
|
| - * extent needed to validate compile-time constant expressions (boolean, int,
|
| - * double, and string types might be set)
|
| - */
|
| -public class CompileTimeConstantAnalyzer {
|
| -
|
| - private class ExpressionVisitor extends ASTVisitor<Void> {
|
| - private boolean checkBoolean(DartNode x, Type type) {
|
| - // Spec 0.11 allows using "null" literal in place of bool.
|
| - if (x instanceof DartNullLiteral) {
|
| - return true;
|
| - }
|
| - // check actual type
|
| - if (!type.equals(boolType)) {
|
| - context.onError(new DartCompilationError(x,
|
| - ResolverErrorCode.EXPECTED_CONSTANT_EXPRESSION_BOOLEAN, type
|
| - .toString()));
|
| - return false;
|
| - }
|
| - return true;
|
| - }
|
| -
|
| - private boolean checkInt(DartNode x, Type type) {
|
| - // Spec 0.11 allows using "null" literal in place of num.
|
| - if (x instanceof DartNullLiteral) {
|
| - return true;
|
| - }
|
| - // check actual type
|
| - if (!type.equals(intType)) {
|
| - context
|
| - .onError(new DartCompilationError(x,
|
| - ResolverErrorCode.EXPECTED_CONSTANT_EXPRESSION_INT, type
|
| - .toString()));
|
| - return false;
|
| - }
|
| - return true;
|
| - }
|
| -
|
| - private boolean checkString(DartNode x, Type type) {
|
| - if (!type.equals(stringType)) {
|
| - context
|
| - .onError(new DartCompilationError(x,
|
| - ResolverErrorCode.EXPECTED_CONSTANT_EXPRESSION_STRING, type
|
| - .toString()));
|
| - return false;
|
| - }
|
| - return true;
|
| - }
|
| -
|
| - private boolean checkNumber(DartNode x, Type type) {
|
| - // for "const" constructor we check "potentially constant expression",
|
| - // so suppose that parameters have correct type
|
| - if (TypeKind.of(type) == TypeKind.DYNAMIC && x.getElement() != null
|
| - && x.getElement().getEnclosingElement() instanceof MethodElement) {
|
| - return true;
|
| - }
|
| - // Spec 0.11 allows using "null" literal in place of num.
|
| - if (x instanceof DartNullLiteral) {
|
| - return true;
|
| - }
|
| - // check actual type
|
| - if (!(type.equals(numType) || type.equals(intType) || type
|
| - .equals(doubleType))) {
|
| - context.onError(new DartCompilationError(x,
|
| - ResolverErrorCode.EXPECTED_CONSTANT_EXPRESSION_NUMBER, type
|
| - .toString()));
|
| -
|
| - return false;
|
| - }
|
| - return true;
|
| - }
|
| -
|
| - private boolean checkNumberBooleanOrStringType(DartNode x, Type type) {
|
| - if (type.equals(intType) || type.equals(boolType)
|
| - || type.equals(numType) || type.equals(doubleType)
|
| - || type.equals(stringType) || (x instanceof DartNullLiteral)) {
|
| - return true;
|
| - } else if (x instanceof DartStringInterpolation) {
|
| - DartStringInterpolation interpolation = (DartStringInterpolation) x;
|
| - for (DartExpression expression : interpolation.getExpressions()) {
|
| - Type expressionType = getMostSpecificType(expression);
|
| - if (!checkNumberBooleanOrStringType(expression, expressionType)) {
|
| - return false;
|
| - }
|
| - }
|
| - return true;
|
| - }
|
| - context.onError(new DartCompilationError(x,
|
| - ResolverErrorCode.EXPECTED_CONSTANT_EXPRESSION_STRING_NUMBER_BOOL,
|
| - type.toString()));
|
| - return false;
|
| - }
|
| -
|
| - /**
|
| - * Logs a general message "expected a constant expression" error. Use a more
|
| - * specific error message when possible.
|
| - */
|
| - private void expectedConstant(HasSourceInfo x) {
|
| - context.onError(new DartCompilationError(x, ResolverErrorCode.EXPECTED_CONSTANT_EXPRESSION));
|
| - }
|
| -
|
| - /**
|
| - * Determine the most specific type assigned to an expression node. Prefer
|
| - * the setting in the expression's element if present. Otherwise, use a type
|
| - * tagged in the expression node itself.
|
| - *
|
| - * @return a non <code>null</code> type value. Dynamic if none other can be
|
| - * determined.
|
| - */
|
| - private Type getMostSpecificType(DartNode node) {
|
| - if (node != null) {
|
| - Type type = inferredTypes.get(node);
|
| - if (type != null) {
|
| - return type;
|
| - }
|
| - Element element = node.getElement();
|
| - if (Elements.isFunctionIdentical(element)) {
|
| - return boolType;
|
| - }
|
| - if (element != null) {
|
| - type = element.getType();
|
| - if (type != null && TypeKind.of(type) != TypeKind.DYNAMIC) {
|
| - return type;
|
| - }
|
| - if (element instanceof VariableElement) {
|
| - VariableElement variable = (VariableElement) element;
|
| - if (variable.getModifiers().isConstant()) {
|
| - DartExpression value = variable.getDefaultValue();
|
| - if (value != null) {
|
| - type = getMostSpecificType(value);
|
| - }
|
| - }
|
| - } else if (element instanceof FieldElement) {
|
| - FieldElement field = (FieldElement) element;
|
| - if (field.getModifiers().isConstant()) {
|
| - type = field.getConstantType();
|
| - }
|
| - }
|
| - if (type != null) {
|
| - return type;
|
| - }
|
| - }
|
| - }
|
| - return dynamicType;
|
| - }
|
| -
|
| - private void rememberInferredType(DartNode x, Type type) {
|
| - if (type != null && ! type.equals(dynamicType)) {
|
| - inferredTypes.put(x, type);
|
| - }
|
| - }
|
| -
|
| - @Override
|
| - public Void visitArrayLiteral(DartArrayLiteral x) {
|
| - if (!x.isConst()) {
|
| - expectedConstant(x);
|
| - } else {
|
| - for (DartExpression expr : x.getExpressions()) {
|
| - expr.accept(this);
|
| - }
|
| - }
|
| - return null;
|
| - }
|
| -
|
| - @Override
|
| - public Void visitBinaryExpression(DartBinaryExpression x) {
|
| - x.visitChildren(this);
|
| -
|
| - DartExpression lhs = x.getArg1();
|
| - DartExpression rhs = x.getArg2();
|
| - Type lhsType = getMostSpecificType(lhs);
|
| - Type rhsType = getMostSpecificType(rhs);
|
| -
|
| - switch (x.getOperator()) {
|
| - case NE:
|
| - case EQ:
|
| - case NE_STRICT:
|
| - case EQ_STRICT:
|
| - if (checkNumberBooleanOrStringType(lhs, lhsType)
|
| - && checkNumberBooleanOrStringType(rhs, rhsType)) {
|
| - rememberInferredType(x, boolType);
|
| - }
|
| - break;
|
| -
|
| - case AND:
|
| - case OR:
|
| - if (checkBoolean(lhs, lhsType) && checkBoolean(rhs, rhsType)) {
|
| - rememberInferredType(x, boolType);
|
| - }
|
| - break;
|
| -
|
| - case BIT_XOR:
|
| - case BIT_AND:
|
| - case BIT_OR:
|
| - case SAR:
|
| - case SHL:
|
| - if (checkInt(lhs, lhsType) && checkInt(rhs, rhsType)) {
|
| - rememberInferredType(x, intType);
|
| - }
|
| - break;
|
| -
|
| - case ADD:
|
| - if (lhsType.equals(stringType)) {
|
| - // TODO(zundel): remove this when + no longer acceptable as string concat operator
|
| - if (checkString(rhs, rhsType)) {
|
| - rememberInferredType(x, stringType);
|
| - }
|
| - } else {
|
| - checkMathExpression(x, lhs, rhs, lhsType, rhsType);
|
| - }
|
| - break;
|
| - case SUB:
|
| - case MUL:
|
| - case DIV:
|
| - checkMathExpression(x, lhs, rhs, lhsType, rhsType);
|
| - break;
|
| - case TRUNC:
|
| - case MOD:
|
| - reportExceptionIfZeroLiteral(x, rhs);
|
| - if (checkNumber(lhs, lhsType) && checkNumber(rhs, rhsType)) {
|
| - rememberInferredType(x, intType);
|
| - }
|
| - break;
|
| - case LT:
|
| - case GT:
|
| - case LTE:
|
| - case GTE:
|
| - if (checkNumber(lhs, lhsType) && checkNumber(rhs, rhsType)) {
|
| - rememberInferredType(x, boolType);
|
| - }
|
| - break;
|
| -
|
| - default:
|
| - // all other operators...
|
| - expectedConstant(x);
|
| - }
|
| - return null;
|
| - }
|
| -
|
| - private void reportExceptionIfZeroLiteral(HasSourceInfo target, DartExpression e) {
|
| - if (e instanceof DartIntegerLiteral) {
|
| - DartIntegerLiteral literal = (DartIntegerLiteral) e;
|
| - if (literal.getValue().equals(BigInteger.ZERO)) {
|
| - context.onError(new DartCompilationError(target,
|
| - ResolverErrorCode.CONSTANTS_EVALUATION_EXCEPTION));
|
| - }
|
| - }
|
| - }
|
| -
|
| - private void checkMathExpression(DartBinaryExpression x,
|
| - DartExpression lhs, DartExpression rhs,
|
| - Type lhsType, Type rhsType) {
|
| - if (checkNumber(lhs, lhsType) && checkNumber(rhs, rhsType)) {
|
| - if (lhsType.equals(intType) && rhsType.equals(intType)) {
|
| - rememberInferredType(x, intType);
|
| - } else if (lhsType.equals(doubleType) && rhsType.equals(doubleType)) {
|
| - rememberInferredType(x, doubleType);
|
| - } else if (lhsType.equals(doubleType) && rhsType.equals(intType)
|
| - || lhsType.equals(intType) && rhsType.equals(doubleType)) {
|
| - rememberInferredType(x, doubleType);
|
| - } else {
|
| - rememberInferredType(x, numType);
|
| - }
|
| - }
|
| - }
|
| -
|
| - @Override
|
| - public Void visitBooleanLiteral(DartBooleanLiteral x) {
|
| - rememberInferredType(x, boolType);
|
| - return null;
|
| - }
|
| -
|
| - @Override
|
| - public Void visitDoubleLiteral(DartDoubleLiteral x) {
|
| - rememberInferredType(x, doubleType);
|
| - return null;
|
| - }
|
| -
|
| - @Override
|
| - public Void visitConditional(DartConditional node) {
|
| - expectedConstant(node);
|
| - return null;
|
| - }
|
| -
|
| - @Override
|
| - public Void visitField(DartField x) {
|
| - x.visitChildren(this);
|
| - if (x.getType() == null || x.getType().equals(dynamicType)) {
|
| - Type type = getMostSpecificType(x.getValue());
|
| - rememberInferredType(x, type);
|
| - }
|
| - return null;
|
| - }
|
| -
|
| - @Override
|
| - public Void visitFunction(DartFunction x) {
|
| - // No need to traverse, functions are always disallowed.
|
| - expectedConstant(x);
|
| - return null;
|
| - }
|
| -
|
| - @Override
|
| - public Void visitFunctionObjectInvocation(DartFunctionObjectInvocation x) {
|
| - // No need to traverse, function object invocations are always disallowed.
|
| - expectedConstant(x);
|
| - return null;
|
| - }
|
| -
|
| - @Override
|
| - public Void visitNamedExpression(DartNamedExpression node) {
|
| - return node.getExpression().accept(this);
|
| - }
|
| -
|
| - @Override
|
| - public Void visitIdentifier(DartIdentifier x) {
|
| - x.visitChildren(this);
|
| -
|
| - if (x.getParent() instanceof DartDeclaration<?>
|
| - && ((DartDeclaration<?>) x.getParent()).getName() == x) {
|
| - return null;
|
| - }
|
| -
|
| - Element element = x.getElement();
|
| - boolean elementIsStatic = element != null
|
| - && (element.getModifiers().isStatic() || Elements.isTopLevel(element));
|
| - switch (ElementKind.of(element)) {
|
| - case CLASS:
|
| - case PARAMETER:
|
| - case LIBRARY_PREFIX:
|
| - break;
|
| -
|
| - case FIELD:
|
| - FieldElement fieldElement = (FieldElement) element;
|
| -
|
| - // Check for circular references.
|
| - if (element != null && visitedElements.contains(element)) {
|
| - context.onError(new DartCompilationError(x, ResolverErrorCode.CIRCULAR_REFERENCE));
|
| - rememberInferredType(x, getMostSpecificType(x));
|
| - return null;
|
| - }
|
| - visitedElements.add(element);
|
| -
|
| - // Should be declared as constant.
|
| - if (!element.getModifiers().isConstant()) {
|
| - expectedConstant(x);
|
| - }
|
| -
|
| - // Infer type by visiting node or cached from Element.
|
| - final Type inferredType;
|
| - if (element instanceof FieldNodeElement) {
|
| - FieldNodeElement fieldNodeElement = (FieldNodeElement) element;
|
| - DartNode fieldNode = fieldNodeElement.getNode();
|
| - fieldNode.accept(this);
|
| - inferredType = getMostSpecificType(fieldNode);
|
| - fieldNodeElement.setConstantType(inferredType);
|
| - } else if (fieldElement.getType() != null
|
| - && !fieldElement.getType().equals(dynamicType)) {
|
| - inferredType = fieldElement.getType();
|
| - } else {
|
| - inferredType = fieldElement.getConstantType();
|
| - }
|
| -
|
| - // Done with this element.
|
| - visitedElements.remove(element);
|
| -
|
| - rememberInferredType(x, inferredType);
|
| - break;
|
| -
|
| - case VARIABLE:
|
| - if (!element.getModifiers().isConstant()) {
|
| - expectedConstant(x);
|
| - }
|
| - return null;
|
| -
|
| - case METHOD:
|
| - if (!elementIsStatic) {
|
| - expectedConstant(x);
|
| - }
|
| - return null;
|
| -
|
| - case NONE:
|
| - default:
|
| - expectedConstant(x);
|
| - return null;
|
| - }
|
| - return null;
|
| - }
|
| -
|
| -
|
| - @Override
|
| - public Void visitIntegerLiteral(DartIntegerLiteral x) {
|
| - rememberInferredType(x, intType);
|
| - return null;
|
| - }
|
| -
|
| - @Override
|
| - public Void visitInvocation(DartInvocation x) {
|
| - // No need to traverse, invocations are always disallowed.
|
| - expectedConstant(x);
|
| - return null;
|
| - }
|
| -
|
| - @Override
|
| - public Void visitMapLiteral(DartMapLiteral x) {
|
| - if (!x.isConst()) {
|
| - expectedConstant(x);
|
| - } else {
|
| - for (DartMapLiteralEntry entry : x.getEntries()) {
|
| - entry.accept(this);
|
| - }
|
| - }
|
| - return null;
|
| - }
|
| -
|
| - @Override
|
| - public Void visitMethodInvocation(DartMethodInvocation x) {
|
| - // No need to traverse, method invocations are always disallowed.
|
| - expectedConstant(x);
|
| - return null;
|
| - }
|
| -
|
| - @Override
|
| - public Void visitNewExpression(DartNewExpression x) {
|
| - if (!x.isConst()) {
|
| - expectedConstant(x);
|
| - } else {
|
| - for (DartExpression arg : x.getArguments()) {
|
| - arg.accept(this);
|
| - }
|
| - }
|
| - rememberInferredType(x, x.getConstructor().getType());
|
| - return null;
|
| - }
|
| -
|
| - @Override
|
| - public Void visitParenthesizedExpression(DartParenthesizedExpression x) {
|
| - x.visitChildren(this);
|
| - Type type = getMostSpecificType(x.getExpression());
|
| - rememberInferredType(x, type);
|
| - return null;
|
| - }
|
| -
|
| - @Override
|
| - public Void visitPropertyAccess(DartPropertyAccess x) {
|
| - switch (ElementKind.of(x.getRealTarget().getElement())) {
|
| - case CLASS:
|
| - case LIBRARY_PREFIX:
|
| - case LIBRARY:
|
| - case NONE:
|
| - // OK.
|
| - break;
|
| - default:
|
| - expectedConstant(x);
|
| - return null;
|
| - }
|
| -
|
| - Type type = getMostSpecificType(x.getName());
|
| - rememberInferredType(x, type);
|
| -
|
| - Element element = x.getName().getElement();
|
| - if (element != null) {
|
| - // OK. Static method reference.
|
| - if (ElementKind.of(element) == ElementKind.METHOD && element.getModifiers().isStatic()) {
|
| - return null;
|
| - }
|
| - // OK. Constant field.
|
| - if (element.getModifiers().isConstant()) {
|
| - return null;
|
| - }
|
| - // Fail.
|
| - expectedConstant(x);
|
| - }
|
| - return null;
|
| - }
|
| -
|
| - @Override
|
| - public Void visitRedirectConstructorInvocation(DartRedirectConstructorInvocation x) {
|
| - Element element = x.getElement();
|
| - if (element != null) {
|
| - if (!element.getModifiers().isConstant()) {
|
| - expectedConstant(x);
|
| - }
|
| - }
|
| - x.visitChildren(this);
|
| - return null;
|
| - }
|
| -
|
| - @Override
|
| - public Void visitStringInterpolation(DartStringInterpolation x) {
|
| - x.visitChildren(this);
|
| - for (DartExpression expression : x.getExpressions()) {
|
| - Type expressionType = getMostSpecificType(expression);
|
| - checkNumberBooleanOrStringType(expression, expressionType);
|
| - }
|
| - return null;
|
| - }
|
| -
|
| - @Override
|
| - public Void visitStringLiteral(DartStringLiteral x) {
|
| - rememberInferredType(x, stringType);
|
| - return null;
|
| - }
|
| -
|
| - @Override
|
| - public Void visitSuperExpression(DartSuperExpression x) {
|
| - if (!x.getElement().getModifiers().isConstant()) {
|
| - expectedConstant(x);
|
| - }
|
| - return null;
|
| - }
|
| -
|
| - @Override
|
| - public Void visitThisExpression(DartThisExpression x) {
|
| - // No need to traverse, this expressions are never constant
|
| - expectedConstant(x);
|
| - return null;
|
| - }
|
| -
|
| - @Override
|
| - public Void visitUnaryExpression(DartUnaryExpression x) {
|
| - x.visitChildren(this);
|
| -
|
| - Type type = getMostSpecificType(x.getArg());
|
| - switch (x.getOperator()) {
|
| - case NOT:
|
| - if (checkBoolean(x.getArg(), type)) {
|
| - rememberInferredType(x, boolType);
|
| - }
|
| - break;
|
| - case SUB:
|
| - if (intType.equals(type)) {
|
| - rememberInferredType(x, intType);
|
| - } else if (checkNumber(x.getArg(), type)) {
|
| - rememberInferredType(x, numType);
|
| - }
|
| - break;
|
| - case BIT_NOT:
|
| - if (checkInt(x.getArg(), type)) {
|
| - rememberInferredType(x, intType);
|
| - }
|
| - break;
|
| - default:
|
| - expectedConstant(x);
|
| - }
|
| - return null;
|
| - }
|
| -
|
| - @Override
|
| - public Void visitSuperConstructorInvocation(DartSuperConstructorInvocation x) {
|
| - x.visitChildren(this);
|
| - return null;
|
| - }
|
| -
|
| - @Override
|
| - public Void visitUnqualifiedInvocation(DartUnqualifiedInvocation x) {
|
| - Element element = x.getElement();
|
| - // "identical"
|
| - if (Elements.isFunctionIdentical(element)) {
|
| - x.visitChildren(this);
|
| - return null;
|
| - }
|
| - // No need to traverse, always disallowed.
|
| - expectedConstant(x);
|
| - return null;
|
| - }
|
| - }
|
| -
|
| - private class FindCompileTimeConstantExpressionsVisitor extends ASTVisitor<Void> {
|
| - private ClassElement currentClass;
|
| - private boolean inConstConstructor;
|
| -
|
| - @Override
|
| - public Void visitArrayLiteral(DartArrayLiteral node) {
|
| - if (node.isConst()) {
|
| - for (DartExpression expr : node.getExpressions()) {
|
| - checkConstantExpression(expr);
|
| - }
|
| - return null;
|
| - }
|
| - return super.visitArrayLiteral(node);
|
| - }
|
| -
|
| - @Override
|
| - public Void visitField(DartField node) {
|
| - if (node.getParent() != null) {
|
| - if (node.getModifiers().isConstant()) {
|
| - Type type = checkConstantExpression(node.getValue());
|
| - if (node.getElement().getType().equals(dynamicType)) {
|
| - node.getElement().setConstantType(type);
|
| - }
|
| - return null;
|
| - }
|
| - }
|
| - return super.visitField(node);
|
| - }
|
| -
|
| - @Override
|
| - public Void visitClass(DartClass node) {
|
| - ClassElement oldClassElement = currentClass;
|
| - currentClass = node.getElement();
|
| - try {
|
| - return super.visitClass(node);
|
| - } finally {
|
| - currentClass = oldClassElement;
|
| - }
|
| - }
|
| -
|
| - @Override
|
| - public Void visitMethodDefinition(DartMethodDefinition node) {
|
| - inConstConstructor = node.getModifiers().isConstant();
|
| - return super.visitMethodDefinition(node);
|
| - }
|
| -
|
| - @Override
|
| - public Void visitInitializer(DartInitializer node) {
|
| - if (inConstConstructor) {
|
| - String name = node.getInitializerName();
|
| - if (name != null) {
|
| - Element member = currentClass.lookupLocalElement(name);
|
| - if (member instanceof FieldElement) {
|
| - if (member.getModifiers().isFinal()) {
|
| - checkConstantExpression(node.getValue());
|
| - }
|
| - }
|
| - } else {
|
| - DartExpression value = node.getValue();
|
| - if (value instanceof DartSuperConstructorInvocation
|
| - || value instanceof DartRedirectConstructorInvocation) {
|
| - List<DartExpression> arguments = ((DartInvocation) value).getArguments();
|
| - for (DartExpression argument : arguments) {
|
| - checkConstantExpression(argument);
|
| - }
|
| - }
|
| - }
|
| - }
|
| - return super.visitInitializer(node);
|
| - }
|
| -
|
| - @Override
|
| - public Void visitCase(DartCase node) {
|
| - checkConstantExpression(node.getExpr());
|
| - return super.visitCase(node);
|
| - }
|
| -
|
| - @Override
|
| - public Void visitMapLiteral(DartMapLiteral node) {
|
| - if (node.isConst()) {
|
| - for (DartMapLiteralEntry entry : node.getEntries()) {
|
| - checkConstantExpression(entry.getKey());
|
| - checkConstantExpression(entry.getValue());
|
| - }
|
| - return null;
|
| - }
|
| - return super.visitMapLiteral(node);
|
| - }
|
| -
|
| - @Override
|
| - public Void visitNewExpression(DartNewExpression node) {
|
| - if (node.isConst()) {
|
| - for (DartExpression arg : node.getArguments()) {
|
| - checkConstantExpression(arg);
|
| - }
|
| - return null;
|
| - }
|
| - return super.visitNewExpression(node);
|
| - }
|
| -
|
| - @Override
|
| - public Void visitParameter(DartParameter node) {
|
| - checkConstantExpression(node.getDefaultExpr());
|
| - List<DartParameter> parameters = node.getFunctionParameters();
|
| - if (parameters != null) {
|
| - for (DartParameter parameter : parameters) {
|
| - visitParameter(parameter);
|
| - }
|
| - }
|
| - return null;
|
| - }
|
| -
|
| - @Override
|
| - public Void visitVariableStatement(DartVariableStatement node) {
|
| - Modifiers modifiers = node.getModifiers();
|
| - if (modifiers.isConstant()) {
|
| - for (DartVariable variable : node.getVariables()) {
|
| - if (variable.getValue() != null) {
|
| - checkConstantExpression(variable.getValue());
|
| - }
|
| - }
|
| - return null;
|
| - }
|
| - return super.visitVariableStatement(node);
|
| - }
|
| -
|
| - @Override
|
| - public Void visitRedirectConstructorInvocation(DartRedirectConstructorInvocation node) {
|
| - // Don't evaluate now, wait until it is referenced and evaluate as part of the expression
|
| - return null;
|
| - }
|
| -
|
| - @Override
|
| - public Void visitSuperConstructorInvocation(DartSuperConstructorInvocation node) {
|
| - // Don't evaluate now, wait until it is referenced and evaluate as part of the expression
|
| - return null;
|
| - }
|
| - }
|
| -
|
| - public static class Phase implements DartCompilationPhase {
|
| - /**
|
| - * Executes element resolution on the given compilation unit.
|
| - *
|
| - * @param context The listener through which compilation errors are reported
|
| - * (not <code>null</code>)
|
| - */
|
| - @Override
|
| - public DartUnit exec(DartUnit unit, DartCompilerContext context,
|
| - CoreTypeProvider typeProvider) {
|
| - new CompileTimeConstantAnalyzer(typeProvider, context).exec(unit);
|
| - return unit;
|
| - }
|
| - }
|
| -
|
| - public Set<Element> visitedElements = Sets.newHashSet();
|
| -
|
| - public Map<DartNode, Type> inferredTypes = Maps.newHashMap();
|
| -
|
| - private final DartCompilerContext context;
|
| - private final Type boolType;
|
| - private final Type doubleType;
|
| - private final Type intType;
|
| - private final Type numType;
|
| - private final Type stringType;
|
| - private final Type dynamicType;
|
| -
|
| - public CompileTimeConstantAnalyzer(CoreTypeProvider typeProvider,
|
| - DartCompilerContext context) {
|
| - this.context = context;
|
| - this.boolType = typeProvider.getBoolType();
|
| - this.doubleType = typeProvider.getDoubleType();
|
| - this.intType = typeProvider.getIntType();
|
| - this.numType = typeProvider.getNumType();
|
| - this.stringType = typeProvider.getStringType();
|
| - this.dynamicType = typeProvider.getDynamicType();
|
| - }
|
| -
|
| - private Type checkConstantExpression(DartExpression expression) {
|
| - if (expression != null) {
|
| - ExpressionVisitor visitor = new ExpressionVisitor();
|
| - expression.accept(visitor);
|
| - return visitor.getMostSpecificType(expression);
|
| - }
|
| - return null;
|
| - }
|
| -
|
| - public void exec(DartUnit unit) {
|
| - unit.accept(new FindCompileTimeConstantExpressionsVisitor());
|
| - }
|
| -}
|
|
|