Create helper to get the object for a Value AST node, including proper non-AST location data

This commit is contained in:
Geoffrey Booth
2018-09-30 23:48:31 -07:00
parent 3fbf76e135
commit 251700549a
2 changed files with 69 additions and 41 deletions

View File

@@ -1666,9 +1666,9 @@
}
isSplice() {
var lastProp, ref1;
ref1 = this.properties, [lastProp] = slice1.call(ref1, -1);
return lastProp instanceof Slice;
var lastProperty, ref1;
ref1 = this.properties, [lastProperty] = slice1.call(ref1, -1);
return lastProperty instanceof Slice;
}
looksStatic(className) {
@@ -1795,14 +1795,38 @@
}
}
// For AST generation, we need an `object` thats this `Value` minus its last
// property, if it has properties.
object() {
var initialProperties, object;
if (!this.hasProperties()) {
return this;
}
// Get all properties except the last one; for a `Value` with only one
// property, `initialProperties` is an empty array.
initialProperties = this.properties.slice(0, this.properties.length - 1);
// Create the `object` that becomes the new “base” for the split-off final
// property.
object = new Value(this.base, initialProperties, this.tag, this.isDefaultValue);
// Add location data to our new node, so that it has correct location data
// for source maps or later conversion into AST location data.
// This new `Value` has only one property, so the location data is just
// that of the parent `Value`s base.
// This new `Value` has multiple properties, so the location data spans
// from the parent `Value`s base to the last property thats included
// in this new node (a.k.a. the second-to-last property of the parent).
object.locationData = initialProperties.length === 0 ? this.base.locationData : mergeLocationData(this.base.locationData, initialProperties[initialProperties.length - 1].locationData);
return object;
}
ast() {
if (!this.hasProperties()) {
// If the `Value` has no properties, the AST node is just whatever this
// nodes `base` is.
return this.base.ast();
}
// Otherwise, call `Base::ast` which in turn calls the `astType`,
// `astProperties` and `astLocationData` methods below.
// Otherwise, call `Base::ast` which in turn calls the `astType` and
// `astProperties` methods below.
return super.ast();
}
@@ -1814,10 +1838,10 @@
// becomes the `property`, and the preceding properties (e.g. `a.b`) become
// a child `Value` node assigned to the `object` property.
astProperties() {
var initialProperties, property, ref1, ref2;
ref1 = this.properties, [...initialProperties] = ref1, [property] = splice.call(initialProperties, -1);
var property, ref1, ref2;
ref1 = this.properties, [property] = slice1.call(ref1, -1);
return {
object: new Value(this.base, initialProperties, this.tag, this.isDefaultValue).ast(),
object: this.object().ast(),
property: property.ast(),
computed: property instanceof Index || !(((ref2 = property.name) != null ? ref2.unwrap() : void 0) instanceof PropertyName),
optional: !!property.soak,
@@ -1825,17 +1849,6 @@
};
}
// When the `Value` has properties, the location data of a
// `MemberExpression` AST node corresponding to a given property should
// span the location of the `Value`s `base` (including parentheses if
// present) through the propertys location.
astLocationData() {
if (this.locationData != null) {
return super.astLocationData();
}
return mergeAstLocationData(this.base.astLocationData(), this.properties[this.properties.length - 1].astLocationData());
}
};
Value.prototype.children = ['base', 'properties'];
@@ -5199,9 +5212,9 @@
//### In
exports.In = In = (function() {
class In extends Base {
constructor(object, array) {
constructor(object1, array) {
super();
this.object = object;
this.object = object1;
this.array = array;
}

View File

@@ -1097,8 +1097,8 @@ exports.Value = class Value extends Base
@base.hasElision()
isSplice: ->
[..., lastProp] = @properties
lastProp instanceof Slice
[..., lastProperty] = @properties
lastProperty instanceof Slice
looksStatic: (className) ->
(@this or @base instanceof ThisLiteral or @base.value is className) and
@@ -1186,12 +1186,36 @@ exports.Value = class Value extends Base
else
@error 'tried to assign to unassignable value'
# For AST generation, we need an `object` thats this `Value` minus its last
# property, if it has properties.
object: ->
return @ unless @hasProperties()
# Get all properties except the last one; for a `Value` with only one
# property, `initialProperties` is an empty array.
initialProperties = @properties[0...@properties.length - 1]
# Create the `object` that becomes the new “base” for the split-off final
# property.
object = new Value @base, initialProperties, @tag, @isDefaultValue
# Add location data to our new node, so that it has correct location data
# for source maps or later conversion into AST location data.
object.locationData =
if initialProperties.length is 0
# This new `Value` has only one property, so the location data is just
# that of the parent `Value`s base.
@base.locationData
else
# This new `Value` has multiple properties, so the location data spans
# from the parent `Value`s base to the last property thats included
# in this new node (a.k.a. the second-to-last property of the parent).
mergeLocationData @base.locationData, initialProperties[initialProperties.length - 1].locationData
object
ast: ->
# If the `Value` has no properties, the AST node is just whatever this
# nodes `base` is.
return @base.ast() unless @hasProperties()
# Otherwise, call `Base::ast` which in turn calls the `astType`,
# `astProperties` and `astLocationData` methods below.
# Otherwise, call `Base::ast` which in turn calls the `astType` and
# `astProperties` methods below.
super()
astType: -> 'MemberExpression'
@@ -1200,22 +1224,13 @@ exports.Value = class Value extends Base
# becomes the `property`, and the preceding properties (e.g. `a.b`) become
# a child `Value` node assigned to the `object` property.
astProperties: ->
[initialProperties..., property] = @properties
object: new Value(@base, initialProperties, @tag, @isDefaultValue).ast()
property: property.ast()
computed: property instanceof Index or property.name?.unwrap() not instanceof PropertyName
optional: !!property.soak
shorthand: !!property.shorthand
# When the `Value` has properties, the location data of a
# `MemberExpression` AST node corresponding to a given property should
# span the location of the `Value`s `base` (including parentheses if
# present) through the propertys location.
astLocationData: ->
return super() if @locationData?
mergeAstLocationData @base.astLocationData(),
@properties[@properties.length - 1].astLocationData()
[..., property] = @properties
return
object: @object().ast()
property: property.ast()
computed: property instanceof Index or property.name?.unwrap() not instanceof PropertyName
optional: !!property.soak
shorthand: !!property.shorthand
#### HereComment