Index: editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/constant/ConstantVisitor.java |
diff --git a/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/constant/ConstantVisitor.java b/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/constant/ConstantVisitor.java |
index 175a74470050d3eb87ee4cdf456bd6d28e092cb3..9253d8569953a58ceee5372dca61c73940dfdb52 100644 |
--- a/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/constant/ConstantVisitor.java |
+++ b/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/constant/ConstantVisitor.java |
@@ -47,15 +47,37 @@ import com.google.dart.engine.element.CompilationUnitElement; |
import com.google.dart.engine.element.ConstructorElement; |
import com.google.dart.engine.element.Element; |
import com.google.dart.engine.element.ExecutableElement; |
+import com.google.dart.engine.element.FieldFormalParameterElement; |
import com.google.dart.engine.element.FunctionElement; |
import com.google.dart.engine.element.FunctionTypeAliasElement; |
import com.google.dart.engine.element.LibraryElement; |
+import com.google.dart.engine.element.ParameterElement; |
import com.google.dart.engine.element.PrefixElement; |
import com.google.dart.engine.element.PropertyAccessorElement; |
import com.google.dart.engine.error.CompileTimeErrorCode; |
import com.google.dart.engine.error.ErrorCode; |
import com.google.dart.engine.internal.element.VariableElementImpl; |
+import com.google.dart.engine.internal.object.BoolState; |
+import com.google.dart.engine.internal.object.DartObjectImpl; |
+import com.google.dart.engine.internal.object.DoubleState; |
+import com.google.dart.engine.internal.object.FunctionState; |
+import com.google.dart.engine.internal.object.GenericState; |
+import com.google.dart.engine.internal.object.InstanceState; |
+import com.google.dart.engine.internal.object.IntState; |
+import com.google.dart.engine.internal.object.ListState; |
+import com.google.dart.engine.internal.object.MapState; |
+import com.google.dart.engine.internal.object.NullState; |
+import com.google.dart.engine.internal.object.StringState; |
+import com.google.dart.engine.internal.object.SymbolState; |
+import com.google.dart.engine.internal.object.TypeState; |
+import com.google.dart.engine.internal.resolver.TypeProvider; |
+import com.google.dart.engine.scanner.Token; |
import com.google.dart.engine.scanner.TokenType; |
+import com.google.dart.engine.type.InterfaceType; |
+import com.google.dart.engine.utilities.dart.ParameterKind; |
+ |
+import java.util.ArrayList; |
+import java.util.HashMap; |
/** |
* Instances of the class {@code ConstantVisitor} evaluate constant expressions to produce their |
@@ -65,37 +87,61 @@ import com.google.dart.engine.scanner.TokenType; |
* <li>A literal number.</li> |
* <li>A literal boolean.</li> |
* <li>A literal string where any interpolated expression is a compile-time constant that evaluates |
- * to a numeric, string or boolean value or to {@code null}.</li> |
- * <li>{@code null}.</li> |
- * <li>A reference to a static constant variable.</li> |
- * <li>An identifier expression that denotes a constant variable, a class or a type parameter.</li> |
+ * to a numeric, string or boolean value or to <b>null</b>.</li> |
+ * <li>A literal symbol.</li> |
+ * <li><b>null</b>.</li> |
+ * <li>A qualified reference to a static constant variable.</li> |
+ * <li>An identifier expression that denotes a constant variable, class or type alias.</li> |
* <li>A constant constructor invocation.</li> |
* <li>A constant list literal.</li> |
* <li>A constant map literal.</li> |
* <li>A simple or qualified identifier denoting a top-level function or a static method.</li> |
- * <li>A parenthesized expression {@code (e)} where {@code e} is a constant expression.</li> |
- * <li>An expression of one of the forms {@code identical(e1, e2)}, {@code e1 == e2}, |
- * {@code e1 != e2} where {@code e1} and {@code e2} are constant expressions that evaluate to a |
- * numeric, string or boolean value or to {@code null}.</li> |
- * <li>An expression of one of the forms {@code !e}, {@code e1 && e2} or {@code e1 || e2}, where |
- * {@code e}, {@code e1} and {@code e2} are constant expressions that evaluate to a boolean value or |
- * to {@code null}.</li> |
- * <li>An expression of one of the forms {@code ~e}, {@code e1 ^ e2}, {@code e1 & e2}, |
- * {@code e1 | e2}, {@code e1 >> e2} or {@code e1 << e2}, where {@code e}, {@code e1} and {@code e2} |
- * are constant expressions that evaluate to an integer value or to {@code null}.</li> |
- * <li>An expression of one of the forms {@code -e}, {@code e1 + e2}, {@code e1 - e2}, |
- * {@code e1 * e2}, {@code e1 / e2}, {@code e1 ~/ e2}, {@code e1 > e2}, {@code e1 < e2}, |
- * {@code e1 >= e2}, {@code e1 <= e2} or {@code e1 % e2}, where {@code e}, {@code e1} and {@code e2} |
- * are constant expressions that evaluate to a numeric value or to {@code null}.</li> |
+ * <li>A parenthesized expression <i>(e)</i> where <i>e</i> is a constant expression.</li> |
+ * <li>An expression of the form <i>identical(e<sub>1</sub>, e<sub>2</sub>)</i> where |
+ * <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant expressions and <i>identical()</i> is |
+ * statically bound to the predefined dart function <i>identical()</i> discussed above.</li> |
+ * <li>An expression of one of the forms <i>e<sub>1</sub> == e<sub>2</sub></i> or <i>e<sub>1</sub> |
+ * != e<sub>2</sub></i> where <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant expressions |
+ * that evaluate to a numeric, string or boolean value.</li> |
+ * <li>An expression of one of the forms <i>!e</i>, <i>e<sub>1</sub> && e<sub>2</sub></i> or |
+ * <i>e<sub>1</sub> || e<sub>2</sub></i>, where <i>e</i>, <i>e1</sub></i> and <i>e2</sub></i> are |
+ * constant expressions that evaluate to a boolean value.</li> |
+ * <li>An expression of one of the forms <i>~e</i>, <i>e<sub>1</sub> ^ e<sub>2</sub></i>, |
+ * <i>e<sub>1</sub> & e<sub>2</sub></i>, <i>e<sub>1</sub> | e<sub>2</sub></i>, <i>e<sub>1</sub> |
+ * >> e<sub>2</sub></i> or <i>e<sub>1</sub> << e<sub>2</sub></i>, where <i>e</i>, |
+ * <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant expressions that evaluate to an |
+ * integer value or to <b>null</b>.</li> |
+ * <li>An expression of one of the forms <i>-e</i>, <i>e<sub>1</sub> + e<sub>2</sub></i>, |
+ * <i>e<sub>1</sub> - e<sub>2</sub></i>, <i>e<sub>1</sub> * e<sub>2</sub></i>, <i>e<sub>1</sub> / |
+ * e<sub>2</sub></i>, <i>e<sub>1</sub> ~/ e<sub>2</sub></i>, <i>e<sub>1</sub> > |
+ * e<sub>2</sub></i>, <i>e<sub>1</sub> < e<sub>2</sub></i>, <i>e<sub>1</sub> >= |
+ * e<sub>2</sub></i>, <i>e<sub>1</sub> <= e<sub>2</sub></i> or <i>e<sub>1</sub> % |
+ * e<sub>2</sub></i>, where <i>e</i>, <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant |
+ * expressions that evaluate to a numeric value or to <b>null</b>.</li> |
+ * <li>An expression of the form <i>e<sub>1</sub> ? e<sub>2</sub> : e<sub>3</sub></i> where |
+ * <i>e<sub>1</sub></i>, <i>e<sub>2</sub></i> and <i>e<sub>3</sub></i> are constant expressions, and |
+ * <i>e<sub>1</sub></i> evaluates to a boolean value.</li> |
* </ul> |
* </blockquote> |
*/ |
public class ConstantVisitor extends UnifyingASTVisitor<EvaluationResultImpl> { |
/** |
+ * The type provider used to access the known types. |
+ */ |
+ private TypeProvider typeProvider; |
+ |
+ /** |
+ * An shared object representing the value 'null'. |
+ */ |
+ private DartObjectImpl nullObject; |
+ |
+ /** |
* Initialize a newly created constant visitor. |
+ * |
+ * @param typeProvider the type provider used to access known types |
*/ |
- public ConstantVisitor() { |
- super(); |
+ public ConstantVisitor(TypeProvider typeProvider) { |
+ this.typeProvider = typeProvider; |
} |
@Override |
@@ -105,7 +151,7 @@ public class ConstantVisitor extends UnifyingASTVisitor<EvaluationResultImpl> { |
if (result == null) { |
result = string.accept(this); |
} else { |
- result = result.concatenate(node, string.accept(this)); |
+ result = result.concatenate(typeProvider, node, string.accept(this)); |
} |
} |
return result; |
@@ -126,43 +172,43 @@ public class ConstantVisitor extends UnifyingASTVisitor<EvaluationResultImpl> { |
// evaluate operator |
switch (operatorType) { |
case AMPERSAND: |
- return leftResult.bitAnd(node, rightResult); |
+ return leftResult.bitAnd(typeProvider, node, rightResult); |
case AMPERSAND_AMPERSAND: |
- return leftResult.logicalAnd(node, rightResult); |
+ return leftResult.logicalAnd(typeProvider, node, rightResult); |
case BANG_EQ: |
- return leftResult.notEqual(node, rightResult); |
+ return leftResult.notEqual(typeProvider, node, rightResult); |
case BAR: |
- return leftResult.bitOr(node, rightResult); |
+ return leftResult.bitOr(typeProvider, node, rightResult); |
case BAR_BAR: |
- return leftResult.logicalOr(node, rightResult); |
+ return leftResult.logicalOr(typeProvider, node, rightResult); |
case CARET: |
- return leftResult.bitXor(node, rightResult); |
+ return leftResult.bitXor(typeProvider, node, rightResult); |
case EQ_EQ: |
- return leftResult.equalEqual(node, rightResult); |
+ return leftResult.equalEqual(typeProvider, node, rightResult); |
case GT: |
- return leftResult.greaterThan(node, rightResult); |
+ return leftResult.greaterThan(typeProvider, node, rightResult); |
case GT_EQ: |
- return leftResult.greaterThanOrEqual(node, rightResult); |
+ return leftResult.greaterThanOrEqual(typeProvider, node, rightResult); |
case GT_GT: |
- return leftResult.shiftRight(node, rightResult); |
+ return leftResult.shiftRight(typeProvider, node, rightResult); |
case LT: |
- return leftResult.lessThan(node, rightResult); |
+ return leftResult.lessThan(typeProvider, node, rightResult); |
case LT_EQ: |
- return leftResult.lessThanOrEqual(node, rightResult); |
+ return leftResult.lessThanOrEqual(typeProvider, node, rightResult); |
case LT_LT: |
- return leftResult.shiftLeft(node, rightResult); |
+ return leftResult.shiftLeft(typeProvider, node, rightResult); |
case MINUS: |
- return leftResult.minus(node, rightResult); |
+ return leftResult.minus(typeProvider, node, rightResult); |
case PERCENT: |
- return leftResult.remainder(node, rightResult); |
+ return leftResult.remainder(typeProvider, node, rightResult); |
case PLUS: |
- return leftResult.add(node, rightResult); |
+ return leftResult.add(typeProvider, node, rightResult); |
case STAR: |
- return leftResult.times(node, rightResult); |
+ return leftResult.times(typeProvider, node, rightResult); |
case SLASH: |
- return leftResult.divide(node, rightResult); |
+ return leftResult.divide(typeProvider, node, rightResult); |
case TILDE_SLASH: |
- return leftResult.integerDivide(node, rightResult); |
+ return leftResult.integerDivide(typeProvider, node, rightResult); |
} |
// TODO(brianwilkerson) Figure out which error to report. |
return error(node, null); |
@@ -170,31 +216,42 @@ public class ConstantVisitor extends UnifyingASTVisitor<EvaluationResultImpl> { |
@Override |
public EvaluationResultImpl visitBooleanLiteral(BooleanLiteral node) { |
- return node.getValue() ? ValidResult.RESULT_TRUE : ValidResult.RESULT_FALSE; |
+ return valid(typeProvider.getBoolType(), BoolState.from(node.getValue())); |
} |
@Override |
public EvaluationResultImpl visitConditionalExpression(ConditionalExpression node) { |
Expression condition = node.getCondition(); |
EvaluationResultImpl conditionResult = condition.accept(this); |
- conditionResult = conditionResult.applyBooleanConversion(condition); |
+ EvaluationResultImpl thenResult = node.getThenExpression().accept(this); |
+ EvaluationResultImpl elseResult = node.getElseExpression().accept(this); |
+ if (conditionResult instanceof ErrorResult) { |
+ return union(union((ErrorResult) conditionResult, thenResult), elseResult); |
+ } else if (!((ValidResult) conditionResult).isBool()) { |
+ return new ErrorResult(condition, CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL); |
+ } else if (thenResult instanceof ErrorResult) { |
+ return union((ErrorResult) thenResult, elseResult); |
+ } else if (elseResult instanceof ErrorResult) { |
+ return elseResult; |
+ } |
+ conditionResult = conditionResult.applyBooleanConversion(typeProvider, condition); |
if (conditionResult instanceof ErrorResult) { |
return conditionResult; |
} |
- EvaluationResultImpl thenResult = node.getThenExpression().accept(this); |
- if (thenResult instanceof ErrorResult) { |
+ ValidResult validResult = (ValidResult) conditionResult; |
+ if (validResult.isTrue()) { |
return thenResult; |
- } |
- EvaluationResultImpl elseResult = node.getElseExpression().accept(this); |
- if (elseResult instanceof ErrorResult) { |
+ } else if (validResult.isFalse()) { |
return elseResult; |
} |
- return (conditionResult == ValidResult.RESULT_TRUE) ? thenResult : elseResult; |
+ InterfaceType thenType = ((ValidResult) thenResult).getValue().getType(); |
+ InterfaceType elseType = ((ValidResult) elseResult).getValue().getType(); |
+ return valid((InterfaceType) thenType.getLeastUpperBound(elseType)); |
} |
@Override |
public EvaluationResultImpl visitDoubleLiteral(DoubleLiteral node) { |
- return new ValidResult(Double.valueOf(node.getValue())); |
+ return valid(typeProvider.getDoubleType(), new DoubleState(node.getValue())); |
} |
@Override |
@@ -205,8 +262,54 @@ public class ConstantVisitor extends UnifyingASTVisitor<EvaluationResultImpl> { |
} |
ConstructorElement constructor = node.getStaticElement(); |
if (constructor != null && constructor.isConst()) { |
- node.getArgumentList().accept(this); |
- return ValidResult.RESULT_OBJECT; |
+ NodeList<Expression> arguments = node.getArgumentList().getArguments(); |
+ int argumentCount = arguments.size(); |
+ DartObjectImpl[] argumentValues = new DartObjectImpl[argumentCount]; |
+ HashMap<String, DartObjectImpl> namedArgumentValues = new HashMap<String, DartObjectImpl>(); |
+ for (int i = 0; i < argumentCount; i++) { |
+ Expression argument = arguments.get(i); |
+ if (argument instanceof NamedExpression) { |
+ NamedExpression namedExpression = (NamedExpression) argument; |
+ String name = namedExpression.getName().getLabel().getName(); |
+ namedArgumentValues.put(name, valueOf(namedExpression.getExpression())); |
+ argumentValues[i] = getNull(); |
+ } else { |
+ argumentValues[i] = valueOf(argument); |
+ } |
+ } |
+ InterfaceType definingClass = (InterfaceType) constructor.getReturnType(); |
+ if (definingClass.getElement().getLibrary().isDartCore()) { |
+ String className = definingClass.getName(); |
+ if (className.equals("Symbol") && argumentCount == 1) { |
+ String argumentValue = argumentValues[0].getStringValue(); |
+ if (argumentValue != null) { |
+ return valid(definingClass, new SymbolState(argumentValue)); |
+ } |
+ } |
+ } |
+ HashMap<String, DartObjectImpl> fieldMap = new HashMap<String, DartObjectImpl>(); |
+ ParameterElement[] parameters = constructor.getParameters(); |
+ int parameterCount = parameters.length; |
+ for (int i = 0; i < parameterCount; i++) { |
+ ParameterElement parameter = parameters[i]; |
+ if (parameter.isInitializingFormal()) { |
+ String fieldName = ((FieldFormalParameterElement) parameter).getField().getName(); |
+ if (parameter.getParameterKind() == ParameterKind.NAMED) { |
+ DartObjectImpl argumentValue = namedArgumentValues.get(parameter.getName()); |
+ if (argumentValue != null) { |
+ fieldMap.put(fieldName, argumentValue); |
+ } |
+ } else if (i < argumentCount) { |
+ fieldMap.put(fieldName, argumentValues[i]); |
+ // Otherwise, the parameter is assumed to be an optional positional parameter for which |
+ // no value was provided. |
+ } |
+ } |
+ } |
+ // TODO(brianwilkerson) This doesn't handle fields initialized in an initializer. We should be |
+ // able to handle fields initialized by the superclass' constructor fairly easily, but other |
+ // initializers will be harder. |
+ return valid(definingClass, new GenericState(fieldMap)); |
} |
// TODO(brianwilkerson) Figure out which error to report. |
return error(node, null); |
@@ -214,18 +317,21 @@ public class ConstantVisitor extends UnifyingASTVisitor<EvaluationResultImpl> { |
@Override |
public EvaluationResultImpl visitIntegerLiteral(IntegerLiteral node) { |
- return new ValidResult(node.getValue()); |
+ return valid(typeProvider.getIntType(), new IntState(node.getValue())); |
} |
@Override |
public EvaluationResultImpl visitInterpolationExpression(InterpolationExpression node) { |
EvaluationResultImpl result = node.getExpression().accept(this); |
- return result.performToString(node); |
+ if (result instanceof ValidResult && !((ValidResult) result).isBoolNumStringOrNull()) { |
+ return error(node, CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING); |
+ } |
+ return result.performToString(typeProvider, node); |
} |
@Override |
public EvaluationResultImpl visitInterpolationString(InterpolationString node) { |
- return new ValidResult(node.getValue()); |
+ return valid(typeProvider.getStringType(), new StringState(node.getValue())); |
} |
@Override |
@@ -234,13 +340,20 @@ public class ConstantVisitor extends UnifyingASTVisitor<EvaluationResultImpl> { |
return new ErrorResult(node, CompileTimeErrorCode.MISSING_CONST_IN_LIST_LITERAL); |
} |
ErrorResult result = null; |
+ ArrayList<DartObjectImpl> elements = new ArrayList<DartObjectImpl>(); |
for (Expression element : node.getElements()) { |
- result = union(result, element.accept(this)); |
+ EvaluationResultImpl elementResult = element.accept(this); |
+ result = union(result, elementResult); |
+ if (elementResult instanceof ValidResult) { |
+ elements.add(((ValidResult) elementResult).getValue()); |
+ } |
} |
if (result != null) { |
return result; |
} |
- return ValidResult.RESULT_OBJECT; |
+ return valid( |
+ typeProvider.getListType(), |
+ new ListState(elements.toArray(new DartObjectImpl[elements.size()]))); |
} |
@Override |
@@ -249,14 +362,20 @@ public class ConstantVisitor extends UnifyingASTVisitor<EvaluationResultImpl> { |
return new ErrorResult(node, CompileTimeErrorCode.MISSING_CONST_IN_MAP_LITERAL); |
} |
ErrorResult result = null; |
+ HashMap<DartObjectImpl, DartObjectImpl> map = new HashMap<DartObjectImpl, DartObjectImpl>(); |
for (MapLiteralEntry entry : node.getEntries()) { |
- result = union(result, entry.getKey().accept(this)); |
- result = union(result, entry.getValue().accept(this)); |
+ EvaluationResultImpl keyResult = entry.getKey().accept(this); |
+ EvaluationResultImpl valueResult = entry.getValue().accept(this); |
+ result = union(result, keyResult); |
+ result = union(result, valueResult); |
+ if (keyResult instanceof ValidResult && valueResult instanceof ValidResult) { |
+ map.put(((ValidResult) keyResult).getValue(), ((ValidResult) valueResult).getValue()); |
+ } |
} |
if (result != null) { |
return result; |
} |
- return ValidResult.RESULT_OBJECT; |
+ return valid(typeProvider.getMapType(), new MapState(map)); |
} |
@Override |
@@ -273,7 +392,7 @@ public class ConstantVisitor extends UnifyingASTVisitor<EvaluationResultImpl> { |
if (library.isDartCore()) { |
EvaluationResultImpl leftArgument = arguments.get(0).accept(this); |
EvaluationResultImpl rightArgument = arguments.get(1).accept(this); |
- return leftArgument.equalEqual(node, rightArgument); |
+ return leftArgument.equalEqual(typeProvider, node, rightArgument); |
} |
} |
} |
@@ -296,7 +415,7 @@ public class ConstantVisitor extends UnifyingASTVisitor<EvaluationResultImpl> { |
@Override |
public EvaluationResultImpl visitNullLiteral(NullLiteral node) { |
- return ValidResult.RESULT_NULL; |
+ return new ValidResult(getNull()); |
} |
@Override |
@@ -327,11 +446,11 @@ public class ConstantVisitor extends UnifyingASTVisitor<EvaluationResultImpl> { |
} |
switch (node.getOperator().getType()) { |
case BANG: |
- return operand.logicalNot(node); |
+ return operand.logicalNot(typeProvider, node); |
case TILDE: |
- return operand.bitNot(node); |
+ return operand.bitNot(typeProvider, node); |
case MINUS: |
- return operand.negated(node); |
+ return operand.negated(typeProvider, node); |
} |
// TODO(brianwilkerson) Figure out which error to report. |
return error(node, null); |
@@ -349,7 +468,7 @@ public class ConstantVisitor extends UnifyingASTVisitor<EvaluationResultImpl> { |
@Override |
public EvaluationResultImpl visitSimpleStringLiteral(SimpleStringLiteral node) { |
- return new ValidResult(node.getValue()); |
+ return valid(typeProvider.getStringType(), new StringState(node.getValue())); |
} |
@Override |
@@ -359,7 +478,7 @@ public class ConstantVisitor extends UnifyingASTVisitor<EvaluationResultImpl> { |
if (result == null) { |
result = element.accept(this); |
} else { |
- result = result.concatenate(node, element.accept(this)); |
+ result = result.concatenate(typeProvider, node, element.accept(this)); |
} |
} |
return result; |
@@ -367,7 +486,15 @@ public class ConstantVisitor extends UnifyingASTVisitor<EvaluationResultImpl> { |
@Override |
public EvaluationResultImpl visitSymbolLiteral(SymbolLiteral node) { |
- return ValidResult.RESULT_SYMBOL; |
+ StringBuilder builder = new StringBuilder(); |
+ Token[] components = node.getComponents(); |
+ for (int i = 0; i < components.length; i++) { |
+ if (i > 0) { |
+ builder.append('.'); |
+ } |
+ builder.append(components[i].getLexeme()); |
+ } |
+ return valid(typeProvider.getSymbolType(), new SymbolState(builder.toString())); |
} |
/** |
@@ -399,17 +526,30 @@ public class ConstantVisitor extends UnifyingASTVisitor<EvaluationResultImpl> { |
return value; |
} |
} else if (element instanceof ExecutableElement) { |
- if (((ExecutableElement) element).isStatic()) { |
- return new ValidResult(element); |
+ ExecutableElement function = (ExecutableElement) element; |
+ if (function.isStatic()) { |
+ return valid(typeProvider.getFunctionType(), new FunctionState(function)); |
} |
} else if (element instanceof ClassElement || element instanceof FunctionTypeAliasElement) { |
- return ValidResult.RESULT_OBJECT; |
+ return valid(typeProvider.getTypeType(), new TypeState(element)); |
} |
// TODO(brianwilkerson) Figure out which error to report. |
return error(node, null); |
} |
/** |
+ * Return an object representing the value 'null'. |
+ * |
+ * @return an object representing the value 'null' |
+ */ |
+ private DartObjectImpl getNull() { |
+ if (nullObject == null) { |
+ nullObject = new DartObjectImpl(typeProvider.getNullType(), NullState.NULL_STATE); |
+ } |
+ return nullObject; |
+ } |
+ |
+ /** |
* Return the union of the errors encoded in the given results. |
* |
* @param leftResult the first set of errors, or {@code null} if there was no previous collection |
@@ -428,4 +568,39 @@ public class ConstantVisitor extends UnifyingASTVisitor<EvaluationResultImpl> { |
} |
return leftResult; |
} |
+ |
+ private ValidResult valid(InterfaceType type) { |
+ if (type.getElement().getLibrary().isDartCore()) { |
+ String typeName = type.getName(); |
+ if (typeName.equals("bool")) { |
+ return valid(type, BoolState.UNKNOWN_VALUE); |
+ } else if (typeName.equals("double")) { |
+ return valid(type, DoubleState.UNKNOWN_VALUE); |
+ } else if (typeName.equals("int")) { |
+ return valid(type, IntState.UNKNOWN_VALUE); |
+ } else if (typeName.equals("String")) { |
+ return valid(type, StringState.UNKNOWN_VALUE); |
+ } |
+ } |
+ return valid(type, GenericState.UNKNOWN_VALUE); |
+ } |
+ |
+ private ValidResult valid(InterfaceType type, InstanceState state) { |
+ return new ValidResult(new DartObjectImpl(type, state)); |
+ } |
+ |
+ /** |
+ * Return the value of the given expression, or a representation of 'null' if the expression |
+ * cannot be evaluated. |
+ * |
+ * @param expression the expression whose value is to be returned |
+ * @return the value of the given expression |
+ */ |
+ private DartObjectImpl valueOf(Expression expression) { |
+ EvaluationResultImpl expressionValue = expression.accept(this); |
+ if (expressionValue instanceof ValidResult) { |
+ return ((ValidResult) expressionValue).getValue(); |
+ } |
+ return getNull(); |
+ } |
} |