ast-types 0.3.34 → 0.3.38
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/def/core.js +1 -1
- package/def/es6.js +2 -1
- package/def/es7.js +1 -1
- package/lib/node-path.js +12 -4
- package/lib/types.js +142 -108
- package/main.js +2 -0
- package/package.json +1 -1
- package/test/run.js +29 -5
package/def/core.js
CHANGED
package/def/es6.js
CHANGED
|
@@ -80,7 +80,8 @@ def("ModuleDeclaration")
|
|
|
80
80
|
def("Property")
|
|
81
81
|
// Esprima extensions not mentioned in the Mozilla Parser API:
|
|
82
82
|
.field("method", isBoolean, defaults["false"])
|
|
83
|
-
.field("shorthand", isBoolean, defaults["false"])
|
|
83
|
+
.field("shorthand", isBoolean, defaults["false"])
|
|
84
|
+
.field("computed", isBoolean, defaults["false"]);
|
|
84
85
|
|
|
85
86
|
def("MethodDefinition")
|
|
86
87
|
.bases("Declaration")
|
package/def/es7.js
CHANGED
package/lib/node-path.js
CHANGED
|
@@ -129,7 +129,7 @@ NPp.needsParens = function(assumeExpressionContext) {
|
|
|
129
129
|
if (!n.Expression.check(node))
|
|
130
130
|
return false;
|
|
131
131
|
|
|
132
|
-
if (
|
|
132
|
+
if (isUnaryLike(node))
|
|
133
133
|
return n.MemberExpression.check(parent)
|
|
134
134
|
&& this.name === "object"
|
|
135
135
|
&& parent.object === node;
|
|
@@ -141,7 +141,7 @@ NPp.needsParens = function(assumeExpressionContext) {
|
|
|
141
141
|
return true;
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
-
if (
|
|
144
|
+
if (isUnaryLike(parent))
|
|
145
145
|
return true;
|
|
146
146
|
|
|
147
147
|
if (n.MemberExpression.check(parent) &&
|
|
@@ -192,7 +192,7 @@ NPp.needsParens = function(assumeExpressionContext) {
|
|
|
192
192
|
|| n.MemberExpression.check(parent)
|
|
193
193
|
|| n.NewExpression.check(parent)
|
|
194
194
|
|| n.ConditionalExpression.check(parent)
|
|
195
|
-
||
|
|
195
|
+
|| isUnaryLike(parent)
|
|
196
196
|
|| n.YieldExpression.check(parent);
|
|
197
197
|
|
|
198
198
|
if (n.NewExpression.check(parent) &&
|
|
@@ -211,7 +211,7 @@ NPp.needsParens = function(assumeExpressionContext) {
|
|
|
211
211
|
|
|
212
212
|
if (n.AssignmentExpression.check(node) ||
|
|
213
213
|
n.ConditionalExpression.check(node)) {
|
|
214
|
-
if (
|
|
214
|
+
if (isUnaryLike(parent))
|
|
215
215
|
return true;
|
|
216
216
|
|
|
217
217
|
if (isBinary(parent))
|
|
@@ -249,6 +249,14 @@ function isBinary(node) {
|
|
|
249
249
|
|| n.LogicalExpression.check(node);
|
|
250
250
|
}
|
|
251
251
|
|
|
252
|
+
function isUnaryLike(node) {
|
|
253
|
+
return n.UnaryExpression.check(node)
|
|
254
|
+
// I considered making SpreadElement and SpreadProperty subtypes
|
|
255
|
+
// of UnaryExpression, but they're not really Expression nodes.
|
|
256
|
+
|| (n.SpreadElement && n.SpreadElement.check(node))
|
|
257
|
+
|| (n.SpreadProperty && n.SpreadProperty.check(node));
|
|
258
|
+
}
|
|
259
|
+
|
|
252
260
|
var PRECEDENCE = {};
|
|
253
261
|
[["||"],
|
|
254
262
|
["&&"],
|
package/lib/types.js
CHANGED
|
@@ -44,7 +44,7 @@ var Tp = Type.prototype;
|
|
|
44
44
|
|
|
45
45
|
// Throughout this file we use Object.defineProperty to prevent
|
|
46
46
|
// redefinition of exported properties.
|
|
47
|
-
|
|
47
|
+
exports.Type = Type;
|
|
48
48
|
|
|
49
49
|
// Like .check, except that failure triggers an AssertionError.
|
|
50
50
|
Tp.assert = function(value, deep) {
|
|
@@ -81,10 +81,7 @@ Tp.toString = function() {
|
|
|
81
81
|
};
|
|
82
82
|
|
|
83
83
|
var builtInTypes = {};
|
|
84
|
-
|
|
85
|
-
enumerable: true,
|
|
86
|
-
value: builtInTypes
|
|
87
|
-
});
|
|
84
|
+
exports.builtInTypes = builtInTypes;
|
|
88
85
|
|
|
89
86
|
function defBuiltInType(example, name) {
|
|
90
87
|
var objStr = objToStr.call(example);
|
|
@@ -268,7 +265,9 @@ function Def(typeName) {
|
|
|
268
265
|
|
|
269
266
|
// These two are populated during finalization.
|
|
270
267
|
allSupertypes: { value: {} }, // Includes own typeName.
|
|
268
|
+
supertypeList: { value: [] }, // Linear inheritance hierarchy.
|
|
271
269
|
allFields: { value: {} }, // Includes inherited fields.
|
|
270
|
+
fieldNames: { value: [] }, // Non-hidden keys of allFields.
|
|
272
271
|
|
|
273
272
|
type: {
|
|
274
273
|
value: new Type(function(value, deep) {
|
|
@@ -279,14 +278,18 @@ function Def(typeName) {
|
|
|
279
278
|
}
|
|
280
279
|
|
|
281
280
|
Def.fromValue = function(value) {
|
|
282
|
-
if (
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
281
|
+
if (value && typeof value === "object") {
|
|
282
|
+
var type = value.type;
|
|
283
|
+
if (typeof type === "string" &&
|
|
284
|
+
hasOwn.call(defCache, type)) {
|
|
285
|
+
var d = defCache[type];
|
|
286
|
+
if (d.finalized) {
|
|
287
|
+
return d;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
289
290
|
}
|
|
291
|
+
|
|
292
|
+
return null;
|
|
290
293
|
};
|
|
291
294
|
|
|
292
295
|
var Dp = Def.prototype;
|
|
@@ -301,6 +304,29 @@ Dp.isSupertypeOf = function(that) {
|
|
|
301
304
|
}
|
|
302
305
|
};
|
|
303
306
|
|
|
307
|
+
// Returns an object mapping from every known type in the defCache to the
|
|
308
|
+
// most specific supertype whose name is an own property of the candidates
|
|
309
|
+
// object.
|
|
310
|
+
exports.computeSupertypeLookupTable = function(candidates) {
|
|
311
|
+
var table = {};
|
|
312
|
+
|
|
313
|
+
for (var typeName in defCache) {
|
|
314
|
+
if (hasOwn.call(defCache, typeName)) {
|
|
315
|
+
var d = defCache[typeName];
|
|
316
|
+
assert.strictEqual(d.finalized, true);
|
|
317
|
+
for (var i = 0; i < d.supertypeList.length; ++i) {
|
|
318
|
+
var superTypeName = d.supertypeList[i];
|
|
319
|
+
if (hasOwn.call(candidates, superTypeName)) {
|
|
320
|
+
table[typeName] = superTypeName;
|
|
321
|
+
break;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
return table;
|
|
328
|
+
};
|
|
329
|
+
|
|
304
330
|
Dp.checkAllFields = function(value, deep) {
|
|
305
331
|
var allFields = this.allFields;
|
|
306
332
|
assert.strictEqual(this.finalized, true);
|
|
@@ -387,36 +413,32 @@ Dp.bases = function() {
|
|
|
387
413
|
Object.defineProperty(Dp, "buildable", { value: false });
|
|
388
414
|
|
|
389
415
|
var builders = {};
|
|
390
|
-
|
|
391
|
-
value: builders
|
|
392
|
-
});
|
|
416
|
+
exports.builders = builders;
|
|
393
417
|
|
|
394
418
|
// This object is used as prototype for any node created by a builder.
|
|
395
419
|
var nodePrototype = {};
|
|
396
420
|
|
|
397
421
|
// Call this function to define a new method to be shared by all AST
|
|
398
422
|
// nodes. The replaced method (if any) is returned for easy wrapping.
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
var old = nodePrototype[name];
|
|
423
|
+
exports.defineMethod = function(name, func) {
|
|
424
|
+
var old = nodePrototype[name];
|
|
402
425
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
426
|
+
// Pass undefined as func to delete nodePrototype[name].
|
|
427
|
+
if (isUndefined.check(func)) {
|
|
428
|
+
delete nodePrototype[name];
|
|
406
429
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
Object.defineProperty(nodePrototype, name, {
|
|
411
|
-
enumerable: true, // For discoverability.
|
|
412
|
-
configurable: true, // For delete proto[name].
|
|
413
|
-
value: func
|
|
414
|
-
});
|
|
415
|
-
}
|
|
430
|
+
} else {
|
|
431
|
+
isFunction.assert(func);
|
|
416
432
|
|
|
417
|
-
|
|
433
|
+
Object.defineProperty(nodePrototype, name, {
|
|
434
|
+
enumerable: true, // For discoverability.
|
|
435
|
+
configurable: true, // For delete proto[name].
|
|
436
|
+
value: func
|
|
437
|
+
});
|
|
418
438
|
}
|
|
419
|
-
|
|
439
|
+
|
|
440
|
+
return old;
|
|
441
|
+
};
|
|
420
442
|
|
|
421
443
|
// Calling the .build method of a Def simultaneously marks the type as
|
|
422
444
|
// buildable (by defining builders[getBuilderName(typeName)]) and
|
|
@@ -547,86 +569,59 @@ Dp.field = function(name, type, defaultFn, hidden) {
|
|
|
547
569
|
};
|
|
548
570
|
|
|
549
571
|
var namedTypes = {};
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
572
|
+
exports.namedTypes = namedTypes;
|
|
573
|
+
|
|
574
|
+
// Like Object.keys, but aware of what fields each AST type should have.
|
|
575
|
+
function getFieldNames(object) {
|
|
576
|
+
var d = Def.fromValue(object);
|
|
577
|
+
if (d) {
|
|
578
|
+
return d.fieldNames.slice(0);
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
assert.strictEqual(
|
|
582
|
+
"type" in object, false,
|
|
583
|
+
"did not recognize object of type " +
|
|
584
|
+
JSON.stringify(object.type)
|
|
585
|
+
);
|
|
586
|
+
|
|
587
|
+
return Object.keys(object);
|
|
588
|
+
}
|
|
589
|
+
exports.getFieldNames = getFieldNames;
|
|
553
590
|
|
|
554
591
|
// Get the value of an object property, taking object.type and default
|
|
555
592
|
// functions into account.
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
return field.getValue(object);
|
|
563
|
-
}
|
|
593
|
+
function getFieldValue(object, fieldName) {
|
|
594
|
+
var d = Def.fromValue(object);
|
|
595
|
+
if (d) {
|
|
596
|
+
var field = d.allFields[fieldName];
|
|
597
|
+
if (field) {
|
|
598
|
+
return field.getValue(object);
|
|
564
599
|
}
|
|
565
|
-
|
|
566
|
-
return object[fieldName];
|
|
567
600
|
}
|
|
568
|
-
|
|
601
|
+
|
|
602
|
+
return object[fieldName];
|
|
603
|
+
}
|
|
604
|
+
exports.getFieldValue = getFieldValue;
|
|
569
605
|
|
|
570
606
|
// Iterate over all defined fields of an object, including those missing
|
|
571
607
|
// or undefined, passing each field name and effective value (as returned
|
|
572
608
|
// by getFieldValue) to the callback. If the object has no corresponding
|
|
573
609
|
// Def, the callback will never be called.
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
Object.keys(all).forEach(function(name) {
|
|
580
|
-
var field = all[name];
|
|
581
|
-
if (!field.hidden) {
|
|
582
|
-
callback.call(this, name, field.getValue(object));
|
|
583
|
-
}
|
|
584
|
-
}, context);
|
|
585
|
-
} else {
|
|
586
|
-
assert.strictEqual(
|
|
587
|
-
"type" in object, false,
|
|
588
|
-
"did not recognize object of type " + JSON.stringify(object.type)
|
|
589
|
-
);
|
|
590
|
-
|
|
591
|
-
// If we could not infer a Def type for this object, just
|
|
592
|
-
// iterate over its keys in the normal way.
|
|
593
|
-
Object.keys(object).forEach(function(name) {
|
|
594
|
-
callback.call(this, name, object[name]);
|
|
595
|
-
}, context);
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
});
|
|
610
|
+
exports.eachField = function(object, callback, context) {
|
|
611
|
+
getFieldNames(object).forEach(function(name) {
|
|
612
|
+
callback.call(this, name, getFieldValue(object, name));
|
|
613
|
+
}, context);
|
|
614
|
+
};
|
|
599
615
|
|
|
600
616
|
// Similar to eachField, except that iteration stops as soon as the
|
|
601
617
|
// callback returns a truthy value. Like Array.prototype.some, the final
|
|
602
618
|
// result is either true or false to indicates whether the callback
|
|
603
619
|
// returned true for any element or not.
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
return Object.keys(all).some(function(name) {
|
|
610
|
-
var field = all[name];
|
|
611
|
-
if (!field.hidden) {
|
|
612
|
-
var value = field.getValue(object);
|
|
613
|
-
return callback.call(this, name, value);
|
|
614
|
-
}
|
|
615
|
-
}, context);
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
assert.strictEqual(
|
|
619
|
-
"type" in object, false,
|
|
620
|
-
"did not recognize object of type " + JSON.stringify(object.type)
|
|
621
|
-
);
|
|
622
|
-
|
|
623
|
-
// If we could not infer a Def type for this object, just iterate
|
|
624
|
-
// over its keys in the normal way.
|
|
625
|
-
return Object.keys(object).some(function(name) {
|
|
626
|
-
return callback.call(this, name, object[name]);
|
|
627
|
-
}, context);
|
|
628
|
-
}
|
|
629
|
-
});
|
|
620
|
+
exports.someField = function(object, callback, context) {
|
|
621
|
+
return getFieldNames(object).some(function(name) {
|
|
622
|
+
return callback.call(this, name, getFieldValue(object, name));
|
|
623
|
+
}, context);
|
|
624
|
+
};
|
|
630
625
|
|
|
631
626
|
// This property will be overridden as true by individual Def instances
|
|
632
627
|
// when they are finalized.
|
|
@@ -650,6 +645,14 @@ Dp.finalize = function() {
|
|
|
650
645
|
extend(allFields, this.ownFields);
|
|
651
646
|
allSupertypes[this.typeName] = this;
|
|
652
647
|
|
|
648
|
+
this.fieldNames.length = 0;
|
|
649
|
+
for (var fieldName in allFields) {
|
|
650
|
+
if (hasOwn.call(allFields, fieldName) &&
|
|
651
|
+
!allFields[fieldName].hidden) {
|
|
652
|
+
this.fieldNames.push(fieldName);
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
|
|
653
656
|
// Types are exported only once they have been finalized.
|
|
654
657
|
Object.defineProperty(namedTypes, this.typeName, {
|
|
655
658
|
enumerable: true,
|
|
@@ -657,9 +660,46 @@ Dp.finalize = function() {
|
|
|
657
660
|
});
|
|
658
661
|
|
|
659
662
|
Object.defineProperty(this, "finalized", { value: true });
|
|
663
|
+
|
|
664
|
+
// A linearization of the inheritance hierarchy.
|
|
665
|
+
populateSupertypeList(this.typeName, this.supertypeList);
|
|
660
666
|
}
|
|
661
667
|
};
|
|
662
668
|
|
|
669
|
+
function populateSupertypeList(typeName, list) {
|
|
670
|
+
list.length = 0;
|
|
671
|
+
list.push(typeName);
|
|
672
|
+
|
|
673
|
+
var lastSeen = {};
|
|
674
|
+
|
|
675
|
+
for (var pos = 0; pos < list.length; ++pos) {
|
|
676
|
+
typeName = list[pos];
|
|
677
|
+
var d = defCache[typeName];
|
|
678
|
+
assert.strictEqual(d.finalized, true);
|
|
679
|
+
|
|
680
|
+
// If we saw typeName earlier in the breadth-first traversal,
|
|
681
|
+
// delete the last-seen occurrence.
|
|
682
|
+
if (hasOwn.call(lastSeen, typeName)) {
|
|
683
|
+
delete list[lastSeen[typeName]];
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
// Record the new index of the last-seen occurrence of typeName.
|
|
687
|
+
lastSeen[typeName] = pos;
|
|
688
|
+
|
|
689
|
+
// Enqueue the base names of this type.
|
|
690
|
+
list.push.apply(list, d.baseNames);
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
// Compaction loop to remove array holes.
|
|
694
|
+
for (var to = 0, from = to, len = list.length; from < len; ++from) {
|
|
695
|
+
if (hasOwn.call(list, from)) {
|
|
696
|
+
list[to++] = list[from];
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
list.length = to;
|
|
701
|
+
}
|
|
702
|
+
|
|
663
703
|
function extend(into, from) {
|
|
664
704
|
Object.keys(from).forEach(function(name) {
|
|
665
705
|
into[name] = from[name];
|
|
@@ -668,14 +708,8 @@ function extend(into, from) {
|
|
|
668
708
|
return into;
|
|
669
709
|
};
|
|
670
710
|
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
value: function() {
|
|
677
|
-
Object.keys(defCache).forEach(function(name) {
|
|
678
|
-
defCache[name].finalize();
|
|
679
|
-
});
|
|
680
|
-
}
|
|
681
|
-
});
|
|
711
|
+
exports.finalize = function() {
|
|
712
|
+
Object.keys(defCache).forEach(function(name) {
|
|
713
|
+
defCache[name].finalize();
|
|
714
|
+
});
|
|
715
|
+
};
|
package/main.js
CHANGED
|
@@ -19,9 +19,11 @@ exports.builtInTypes = types.builtInTypes;
|
|
|
19
19
|
exports.namedTypes = types.namedTypes;
|
|
20
20
|
exports.builders = types.builders;
|
|
21
21
|
exports.defineMethod = types.defineMethod;
|
|
22
|
+
exports.getFieldNames = types.getFieldNames;
|
|
22
23
|
exports.getFieldValue = types.getFieldValue;
|
|
23
24
|
exports.eachField = types.eachField;
|
|
24
25
|
exports.someField = types.someField;
|
|
25
26
|
exports.traverse = require("./lib/traverse");
|
|
26
27
|
exports.finalize = types.finalize;
|
|
27
28
|
exports.NodePath = require("./lib/node-path");
|
|
29
|
+
exports.computeSupertypeLookupTable = types.computeSupertypeLookupTable;
|
package/package.json
CHANGED
package/test/run.js
CHANGED
|
@@ -47,6 +47,32 @@ describe("isSupertypeOf", function() {
|
|
|
47
47
|
});
|
|
48
48
|
});
|
|
49
49
|
|
|
50
|
+
describe("computeSupertypeLookupTable", function() {
|
|
51
|
+
it("should resolve the most precise supertypes", function() {
|
|
52
|
+
var table = types.computeSupertypeLookupTable({
|
|
53
|
+
Function: true,
|
|
54
|
+
Declaration: true,
|
|
55
|
+
ArrowFunctionExpression: true,
|
|
56
|
+
Expression: true,
|
|
57
|
+
Identifier: true
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
function check(subtype, expectedSupertype) {
|
|
61
|
+
assert.strictEqual(table[subtype], expectedSupertype);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
check("FunctionExpression", "Function");
|
|
65
|
+
check("FunctionDeclaration", "Function");
|
|
66
|
+
check("VariableDeclaration", "Declaration");
|
|
67
|
+
check("Identifier", "Identifier");
|
|
68
|
+
check("ArrowFunctionExpression", "ArrowFunctionExpression");
|
|
69
|
+
check("ForInStatement");
|
|
70
|
+
check("Node");
|
|
71
|
+
check("ThisExpression", "Expression");
|
|
72
|
+
check("Property");
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
|
|
50
76
|
describe("shallow and deep checks", function() {
|
|
51
77
|
var index = b.identifier("foo");
|
|
52
78
|
var decl = b.variableDeclaration("var", [
|
|
@@ -248,9 +274,7 @@ describe("types.eachField", function() {
|
|
|
248
274
|
}
|
|
249
275
|
|
|
250
276
|
it("should give correct keys for supertypes", function() {
|
|
251
|
-
check({ type: "Expression" }, [
|
|
252
|
-
"type", "loc"
|
|
253
|
-
]);
|
|
277
|
+
check({ type: "Expression" }, ["type"]);
|
|
254
278
|
});
|
|
255
279
|
|
|
256
280
|
it("should work for non-buildable types", function() {
|
|
@@ -266,12 +290,12 @@ describe("types.eachField", function() {
|
|
|
266
290
|
it("should respect hidden fields", function() {
|
|
267
291
|
check({ type: "TryStatement" }, [
|
|
268
292
|
// Note that the "handlers" field is now hidden from eachField.
|
|
269
|
-
"type", "block", "handler", "guardedHandlers", "finalizer"
|
|
293
|
+
"type", "block", "handler", "guardedHandlers", "finalizer"
|
|
270
294
|
]);
|
|
271
295
|
});
|
|
272
296
|
|
|
273
297
|
check({ type: "CatchClause" }, [
|
|
274
|
-
"type", "param", "guard", "body"
|
|
298
|
+
"type", "param", "guard", "body"
|
|
275
299
|
]);
|
|
276
300
|
|
|
277
301
|
it("should complain about invalid types", function() {
|