33// BSD-style license that can be found in the LICENSE file.
44
55import 'package:analyzer/dart/constant/value.dart' ;
6+ import 'package:analyzer/dart/element/element.dart' ;
7+
8+ /// Throws an exception if [root] or its super(s) does not contain [name] .
9+ void _assertHasField (ClassElement root, String name) {
10+ var element = root;
11+ while (element != null ) {
12+ final field = element.getField (name);
13+ if (field != null ) {
14+ return ;
15+ }
16+ element = element.supertype? .element;
17+ }
18+ final allFields = root.fields.toSet ();
19+ root.allSupertypes.forEach ((t) => allFields.addAll (t.element.fields));
20+ throw new FormatException (
21+ 'Class ${root .name } does not have field "$name ".' ,
22+ 'Fields: $allFields ' ,
23+ );
24+ }
625
726/// Returns whether or not [object] is or represents a `null` value.
827bool _isNull (DartObject object) => object? .isNull != false ;
@@ -43,6 +62,26 @@ abstract class ConstantReader {
4362 /// Throws [FormatException] if [isInt] is `false` .
4463 int get intValue;
4564
65+ /// Returns whether this constant represents a `List` literal.
66+ ///
67+ /// If `true` , [listValue] will return a `List` (not throw).
68+ bool get isList;
69+
70+ /// Returns this constant as a `List` value.
71+ ///
72+ /// Throws [FormatException] if [isList] is `false` .
73+ List <DartObject > get listValue;
74+
75+ /// Returns whether this constant represents a `Map` literal.
76+ ///
77+ /// If `true` , [listValue] will return a `Map` (not throw).
78+ bool get isMap;
79+
80+ /// Returns this constant as a `Map` value.
81+ ///
82+ /// Throws [FormatException] if [isMap] is `false` .
83+ Map <DartObject , DartObject > get mapValue;
84+
4685 /// Returns whether this constant represents a `String` literal.
4786 ///
4887 /// If `true` , [stringValue] will return a `String` (not throw).
@@ -60,33 +99,49 @@ abstract class ConstantReader {
6099 ConstantReader read (String field);
61100}
62101
102+ dynamic _throw (String expected, [dynamic object]) {
103+ throw new FormatException ('Not a $expected ' , '$object ' );
104+ }
105+
63106/// Implements a [ConstantReader] representing a `null` value.
64107class _NullConstant implements ConstantReader {
65108 const _NullConstant ();
66109
67110 @override
68- bool get boolValue => throw new FormatException ('Not a bool' , 'null' );
111+ bool get boolValue => _throw ('bool' );
112+
113+ @override
114+ int get intValue => _throw ('int' );
115+
116+ @override
117+ String get stringValue => _throw ('String' );
69118
70119 @override
71- int get intValue => throw new FormatException ( 'Not an int' , 'null ' );
120+ List < DartObject > get listValue => _throw ( 'List ' );
72121
73122 @override
74- String get stringValue => throw new FormatException ( 'Not a String' , 'null ' );
123+ Map < DartObject , DartObject > get mapValue => _throw ( 'Map ' );
75124
76125 @override
77126 bool get isBool => false ;
78127
79128 @override
80129 bool get isInt => false ;
81130
131+ @override
132+ bool get isList => false ;
133+
134+ @override
135+ bool get isMap => false ;
136+
82137 @override
83138 bool get isNull => true ;
84139
85140 @override
86141 bool get isString => false ;
87142
88143 @override
89- ConstantReader read (_) => this ;
144+ ConstantReader read (_) => throw new UnsupportedError ( 'Null' ) ;
90145}
91146
92147/// Default implementation of [ConstantReader] .
@@ -96,33 +151,51 @@ class _Constant implements ConstantReader {
96151 const _Constant (this ._object);
97152
98153 @override
99- bool get boolValue => isBool
100- ? _object.toBoolValue ()
101- : throw new FormatException ('Not a bool' , _object);
154+ bool get boolValue =>
155+ isBool ? _object.toBoolValue () : _throw ('bool' , _object);
156+
157+ @override
158+ int get intValue => isInt ? _object.toIntValue () : _throw ('int' , _object);
159+
160+ @override
161+ String get stringValue =>
162+ isString ? _object.toStringValue () : _throw ('String' , _object);
102163
103164 @override
104- int get intValue => isInt
105- ? _object.toIntValue ()
106- : throw new FormatException ('Not an int' , _object);
165+ List <DartObject > get listValue =>
166+ isList ? _object.toListValue () : _throw ('List' , _object);
107167
108168 @override
109- String get stringValue => isString
110- ? _object.toStringValue ()
111- : throw new FormatException ('Not a String' , _object);
169+ Map <DartObject , DartObject > get mapValue =>
170+ isMap ? _object.toMapValue () : _throw ('Map' , _object);
112171
113172 @override
114173 bool get isBool => _object.toBoolValue () != null ;
115174
116175 @override
117176 bool get isInt => _object.toIntValue () != null ;
118177
178+ @override
179+ bool get isList => _object? .toListValue () != null ;
180+
119181 @override
120182 bool get isNull => _isNull (_object);
121183
184+ @override
185+ bool get isMap => _object? .toMapValue () != null ;
186+
122187 @override
123188 bool get isString => _object.toStringValue () != null ;
124189
125190 @override
126- ConstantReader read (String field) =>
127- new ConstantReader (_getFieldRecursive (_object, field));
191+ ConstantReader read (String field) {
192+ final constant = new ConstantReader (_getFieldRecursive (_object, field));
193+ if (constant.isNull) {
194+ _assertHasField (_object? .type? .element, field);
195+ }
196+ return constant;
197+ }
198+
199+ @override
200+ String toString () => 'ConstantReader ${_object }' ;
128201}
0 commit comments