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

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

Issue 2196483002: Revert "Revert "fix #26141, add support for type arguments to constants"" (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: fix language tests 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
« no previous file with comments | « pkg/analyzer/lib/src/dart/ast/utilities.dart ('k') | pkg/analyzer/lib/src/dart/constant/value.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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..45c3bda38126a82d0a935f0e197f9269f2ec77ea 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();
@@ -409,7 +415,7 @@ class ConstantEvaluationEngine {
DartObjectImpl evaluateConstructorCall(
AstNode node,
- NodeList<Expression> arguments,
+ List<Expression> arguments,
ConstructorElement constructor,
ConstantVisitor constantVisitor,
ErrorReporter errorReporter) {
@@ -515,25 +521,49 @@ 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>();
+
+ // In strong mode, we allow constants to have type arguments.
+ //
+ // They will be added to the lexical environment when evaluating
+ // subexpressions.
+ HashMap<String, DartObjectImpl> typeArgumentMap;
+ if (strongMode) {
+ // Instantiate the constructor with the in-scope type arguments.
+ definingClass = constantVisitor.evaluateType(definingClass);
+ constructor = ConstructorMember.from(constructorBase, definingClass);
+
+ typeArgumentMap = new HashMap<String, DartObjectImpl>.fromIterables(
+ definingClass.typeParameters.map((t) => t.name),
+ definingClass.typeArguments.map(constantVisitor.typeConstant));
+ }
+
+ var fieldMap = new HashMap<String, DartObjectImpl>();
+ 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) {
+ fieldValue = field.constantInitializer.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 +579,7 @@ class ConstantEvaluationEngine {
new HashMap<String, DartObjectImpl>();
List<ParameterElement> parameters = constructor.parameters;
int parameterCount = parameters.length;
+
for (int i = 0; i < parameterCount; i++) {
ParameterElement parameter = parameters[i];
ParameterElement baseParameter = parameter;
@@ -574,12 +605,23 @@ 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 && baseParameter is ConstVariableElement) {
+ var defaultValue =
+ (baseParameter as ConstVariableElement).constantInitializer;
+ 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) {
@@ -677,6 +719,7 @@ class ConstantEvaluationEngine {
if (superArguments == null) {
superArguments = new NodeList<Expression>(null);
}
+
evaluateSuperConstructorCall(node, fieldMap, superConstructor,
superArguments, initializerVisitor, errorReporter);
}
@@ -688,7 +731,7 @@ class ConstantEvaluationEngine {
AstNode node,
HashMap<String, DartObjectImpl> fieldMap,
ConstructorElement superConstructor,
- NodeList<Expression> superArguments,
+ List<Expression> superArguments,
ConstantVisitor initializerVisitor,
ErrorReporter errorReporter) {
if (superConstructor != null && superConstructor.isConst) {
@@ -1231,6 +1274,7 @@ class ConstantVisitor extends UnifyingAstVisitor<DartObjectImpl> {
// problem - the error has already been reported.
return null;
}
+
return evaluationEngine.evaluateConstructorCall(
node, node.argumentList.arguments, constructor, this, _errorReporter);
}
@@ -1274,9 +1318,9 @@ class ConstantVisitor extends UnifyingAstVisitor<DartObjectImpl> {
return null;
}
DartType elementType = _typeProvider.dynamicType;
- if (node.typeArguments != null &&
- node.typeArguments.arguments.length == 1) {
- DartType type = node.typeArguments.arguments[0].type;
+ NodeList<TypeName> typeArgs = node.typeArguments?.arguments;
+ if (typeArgs?.length == 1) {
+ DartType type = visitTypeName(typeArgs[0])?.toTypeValue();
if (type != null) {
elementType = type;
}
@@ -1309,13 +1353,13 @@ class ConstantVisitor extends UnifyingAstVisitor<DartObjectImpl> {
}
DartType keyType = _typeProvider.dynamicType;
DartType valueType = _typeProvider.dynamicType;
- if (node.typeArguments != null &&
- node.typeArguments.arguments.length == 2) {
- DartType keyTypeCandidate = node.typeArguments.arguments[0].type;
+ NodeList<TypeName> typeArgs = node.typeArguments?.arguments;
+ if (typeArgs?.length == 2) {
+ DartType keyTypeCandidate = visitTypeName(typeArgs[0])?.toTypeValue();
if (keyTypeCandidate != null) {
keyType = keyTypeCandidate;
}
- DartType valueTypeCandidate = node.typeArguments.arguments[1].type;
+ DartType valueTypeCandidate = visitTypeName(typeArgs[1])?.toTypeValue();
if (valueTypeCandidate != null) {
valueType = valueTypeCandidate;
}
@@ -1465,6 +1509,56 @@ class ConstantVisitor extends UnifyingAstVisitor<DartObjectImpl> {
_typeProvider.symbolType, new SymbolState(buffer.toString()));
}
+ @override
+ DartObjectImpl visitTypeName(TypeName node) {
+ DartType type = evaluateType(node.type);
+ if (type == null) {
+ return super.visitTypeName(node);
+ }
+ return typeConstant(type);
+ }
+
+ /**
+ * Given a [type], returns the constant value that contains that type value.
+ */
+ DartObjectImpl typeConstant(DartType type) {
+ return new DartObjectImpl(_typeProvider.typeType, new TypeState(type));
+ }
+
+ /**
+ * Given a [type] that may contain free type variables, evaluate them against
+ * the current lexical environment and return the substituted type.
+ */
+ DartType evaluateType(DartType type) {
+ if (type is TypeParameterType) {
+ if (!evaluationEngine.strongMode) {
+ return null;
Paul Berry 2016/07/29 12:22:46 Nit: it would be nice to have a comment explaining
Jennifer Messerly 2016/07/29 16:04:50 Done.
+ }
+
+ String name = type.name;
+ if (_lexicalEnvironment != null) {
+ return _lexicalEnvironment[name]?.toTypeValue() ?? type;
+ }
+ return type;
+ }
+ if (type is ParameterizedType) {
+ List<DartType> typeArguments;
+ for (int i = 0; i < type.typeArguments.length; i++) {
+ DartType ta = type.typeArguments[i];
+ DartType t = evaluateType(ta);
+ if (!identical(t, ta)) {
+ if (typeArguments == null) {
+ typeArguments = type.typeArguments.toList(growable: false);
+ }
+ typeArguments[i] = t;
+ }
+ }
+ if (typeArguments == null) return type;
+ return type.substitute2(typeArguments, type.typeArguments);
+ }
+ return type;
+ }
+
/**
* Create an error associated with the given [node]. The error will have the
* given error [code].
@@ -1497,10 +1591,12 @@ 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) {
+ if (evaluationEngine.strongMode ||
+ variableElement is! TypeParameterElement) {
+ return new DartObjectImpl(
+ _typeProvider.typeType, new TypeState(variableElement.type));
+ }
}
// TODO(brianwilkerson) Figure out which error to report.
_error(node, null);
« no previous file with comments | « pkg/analyzer/lib/src/dart/ast/utilities.dart ('k') | pkg/analyzer/lib/src/dart/constant/value.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698