ast-types 0.11.5 → 0.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.travis.yml +2 -2
- package/def/babel-core.d.ts +2 -0
- package/def/babel-core.js +250 -290
- package/def/babel.d.ts +2 -0
- package/def/babel.js +12 -3
- package/def/core.d.ts +2 -0
- package/def/core.js +57 -126
- package/def/es-proposals.d.ts +2 -0
- package/def/es-proposals.js +34 -32
- package/def/es6.d.ts +2 -0
- package/def/es6.js +210 -253
- package/def/es7.d.ts +2 -0
- package/def/es7.js +35 -41
- package/def/esprima.d.ts +2 -0
- package/def/esprima.js +50 -71
- package/def/flow.d.ts +2 -0
- package/def/flow.js +289 -393
- package/def/jsx.d.ts +2 -0
- package/def/jsx.js +99 -125
- package/def/type-annotations.d.ts +7 -0
- package/def/type-annotations.js +42 -0
- package/def/typescript.d.ts +2 -0
- package/def/typescript.js +326 -444
- package/fork.d.ts +46 -0
- package/fork.js +40 -31
- package/gen/builders.d.ts +2539 -0
- package/gen/builders.js +2 -0
- package/gen/kinds.d.ts +259 -0
- package/gen/kinds.js +2 -0
- package/gen/namedTypes.d.ts +262 -0
- package/gen/namedTypes.js +2 -0
- package/gen/nodes.d.ts +1255 -0
- package/gen/nodes.js +2 -0
- package/gen/visitor.d.ts +263 -0
- package/gen/visitor.js +2 -0
- package/lib/equiv.d.ts +5 -0
- package/lib/equiv.js +19 -49
- package/lib/node-path.d.ts +22 -0
- package/lib/node-path.js +60 -125
- package/lib/path-visitor.d.ts +52 -0
- package/lib/path-visitor.js +117 -194
- package/lib/path.d.ts +25 -0
- package/lib/path.js +71 -107
- package/lib/scope.d.ts +26 -0
- package/lib/scope.js +100 -143
- package/lib/shared.d.ts +13 -0
- package/lib/shared.js +34 -31
- package/lib/types.d.ts +140 -0
- package/lib/types.js +584 -676
- package/main.d.ts +16 -0
- package/main.js +33 -18
- package/package.json +24 -7
- package/tsconfig.json +20 -0
- package/types.d.ts +6 -0
- package/types.js +2 -0
- package/def/e4x.js +0 -86
- package/def/mozilla.js +0 -42
package/lib/types.js
CHANGED
|
@@ -1,119 +1,326 @@
|
|
|
1
|
-
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __extends = (this && this.__extends) || (function () {
|
|
3
|
+
var extendStatics = function (d, b) {
|
|
4
|
+
extendStatics = Object.setPrototypeOf ||
|
|
5
|
+
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
6
|
+
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
|
7
|
+
return extendStatics(d, b);
|
|
8
|
+
};
|
|
9
|
+
return function (d, b) {
|
|
10
|
+
extendStatics(d, b);
|
|
11
|
+
function __() { this.constructor = d; }
|
|
12
|
+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
13
|
+
};
|
|
14
|
+
})();
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
16
|
var Op = Object.prototype;
|
|
6
17
|
var objToStr = Op.toString;
|
|
7
|
-
var funObjStr = objToStr.call(function(){});
|
|
8
|
-
var strObjStr = objToStr.call("");
|
|
9
18
|
var hasOwn = Op.hasOwnProperty;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
var BaseType = /** @class */ (function () {
|
|
20
|
+
function BaseType() {
|
|
21
|
+
}
|
|
22
|
+
BaseType.prototype.assert = function (value, deep) {
|
|
23
|
+
if (!this.check(value, deep)) {
|
|
24
|
+
var str = shallowStringify(value);
|
|
25
|
+
throw new Error(str + " does not match type " + this);
|
|
26
|
+
}
|
|
27
|
+
return true;
|
|
28
|
+
};
|
|
29
|
+
BaseType.prototype.arrayOf = function () {
|
|
30
|
+
var elemType = this;
|
|
31
|
+
return new ArrayType(elemType);
|
|
32
|
+
};
|
|
33
|
+
return BaseType;
|
|
34
|
+
}());
|
|
35
|
+
var ArrayType = /** @class */ (function (_super) {
|
|
36
|
+
__extends(ArrayType, _super);
|
|
37
|
+
function ArrayType(elemType) {
|
|
38
|
+
var _this = _super.call(this) || this;
|
|
39
|
+
_this.elemType = elemType;
|
|
40
|
+
_this.kind = "ArrayType";
|
|
41
|
+
return _this;
|
|
42
|
+
}
|
|
43
|
+
ArrayType.prototype.toString = function () {
|
|
44
|
+
return "[" + this.elemType + "]";
|
|
45
|
+
};
|
|
46
|
+
ArrayType.prototype.check = function (value, deep) {
|
|
47
|
+
var _this = this;
|
|
48
|
+
return Array.isArray(value) && value.every(function (elem) { return _this.elemType.check(elem, deep); });
|
|
49
|
+
};
|
|
50
|
+
return ArrayType;
|
|
51
|
+
}(BaseType));
|
|
52
|
+
var IdentityType = /** @class */ (function (_super) {
|
|
53
|
+
__extends(IdentityType, _super);
|
|
54
|
+
function IdentityType(value) {
|
|
55
|
+
var _this = _super.call(this) || this;
|
|
56
|
+
_this.value = value;
|
|
57
|
+
_this.kind = "IdentityType";
|
|
58
|
+
return _this;
|
|
59
|
+
}
|
|
60
|
+
IdentityType.prototype.toString = function () {
|
|
61
|
+
return String(this.value);
|
|
62
|
+
};
|
|
63
|
+
IdentityType.prototype.check = function (value, deep) {
|
|
64
|
+
var result = value === this.value;
|
|
65
|
+
if (!result && typeof deep === "function") {
|
|
66
|
+
deep(this, value);
|
|
67
|
+
}
|
|
68
|
+
return result;
|
|
69
|
+
};
|
|
70
|
+
return IdentityType;
|
|
71
|
+
}(BaseType));
|
|
72
|
+
var ObjectType = /** @class */ (function (_super) {
|
|
73
|
+
__extends(ObjectType, _super);
|
|
74
|
+
function ObjectType(fields) {
|
|
75
|
+
var _this = _super.call(this) || this;
|
|
76
|
+
_this.fields = fields;
|
|
77
|
+
_this.kind = "ObjectType";
|
|
78
|
+
return _this;
|
|
79
|
+
}
|
|
80
|
+
ObjectType.prototype.toString = function () {
|
|
81
|
+
return "{ " + this.fields.join(", ") + " }";
|
|
82
|
+
};
|
|
83
|
+
ObjectType.prototype.check = function (value, deep) {
|
|
84
|
+
return (objToStr.call(value) === objToStr.call({}) &&
|
|
85
|
+
this.fields.every(function (field) {
|
|
86
|
+
return field.type.check(value[field.name], deep);
|
|
87
|
+
}));
|
|
88
|
+
};
|
|
89
|
+
return ObjectType;
|
|
90
|
+
}(BaseType));
|
|
91
|
+
var OrType = /** @class */ (function (_super) {
|
|
92
|
+
__extends(OrType, _super);
|
|
93
|
+
function OrType(types) {
|
|
94
|
+
var _this = _super.call(this) || this;
|
|
95
|
+
_this.types = types;
|
|
96
|
+
_this.kind = "OrType";
|
|
97
|
+
return _this;
|
|
98
|
+
}
|
|
99
|
+
OrType.prototype.toString = function () {
|
|
100
|
+
return this.types.join(" | ");
|
|
101
|
+
};
|
|
102
|
+
OrType.prototype.check = function (value, deep) {
|
|
103
|
+
return this.types.some(function (type) {
|
|
104
|
+
return type.check(value, deep);
|
|
105
|
+
});
|
|
106
|
+
};
|
|
107
|
+
return OrType;
|
|
108
|
+
}(BaseType));
|
|
109
|
+
var PredicateType = /** @class */ (function (_super) {
|
|
110
|
+
__extends(PredicateType, _super);
|
|
111
|
+
function PredicateType(name, predicate) {
|
|
112
|
+
var _this = _super.call(this) || this;
|
|
113
|
+
_this.name = name;
|
|
114
|
+
_this.predicate = predicate;
|
|
115
|
+
_this.kind = "PredicateType";
|
|
116
|
+
return _this;
|
|
117
|
+
}
|
|
118
|
+
PredicateType.prototype.toString = function () {
|
|
119
|
+
return this.name;
|
|
120
|
+
};
|
|
121
|
+
PredicateType.prototype.check = function (value, deep) {
|
|
122
|
+
var result = this.predicate(value, deep);
|
|
123
|
+
if (!result && typeof deep === "function") {
|
|
124
|
+
deep(this, value);
|
|
125
|
+
}
|
|
126
|
+
return result;
|
|
127
|
+
};
|
|
128
|
+
return PredicateType;
|
|
129
|
+
}(BaseType));
|
|
130
|
+
var Def = /** @class */ (function () {
|
|
131
|
+
function Def(type, typeName) {
|
|
132
|
+
this.type = type;
|
|
133
|
+
this.typeName = typeName;
|
|
134
|
+
this.baseNames = [];
|
|
135
|
+
this.ownFields = Object.create(null);
|
|
136
|
+
// Includes own typeName. Populated during finalization.
|
|
137
|
+
this.allSupertypes = Object.create(null);
|
|
138
|
+
// Linear inheritance hierarchy. Populated during finalization.
|
|
139
|
+
this.supertypeList = [];
|
|
140
|
+
// Includes inherited fields.
|
|
141
|
+
this.allFields = Object.create(null);
|
|
142
|
+
// Non-hidden keys of allFields.
|
|
143
|
+
this.fieldNames = [];
|
|
144
|
+
// This property will be overridden as true by individual Def instances
|
|
145
|
+
// when they are finalized.
|
|
146
|
+
this.finalized = false;
|
|
147
|
+
// False by default until .build(...) is called on an instance.
|
|
148
|
+
this.buildable = false;
|
|
149
|
+
this.buildParams = [];
|
|
150
|
+
}
|
|
151
|
+
Def.prototype.isSupertypeOf = function (that) {
|
|
152
|
+
if (that instanceof Def) {
|
|
153
|
+
if (this.finalized !== true ||
|
|
154
|
+
that.finalized !== true) {
|
|
155
|
+
throw new Error("");
|
|
156
|
+
}
|
|
157
|
+
return hasOwn.call(that.allSupertypes, this.typeName);
|
|
22
158
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
159
|
+
else {
|
|
160
|
+
throw new Error(that + " is not a Def");
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
Def.prototype.checkAllFields = function (value, deep) {
|
|
164
|
+
var allFields = this.allFields;
|
|
165
|
+
if (this.finalized !== true) {
|
|
166
|
+
throw new Error("" + this.typeName);
|
|
28
167
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
throw new Error(name + " is neither a function nor a string");
|
|
168
|
+
function checkFieldByName(name) {
|
|
169
|
+
var field = allFields[name];
|
|
170
|
+
var type = field.type;
|
|
171
|
+
var child = field.getValue(value);
|
|
172
|
+
return type.check(child, deep);
|
|
35
173
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
174
|
+
return value !== null &&
|
|
175
|
+
typeof value === "object" &&
|
|
176
|
+
Object.keys(allFields).every(checkFieldByName);
|
|
177
|
+
};
|
|
178
|
+
Def.prototype.bases = function () {
|
|
179
|
+
var supertypeNames = [];
|
|
180
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
181
|
+
supertypeNames[_i] = arguments[_i];
|
|
182
|
+
}
|
|
183
|
+
var bases = this.baseNames;
|
|
184
|
+
if (this.finalized) {
|
|
185
|
+
if (supertypeNames.length !== bases.length) {
|
|
186
|
+
throw new Error("");
|
|
187
|
+
}
|
|
188
|
+
for (var i = 0; i < supertypeNames.length; i++) {
|
|
189
|
+
if (supertypeNames[i] !== bases[i]) {
|
|
190
|
+
throw new Error("");
|
|
45
191
|
}
|
|
46
192
|
}
|
|
193
|
+
return this;
|
|
194
|
+
}
|
|
195
|
+
supertypeNames.forEach(function (baseName) {
|
|
196
|
+
// This indexOf lookup may be O(n), but the typical number of base
|
|
197
|
+
// names is very small, and indexOf is a native Array method.
|
|
198
|
+
if (bases.indexOf(baseName) < 0) {
|
|
199
|
+
bases.push(baseName);
|
|
200
|
+
}
|
|
47
201
|
});
|
|
202
|
+
return this; // For chaining.
|
|
203
|
+
};
|
|
204
|
+
return Def;
|
|
205
|
+
}());
|
|
206
|
+
exports.Def = Def;
|
|
207
|
+
var Field = /** @class */ (function () {
|
|
208
|
+
function Field(name, type, defaultFn, hidden) {
|
|
209
|
+
this.name = name;
|
|
210
|
+
this.type = type;
|
|
211
|
+
this.defaultFn = defaultFn;
|
|
212
|
+
this.hidden = !!hidden;
|
|
48
213
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
// Like .check, except that failure triggers an AssertionError.
|
|
57
|
-
Tp.assert = function (value, deep) {
|
|
58
|
-
if (!this.check(value, deep)) {
|
|
59
|
-
var str = shallowStringify(value);
|
|
60
|
-
throw new Error(str + " does not match type " + this);
|
|
214
|
+
Field.prototype.toString = function () {
|
|
215
|
+
return JSON.stringify(this.name) + ": " + this.type;
|
|
216
|
+
};
|
|
217
|
+
Field.prototype.getValue = function (obj) {
|
|
218
|
+
var value = obj[this.name];
|
|
219
|
+
if (typeof value !== "undefined") {
|
|
220
|
+
return value;
|
|
61
221
|
}
|
|
62
|
-
|
|
222
|
+
if (typeof this.defaultFn === "function") {
|
|
223
|
+
value = this.defaultFn.call(obj);
|
|
224
|
+
}
|
|
225
|
+
return value;
|
|
63
226
|
};
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
return
|
|
73
|
-
|
|
74
|
-
return JSON.stringify(value);
|
|
227
|
+
return Field;
|
|
228
|
+
}());
|
|
229
|
+
function shallowStringify(value) {
|
|
230
|
+
if (Array.isArray(value)) {
|
|
231
|
+
return "[" + value.map(shallowStringify).join(", ") + "]";
|
|
232
|
+
}
|
|
233
|
+
if (value && typeof value === "object") {
|
|
234
|
+
return "{ " + Object.keys(value).map(function (key) {
|
|
235
|
+
return key + ": " + value[key];
|
|
236
|
+
}).join(", ") + " }";
|
|
75
237
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
238
|
+
return JSON.stringify(value);
|
|
239
|
+
}
|
|
240
|
+
function typesPlugin(_fork) {
|
|
241
|
+
var Type = {
|
|
242
|
+
or: function () {
|
|
243
|
+
var types = [];
|
|
244
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
245
|
+
types[_i] = arguments[_i];
|
|
246
|
+
}
|
|
247
|
+
return new OrType(types.map(function (type) { return Type.from(type); }));
|
|
248
|
+
},
|
|
249
|
+
from: function (value, name) {
|
|
250
|
+
if (value instanceof ArrayType ||
|
|
251
|
+
value instanceof IdentityType ||
|
|
252
|
+
value instanceof ObjectType ||
|
|
253
|
+
value instanceof OrType ||
|
|
254
|
+
value instanceof PredicateType) {
|
|
255
|
+
return value;
|
|
256
|
+
}
|
|
257
|
+
// The Def type is used as a helper for constructing compound
|
|
258
|
+
// interface types for AST nodes.
|
|
259
|
+
if (value instanceof Def) {
|
|
260
|
+
return value.type;
|
|
261
|
+
}
|
|
262
|
+
// Support [ElemType] syntax.
|
|
263
|
+
if (isArray.check(value)) {
|
|
264
|
+
if (value.length !== 1) {
|
|
265
|
+
throw new Error("only one element type is permitted for typed arrays");
|
|
266
|
+
}
|
|
267
|
+
return new ArrayType(Type.from(value[0]));
|
|
268
|
+
}
|
|
269
|
+
// Support { someField: FieldType, ... } syntax.
|
|
270
|
+
if (isObject.check(value)) {
|
|
271
|
+
return new ObjectType(Object.keys(value).map(function (name) {
|
|
272
|
+
return new Field(name, Type.from(value[name], name));
|
|
273
|
+
}));
|
|
274
|
+
}
|
|
275
|
+
if (typeof value === "function") {
|
|
276
|
+
var bicfIndex = builtInCtorFns.indexOf(value);
|
|
277
|
+
if (bicfIndex >= 0) {
|
|
278
|
+
return builtInCtorTypes[bicfIndex];
|
|
279
|
+
}
|
|
280
|
+
if (typeof name !== "string") {
|
|
281
|
+
throw new Error("missing name");
|
|
282
|
+
}
|
|
283
|
+
return new PredicateType(name, value);
|
|
284
|
+
}
|
|
285
|
+
// As a last resort, toType returns a type that matches any value that
|
|
286
|
+
// is === from. This is primarily useful for literal values like
|
|
287
|
+
// toType(null), but it has the additional advantage of allowing
|
|
288
|
+
// toType to be a total function.
|
|
289
|
+
return new IdentityType(value);
|
|
290
|
+
},
|
|
291
|
+
// Define a type whose name is registered in a namespace (the defCache) so
|
|
292
|
+
// that future definitions will return the same type given the same name.
|
|
293
|
+
// In particular, this system allows for circular and forward definitions.
|
|
294
|
+
// The Def object d returned from Type.def may be used to configure the
|
|
295
|
+
// type d.type by calling methods such as d.bases, d.build, and d.field.
|
|
296
|
+
def: function (typeName) {
|
|
297
|
+
return hasOwn.call(defCache, typeName)
|
|
298
|
+
? defCache[typeName]
|
|
299
|
+
: defCache[typeName] = new DefImpl(typeName);
|
|
300
|
+
},
|
|
301
|
+
hasDef: function (typeName) {
|
|
302
|
+
return hasOwn.call(defCache, typeName);
|
|
303
|
+
}
|
|
87
304
|
};
|
|
88
|
-
|
|
89
305
|
var builtInCtorFns = [];
|
|
90
306
|
var builtInCtorTypes = [];
|
|
91
307
|
var builtInTypes = {};
|
|
92
|
-
exports.builtInTypes = builtInTypes;
|
|
93
|
-
|
|
94
308
|
function defBuiltInType(example, name) {
|
|
95
309
|
var objStr = objToStr.call(example);
|
|
96
|
-
|
|
97
|
-
var type = new Type(function (value) {
|
|
98
|
-
return objToStr.call(value) === objStr;
|
|
99
|
-
}, name);
|
|
100
|
-
|
|
310
|
+
var type = new PredicateType(name, function (value) { return objToStr.call(value) === objStr; });
|
|
101
311
|
builtInTypes[name] = type;
|
|
102
|
-
|
|
103
312
|
if (example && typeof example.constructor === "function") {
|
|
104
313
|
builtInCtorFns.push(example.constructor);
|
|
105
314
|
builtInCtorTypes.push(type);
|
|
106
315
|
}
|
|
107
|
-
|
|
108
316
|
return type;
|
|
109
317
|
}
|
|
110
|
-
|
|
111
318
|
// These types check the underlying [[Class]] attribute of the given
|
|
112
319
|
// value, rather than using the problematic typeof operator. Note however
|
|
113
320
|
// that no subtyping is considered; so, for instance, isObject.check
|
|
114
321
|
// returns false for [], /./, new Date, and null.
|
|
115
322
|
var isString = defBuiltInType("truthy", "string");
|
|
116
|
-
var isFunction = defBuiltInType(function () {}, "function");
|
|
323
|
+
var isFunction = defBuiltInType(function () { }, "function");
|
|
117
324
|
var isArray = defBuiltInType([], "array");
|
|
118
325
|
var isObject = defBuiltInType({}, "object");
|
|
119
326
|
var isRegExp = defBuiltInType(/./, "RegExp");
|
|
@@ -122,218 +329,254 @@ module.exports = function () {
|
|
|
122
329
|
var isBoolean = defBuiltInType(true, "boolean");
|
|
123
330
|
var isNull = defBuiltInType(null, "null");
|
|
124
331
|
var isUndefined = defBuiltInType(void 0, "undefined");
|
|
125
|
-
|
|
126
|
-
// There are a number of idiomatic ways of expressing types, so this
|
|
127
|
-
// function serves to coerce them all to actual Type objects. Note that
|
|
128
|
-
// providing the name argument is not necessary in most cases.
|
|
129
|
-
function toType(from, name) {
|
|
130
|
-
// The toType function should of course be idempotent.
|
|
131
|
-
if (from instanceof Type)
|
|
132
|
-
return from;
|
|
133
|
-
|
|
134
|
-
// The Def type is used as a helper for constructing compound
|
|
135
|
-
// interface types for AST nodes.
|
|
136
|
-
if (from instanceof Def)
|
|
137
|
-
return from.type;
|
|
138
|
-
|
|
139
|
-
// Support [ElemType] syntax.
|
|
140
|
-
if (isArray.check(from))
|
|
141
|
-
return Type.fromArray(from);
|
|
142
|
-
|
|
143
|
-
// Support { someField: FieldType, ... } syntax.
|
|
144
|
-
if (isObject.check(from))
|
|
145
|
-
return Type.fromObject(from);
|
|
146
|
-
|
|
147
|
-
if (isFunction.check(from)) {
|
|
148
|
-
var bicfIndex = builtInCtorFns.indexOf(from);
|
|
149
|
-
if (bicfIndex >= 0) {
|
|
150
|
-
return builtInCtorTypes[bicfIndex];
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// If isFunction.check(from), and from is not a built-in
|
|
154
|
-
// constructor, assume from is a binary predicate function we can
|
|
155
|
-
// use to define the type.
|
|
156
|
-
return new Type(from, name);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// As a last resort, toType returns a type that matches any value that
|
|
160
|
-
// is === from. This is primarily useful for literal values like
|
|
161
|
-
// toType(null), but it has the additional advantage of allowing
|
|
162
|
-
// toType to be a total function.
|
|
163
|
-
return new Type(function (value) {
|
|
164
|
-
return value === from;
|
|
165
|
-
}, isUndefined.check(name) ? function () {
|
|
166
|
-
return from + "";
|
|
167
|
-
} : name);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
// Returns a type that matches the given value iff any of type1, type2,
|
|
171
|
-
// etc. match the value.
|
|
172
|
-
Type.or = function (/* type1, type2, ... */) {
|
|
173
|
-
var types = [];
|
|
174
|
-
var len = arguments.length;
|
|
175
|
-
for (var i = 0; i < len; ++i)
|
|
176
|
-
types.push(toType(arguments[i]));
|
|
177
|
-
|
|
178
|
-
return new Type(function (value, deep) {
|
|
179
|
-
for (var i = 0; i < len; ++i)
|
|
180
|
-
if (types[i].check(value, deep))
|
|
181
|
-
return true;
|
|
182
|
-
return false;
|
|
183
|
-
}, function () {
|
|
184
|
-
return types.join(" | ");
|
|
185
|
-
});
|
|
186
|
-
};
|
|
187
|
-
|
|
188
|
-
Type.fromArray = function (arr) {
|
|
189
|
-
if (!isArray.check(arr)) {
|
|
190
|
-
throw new Error("");
|
|
191
|
-
}
|
|
192
|
-
if (arr.length !== 1) {
|
|
193
|
-
throw new Error("only one element type is permitted for typed arrays");
|
|
194
|
-
}
|
|
195
|
-
return toType(arr[0]).arrayOf();
|
|
196
|
-
};
|
|
197
|
-
|
|
198
|
-
Tp.arrayOf = function () {
|
|
199
|
-
var elemType = this;
|
|
200
|
-
return new Type(function (value, deep) {
|
|
201
|
-
return isArray.check(value) && value.every(function (elem) {
|
|
202
|
-
return elemType.check(elem, deep);
|
|
203
|
-
});
|
|
204
|
-
}, function () {
|
|
205
|
-
return "[" + elemType + "]";
|
|
206
|
-
});
|
|
207
|
-
};
|
|
208
|
-
|
|
209
|
-
Type.fromObject = function (obj) {
|
|
210
|
-
var fields = Object.keys(obj).map(function (name) {
|
|
211
|
-
return new Field(name, obj[name]);
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
return new Type(function (value, deep) {
|
|
215
|
-
return isObject.check(value) && fields.every(function (field) {
|
|
216
|
-
return field.type.check(value[field.name], deep);
|
|
217
|
-
});
|
|
218
|
-
}, function () {
|
|
219
|
-
return "{ " + fields.join(", ") + " }";
|
|
220
|
-
});
|
|
221
|
-
};
|
|
222
|
-
|
|
223
|
-
function Field(name, type, defaultFn, hidden) {
|
|
224
|
-
var self = this;
|
|
225
|
-
|
|
226
|
-
if (!(self instanceof Field)) {
|
|
227
|
-
throw new Error("Field constructor cannot be invoked without 'new'");
|
|
228
|
-
}
|
|
229
|
-
isString.assert(name);
|
|
230
|
-
|
|
231
|
-
type = toType(type);
|
|
232
|
-
|
|
233
|
-
var properties = {
|
|
234
|
-
name: {value: name},
|
|
235
|
-
type: {value: type},
|
|
236
|
-
hidden: {value: !!hidden}
|
|
237
|
-
};
|
|
238
|
-
|
|
239
|
-
if (isFunction.check(defaultFn)) {
|
|
240
|
-
properties.defaultFn = {value: defaultFn};
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
Object.defineProperties(self, properties);
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
var Fp = Field.prototype;
|
|
247
|
-
|
|
248
|
-
Fp.toString = function () {
|
|
249
|
-
return JSON.stringify(this.name) + ": " + this.type;
|
|
250
|
-
};
|
|
251
|
-
|
|
252
|
-
Fp.getValue = function (obj) {
|
|
253
|
-
var value = obj[this.name];
|
|
254
|
-
|
|
255
|
-
if (!isUndefined.check(value))
|
|
256
|
-
return value;
|
|
257
|
-
|
|
258
|
-
if (this.defaultFn)
|
|
259
|
-
value = this.defaultFn.call(obj);
|
|
260
|
-
|
|
261
|
-
return value;
|
|
262
|
-
};
|
|
263
|
-
|
|
264
|
-
// Define a type whose name is registered in a namespace (the defCache) so
|
|
265
|
-
// that future definitions will return the same type given the same name.
|
|
266
|
-
// In particular, this system allows for circular and forward definitions.
|
|
267
|
-
// The Def object d returned from Type.def may be used to configure the
|
|
268
|
-
// type d.type by calling methods such as d.bases, d.build, and d.field.
|
|
269
|
-
Type.def = function (typeName) {
|
|
270
|
-
isString.assert(typeName);
|
|
271
|
-
return hasOwn.call(defCache, typeName)
|
|
272
|
-
? defCache[typeName]
|
|
273
|
-
: defCache[typeName] = new Def(typeName);
|
|
274
|
-
};
|
|
275
|
-
|
|
276
332
|
// In order to return the same Def instance every time Type.def is called
|
|
277
333
|
// with a particular name, those instances need to be stored in a cache.
|
|
278
334
|
var defCache = Object.create(null);
|
|
279
|
-
|
|
280
|
-
function Def(typeName) {
|
|
281
|
-
var self = this;
|
|
282
|
-
if (!(self instanceof Def)) {
|
|
283
|
-
throw new Error("Def constructor cannot be invoked without 'new'");
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
Object.defineProperties(self, {
|
|
287
|
-
typeName: {value: typeName},
|
|
288
|
-
baseNames: {value: []},
|
|
289
|
-
ownFields: {value: Object.create(null)},
|
|
290
|
-
|
|
291
|
-
// These two are populated during finalization.
|
|
292
|
-
allSupertypes: {value: Object.create(null)}, // Includes own typeName.
|
|
293
|
-
supertypeList: {value: []}, // Linear inheritance hierarchy.
|
|
294
|
-
allFields: {value: Object.create(null)}, // Includes inherited fields.
|
|
295
|
-
fieldNames: {value: []}, // Non-hidden keys of allFields.
|
|
296
|
-
|
|
297
|
-
type: {
|
|
298
|
-
value: new Type(function (value, deep) {
|
|
299
|
-
return self.check(value, deep);
|
|
300
|
-
}, typeName)
|
|
301
|
-
}
|
|
302
|
-
});
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
Def.fromValue = function (value) {
|
|
335
|
+
function defFromValue(value) {
|
|
306
336
|
if (value && typeof value === "object") {
|
|
307
337
|
var type = value.type;
|
|
308
338
|
if (typeof type === "string" &&
|
|
309
|
-
|
|
339
|
+
hasOwn.call(defCache, type)) {
|
|
310
340
|
var d = defCache[type];
|
|
311
341
|
if (d.finalized) {
|
|
312
342
|
return d;
|
|
313
343
|
}
|
|
314
344
|
}
|
|
315
345
|
}
|
|
316
|
-
|
|
317
346
|
return null;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
347
|
+
}
|
|
348
|
+
var DefImpl = /** @class */ (function (_super) {
|
|
349
|
+
__extends(DefImpl, _super);
|
|
350
|
+
function DefImpl(typeName) {
|
|
351
|
+
var _this = _super.call(this, new PredicateType(typeName, function (value, deep) { return _this.check(value, deep); }), typeName) || this;
|
|
352
|
+
return _this;
|
|
353
|
+
}
|
|
354
|
+
DefImpl.prototype.check = function (value, deep) {
|
|
355
|
+
if (this.finalized !== true) {
|
|
356
|
+
throw new Error("prematurely checking unfinalized type " + this.typeName);
|
|
327
357
|
}
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
358
|
+
// A Def type can only match an object value.
|
|
359
|
+
if (value === null || typeof value !== "object") {
|
|
360
|
+
return false;
|
|
361
|
+
}
|
|
362
|
+
var vDef = defFromValue(value);
|
|
363
|
+
if (!vDef) {
|
|
364
|
+
// If we couldn't infer the Def associated with the given value,
|
|
365
|
+
// and we expected it to be a SourceLocation or a Position, it was
|
|
366
|
+
// probably just missing a "type" field (because Esprima does not
|
|
367
|
+
// assign a type property to such nodes). Be optimistic and let
|
|
368
|
+
// this.checkAllFields make the final decision.
|
|
369
|
+
if (this.typeName === "SourceLocation" ||
|
|
370
|
+
this.typeName === "Position") {
|
|
371
|
+
return this.checkAllFields(value, deep);
|
|
372
|
+
}
|
|
373
|
+
// Calling this.checkAllFields for any other type of node is both
|
|
374
|
+
// bad for performance and way too forgiving.
|
|
375
|
+
return false;
|
|
376
|
+
}
|
|
377
|
+
// If checking deeply and vDef === this, then we only need to call
|
|
378
|
+
// checkAllFields once. Calling checkAllFields is too strict when deep
|
|
379
|
+
// is false, because then we only care about this.isSupertypeOf(vDef).
|
|
380
|
+
if (deep && vDef === this) {
|
|
381
|
+
return this.checkAllFields(value, deep);
|
|
382
|
+
}
|
|
383
|
+
// In most cases we rely exclusively on isSupertypeOf to make O(1)
|
|
384
|
+
// subtyping determinations. This suffices in most situations outside
|
|
385
|
+
// of unit tests, since interface conformance is checked whenever new
|
|
386
|
+
// instances are created using builder functions.
|
|
387
|
+
if (!this.isSupertypeOf(vDef)) {
|
|
388
|
+
return false;
|
|
389
|
+
}
|
|
390
|
+
// The exception is when deep is true; then, we recursively check all
|
|
391
|
+
// fields.
|
|
392
|
+
if (!deep) {
|
|
393
|
+
return true;
|
|
394
|
+
}
|
|
395
|
+
// Use the more specific Def (vDef) to perform the deep check, but
|
|
396
|
+
// shallow-check fields defined by the less specific Def (this).
|
|
397
|
+
return vDef.checkAllFields(value, deep)
|
|
398
|
+
&& this.checkAllFields(value, false);
|
|
399
|
+
};
|
|
400
|
+
DefImpl.prototype.build = function () {
|
|
401
|
+
var _this = this;
|
|
402
|
+
var buildParams = [];
|
|
403
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
404
|
+
buildParams[_i] = arguments[_i];
|
|
405
|
+
}
|
|
406
|
+
// Calling Def.prototype.build multiple times has the effect of merely
|
|
407
|
+
// redefining this property.
|
|
408
|
+
this.buildParams = buildParams;
|
|
409
|
+
if (this.buildable) {
|
|
410
|
+
// If this Def is already buildable, update self.buildParams and
|
|
411
|
+
// continue using the old builder function.
|
|
412
|
+
return this;
|
|
413
|
+
}
|
|
414
|
+
// Every buildable type will have its "type" field filled in
|
|
415
|
+
// automatically. This includes types that are not subtypes of Node,
|
|
416
|
+
// like SourceLocation, but that seems harmless (TODO?).
|
|
417
|
+
this.field("type", String, function () { return _this.typeName; });
|
|
418
|
+
// Override Dp.buildable for this Def instance.
|
|
419
|
+
this.buildable = true;
|
|
420
|
+
var addParam = function (built, param, arg, isArgAvailable) {
|
|
421
|
+
if (hasOwn.call(built, param))
|
|
422
|
+
return;
|
|
423
|
+
var all = _this.allFields;
|
|
424
|
+
if (!hasOwn.call(all, param)) {
|
|
425
|
+
throw new Error("" + param);
|
|
426
|
+
}
|
|
427
|
+
var field = all[param];
|
|
428
|
+
var type = field.type;
|
|
429
|
+
var value;
|
|
430
|
+
if (isArgAvailable) {
|
|
431
|
+
value = arg;
|
|
432
|
+
}
|
|
433
|
+
else if (field.defaultFn) {
|
|
434
|
+
// Expose the partially-built object to the default
|
|
435
|
+
// function as its `this` object.
|
|
436
|
+
value = field.defaultFn.call(built);
|
|
437
|
+
}
|
|
438
|
+
else {
|
|
439
|
+
var message = "no value or default function given for field " +
|
|
440
|
+
JSON.stringify(param) + " of " + _this.typeName + "(" +
|
|
441
|
+
_this.buildParams.map(function (name) {
|
|
442
|
+
return all[name];
|
|
443
|
+
}).join(", ") + ")";
|
|
444
|
+
throw new Error(message);
|
|
445
|
+
}
|
|
446
|
+
if (!type.check(value)) {
|
|
447
|
+
throw new Error(shallowStringify(value) +
|
|
448
|
+
" does not match field " + field +
|
|
449
|
+
" of type " + _this.typeName);
|
|
450
|
+
}
|
|
451
|
+
built[param] = value;
|
|
452
|
+
};
|
|
453
|
+
// Calling the builder function will construct an instance of the Def,
|
|
454
|
+
// with positional arguments mapped to the fields original passed to .build.
|
|
455
|
+
// If not enough arguments are provided, the default value for the remaining fields
|
|
456
|
+
// will be used.
|
|
457
|
+
var builder = function () {
|
|
458
|
+
var args = [];
|
|
459
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
460
|
+
args[_i] = arguments[_i];
|
|
461
|
+
}
|
|
462
|
+
var argc = args.length;
|
|
463
|
+
if (!_this.finalized) {
|
|
464
|
+
throw new Error("attempting to instantiate unfinalized type " +
|
|
465
|
+
_this.typeName);
|
|
466
|
+
}
|
|
467
|
+
var built = Object.create(nodePrototype);
|
|
468
|
+
_this.buildParams.forEach(function (param, i) {
|
|
469
|
+
if (i < argc) {
|
|
470
|
+
addParam(built, param, args[i], true);
|
|
471
|
+
}
|
|
472
|
+
else {
|
|
473
|
+
addParam(built, param, null, false);
|
|
474
|
+
}
|
|
475
|
+
});
|
|
476
|
+
Object.keys(_this.allFields).forEach(function (param) {
|
|
477
|
+
// Use the default value.
|
|
478
|
+
addParam(built, param, null, false);
|
|
479
|
+
});
|
|
480
|
+
// Make sure that the "type" field was filled automatically.
|
|
481
|
+
if (built.type !== _this.typeName) {
|
|
482
|
+
throw new Error("");
|
|
483
|
+
}
|
|
484
|
+
return built;
|
|
485
|
+
};
|
|
486
|
+
// Calling .from on the builder function will construct an instance of the Def,
|
|
487
|
+
// using field values from the passed object. For fields missing from the passed object,
|
|
488
|
+
// their default value will be used.
|
|
489
|
+
builder.from = function (obj) {
|
|
490
|
+
if (!_this.finalized) {
|
|
491
|
+
throw new Error("attempting to instantiate unfinalized type " +
|
|
492
|
+
_this.typeName);
|
|
493
|
+
}
|
|
494
|
+
var built = Object.create(nodePrototype);
|
|
495
|
+
Object.keys(_this.allFields).forEach(function (param) {
|
|
496
|
+
if (hasOwn.call(obj, param)) {
|
|
497
|
+
addParam(built, param, obj[param], true);
|
|
498
|
+
}
|
|
499
|
+
else {
|
|
500
|
+
addParam(built, param, null, false);
|
|
501
|
+
}
|
|
502
|
+
});
|
|
503
|
+
// Make sure that the "type" field was filled automatically.
|
|
504
|
+
if (built.type !== _this.typeName) {
|
|
505
|
+
throw new Error("");
|
|
506
|
+
}
|
|
507
|
+
return built;
|
|
508
|
+
};
|
|
509
|
+
Object.defineProperty(builders, getBuilderName(this.typeName), {
|
|
510
|
+
enumerable: true,
|
|
511
|
+
value: builder
|
|
512
|
+
});
|
|
513
|
+
return this;
|
|
514
|
+
};
|
|
515
|
+
// The reason fields are specified using .field(...) instead of an object
|
|
516
|
+
// literal syntax is somewhat subtle: the object literal syntax would
|
|
517
|
+
// support only one key and one value, but with .field(...) we can pass
|
|
518
|
+
// any number of arguments to specify the field.
|
|
519
|
+
DefImpl.prototype.field = function (name, type, defaultFn, hidden) {
|
|
520
|
+
if (this.finalized) {
|
|
521
|
+
console.error("Ignoring attempt to redefine field " +
|
|
522
|
+
JSON.stringify(name) + " of finalized type " +
|
|
523
|
+
JSON.stringify(this.typeName));
|
|
524
|
+
return this;
|
|
525
|
+
}
|
|
526
|
+
this.ownFields[name] = new Field(name, Type.from(type), defaultFn, hidden);
|
|
527
|
+
return this; // For chaining.
|
|
528
|
+
};
|
|
529
|
+
DefImpl.prototype.finalize = function () {
|
|
530
|
+
var _this = this;
|
|
531
|
+
// It's not an error to finalize a type more than once, but only the
|
|
532
|
+
// first call to .finalize does anything.
|
|
533
|
+
if (!this.finalized) {
|
|
534
|
+
var allFields = this.allFields;
|
|
535
|
+
var allSupertypes = this.allSupertypes;
|
|
536
|
+
this.baseNames.forEach(function (name) {
|
|
537
|
+
var def = defCache[name];
|
|
538
|
+
if (def instanceof Def) {
|
|
539
|
+
def.finalize();
|
|
540
|
+
extend(allFields, def.allFields);
|
|
541
|
+
extend(allSupertypes, def.allSupertypes);
|
|
542
|
+
}
|
|
543
|
+
else {
|
|
544
|
+
var message = "unknown supertype name " +
|
|
545
|
+
JSON.stringify(name) +
|
|
546
|
+
" for subtype " +
|
|
547
|
+
JSON.stringify(_this.typeName);
|
|
548
|
+
throw new Error(message);
|
|
549
|
+
}
|
|
550
|
+
});
|
|
551
|
+
// TODO Warn if fields are overridden with incompatible types.
|
|
552
|
+
extend(allFields, this.ownFields);
|
|
553
|
+
allSupertypes[this.typeName] = this;
|
|
554
|
+
this.fieldNames.length = 0;
|
|
555
|
+
for (var fieldName in allFields) {
|
|
556
|
+
if (hasOwn.call(allFields, fieldName) &&
|
|
557
|
+
!allFields[fieldName].hidden) {
|
|
558
|
+
this.fieldNames.push(fieldName);
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
// Types are exported only once they have been finalized.
|
|
562
|
+
Object.defineProperty(namedTypes, this.typeName, {
|
|
563
|
+
enumerable: true,
|
|
564
|
+
value: this.type
|
|
565
|
+
});
|
|
566
|
+
this.finalized = true;
|
|
567
|
+
// A linearization of the inheritance hierarchy.
|
|
568
|
+
populateSupertypeList(this.typeName, this.supertypeList);
|
|
569
|
+
if (this.buildable &&
|
|
570
|
+
this.supertypeList.lastIndexOf("Expression") >= 0) {
|
|
571
|
+
wrapExpressionBuilderWithStatement(this.typeName);
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
};
|
|
575
|
+
return DefImpl;
|
|
576
|
+
}(Def));
|
|
334
577
|
// Note that the list returned by this function is a copy of the internal
|
|
335
578
|
// supertypeList, *without* the typeName itself as the first element.
|
|
336
|
-
|
|
579
|
+
function getSupertypeNames(typeName) {
|
|
337
580
|
if (!hasOwn.call(defCache, typeName)) {
|
|
338
581
|
throw new Error("");
|
|
339
582
|
}
|
|
@@ -342,16 +585,14 @@ module.exports = function () {
|
|
|
342
585
|
throw new Error("");
|
|
343
586
|
}
|
|
344
587
|
return d.supertypeList.slice(1);
|
|
345
|
-
}
|
|
346
|
-
|
|
588
|
+
}
|
|
347
589
|
// Returns an object mapping from every known type in the defCache to the
|
|
348
590
|
// most specific supertype whose name is an own property of the candidates
|
|
349
591
|
// object.
|
|
350
|
-
|
|
592
|
+
function computeSupertypeLookupTable(candidates) {
|
|
351
593
|
var table = {};
|
|
352
594
|
var typeNames = Object.keys(defCache);
|
|
353
595
|
var typeNameCount = typeNames.length;
|
|
354
|
-
|
|
355
596
|
for (var i = 0; i < typeNameCount; ++i) {
|
|
356
597
|
var typeName = typeNames[i];
|
|
357
598
|
var d = defCache[typeName];
|
|
@@ -366,287 +607,29 @@ module.exports = function () {
|
|
|
366
607
|
}
|
|
367
608
|
}
|
|
368
609
|
}
|
|
369
|
-
|
|
370
610
|
return table;
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
Dp.checkAllFields = function (value, deep) {
|
|
374
|
-
var allFields = this.allFields;
|
|
375
|
-
if (this.finalized !== true) {
|
|
376
|
-
throw new Error("" + this.typeName);
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
function checkFieldByName(name) {
|
|
380
|
-
var field = allFields[name];
|
|
381
|
-
var type = field.type;
|
|
382
|
-
var child = field.getValue(value);
|
|
383
|
-
return type.check(child, deep);
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
return isObject.check(value)
|
|
387
|
-
&& Object.keys(allFields).every(checkFieldByName);
|
|
388
|
-
};
|
|
389
|
-
|
|
390
|
-
Dp.check = function (value, deep) {
|
|
391
|
-
if (this.finalized !== true) {
|
|
392
|
-
throw new Error(
|
|
393
|
-
"prematurely checking unfinalized type " + this.typeName
|
|
394
|
-
);
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
// A Def type can only match an object value.
|
|
398
|
-
if (!isObject.check(value))
|
|
399
|
-
return false;
|
|
400
|
-
|
|
401
|
-
var vDef = Def.fromValue(value);
|
|
402
|
-
if (!vDef) {
|
|
403
|
-
// If we couldn't infer the Def associated with the given value,
|
|
404
|
-
// and we expected it to be a SourceLocation or a Position, it was
|
|
405
|
-
// probably just missing a "type" field (because Esprima does not
|
|
406
|
-
// assign a type property to such nodes). Be optimistic and let
|
|
407
|
-
// this.checkAllFields make the final decision.
|
|
408
|
-
if (this.typeName === "SourceLocation" ||
|
|
409
|
-
this.typeName === "Position") {
|
|
410
|
-
return this.checkAllFields(value, deep);
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
// Calling this.checkAllFields for any other type of node is both
|
|
414
|
-
// bad for performance and way too forgiving.
|
|
415
|
-
return false;
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
// If checking deeply and vDef === this, then we only need to call
|
|
419
|
-
// checkAllFields once. Calling checkAllFields is too strict when deep
|
|
420
|
-
// is false, because then we only care about this.isSupertypeOf(vDef).
|
|
421
|
-
if (deep && vDef === this)
|
|
422
|
-
return this.checkAllFields(value, deep);
|
|
423
|
-
|
|
424
|
-
// In most cases we rely exclusively on isSupertypeOf to make O(1)
|
|
425
|
-
// subtyping determinations. This suffices in most situations outside
|
|
426
|
-
// of unit tests, since interface conformance is checked whenever new
|
|
427
|
-
// instances are created using builder functions.
|
|
428
|
-
if (!this.isSupertypeOf(vDef))
|
|
429
|
-
return false;
|
|
430
|
-
|
|
431
|
-
// The exception is when deep is true; then, we recursively check all
|
|
432
|
-
// fields.
|
|
433
|
-
if (!deep)
|
|
434
|
-
return true;
|
|
435
|
-
|
|
436
|
-
// Use the more specific Def (vDef) to perform the deep check, but
|
|
437
|
-
// shallow-check fields defined by the less specific Def (this).
|
|
438
|
-
return vDef.checkAllFields(value, deep)
|
|
439
|
-
&& this.checkAllFields(value, false);
|
|
440
|
-
};
|
|
441
|
-
|
|
442
|
-
Dp.bases = function () {
|
|
443
|
-
var args = slice.call(arguments);
|
|
444
|
-
var bases = this.baseNames;
|
|
445
|
-
|
|
446
|
-
if (this.finalized) {
|
|
447
|
-
if (args.length !== bases.length) {
|
|
448
|
-
throw new Error("");
|
|
449
|
-
}
|
|
450
|
-
for (var i = 0; i < args.length; i++) {
|
|
451
|
-
if (args[i] !== bases[i]) {
|
|
452
|
-
throw new Error("");
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
return this;
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
args.forEach(function (baseName) {
|
|
459
|
-
isString.assert(baseName);
|
|
460
|
-
|
|
461
|
-
// This indexOf lookup may be O(n), but the typical number of base
|
|
462
|
-
// names is very small, and indexOf is a native Array method.
|
|
463
|
-
if (bases.indexOf(baseName) < 0)
|
|
464
|
-
bases.push(baseName);
|
|
465
|
-
});
|
|
466
|
-
|
|
467
|
-
return this; // For chaining.
|
|
468
|
-
};
|
|
469
|
-
|
|
470
|
-
// False by default until .build(...) is called on an instance.
|
|
471
|
-
Object.defineProperty(Dp, "buildable", {value: false});
|
|
472
|
-
|
|
473
|
-
var builders = {};
|
|
474
|
-
exports.builders = builders;
|
|
475
|
-
|
|
611
|
+
}
|
|
612
|
+
var builders = Object.create(null);
|
|
476
613
|
// This object is used as prototype for any node created by a builder.
|
|
477
614
|
var nodePrototype = {};
|
|
478
|
-
|
|
479
615
|
// Call this function to define a new method to be shared by all AST
|
|
480
|
-
|
|
481
|
-
|
|
616
|
+
// nodes. The replaced method (if any) is returned for easy wrapping.
|
|
617
|
+
function defineMethod(name, func) {
|
|
482
618
|
var old = nodePrototype[name];
|
|
483
|
-
|
|
484
619
|
// Pass undefined as func to delete nodePrototype[name].
|
|
485
620
|
if (isUndefined.check(func)) {
|
|
486
621
|
delete nodePrototype[name];
|
|
487
|
-
|
|
488
|
-
|
|
622
|
+
}
|
|
623
|
+
else {
|
|
489
624
|
isFunction.assert(func);
|
|
490
|
-
|
|
491
625
|
Object.defineProperty(nodePrototype, name, {
|
|
492
|
-
enumerable: true,
|
|
493
|
-
configurable: true,
|
|
626
|
+
enumerable: true,
|
|
627
|
+
configurable: true,
|
|
494
628
|
value: func
|
|
495
629
|
});
|
|
496
630
|
}
|
|
497
|
-
|
|
498
631
|
return old;
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
var isArrayOfString = isString.arrayOf();
|
|
502
|
-
|
|
503
|
-
// Calling the .build method of a Def simultaneously marks the type as
|
|
504
|
-
// buildable (by defining builders[getBuilderName(typeName)]) and
|
|
505
|
-
// specifies the order of arguments that should be passed to the builder
|
|
506
|
-
// function to create an instance of the type.
|
|
507
|
-
Dp.build = function (/* param1, param2, ... */) {
|
|
508
|
-
var self = this;
|
|
509
|
-
|
|
510
|
-
var newBuildParams = slice.call(arguments);
|
|
511
|
-
isArrayOfString.assert(newBuildParams);
|
|
512
|
-
|
|
513
|
-
// Calling Def.prototype.build multiple times has the effect of merely
|
|
514
|
-
// redefining this property.
|
|
515
|
-
Object.defineProperty(self, "buildParams", {
|
|
516
|
-
value: newBuildParams,
|
|
517
|
-
writable: false,
|
|
518
|
-
enumerable: false,
|
|
519
|
-
configurable: true
|
|
520
|
-
});
|
|
521
|
-
|
|
522
|
-
if (self.buildable) {
|
|
523
|
-
// If this Def is already buildable, update self.buildParams and
|
|
524
|
-
// continue using the old builder function.
|
|
525
|
-
return self;
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
// Every buildable type will have its "type" field filled in
|
|
529
|
-
// automatically. This includes types that are not subtypes of Node,
|
|
530
|
-
// like SourceLocation, but that seems harmless (TODO?).
|
|
531
|
-
self.field("type", String, function () { return self.typeName });
|
|
532
|
-
|
|
533
|
-
// Override Dp.buildable for this Def instance.
|
|
534
|
-
Object.defineProperty(self, "buildable", {value: true});
|
|
535
|
-
|
|
536
|
-
function addParam(built, param, arg, isArgAvailable) {
|
|
537
|
-
if (hasOwn.call(built, param))
|
|
538
|
-
return;
|
|
539
|
-
|
|
540
|
-
var all = self.allFields;
|
|
541
|
-
if (!hasOwn.call(all, param)) {
|
|
542
|
-
throw new Error("" + param);
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
var field = all[param];
|
|
546
|
-
var type = field.type;
|
|
547
|
-
var value;
|
|
548
|
-
|
|
549
|
-
if (isArgAvailable) {
|
|
550
|
-
value = arg;
|
|
551
|
-
} else if (field.defaultFn) {
|
|
552
|
-
// Expose the partially-built object to the default
|
|
553
|
-
// function as its `this` object.
|
|
554
|
-
value = field.defaultFn.call(built);
|
|
555
|
-
} else {
|
|
556
|
-
var message = "no value or default function given for field " +
|
|
557
|
-
JSON.stringify(param) + " of " + self.typeName + "(" +
|
|
558
|
-
self.buildParams.map(function (name) {
|
|
559
|
-
return all[name];
|
|
560
|
-
}).join(", ") + ")";
|
|
561
|
-
throw new Error(message);
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
if (!type.check(value)) {
|
|
565
|
-
throw new Error(
|
|
566
|
-
shallowStringify(value) +
|
|
567
|
-
" does not match field " + field +
|
|
568
|
-
" of type " + self.typeName
|
|
569
|
-
);
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
built[param] = value;
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
// Calling the builder function will construct an instance of the Def,
|
|
576
|
-
// with positional arguments mapped to the fields original passed to .build.
|
|
577
|
-
// If not enough arguments are provided, the default value for the remaining fields
|
|
578
|
-
// will be used.
|
|
579
|
-
function builder() {
|
|
580
|
-
var args = arguments;
|
|
581
|
-
var argc = args.length;
|
|
582
|
-
|
|
583
|
-
if (!self.finalized) {
|
|
584
|
-
throw new Error(
|
|
585
|
-
"attempting to instantiate unfinalized type " +
|
|
586
|
-
self.typeName
|
|
587
|
-
);
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
var built = Object.create(nodePrototype);
|
|
591
|
-
|
|
592
|
-
self.buildParams.forEach(function (param, i) {
|
|
593
|
-
if (i < argc) {
|
|
594
|
-
addParam(built, param, args[i], true)
|
|
595
|
-
} else {
|
|
596
|
-
addParam(built, param, null, false);
|
|
597
|
-
}
|
|
598
|
-
});
|
|
599
|
-
|
|
600
|
-
Object.keys(self.allFields).forEach(function (param) {
|
|
601
|
-
// Use the default value.
|
|
602
|
-
addParam(built, param, null, false);
|
|
603
|
-
});
|
|
604
|
-
|
|
605
|
-
// Make sure that the "type" field was filled automatically.
|
|
606
|
-
if (built.type !== self.typeName) {
|
|
607
|
-
throw new Error("");
|
|
608
|
-
}
|
|
609
|
-
|
|
610
|
-
return built;
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
// Calling .from on the builder function will construct an instance of the Def,
|
|
614
|
-
// using field values from the passed object. For fields missing from the passed object,
|
|
615
|
-
// their default value will be used.
|
|
616
|
-
builder.from = function (obj) {
|
|
617
|
-
if (!self.finalized) {
|
|
618
|
-
throw new Error(
|
|
619
|
-
"attempting to instantiate unfinalized type " +
|
|
620
|
-
self.typeName
|
|
621
|
-
);
|
|
622
|
-
}
|
|
623
|
-
|
|
624
|
-
var built = Object.create(nodePrototype);
|
|
625
|
-
|
|
626
|
-
Object.keys(self.allFields).forEach(function (param) {
|
|
627
|
-
if (hasOwn.call(obj, param)) {
|
|
628
|
-
addParam(built, param, obj[param], true);
|
|
629
|
-
} else {
|
|
630
|
-
addParam(built, param, null, false);
|
|
631
|
-
}
|
|
632
|
-
});
|
|
633
|
-
|
|
634
|
-
// Make sure that the "type" field was filled automatically.
|
|
635
|
-
if (built.type !== self.typeName) {
|
|
636
|
-
throw new Error("");
|
|
637
|
-
}
|
|
638
|
-
|
|
639
|
-
return built;
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
Object.defineProperty(builders, getBuilderName(self.typeName), {
|
|
643
|
-
enumerable: true,
|
|
644
|
-
value: builder
|
|
645
|
-
});
|
|
646
|
-
|
|
647
|
-
return self; // For chaining.
|
|
648
|
-
};
|
|
649
|
-
|
|
632
|
+
}
|
|
650
633
|
function getBuilderName(typeName) {
|
|
651
634
|
return typeName.replace(/^[A-Z]+/, function (upperCasePrefix) {
|
|
652
635
|
var len = upperCasePrefix.length;
|
|
@@ -658,216 +641,141 @@ module.exports = function () {
|
|
|
658
641
|
// If there's more than one initial capital letter, lower-case
|
|
659
642
|
// all but the last one, so that XMLDefaultDeclaration (for
|
|
660
643
|
// example) becomes xmlDefaultDeclaration.
|
|
661
|
-
return upperCasePrefix.slice(
|
|
662
|
-
|
|
663
|
-
upperCasePrefix.charAt(len - 1);
|
|
644
|
+
return upperCasePrefix.slice(0, len - 1).toLowerCase() +
|
|
645
|
+
upperCasePrefix.charAt(len - 1);
|
|
664
646
|
}
|
|
665
647
|
});
|
|
666
648
|
}
|
|
667
|
-
exports.getBuilderName = getBuilderName;
|
|
668
|
-
|
|
669
649
|
function getStatementBuilderName(typeName) {
|
|
670
650
|
typeName = getBuilderName(typeName);
|
|
671
651
|
return typeName.replace(/(Expression)?$/, "Statement");
|
|
672
652
|
}
|
|
673
|
-
exports.getStatementBuilderName = getStatementBuilderName;
|
|
674
|
-
|
|
675
|
-
// The reason fields are specified using .field(...) instead of an object
|
|
676
|
-
// literal syntax is somewhat subtle: the object literal syntax would
|
|
677
|
-
// support only one key and one value, but with .field(...) we can pass
|
|
678
|
-
// any number of arguments to specify the field.
|
|
679
|
-
Dp.field = function (name, type, defaultFn, hidden) {
|
|
680
|
-
if (this.finalized) {
|
|
681
|
-
console.error("Ignoring attempt to redefine field " +
|
|
682
|
-
JSON.stringify(name) + " of finalized type " +
|
|
683
|
-
JSON.stringify(this.typeName));
|
|
684
|
-
return this;
|
|
685
|
-
}
|
|
686
|
-
this.ownFields[name] = new Field(name, type, defaultFn, hidden);
|
|
687
|
-
return this; // For chaining.
|
|
688
|
-
};
|
|
689
|
-
|
|
690
653
|
var namedTypes = {};
|
|
691
|
-
exports.namedTypes = namedTypes;
|
|
692
|
-
|
|
693
654
|
// Like Object.keys, but aware of what fields each AST type should have.
|
|
694
655
|
function getFieldNames(object) {
|
|
695
|
-
var d =
|
|
656
|
+
var d = defFromValue(object);
|
|
696
657
|
if (d) {
|
|
697
658
|
return d.fieldNames.slice(0);
|
|
698
659
|
}
|
|
699
|
-
|
|
700
660
|
if ("type" in object) {
|
|
701
|
-
throw new Error(
|
|
702
|
-
|
|
703
|
-
JSON.stringify(object.type)
|
|
704
|
-
);
|
|
661
|
+
throw new Error("did not recognize object of type " +
|
|
662
|
+
JSON.stringify(object.type));
|
|
705
663
|
}
|
|
706
|
-
|
|
707
664
|
return Object.keys(object);
|
|
708
665
|
}
|
|
709
|
-
exports.getFieldNames = getFieldNames;
|
|
710
|
-
|
|
711
666
|
// Get the value of an object property, taking object.type and default
|
|
712
667
|
// functions into account.
|
|
713
668
|
function getFieldValue(object, fieldName) {
|
|
714
|
-
var d =
|
|
669
|
+
var d = defFromValue(object);
|
|
715
670
|
if (d) {
|
|
716
671
|
var field = d.allFields[fieldName];
|
|
717
672
|
if (field) {
|
|
718
673
|
return field.getValue(object);
|
|
719
674
|
}
|
|
720
675
|
}
|
|
721
|
-
|
|
722
676
|
return object && object[fieldName];
|
|
723
677
|
}
|
|
724
|
-
exports.getFieldValue = getFieldValue;
|
|
725
|
-
|
|
726
678
|
// Iterate over all defined fields of an object, including those missing
|
|
727
679
|
// or undefined, passing each field name and effective value (as returned
|
|
728
680
|
// by getFieldValue) to the callback. If the object has no corresponding
|
|
729
681
|
// Def, the callback will never be called.
|
|
730
|
-
|
|
682
|
+
function eachField(object, callback, context) {
|
|
731
683
|
getFieldNames(object).forEach(function (name) {
|
|
732
684
|
callback.call(this, name, getFieldValue(object, name));
|
|
733
685
|
}, context);
|
|
734
|
-
}
|
|
735
|
-
|
|
686
|
+
}
|
|
736
687
|
// Similar to eachField, except that iteration stops as soon as the
|
|
737
688
|
// callback returns a truthy value. Like Array.prototype.some, the final
|
|
738
689
|
// result is either true or false to indicates whether the callback
|
|
739
690
|
// returned true for any element or not.
|
|
740
|
-
|
|
691
|
+
function someField(object, callback, context) {
|
|
741
692
|
return getFieldNames(object).some(function (name) {
|
|
742
693
|
return callback.call(this, name, getFieldValue(object, name));
|
|
743
694
|
}, context);
|
|
744
|
-
}
|
|
745
|
-
|
|
746
|
-
// This property will be overridden as true by individual Def instances
|
|
747
|
-
// when they are finalized.
|
|
748
|
-
Object.defineProperty(Dp, "finalized", {value: false});
|
|
749
|
-
|
|
750
|
-
Dp.finalize = function () {
|
|
751
|
-
var self = this;
|
|
752
|
-
|
|
753
|
-
// It's not an error to finalize a type more than once, but only the
|
|
754
|
-
// first call to .finalize does anything.
|
|
755
|
-
if (!self.finalized) {
|
|
756
|
-
var allFields = self.allFields;
|
|
757
|
-
var allSupertypes = self.allSupertypes;
|
|
758
|
-
|
|
759
|
-
self.baseNames.forEach(function (name) {
|
|
760
|
-
var def = defCache[name];
|
|
761
|
-
if (def instanceof Def) {
|
|
762
|
-
def.finalize();
|
|
763
|
-
extend(allFields, def.allFields);
|
|
764
|
-
extend(allSupertypes, def.allSupertypes);
|
|
765
|
-
} else {
|
|
766
|
-
var message = "unknown supertype name " +
|
|
767
|
-
JSON.stringify(name) +
|
|
768
|
-
" for subtype " +
|
|
769
|
-
JSON.stringify(self.typeName);
|
|
770
|
-
throw new Error(message);
|
|
771
|
-
}
|
|
772
|
-
});
|
|
773
|
-
|
|
774
|
-
// TODO Warn if fields are overridden with incompatible types.
|
|
775
|
-
extend(allFields, self.ownFields);
|
|
776
|
-
allSupertypes[self.typeName] = self;
|
|
777
|
-
|
|
778
|
-
self.fieldNames.length = 0;
|
|
779
|
-
for (var fieldName in allFields) {
|
|
780
|
-
if (hasOwn.call(allFields, fieldName) &&
|
|
781
|
-
!allFields[fieldName].hidden) {
|
|
782
|
-
self.fieldNames.push(fieldName);
|
|
783
|
-
}
|
|
784
|
-
}
|
|
785
|
-
|
|
786
|
-
// Types are exported only once they have been finalized.
|
|
787
|
-
Object.defineProperty(namedTypes, self.typeName, {
|
|
788
|
-
enumerable: true,
|
|
789
|
-
value: self.type
|
|
790
|
-
});
|
|
791
|
-
|
|
792
|
-
Object.defineProperty(self, "finalized", {value: true});
|
|
793
|
-
|
|
794
|
-
// A linearization of the inheritance hierarchy.
|
|
795
|
-
populateSupertypeList(self.typeName, self.supertypeList);
|
|
796
|
-
|
|
797
|
-
if (self.buildable && self.supertypeList.lastIndexOf("Expression") >= 0) {
|
|
798
|
-
wrapExpressionBuilderWithStatement(self.typeName);
|
|
799
|
-
}
|
|
800
|
-
}
|
|
801
|
-
};
|
|
802
|
-
|
|
695
|
+
}
|
|
803
696
|
// Adds an additional builder for Expression subtypes
|
|
804
697
|
// that wraps the built Expression in an ExpressionStatements.
|
|
805
698
|
function wrapExpressionBuilderWithStatement(typeName) {
|
|
806
699
|
var wrapperName = getStatementBuilderName(typeName);
|
|
807
|
-
|
|
808
700
|
// skip if the builder already exists
|
|
809
|
-
if (builders[wrapperName])
|
|
810
|
-
|
|
701
|
+
if (builders[wrapperName])
|
|
702
|
+
return;
|
|
811
703
|
// the builder function to wrap with builders.ExpressionStatement
|
|
812
704
|
var wrapped = builders[getBuilderName(typeName)];
|
|
813
|
-
|
|
814
705
|
// skip if there is nothing to wrap
|
|
815
|
-
if (!wrapped)
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
706
|
+
if (!wrapped)
|
|
707
|
+
return;
|
|
708
|
+
var builder = function () {
|
|
709
|
+
var args = [];
|
|
710
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
711
|
+
args[_i] = arguments[_i];
|
|
712
|
+
}
|
|
713
|
+
return builders.expressionStatement(wrapped.apply(builders, args));
|
|
714
|
+
};
|
|
715
|
+
builder.from = function () {
|
|
716
|
+
var args = [];
|
|
717
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
718
|
+
args[_i] = arguments[_i];
|
|
719
|
+
}
|
|
720
|
+
return builders.expressionStatement(wrapped.from.apply(builders, args));
|
|
819
721
|
};
|
|
722
|
+
builders[wrapperName] = builder;
|
|
820
723
|
}
|
|
821
|
-
|
|
822
724
|
function populateSupertypeList(typeName, list) {
|
|
823
725
|
list.length = 0;
|
|
824
726
|
list.push(typeName);
|
|
825
|
-
|
|
826
727
|
var lastSeen = Object.create(null);
|
|
827
|
-
|
|
828
728
|
for (var pos = 0; pos < list.length; ++pos) {
|
|
829
729
|
typeName = list[pos];
|
|
830
730
|
var d = defCache[typeName];
|
|
831
731
|
if (d.finalized !== true) {
|
|
832
732
|
throw new Error("");
|
|
833
733
|
}
|
|
834
|
-
|
|
835
734
|
// If we saw typeName earlier in the breadth-first traversal,
|
|
836
735
|
// delete the last-seen occurrence.
|
|
837
736
|
if (hasOwn.call(lastSeen, typeName)) {
|
|
838
737
|
delete list[lastSeen[typeName]];
|
|
839
738
|
}
|
|
840
|
-
|
|
841
739
|
// Record the new index of the last-seen occurrence of typeName.
|
|
842
740
|
lastSeen[typeName] = pos;
|
|
843
|
-
|
|
844
741
|
// Enqueue the base names of this type.
|
|
845
742
|
list.push.apply(list, d.baseNames);
|
|
846
743
|
}
|
|
847
|
-
|
|
848
744
|
// Compaction loop to remove array holes.
|
|
849
745
|
for (var to = 0, from = to, len = list.length; from < len; ++from) {
|
|
850
746
|
if (hasOwn.call(list, from)) {
|
|
851
747
|
list[to++] = list[from];
|
|
852
748
|
}
|
|
853
749
|
}
|
|
854
|
-
|
|
855
750
|
list.length = to;
|
|
856
751
|
}
|
|
857
|
-
|
|
858
752
|
function extend(into, from) {
|
|
859
753
|
Object.keys(from).forEach(function (name) {
|
|
860
754
|
into[name] = from[name];
|
|
861
755
|
});
|
|
862
|
-
|
|
863
756
|
return into;
|
|
864
|
-
}
|
|
865
|
-
|
|
866
|
-
exports.finalize = function () {
|
|
757
|
+
}
|
|
758
|
+
function finalize() {
|
|
867
759
|
Object.keys(defCache).forEach(function (name) {
|
|
868
760
|
defCache[name].finalize();
|
|
869
761
|
});
|
|
762
|
+
}
|
|
763
|
+
return {
|
|
764
|
+
Type: Type,
|
|
765
|
+
builtInTypes: builtInTypes,
|
|
766
|
+
getSupertypeNames: getSupertypeNames,
|
|
767
|
+
computeSupertypeLookupTable: computeSupertypeLookupTable,
|
|
768
|
+
builders: builders,
|
|
769
|
+
defineMethod: defineMethod,
|
|
770
|
+
getBuilderName: getBuilderName,
|
|
771
|
+
getStatementBuilderName: getStatementBuilderName,
|
|
772
|
+
namedTypes: namedTypes,
|
|
773
|
+
getFieldNames: getFieldNames,
|
|
774
|
+
getFieldValue: getFieldValue,
|
|
775
|
+
eachField: eachField,
|
|
776
|
+
someField: someField,
|
|
777
|
+
finalize: finalize,
|
|
870
778
|
};
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
779
|
+
}
|
|
780
|
+
exports.default = typesPlugin;
|
|
781
|
+
;
|