Index: pkg/compiler/lib/src/constants/values.dart |
diff --git a/pkg/compiler/lib/src/constants/values.dart b/pkg/compiler/lib/src/constants/values.dart |
index 24b6370024005d7d1c2dc8fe968f434a150321e3..5404d7042249a05251b33261b67cd6f985a812e8 100644 |
--- a/pkg/compiler/lib/src/constants/values.dart |
+++ b/pkg/compiler/lib/src/constants/values.dart |
@@ -7,14 +7,17 @@ library dart2js.constants.values; |
import '../common.dart'; |
import '../core_types.dart'; |
import '../dart_types.dart'; |
-import '../elements/elements.dart' |
- show ClassElement, |
- Element, |
- FieldElement, |
- FunctionElement, |
- PrefixElement; |
+import '../diagnostics/invariant.dart' show |
+ DEBUG_MODE; |
+import '../elements/elements.dart' show |
+ ClassElement, |
+ Element, |
+ FieldElement, |
+ FunctionElement, |
+ PrefixElement; |
import '../tree/tree.dart' hide unparse; |
-import '../util/util.dart' show Hashing; |
+import '../util/util.dart' show |
+ Hashing; |
abstract class ConstantValueVisitor<R, A> { |
const ConstantValueVisitor(); |
@@ -32,6 +35,7 @@ abstract class ConstantValueVisitor<R, A> { |
R visitInterceptor(InterceptorConstantValue constant, A arg); |
R visitSynthetic(SyntheticConstantValue constant, A arg); |
R visitDeferred(DeferredConstantValue constant, A arg); |
+ R visitNonConstant(NonConstantValue constant, A arg); |
} |
abstract class ConstantValue { |
@@ -633,13 +637,40 @@ class ConstructedConstantValue extends ObjectConstantValue { |
final Map<FieldElement, ConstantValue> fields; |
final int hashCode; |
- ConstructedConstantValue(InterfaceType type, |
- Map<FieldElement, ConstantValue> fields) |
- : this.fields = fields, |
- hashCode = Hashing.mapHash(fields, Hashing.objectHash(type)), |
- super(type) { |
+ factory ConstructedConstantValue( |
+ InterfaceType type, |
+ Map<FieldElement, ConstantValue> fields) { |
+ fields = normalizeFields(type, fields); |
+ int hashCode = Hashing.mapHash(fields, Hashing.objectHash(type)); |
+ return new ConstructedConstantValue._(type, fields, hashCode); |
+ } |
+ |
+ ConstructedConstantValue._(InterfaceType type, this.fields, this.hashCode) |
+ : super(type) { |
assert(type != null); |
- assert(!fields.containsValue(null)); |
+ assert(invariant(NO_LOCATION_SPANNABLE, !fields.containsValue(null), |
+ message: () { |
+ DEBUG_MODE = true; |
+ return "Null field value for constructed constant of type '$type' " |
+ "with fields ${fields}."; |
+ })); |
+ } |
+ |
+ static Map<FieldElement, ConstantValue> normalizeFields( |
+ InterfaceType type, Map<FieldElement, ConstantValue> fields) { |
+ Map<FieldElement, ConstantValue> normalizedFields = |
+ <FieldElement, ConstantValue>{}; |
+ type.element.implementation.forEachInstanceField( |
+ (ClassElement enclosingClass, FieldElement field) { |
+ assert(invariant(NO_LOCATION_SPANNABLE, fields.containsKey(field), |
+ message: () { |
+ DEBUG_MODE = true; |
+ return "No field value provided for $field in constructed constant " |
+ "of type '$type' with fields ${fields}."; |
+ })); |
+ normalizedFields[field] = fields[field]; |
+ }, includeSuperAndInjectedMembers: true); |
+ return normalizedFields; |
} |
bool get isConstructedObject => true; |
@@ -734,7 +765,7 @@ class NonConstantValue extends ConstantValue { |
@override |
accept(ConstantValueVisitor visitor, arg) { |
- // TODO(johnniwinther): Should this be part of the visiting? |
+ return visitor.visitNonConstant(this, arg); |
} |
@override |
@@ -748,4 +779,4 @@ class NonConstantValue extends ConstantValue { |
@override |
String unparse() => '>>non-constant<<'; |
-} |
+} |