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()); |
- } |
-} |