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

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

Issue 1099953004: In constant evaluation, handle final vars initialized at declaration site. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 8 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/generated/constant.dart
diff --git a/pkg/analyzer/lib/src/generated/constant.dart b/pkg/analyzer/lib/src/generated/constant.dart
index 7c866c1014e63dafc44514fa484a7dbc7e95d3ea..6aafe29f04a2986e1380ede8cf5b77cc0326f051 100644
--- a/pkg/analyzer/lib/src/generated/constant.dart
+++ b/pkg/analyzer/lib/src/generated/constant.dart
@@ -303,6 +303,11 @@ class ConstantFinder extends RecursiveAstVisitor<Object> {
*/
final List<Annotation> annotations = <Annotation>[];
+ /**
+ * True if instance variables marked as "final" should be treated as "const".
+ */
+ bool treatFinalInstanceVarAsConst = false;
+
@override
Object visitAnnotation(Annotation node) {
super.visitAnnotation(node);
@@ -311,6 +316,22 @@ class ConstantFinder extends RecursiveAstVisitor<Object> {
}
@override
+ Object visitClassDeclaration(ClassDeclaration node) {
+ bool prevTreatFinalInstanceVarAsConst = treatFinalInstanceVarAsConst;
+ if (node.element.constructors.any((ConstructorElement e) => e.isConst)) {
+ // Instance vars marked "final" need to be included in the dependency
+ // graph, since constant constructors implicitly use the values in their
+ // initializers.
+ treatFinalInstanceVarAsConst = true;
+ }
+ try {
+ return super.visitClassDeclaration(node);
+ } finally {
+ treatFinalInstanceVarAsConst = prevTreatFinalInstanceVarAsConst;
+ }
+ }
+
+ @override
Object visitConstructorDeclaration(ConstructorDeclaration node) {
super.visitConstructorDeclaration(node);
if (node.constKeyword != null) {
@@ -335,7 +356,13 @@ class ConstantFinder extends RecursiveAstVisitor<Object> {
Object visitVariableDeclaration(VariableDeclaration node) {
super.visitVariableDeclaration(node);
Expression initializer = node.initializer;
- if (initializer != null && node.isConst) {
+ VariableElement element = node.element;
+ if (initializer != null &&
+ (node.isConst ||
+ treatFinalInstanceVarAsConst &&
+ element is FieldElement &&
+ node.isFinal &&
+ !element.isStatic)) {
if (node.element != null) {
variableMap[node.element as PotentiallyConstVariableElement] = node;
}
@@ -454,6 +481,13 @@ class ConstantValueComputer {
void beforeComputeValue(AstNode constNode) {}
/**
+ * This method is called just before getting the constant value of a field
+ * with an initializer. Unit tests will override this method to introduce
+ * additional error checking.
+ */
+ void beforeGetFieldEvaluationResult(FieldElementImpl field) {}
+
+ /**
* This method is called just before getting the constant initializers
* associated with the [constructor]. Unit tests will override this method to
* introduce additional error checking.
@@ -520,6 +554,16 @@ class ConstantValueComputer {
}
}
}
+ for (FieldElement field in element.enclosingElement.fields) {
+ // Note: non-static const isn't allowed but we handle it anyway so that
+ // we won't be confused by incorrect code.
+ if ((field.isFinal || field.isConst) && !field.isStatic) {
+ VariableDeclaration fieldDeclaration = _variableDeclarationMap[field];
+ if (fieldDeclaration != null) {
+ referenceGraph.addEdge(declaration, fieldDeclaration);
+ }
+ }
+ }
for (FormalParameter parameter in declaration.parameters.parameters) {
referenceGraph.addNode(parameter);
referenceGraph.addEdge(declaration, parameter);
@@ -581,6 +625,10 @@ class ConstantValueComputer {
ConstructorElement constructor) =>
constructorDeclarationMap[_getConstructorBase(constructor)];
+ VariableDeclaration findVariableDeclaration(
+ PotentiallyConstVariableElement variable) =>
+ _variableDeclarationMap[variable];
+
/**
* Check that the arguments to a call to fromEnvironment() are correct. The
* [arguments] are the AST nodes of the arguments. The [argumentValues] are
@@ -898,6 +946,25 @@ class ConstantValueComputer {
}
HashMap<String, DartObjectImpl> fieldMap =
new HashMap<String, DartObjectImpl>();
+ // Start with final fields that are initialized at their declaration site.
+ for (FieldElement field in constructor.enclosingElement.fields) {
+ if ((field.isFinal || field.isConst) &&
+ !field.isStatic &&
+ field is ConstFieldElementImpl) {
+ beforeGetFieldEvaluationResult(field);
+ EvaluationResultImpl evaluationResult = field.evaluationResult;
+ DartType fieldType =
+ FieldMember.from(field, constructor.returnType).type;
+ DartObjectImpl fieldValue = evaluationResult.value;
+ if (fieldValue != null && !_runtimeTypeMatch(fieldValue, fieldType)) {
+ errorReporter.reportErrorForNode(
+ CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH,
+ node, [fieldValue.type, field.name, fieldType]);
+ }
+ fieldMap[field.name] = evaluationResult.value;
+ }
+ }
+ // Now evaluate the constructor declaration.
HashMap<String, DartObjectImpl> parameterMap =
new HashMap<String, DartObjectImpl>();
List<ParameterElement> parameters = constructor.parameters;
« no previous file with comments | « no previous file | pkg/analyzer/lib/src/generated/element.dart » ('j') | pkg/analyzer/lib/src/generated/resolver.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698