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 CHANGED
@@ -16,7 +16,7 @@ def("Node")
16
16
  .field("loc", or(
17
17
  def("SourceLocation"),
18
18
  null
19
- ), defaults["null"]);
19
+ ), defaults["null"], true);
20
20
 
21
21
  def("SourceLocation")
22
22
  .build("start", "end", "source")
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
@@ -32,4 +32,4 @@ def("AwaitExpression")
32
32
  .bases("Expression")
33
33
  .build("argument", "all")
34
34
  .field("argument", or(def("Expression"), null))
35
- .field("all", isBoolean, false);
35
+ .field("all", isBoolean, defaults["false"]);
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 (n.UnaryExpression.check(node))
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 (n.UnaryExpression.check(parent))
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
- || n.UnaryExpression.check(parent)
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 (n.UnaryExpression.check(parent))
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
- Object.defineProperty(exports, "Type", { value: Type });
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
- Object.defineProperty(exports, "builtInTypes", {
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 (isObject.check(value) &&
283
- hasOwn.call(value, "type") &&
284
- hasOwn.call(defCache, value.type))
285
- {
286
- var vDef = defCache[value.type];
287
- assert.strictEqual(vDef.finalized, true);
288
- return vDef;
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
- Object.defineProperty(exports, "builders", {
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
- Object.defineProperty(exports, "defineMethod", {
400
- value: function(name, func) {
401
- var old = nodePrototype[name];
423
+ exports.defineMethod = function(name, func) {
424
+ var old = nodePrototype[name];
402
425
 
403
- // Pass undefined as func to delete nodePrototype[name].
404
- if (isUndefined.check(func)) {
405
- delete nodePrototype[name];
426
+ // Pass undefined as func to delete nodePrototype[name].
427
+ if (isUndefined.check(func)) {
428
+ delete nodePrototype[name];
406
429
 
407
- } else {
408
- isFunction.assert(func);
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
- return old;
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
- Object.defineProperty(exports, "namedTypes", {
551
- value: namedTypes
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
- Object.defineProperty(exports, "getFieldValue", {
557
- value: function(object, fieldName) {
558
- var d = Def.fromValue(object);
559
- if (d) {
560
- var field = d.allFields[fieldName];
561
- if (field) {
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
- Object.defineProperty(exports, "eachField", {
575
- value: function(object, callback, context) {
576
- var d = Def.fromValue(object);
577
- if (d) {
578
- var all = d.allFields;
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
- Object.defineProperty(exports, "someField", {
605
- value: function(object, callback, context) {
606
- var d = Def.fromValue(object);
607
- if (d) {
608
- var all = d.allFields;
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
- Object.defineProperty(exports, "finalize", {
672
- // This function should be called at the end of any complete file of
673
- // type definitions. It declares that everything defined so far is
674
- // complete and needs no further modification, and defines all
675
- // finalized types as properties of exports.namedTypes.
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
@@ -18,7 +18,7 @@
18
18
  "transformation",
19
19
  "syntax"
20
20
  ],
21
- "version": "0.3.34",
21
+ "version": "0.3.38",
22
22
  "homepage": "http://github.com/benjamn/ast-types",
23
23
  "repository": {
24
24
  "type": "git",
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", "loc"
293
+ "type", "block", "handler", "guardedHandlers", "finalizer"
270
294
  ]);
271
295
  });
272
296
 
273
297
  check({ type: "CatchClause" }, [
274
- "type", "param", "guard", "body", "loc"
298
+ "type", "param", "guard", "body"
275
299
  ]);
276
300
 
277
301
  it("should complain about invalid types", function() {