Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(607)

Unified Diff: pkg/analyzer/lib/src/dart/constant/evaluation.dart

Issue 2167263002: fix #26141, add support for type arguments to constants (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/analyzer/lib/src/dart/constant/evaluation.dart
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index 57eee8973823954d54ef94305c1c0136612c826c..fcc14e114871f6141ba89614b895a02ca94c587a 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -75,6 +75,9 @@ class ConstantEvaluationEngine {
*/
final ConstantEvaluationValidator validator;
+ /** Whether we are running in strong mode. */
+ final bool strongMode;
+
/**
* Initialize a newly created [ConstantEvaluationEngine]. The [typeProvider]
* is used to access known types. [_declaredVariables] is the set of
@@ -82,9 +85,12 @@ class ConstantEvaluationEngine {
* given, is used to verify correct dependency analysis when running unit
* tests.
*/
- ConstantEvaluationEngine(this.typeProvider, this._declaredVariables,
+ ConstantEvaluationEngine(TypeProvider typeProvider, this._declaredVariables,
{ConstantEvaluationValidator validator, TypeSystem typeSystem})
- : validator =
+ : typeProvider = typeProvider,
+ strongMode =
+ typeProvider.objectType.element.context.analysisOptions.strongMode,
+ validator =
validator ?? new ConstantEvaluationValidator_ForProduction(),
typeSystem = typeSystem ?? new TypeSystemImpl();
@@ -231,6 +237,7 @@ class ConstantEvaluationEngine {
new ConstantVisitor(this, errorReporter);
DartObjectImpl result = evaluateConstructorCall(
constNode,
+ [],
constNode.arguments.arguments,
element,
constantVisitor,
@@ -409,7 +416,8 @@ class ConstantEvaluationEngine {
DartObjectImpl evaluateConstructorCall(
AstNode node,
- NodeList<Expression> arguments,
+ List<DartType> typeArguments,
+ List<Expression> arguments,
ConstructorElement constructor,
ConstantVisitor constantVisitor,
ErrorReporter errorReporter) {
@@ -515,25 +523,41 @@ class ConstantEvaluationEngine {
// so consider it an unknown value to suppress further errors.
return new DartObjectImpl.validWithUnknownValue(definingClass);
}
- HashMap<String, DartObjectImpl> fieldMap =
- new HashMap<String, DartObjectImpl>();
+ var fieldMap = new HashMap<String, DartObjectImpl>();
+ var typeArgumentMap = new HashMap<String, DartObjectImpl>.fromIterables(
+ (constructor.returnType as ParameterizedType)
+ .typeParameters
+ .map((t) => t.name),
+ typeArguments.map((t) =>
+ new DartObjectImpl(typeProvider.typeType, new TypeState(t))));
+
+ var fieldInitVisitor = new ConstantVisitor(this, errorReporter,
+ lexicalEnvironment: typeArgumentMap);
// Start with final fields that are initialized at their declaration site.
- for (FieldElement field in constructor.enclosingElement.fields) {
+ List<FieldElement> fields = constructor.enclosingElement.fields;
+ for (int i = 0; i < fields.length; i++) {
+ FieldElement field = fields[i];
if ((field.isFinal || field.isConst) &&
!field.isStatic &&
field is ConstFieldElementImpl) {
validator.beforeGetFieldEvaluationResult(field);
- EvaluationResultImpl evaluationResult = field.evaluationResult;
+
+ DartObjectImpl fieldValue;
+ if (strongMode) {
+ var fieldInit = constructorBase.fieldInitializers[i].initializer;
+ fieldValue = fieldInit.accept(fieldInitVisitor);
+ } else {
+ fieldValue = field.evaluationResult?.value;
+ }
// It is possible that the evaluation result is null.
// This happens for example when we have duplicate fields.
// class Test {final x = 1; final x = 2; const Test();}
- if (evaluationResult == null) {
+ if (fieldValue == null) {
continue;
}
// Match the value and the type.
DartType fieldType =
FieldMember.from(field, constructor.returnType).type;
- DartObjectImpl fieldValue = evaluationResult.value;
if (fieldValue != null && !runtimeTypeMatch(fieldValue, fieldType)) {
errorReporter.reportErrorForNode(
CheckedModeCompileTimeErrorCode
@@ -549,6 +573,14 @@ class ConstantEvaluationEngine {
new HashMap<String, DartObjectImpl>();
List<ParameterElement> parameters = constructor.parameters;
int parameterCount = parameters.length;
+
+ HashMap<ParameterElement, DefaultFormalParameter> parameterDefaultMap;
+ if (strongMode) {
+ parameterDefaultMap = new HashMap.fromIterable(
+ constructorBase.parameterInitializers,
+ key: (p) => p.parameter.element);
+ }
+
for (int i = 0; i < parameterCount; i++) {
ParameterElement parameter = parameters[i];
ParameterElement baseParameter = parameter;
@@ -574,12 +606,22 @@ class ConstantEvaluationEngine {
// The parameter is an optional positional parameter for which no value
// was provided, so use the default value.
validator.beforeGetParameterDefault(baseParameter);
- EvaluationResultImpl evaluationResult = baseParameter.evaluationResult;
- if (evaluationResult == null) {
- // No default was provided, so the default value is null.
- argumentValue = typeProvider.nullObject;
- } else if (evaluationResult.value != null) {
- argumentValue = evaluationResult.value;
+ if (strongMode) {
+ var defaultValue = parameterDefaultMap[parameter]?.defaultValue;
+ if (defaultValue == null) {
+ argumentValue = typeProvider.nullObject;
+ } else {
+ argumentValue = defaultValue.accept(fieldInitVisitor);
+ }
+ } else {
+ EvaluationResultImpl evaluationResult =
+ baseParameter.evaluationResult;
+ if (evaluationResult == null) {
+ // No default was provided, so the default value is null.
+ argumentValue = typeProvider.nullObject;
+ } else if (evaluationResult.value != null) {
+ argumentValue = evaluationResult.value;
+ }
}
}
if (argumentValue != null) {
@@ -661,6 +703,7 @@ class ConstantEvaluationEngine {
if (constructor != null && constructor.isConst) {
return evaluateConstructorCall(
node,
+ typeArguments,
initializer.argumentList.arguments,
constructor,
initializerVisitor,
@@ -677,8 +720,15 @@ class ConstantEvaluationEngine {
if (superArguments == null) {
superArguments = new NodeList<Expression>(null);
}
- evaluateSuperConstructorCall(node, fieldMap, superConstructor,
- superArguments, initializerVisitor, errorReporter);
+
+ evaluateSuperConstructorCall(
+ node,
+ fieldMap,
+ superConstructor,
+ superclass.typeArguments,
+ superArguments,
+ initializerVisitor,
+ errorReporter);
}
}
return new DartObjectImpl(definingClass, new GenericState(fieldMap));
@@ -688,12 +738,18 @@ class ConstantEvaluationEngine {
AstNode node,
HashMap<String, DartObjectImpl> fieldMap,
ConstructorElement superConstructor,
- NodeList<Expression> superArguments,
+ List<DartType> superTypeArguments,
+ List<Expression> superArguments,
ConstantVisitor initializerVisitor,
ErrorReporter errorReporter) {
if (superConstructor != null && superConstructor.isConst) {
- DartObjectImpl evaluationResult = evaluateConstructorCall(node,
- superArguments, superConstructor, initializerVisitor, errorReporter);
+ DartObjectImpl evaluationResult = evaluateConstructorCall(
+ node,
+ superTypeArguments,
+ superArguments,
+ superConstructor,
+ initializerVisitor,
+ errorReporter);
if (evaluationResult != null) {
fieldMap[GenericState.SUPERCLASS_FIELD] = evaluationResult;
}
@@ -1231,8 +1287,25 @@ class ConstantVisitor extends UnifyingAstVisitor<DartObjectImpl> {
// problem - the error has already been reported.
return null;
}
- return evaluationEngine.evaluateConstructorCall(
- node, node.argumentList.arguments, constructor, this, _errorReporter);
+
+ var type = constructor.returnType as ParameterizedType;
+ var typeArguments = type.typeArguments.map((t) {
+ if (t is TypeParameterType && _lexicalEnvironment != null) {
+ return _lexicalEnvironment[t.name]?.toTypeValue() ?? t;
+ }
+ return t;
+ }).toList();
+
+ if (constructor is ConstructorMember) {
+ constructor = (constructor as ConstructorMember).baseElement;
+ }
+
+ constructor = ConstructorMember.from(
+ constructor,
+ type.substitute2(typeArguments, type.typeArguments));
+
+ return evaluationEngine.evaluateConstructorCall(node, typeArguments,
+ node.argumentList.arguments, constructor, this, _errorReporter);
}
@override
@@ -1465,6 +1538,16 @@ class ConstantVisitor extends UnifyingAstVisitor<DartObjectImpl> {
_typeProvider.symbolType, new SymbolState(buffer.toString()));
}
+ @override
+ DartObjectImpl visitTypeName(TypeName node) {
+ // TODO(jmesserly): what to do about type arguments?
+ String name = node.name.name;
+ if (_lexicalEnvironment != null && _lexicalEnvironment.containsKey(name)) {
+ return _lexicalEnvironment[name];
+ }
+ return new DartObjectImpl(_typeProvider.typeType, new TypeState(node.type));
+ }
+
/**
* Create an error associated with the given [node]. The error will have the
* given error [code].
@@ -1497,10 +1580,9 @@ class ConstantVisitor extends UnifyingAstVisitor<DartObjectImpl> {
}
return new DartObjectImpl(functionType, new FunctionState(function));
}
- } else if (variableElement is ClassElement ||
- variableElement is FunctionTypeAliasElement ||
- variableElement is DynamicElementImpl) {
- return new DartObjectImpl(_typeProvider.typeType, new TypeState(element));
+ } else if (variableElement is TypeDefiningElement) {
+ return new DartObjectImpl(
+ _typeProvider.typeType, new TypeState(variableElement.type));
}
// TODO(brianwilkerson) Figure out which error to report.
_error(node, null);

Powered by Google App Engine
This is Rietveld 408576698