If AST (#5160)
* updated grammar * updated grammar * tests * location data tests * fix from code review
This commit is contained in:
parent
74e0798f89
commit
806a442894
|
@ -1991,7 +1991,7 @@
|
|||
LOC(1)(Block.wrap([$1])),
|
||||
{
|
||||
type: $2,
|
||||
statement: true
|
||||
postfix: true
|
||||
});
|
||||
}),
|
||||
o('Expression POST_IF Expression',
|
||||
|
@ -2000,7 +2000,7 @@
|
|||
LOC(1)(Block.wrap([$1])),
|
||||
{
|
||||
type: $2,
|
||||
statement: true
|
||||
postfix: true
|
||||
});
|
||||
})
|
||||
],
|
||||
|
@ -2035,7 +2035,7 @@
|
|||
LOC(1)(Block.wrap([$1])),
|
||||
{
|
||||
type: $2,
|
||||
statement: true
|
||||
postfix: true
|
||||
});
|
||||
}),
|
||||
o('Expression POST_IF ExpressionLine',
|
||||
|
@ -2044,7 +2044,7 @@
|
|||
LOC(1)(Block.wrap([$1])),
|
||||
{
|
||||
type: $2,
|
||||
statement: true
|
||||
postfix: true
|
||||
});
|
||||
})
|
||||
],
|
||||
|
|
|
@ -363,7 +363,11 @@
|
|||
// as JSON. This is what the `ast` option in the Node API returns.
|
||||
// We try to follow the [Babel AST spec](https://github.com/babel/babel/blob/master/packages/babel-parser/ast/spec.md)
|
||||
// as closely as possible, for improved interoperability with other tools.
|
||||
ast(o) {
|
||||
ast(o, level) {
|
||||
o = Object.assign({}, o);
|
||||
if (level != null) {
|
||||
o.level = level;
|
||||
}
|
||||
// Every abstract syntax tree node object has four categories of properties:
|
||||
// - type, stored in the `type` field and a string like `NumberLiteral`.
|
||||
// - location data, stored in the `loc`, `start`, `end` and `range` fields.
|
||||
|
@ -373,7 +377,7 @@
|
|||
// `parsedValue` are all top level fields in the AST node object. We have
|
||||
// separate methods for returning each category, that we merge together here.
|
||||
return Object.assign({}, {
|
||||
type: this.astType()
|
||||
type: this.astType(o)
|
||||
}, this.astProperties(o), this.astLocationData());
|
||||
}
|
||||
|
||||
|
@ -699,6 +703,7 @@
|
|||
}
|
||||
|
||||
ast(o) {
|
||||
o.level = LEVEL_TOP;
|
||||
this.initializeScope(o);
|
||||
return super.ast(o);
|
||||
}
|
||||
|
@ -1457,8 +1462,8 @@
|
|||
return [this.makeCode('['), ...this.value.compileToFragments(o, LEVEL_LIST), this.makeCode(']')];
|
||||
}
|
||||
|
||||
ast(o) {
|
||||
return this.value.ast(o);
|
||||
ast(o, level) {
|
||||
return this.value.ast(o, level);
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -1636,7 +1641,7 @@
|
|||
astProperties(o) {
|
||||
var ref1, ref2;
|
||||
return {
|
||||
argument: (ref1 = (ref2 = this.expression) != null ? ref2.ast(o) : void 0) != null ? ref1 : null
|
||||
argument: (ref1 = (ref2 = this.expression) != null ? ref2.ast(o, LEVEL_PAREN) : void 0) != null ? ref1 : null
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1673,11 +1678,11 @@
|
|||
}
|
||||
}
|
||||
|
||||
ast(o) {
|
||||
ast(o, level) {
|
||||
this.checkScope(o);
|
||||
return new Op(this.keyword, new Return(this.expression).withLocationDataFrom(this.expression != null ? {
|
||||
locationData: mergeLocationData(this.returnKeyword.locationData, this.expression.locationData)
|
||||
} : this.returnKeyword)).withLocationDataFrom(this).ast(o);
|
||||
} : this.returnKeyword)).withLocationDataFrom(this).ast(o, level);
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -1990,15 +1995,15 @@
|
|||
return object;
|
||||
}
|
||||
|
||||
ast(o) {
|
||||
ast(o, level) {
|
||||
if (!this.hasProperties()) {
|
||||
// If the `Value` has no properties, the AST node is just whatever this
|
||||
// node’s `base` is.
|
||||
return this.base.ast(o);
|
||||
return this.base.ast(o, level);
|
||||
}
|
||||
// Otherwise, call `Base::ast` which in turn calls the `astType` and
|
||||
// `astProperties` methods below.
|
||||
return super.ast(o);
|
||||
return super.ast(o, level);
|
||||
}
|
||||
|
||||
astType() {
|
||||
|
@ -2019,7 +2024,7 @@
|
|||
property.name.csx = true;
|
||||
}
|
||||
return {
|
||||
object: this.object().ast(o),
|
||||
object: this.object().ast(o, LEVEL_ACCESS),
|
||||
property: property.ast(o),
|
||||
computed: property instanceof Index || !(((ref2 = property.name) != null ? ref2.unwrap() : void 0) instanceof PropertyName),
|
||||
optional: !!property.soak,
|
||||
|
@ -2260,13 +2265,13 @@
|
|||
return fragments;
|
||||
}
|
||||
|
||||
ast() {
|
||||
ast(o) {
|
||||
var attribute, j, len1, ref1, results;
|
||||
ref1 = this.attributes;
|
||||
results = [];
|
||||
for (j = 0, len1 = ref1.length; j < len1; j++) {
|
||||
attribute = ref1[j];
|
||||
results.push(attribute.ast());
|
||||
results.push(attribute.ast(o));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
@ -2315,7 +2320,7 @@
|
|||
return !this.tagName.base.value.length;
|
||||
}
|
||||
|
||||
ast(o) {
|
||||
ast(o, level) {
|
||||
var tagName;
|
||||
// The location data spanning the opening element < ... > is captured by
|
||||
// the generated Arr which contains the element's attributes
|
||||
|
@ -2325,7 +2330,7 @@
|
|||
if (this.content != null) {
|
||||
this.closingElementLocationData = mergeAstLocationData(jisonLocationDataToAstLocationData(tagName.closingTagOpeningBracketLocationData), jisonLocationDataToAstLocationData(tagName.closingTagClosingBracketLocationData));
|
||||
}
|
||||
return super.ast(o);
|
||||
return super.ast(o, level);
|
||||
}
|
||||
|
||||
astType() {
|
||||
|
@ -2601,14 +2606,14 @@
|
|||
astProperties(o) {
|
||||
var arg;
|
||||
return {
|
||||
callee: this.variable.ast(o),
|
||||
callee: this.variable.ast(o, LEVEL_ACCESS),
|
||||
arguments: (function() {
|
||||
var j, len1, ref1, results;
|
||||
ref1 = this.args;
|
||||
results = [];
|
||||
for (j = 0, len1 = ref1.length; j < len1; j++) {
|
||||
arg = ref1[j];
|
||||
results.push(arg.ast(o));
|
||||
results.push(arg.ast(o, LEVEL_LIST));
|
||||
}
|
||||
return results;
|
||||
}).call(this),
|
||||
|
@ -2795,11 +2800,11 @@
|
|||
}
|
||||
}
|
||||
|
||||
ast(o) {
|
||||
ast(o, level) {
|
||||
// Babel doesn’t have an AST node for `Access`, but rather just includes
|
||||
// this Access node’s child `name` Identifier node as the `property` of
|
||||
// the `MemberExpression` node.
|
||||
return this.name.ast(o);
|
||||
return this.name.ast(o, level);
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -2830,13 +2835,13 @@
|
|||
return this.index.shouldCache();
|
||||
}
|
||||
|
||||
ast(o) {
|
||||
ast(o, level) {
|
||||
// Babel doesn’t have an AST node for `Index`, but rather just includes
|
||||
// this Index node’s child `index` Identifier node as the `property` of
|
||||
// the `MemberExpression` node. The fact that the `MemberExpression`’s
|
||||
// `property` is an Index means that `computed` is `true` for the
|
||||
// `MemberExpression`.
|
||||
return this.index.ast(o);
|
||||
return this.index.ast(o, level);
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -3019,8 +3024,8 @@
|
|||
return [this.makeCode(`.slice(${fragmentsToText(fromCompiled)}${toStr || ''})`)];
|
||||
}
|
||||
|
||||
ast(o) {
|
||||
return this.range.ast(o);
|
||||
ast(o, level) {
|
||||
return this.range.ast(o, level);
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -3568,7 +3573,7 @@
|
|||
results = [];
|
||||
for (j = 0, len1 = ref1.length; j < len1; j++) {
|
||||
object = ref1[j];
|
||||
results.push(object.ast(o));
|
||||
results.push(object.ast(o, LEVEL_LIST));
|
||||
}
|
||||
return results;
|
||||
}).call(this)
|
||||
|
@ -4863,8 +4868,8 @@
|
|||
astProperties(o) {
|
||||
var ref1, ret;
|
||||
ret = {
|
||||
right: this.value.ast(o),
|
||||
left: this.variable.ast(o)
|
||||
right: this.value.ast(o, LEVEL_LIST),
|
||||
left: this.variable.ast(o, LEVEL_LIST)
|
||||
};
|
||||
if (!this.isDefaultAssignment()) {
|
||||
ret.operator = (ref1 = this.originalContext) != null ? ref1 : '=';
|
||||
|
@ -5341,9 +5346,9 @@
|
|||
return results;
|
||||
}
|
||||
|
||||
ast(o) {
|
||||
ast(o, level) {
|
||||
this.updateOptions(o);
|
||||
return super.ast(o);
|
||||
return super.ast(o, level);
|
||||
}
|
||||
|
||||
astType() {
|
||||
|
@ -5389,7 +5394,7 @@
|
|||
}
|
||||
return results;
|
||||
}).call(this),
|
||||
body: this.body.ast(o),
|
||||
body: this.body.ast(o, LEVEL_TOP),
|
||||
generator: !!this.isGenerator,
|
||||
async: !!this.isAsync,
|
||||
// We never generate named functions, so specify `id` as `null`, which
|
||||
|
@ -5617,7 +5622,7 @@
|
|||
|
||||
astProperties(o) {
|
||||
return {
|
||||
argument: this.name.ast(o),
|
||||
argument: this.name.ast(o, LEVEL_OP),
|
||||
postfix: this.postfix
|
||||
};
|
||||
}
|
||||
|
@ -6078,11 +6083,11 @@
|
|||
return super.toString(idt, this.constructor.name + ' ' + this.operator);
|
||||
}
|
||||
|
||||
ast(o) {
|
||||
ast(o, level) {
|
||||
if (this.isYield() || this.isAwait()) {
|
||||
this.checkContinuation(o);
|
||||
}
|
||||
return super.ast(o);
|
||||
return super.ast(o, level);
|
||||
}
|
||||
|
||||
astType() {
|
||||
|
@ -6111,8 +6116,8 @@
|
|||
|
||||
astProperties(o) {
|
||||
var argument, firstAst, ref1, secondAst;
|
||||
firstAst = this.first.ast(o);
|
||||
secondAst = (ref1 = this.second) != null ? ref1.ast(o) : void 0;
|
||||
firstAst = this.first.ast(o, LEVEL_OP);
|
||||
secondAst = (ref1 = this.second) != null ? ref1.ast(o, LEVEL_OP) : void 0;
|
||||
switch (false) {
|
||||
case !this.isUnary():
|
||||
argument = this.isYield() && this.first.unwrap().value === '' ? null : firstAst;
|
||||
|
@ -6290,10 +6295,10 @@
|
|||
astProperties(o) {
|
||||
var ref1, ref2;
|
||||
return {
|
||||
block: this.attempt.ast(o),
|
||||
block: this.attempt.ast(o, LEVEL_TOP),
|
||||
handler: (ref1 = (ref2 = this.catch) != null ? ref2.ast(o) : void 0) != null ? ref1 : null,
|
||||
// Include `finally` keyword in location data.
|
||||
finalizer: this.ensure != null ? Object.assign(this.ensure.ast(o), mergeAstLocationData(jisonLocationDataToAstLocationData(this.finallyTag.locationData), this.ensure.astLocationData())) : null
|
||||
finalizer: this.ensure != null ? Object.assign(this.ensure.ast(o, LEVEL_TOP), mergeAstLocationData(jisonLocationDataToAstLocationData(this.finallyTag.locationData), this.ensure.astLocationData())) : null
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -6355,7 +6360,7 @@
|
|||
var ref1, ref2;
|
||||
return {
|
||||
param: (ref1 = (ref2 = this.errorVariable) != null ? ref2.ast(o) : void 0) != null ? ref1 : null,
|
||||
body: this.recovery.ast(o)
|
||||
body: this.recovery.ast(o, LEVEL_TOP)
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -6394,7 +6399,7 @@
|
|||
|
||||
astProperties(o) {
|
||||
return {
|
||||
argument: this.expression.ast(o)
|
||||
argument: this.expression.ast(o, LEVEL_LIST)
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -6535,7 +6540,7 @@
|
|||
}
|
||||
|
||||
ast(o) {
|
||||
return this.body.unwrap().ast(o);
|
||||
return this.body.unwrap().ast(o, LEVEL_PAREN);
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -7083,7 +7088,7 @@
|
|||
astProperties(o) {
|
||||
var ref1, ref2;
|
||||
return {
|
||||
discriminant: (ref1 = (ref2 = this.subject) != null ? ref2.ast(o) : void 0) != null ? ref1 : null,
|
||||
discriminant: (ref1 = (ref2 = this.subject) != null ? ref2.ast(o, LEVEL_PAREN) : void 0) != null ? ref1 : null,
|
||||
cases: this.casesAst(o)
|
||||
};
|
||||
}
|
||||
|
@ -7110,8 +7115,8 @@
|
|||
astProperties(o) {
|
||||
var ref1, ref2, ref3, ref4;
|
||||
return {
|
||||
test: (ref1 = (ref2 = this.test) != null ? ref2.ast(o) : void 0) != null ? ref1 : null,
|
||||
consequent: (ref3 = (ref4 = this.block) != null ? ref4.ast(o).body : void 0) != null ? ref3 : [],
|
||||
test: (ref1 = (ref2 = this.test) != null ? ref2.ast(o, LEVEL_PAREN) : void 0) != null ? ref1 : null,
|
||||
consequent: (ref3 = (ref4 = this.block) != null ? ref4.ast(o, LEVEL_TOP).body : void 0) != null ? ref3 : [],
|
||||
trailing: !!this.trailing
|
||||
};
|
||||
}
|
||||
|
@ -7149,13 +7154,13 @@
|
|||
// because ternaries are already proper expressions, and don’t need conversion.
|
||||
exports.If = If = (function() {
|
||||
class If extends Base {
|
||||
constructor(condition, body1, options = {}) {
|
||||
constructor(condition1, body1, options = {}) {
|
||||
super();
|
||||
this.condition = condition1;
|
||||
this.body = body1;
|
||||
this.condition = options.type === 'unless' ? condition.invert() : condition;
|
||||
this.elseBody = null;
|
||||
this.isChain = false;
|
||||
({soak: this.soak} = options);
|
||||
({soak: this.soak, postfix: this.postfix, type: this.type} = options);
|
||||
if (this.condition.comments) {
|
||||
moveComments(this.condition, this);
|
||||
}
|
||||
|
@ -7175,10 +7180,14 @@
|
|||
addElse(elseBody) {
|
||||
if (this.isChain) {
|
||||
this.elseBodyNode().addElse(elseBody);
|
||||
this.locationData = mergeLocationData(this.locationData, this.elseBodyNode().locationData);
|
||||
} else {
|
||||
this.isChain = elseBody instanceof If;
|
||||
this.elseBody = this.ensureBlock(elseBody);
|
||||
this.elseBody.updateLocationDataIfMissing(elseBody.locationData);
|
||||
if ((this.locationData != null) && (this.elseBody.locationData != null)) {
|
||||
this.locationData = mergeLocationData(this.locationData, this.elseBody.locationData);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
@ -7227,12 +7236,12 @@
|
|||
child = del(o, 'chainChild');
|
||||
exeq = del(o, 'isExistentialEquals');
|
||||
if (exeq) {
|
||||
return new If(this.condition.invert(), this.elseBodyNode(), {
|
||||
return new If(this.processedCondition().invert(), this.elseBodyNode(), {
|
||||
type: 'if'
|
||||
}).compileToFragments(o);
|
||||
}
|
||||
indent = o.indent + TAB;
|
||||
cond = this.condition.compileToFragments(o, LEVEL_PAREN);
|
||||
cond = this.processedCondition().compileToFragments(o, LEVEL_PAREN);
|
||||
body = this.ensureBlock(this.body).compileToFragments(merge(o, {indent}));
|
||||
ifPart = [].concat(this.makeCode("if ("), cond, this.makeCode(") {\n"), body, this.makeCode(`\n${this.tab}}`));
|
||||
if (!child) {
|
||||
|
@ -7254,7 +7263,7 @@
|
|||
// Compile the `If` as a conditional operator.
|
||||
compileExpression(o) {
|
||||
var alt, body, cond, fragments;
|
||||
cond = this.condition.compileToFragments(o, LEVEL_COND);
|
||||
cond = this.processedCondition().compileToFragments(o, LEVEL_COND);
|
||||
body = this.bodyNode().compileToFragments(o, LEVEL_LIST);
|
||||
alt = this.elseBodyNode() ? this.elseBodyNode().compileToFragments(o, LEVEL_LIST) : [this.makeCode('void 0')];
|
||||
fragments = cond.concat(this.makeCode(" ? "), body, this.makeCode(" : "), alt);
|
||||
|
@ -7269,6 +7278,34 @@
|
|||
return this.soak && this;
|
||||
}
|
||||
|
||||
processedCondition() {
|
||||
return this.processedConditionCache != null ? this.processedConditionCache : this.processedConditionCache = this.type === 'unless' ? this.condition.invert() : this.condition;
|
||||
}
|
||||
|
||||
isStatementAst(o) {
|
||||
return o.level === LEVEL_TOP;
|
||||
}
|
||||
|
||||
astType(o) {
|
||||
if (this.isStatementAst(o)) {
|
||||
return 'IfStatement';
|
||||
} else {
|
||||
return 'ConditionalExpression';
|
||||
}
|
||||
}
|
||||
|
||||
astProperties(o) {
|
||||
var isStatement, ref1, ref2;
|
||||
isStatement = this.isStatementAst(o);
|
||||
return {
|
||||
test: this.condition.ast(o, isStatement ? LEVEL_PAREN : LEVEL_COND),
|
||||
consequent: isStatement ? this.body.ast(o, LEVEL_TOP) : this.bodyNode().ast(o, LEVEL_TOP),
|
||||
alternate: this.isChain ? this.elseBody.unwrap().ast(o, isStatement ? LEVEL_TOP : LEVEL_COND) : (ref1 = (ref2 = this.elseBody) != null ? ref2.ast(o, LEVEL_TOP) : void 0) != null ? ref1 : null,
|
||||
postfix: !!this.postfix,
|
||||
inverted: this.type === 'unless'
|
||||
};
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
If.prototype.children = ['condition', 'body', 'elseBody'];
|
||||
|
|
|
@ -984,7 +984,7 @@ this.$ = yy.addDataToNode(yy, _$[$0-2], $$[$0-2], _$[$0], $$[$0], true)(new yy.I
|
|||
yy.addDataToNode(yy, _$[$0-2], $$[$0-2], null, null, true)(yy.Block.wrap([$$[$0-2]])),
|
||||
{
|
||||
type: $$[$0-1],
|
||||
statement: true
|
||||
postfix: true
|
||||
}));
|
||||
break;
|
||||
case 360:
|
||||
|
|
|
@ -817,8 +817,8 @@ grammar =
|
|||
If: [
|
||||
o 'IfBlock'
|
||||
o 'IfBlock ELSE Block', -> $1.addElse $3
|
||||
o 'Statement POST_IF Expression', -> new If $3, LOC(1)(Block.wrap [$1]), type: $2, statement: true
|
||||
o 'Expression POST_IF Expression', -> new If $3, LOC(1)(Block.wrap [$1]), type: $2, statement: true
|
||||
o 'Statement POST_IF Expression', -> new If $3, LOC(1)(Block.wrap [$1]), type: $2, postfix: true
|
||||
o 'Expression POST_IF Expression', -> new If $3, LOC(1)(Block.wrap [$1]), type: $2, postfix: true
|
||||
]
|
||||
|
||||
IfBlockLine: [
|
||||
|
@ -829,8 +829,8 @@ grammar =
|
|||
IfLine: [
|
||||
o 'IfBlockLine'
|
||||
o 'IfBlockLine ELSE Block', -> $1.addElse $3
|
||||
o 'Statement POST_IF ExpressionLine', -> new If $3, LOC(1)(Block.wrap [$1]), type: $2, statement: true
|
||||
o 'Expression POST_IF ExpressionLine', -> new If $3, LOC(1)(Block.wrap [$1]), type: $2, statement: true
|
||||
o 'Statement POST_IF ExpressionLine', -> new If $3, LOC(1)(Block.wrap [$1]), type: $2, postfix: true
|
||||
o 'Expression POST_IF ExpressionLine', -> new If $3, LOC(1)(Block.wrap [$1]), type: $2, postfix: true
|
||||
]
|
||||
|
||||
# Arithmetic and logical operators, working on one or more operands.
|
||||
|
|
130
src/nodes.coffee
130
src/nodes.coffee
|
@ -270,7 +270,9 @@ exports.Base = class Base
|
|||
# as JSON. This is what the `ast` option in the Node API returns.
|
||||
# We try to follow the [Babel AST spec](https://github.com/babel/babel/blob/master/packages/babel-parser/ast/spec.md)
|
||||
# as closely as possible, for improved interoperability with other tools.
|
||||
ast: (o) ->
|
||||
ast: (o, level) ->
|
||||
o = Object.assign {}, o
|
||||
o.level = level if level?
|
||||
# Every abstract syntax tree node object has four categories of properties:
|
||||
# - type, stored in the `type` field and a string like `NumberLiteral`.
|
||||
# - location data, stored in the `loc`, `start`, `end` and `range` fields.
|
||||
|
@ -279,7 +281,7 @@ exports.Base = class Base
|
|||
# These fields are all intermixed in the Babel spec; `type` and `start` and
|
||||
# `parsedValue` are all top level fields in the AST node object. We have
|
||||
# separate methods for returning each category, that we merge together here.
|
||||
Object.assign {}, {type: @astType()}, @astProperties(o), @astLocationData()
|
||||
Object.assign {}, {type: @astType(o)}, @astProperties(o), @astLocationData()
|
||||
|
||||
# By default, a node class has no specific properties.
|
||||
astProperties: -> {}
|
||||
|
@ -498,6 +500,7 @@ exports.Root = class Root extends Base
|
|||
o.scope.parameter name for name in o.locals or []
|
||||
|
||||
ast: (o) ->
|
||||
o.level = LEVEL_TOP
|
||||
@initializeScope o
|
||||
super o
|
||||
|
||||
|
@ -1011,8 +1014,8 @@ exports.ComputedPropertyName = class ComputedPropertyName extends PropertyName
|
|||
compileNode: (o) ->
|
||||
[@makeCode('['), @value.compileToFragments(o, LEVEL_LIST)..., @makeCode(']')]
|
||||
|
||||
ast: (o) ->
|
||||
@value.ast o
|
||||
ast: (o, level) ->
|
||||
@value.ast o, level
|
||||
|
||||
exports.StatementLiteral = class StatementLiteral extends Literal
|
||||
isStatement: YES
|
||||
|
@ -1121,7 +1124,7 @@ exports.Return = class Return extends Base
|
|||
astType: -> 'ReturnStatement'
|
||||
|
||||
astProperties: (o) ->
|
||||
argument: @expression?.ast(o) ? null
|
||||
argument: @expression?.ast(o, LEVEL_PAREN) ? null
|
||||
|
||||
# Parent class for `YieldReturn`/`AwaitReturn`.
|
||||
exports.FuncDirectiveReturn = class FuncDirectiveReturn extends Return
|
||||
|
@ -1138,7 +1141,7 @@ exports.FuncDirectiveReturn = class FuncDirectiveReturn extends Return
|
|||
|
||||
isStatementAst: NO
|
||||
|
||||
ast: (o) ->
|
||||
ast: (o, level) ->
|
||||
@checkScope o
|
||||
|
||||
new Op @keyword,
|
||||
|
@ -1150,7 +1153,7 @@ exports.FuncDirectiveReturn = class FuncDirectiveReturn extends Return
|
|||
@returnKeyword
|
||||
)
|
||||
.withLocationDataFrom @
|
||||
.ast o
|
||||
.ast o, level
|
||||
|
||||
# `yield return` works exactly like `return`, except that it turns the function
|
||||
# into a generator.
|
||||
|
@ -1339,13 +1342,13 @@ exports.Value = class Value extends Base
|
|||
mergeLocationData @base.locationData, initialProperties[initialProperties.length - 1].locationData
|
||||
object
|
||||
|
||||
ast: (o) ->
|
||||
ast: (o, level) ->
|
||||
# If the `Value` has no properties, the AST node is just whatever this
|
||||
# node’s `base` is.
|
||||
return @base.ast o unless @hasProperties()
|
||||
return @base.ast o, level unless @hasProperties()
|
||||
# Otherwise, call `Base::ast` which in turn calls the `astType` and
|
||||
# `astProperties` methods below.
|
||||
super o
|
||||
super o, level
|
||||
|
||||
astType: ->
|
||||
if @isCSXTag()
|
||||
|
@ -1360,7 +1363,7 @@ exports.Value = class Value extends Base
|
|||
[..., property] = @properties
|
||||
property.name.csx = yes if @isCSXTag()
|
||||
return
|
||||
object: @object().ast o
|
||||
object: @object().ast o, LEVEL_ACCESS
|
||||
property: property.ast o
|
||||
computed: property instanceof Index or property.name?.unwrap() not instanceof PropertyName
|
||||
optional: !!property.soak
|
||||
|
@ -1519,8 +1522,8 @@ exports.CSXAttributes = class CSXAttributes extends Base
|
|||
fragments.push attribute.compileToFragments(o, LEVEL_TOP)...
|
||||
fragments
|
||||
|
||||
ast: ->
|
||||
attribute.ast() for attribute in @attributes
|
||||
ast: (o) ->
|
||||
attribute.ast(o) for attribute in @attributes
|
||||
|
||||
# Node for a CSX element
|
||||
exports.CSXElement = class CSXElement extends Base
|
||||
|
@ -1545,7 +1548,7 @@ exports.CSXElement = class CSXElement extends Base
|
|||
isFragment: ->
|
||||
!@tagName.base.value.length
|
||||
|
||||
ast: (o) ->
|
||||
ast: (o, level) ->
|
||||
# The location data spanning the opening element < ... > is captured by
|
||||
# the generated Arr which contains the element's attributes
|
||||
@openingElementLocationData = jisonLocationDataToAstLocationData @attributes.locationData
|
||||
|
@ -1558,7 +1561,7 @@ exports.CSXElement = class CSXElement extends Base
|
|||
jisonLocationDataToAstLocationData tagName.closingTagClosingBracketLocationData
|
||||
)
|
||||
|
||||
super o
|
||||
super o, level
|
||||
|
||||
astType: ->
|
||||
if @isFragment()
|
||||
|
@ -1769,8 +1772,8 @@ exports.Call = class Call extends Base
|
|||
|
||||
astProperties: (o) ->
|
||||
return
|
||||
callee: @variable.ast o
|
||||
arguments: arg.ast(o) for arg in @args
|
||||
callee: @variable.ast o, LEVEL_ACCESS
|
||||
arguments: arg.ast(o, LEVEL_LIST) for arg in @args
|
||||
optional: !!@soak
|
||||
implicit: !!@implicit
|
||||
|
||||
|
@ -1890,11 +1893,11 @@ exports.Access = class Access extends Base
|
|||
|
||||
shouldCache: NO
|
||||
|
||||
ast: (o) ->
|
||||
ast: (o, level) ->
|
||||
# Babel doesn’t have an AST node for `Access`, but rather just includes
|
||||
# this Access node’s child `name` Identifier node as the `property` of
|
||||
# the `MemberExpression` node.
|
||||
@name.ast o
|
||||
@name.ast o, level
|
||||
|
||||
#### Index
|
||||
|
||||
|
@ -1911,13 +1914,13 @@ exports.Index = class Index extends Base
|
|||
shouldCache: ->
|
||||
@index.shouldCache()
|
||||
|
||||
ast: (o) ->
|
||||
ast: (o, level) ->
|
||||
# Babel doesn’t have an AST node for `Index`, but rather just includes
|
||||
# this Index node’s child `index` Identifier node as the `property` of
|
||||
# the `MemberExpression` node. The fact that the `MemberExpression`’s
|
||||
# `property` is an Index means that `computed` is `true` for the
|
||||
# `MemberExpression`.
|
||||
@index.ast o
|
||||
@index.ast o, level
|
||||
|
||||
#### Range
|
||||
|
||||
|
@ -2074,8 +2077,8 @@ exports.Slice = class Slice extends Base
|
|||
"+#{fragmentsToText compiled} + 1 || 9e9"
|
||||
[@makeCode ".slice(#{ fragmentsToText fromCompiled }#{ toStr or '' })"]
|
||||
|
||||
ast: (o) ->
|
||||
@range.ast(o)
|
||||
ast: (o, level) ->
|
||||
@range.ast(o, level)
|
||||
|
||||
#### Obj
|
||||
|
||||
|
@ -2388,7 +2391,7 @@ exports.Arr = class Arr extends Base
|
|||
astProperties: (o) ->
|
||||
return
|
||||
elements:
|
||||
object.ast(o) for object in @objects
|
||||
object.ast(o, LEVEL_LIST) for object in @objects
|
||||
|
||||
#### Class
|
||||
|
||||
|
@ -3263,8 +3266,8 @@ exports.Assign = class Assign extends Base
|
|||
|
||||
astProperties: (o) ->
|
||||
ret =
|
||||
right: @value.ast o
|
||||
left: @variable.ast o
|
||||
right: @value.ast o, LEVEL_LIST
|
||||
left: @variable.ast o, LEVEL_LIST
|
||||
|
||||
unless @isDefaultAssignment()
|
||||
ret.operator = @originalContext ? '='
|
||||
|
@ -3599,9 +3602,9 @@ exports.Code = class Code extends Base
|
|||
for {name} in @params when name instanceof Arr or name instanceof Obj
|
||||
name.propagateLhs yes
|
||||
|
||||
ast: (o) ->
|
||||
ast: (o, level) ->
|
||||
@updateOptions o
|
||||
super o
|
||||
super o, level
|
||||
|
||||
astType: ->
|
||||
if @bound
|
||||
|
@ -3624,7 +3627,7 @@ exports.Code = class Code extends Base
|
|||
astProperties: (o) ->
|
||||
return
|
||||
params: @paramForAst(param).ast(o) for param in @params
|
||||
body: @body.ast o
|
||||
body: @body.ast o, LEVEL_TOP
|
||||
generator: !!@isGenerator
|
||||
async: !!@isAsync
|
||||
# We never generate named functions, so specify `id` as `null`, which
|
||||
|
@ -3772,7 +3775,7 @@ exports.Splat = class Splat extends Base
|
|||
'SpreadElement'
|
||||
|
||||
astProperties: (o) -> {
|
||||
argument: @name.ast o
|
||||
argument: @name.ast o, LEVEL_OP
|
||||
@postfix
|
||||
}
|
||||
|
||||
|
@ -4097,9 +4100,9 @@ exports.Op = class Op extends Base
|
|||
toString: (idt) ->
|
||||
super idt, @constructor.name + ' ' + @operator
|
||||
|
||||
ast: (o) ->
|
||||
ast: (o, level) ->
|
||||
@checkContinuation o if @isYield() or @isAwait()
|
||||
super o
|
||||
super o, level
|
||||
|
||||
astType: ->
|
||||
return 'AwaitExpression' if @isAwait()
|
||||
|
@ -4112,8 +4115,8 @@ exports.Op = class Op extends Base
|
|||
else 'BinaryExpression'
|
||||
|
||||
astProperties: (o) ->
|
||||
firstAst = @first.ast o
|
||||
secondAst = @second?.ast o
|
||||
firstAst = @first.ast o, LEVEL_OP
|
||||
secondAst = @second?.ast o, LEVEL_OP
|
||||
switch
|
||||
when @isUnary()
|
||||
argument =
|
||||
|
@ -4219,11 +4222,11 @@ exports.Try = class Try extends Base
|
|||
|
||||
astProperties: (o) ->
|
||||
return
|
||||
block: @attempt.ast o
|
||||
block: @attempt.ast o, LEVEL_TOP
|
||||
handler: @catch?.ast(o) ? null
|
||||
finalizer:
|
||||
if @ensure?
|
||||
Object.assign @ensure.ast(o),
|
||||
Object.assign @ensure.ast(o, LEVEL_TOP),
|
||||
# Include `finally` keyword in location data.
|
||||
mergeAstLocationData(
|
||||
jisonLocationDataToAstLocationData(@finallyTag.locationData),
|
||||
|
@ -4263,7 +4266,7 @@ exports.Catch = class Catch extends Base
|
|||
astProperties: (o) ->
|
||||
return
|
||||
param: @errorVariable?.ast(o) ? null
|
||||
body: @recovery.ast o
|
||||
body: @recovery.ast o, LEVEL_TOP
|
||||
|
||||
#### Throw
|
||||
|
||||
|
@ -4291,7 +4294,7 @@ exports.Throw = class Throw extends Base
|
|||
|
||||
astProperties: (o) ->
|
||||
return
|
||||
argument: @expression.ast o
|
||||
argument: @expression.ast o, LEVEL_LIST
|
||||
|
||||
#### Existence
|
||||
|
||||
|
@ -4380,7 +4383,7 @@ exports.Parens = class Parens extends Base
|
|||
return @wrapInBraces fragments if @csxAttribute
|
||||
if bare then fragments else @wrapInParentheses fragments
|
||||
|
||||
ast: (o) -> @body.unwrap().ast o
|
||||
ast: (o) -> @body.unwrap().ast o, LEVEL_PAREN
|
||||
|
||||
#### StringWithInterpolations
|
||||
|
||||
|
@ -4703,7 +4706,7 @@ exports.Switch = class Switch extends Base
|
|||
|
||||
astProperties: (o) ->
|
||||
return
|
||||
discriminant: @subject?.ast(o) ? null
|
||||
discriminant: @subject?.ast(o, LEVEL_PAREN) ? null
|
||||
cases: @casesAst o
|
||||
|
||||
class SwitchCase extends Base
|
||||
|
@ -4714,8 +4717,8 @@ class SwitchCase extends Base
|
|||
|
||||
astProperties: (o) ->
|
||||
return
|
||||
test: @test?.ast(o) ? null
|
||||
consequent: @block?.ast(o).body ? []
|
||||
test: @test?.ast(o, LEVEL_PAREN) ? null
|
||||
consequent: @block?.ast(o, LEVEL_TOP).body ? []
|
||||
trailing: !!@trailing
|
||||
|
||||
exports.SwitchWhen = class SwitchWhen extends Base
|
||||
|
@ -4732,12 +4735,11 @@ exports.SwitchWhen = class SwitchWhen extends Base
|
|||
# Single-expression **Ifs** are compiled into conditional operators if possible,
|
||||
# because ternaries are already proper expressions, and don’t need conversion.
|
||||
exports.If = class If extends Base
|
||||
constructor: (condition, @body, options = {}) ->
|
||||
constructor: (@condition, @body, options = {}) ->
|
||||
super()
|
||||
@condition = if options.type is 'unless' then condition.invert() else condition
|
||||
@elseBody = null
|
||||
@isChain = false
|
||||
{@soak} = options
|
||||
{@soak, @postfix, @type} = options
|
||||
moveComments @condition, @ if @condition.comments
|
||||
|
||||
children: ['condition', 'body', 'elseBody']
|
||||
|
@ -4749,10 +4751,12 @@ exports.If = class If extends Base
|
|||
addElse: (elseBody) ->
|
||||
if @isChain
|
||||
@elseBodyNode().addElse elseBody
|
||||
@locationData = mergeLocationData @locationData, @elseBodyNode().locationData
|
||||
else
|
||||
@isChain = elseBody instanceof If
|
||||
@elseBody = @ensureBlock elseBody
|
||||
@elseBody.updateLocationDataIfMissing elseBody.locationData
|
||||
@locationData = mergeLocationData @locationData, @elseBody.locationData if @locationData? and @elseBody.locationData?
|
||||
this
|
||||
|
||||
# The **If** only compiles into a statement if either of its bodies needs
|
||||
|
@ -4782,10 +4786,10 @@ exports.If = class If extends Base
|
|||
exeq = del o, 'isExistentialEquals'
|
||||
|
||||
if exeq
|
||||
return new If(@condition.invert(), @elseBodyNode(), type: 'if').compileToFragments o
|
||||
return new If(@processedCondition().invert(), @elseBodyNode(), type: 'if').compileToFragments o
|
||||
|
||||
indent = o.indent + TAB
|
||||
cond = @condition.compileToFragments o, LEVEL_PAREN
|
||||
cond = @processedCondition().compileToFragments o, LEVEL_PAREN
|
||||
body = @ensureBlock(@body).compileToFragments merge o, {indent}
|
||||
ifPart = [].concat @makeCode("if ("), cond, @makeCode(") {\n"), body, @makeCode("\n#{@tab}}")
|
||||
ifPart.unshift @makeCode @tab unless child
|
||||
|
@ -4800,7 +4804,7 @@ exports.If = class If extends Base
|
|||
|
||||
# Compile the `If` as a conditional operator.
|
||||
compileExpression: (o) ->
|
||||
cond = @condition.compileToFragments o, LEVEL_COND
|
||||
cond = @processedCondition().compileToFragments o, LEVEL_COND
|
||||
body = @bodyNode().compileToFragments o, LEVEL_LIST
|
||||
alt = if @elseBodyNode() then @elseBodyNode().compileToFragments(o, LEVEL_LIST) else [@makeCode('void 0')]
|
||||
fragments = cond.concat @makeCode(" ? "), body, @makeCode(" : "), alt
|
||||
|
@ -4809,6 +4813,36 @@ exports.If = class If extends Base
|
|||
unfoldSoak: ->
|
||||
@soak and this
|
||||
|
||||
processedCondition: ->
|
||||
@processedConditionCache ?= if @type is 'unless' then @condition.invert() else @condition
|
||||
|
||||
isStatementAst: (o) ->
|
||||
o.level is LEVEL_TOP
|
||||
|
||||
astType: (o) ->
|
||||
if @isStatementAst o
|
||||
'IfStatement'
|
||||
else
|
||||
'ConditionalExpression'
|
||||
|
||||
astProperties: (o) ->
|
||||
isStatement = @isStatementAst o
|
||||
|
||||
return
|
||||
test: @condition.ast o, if isStatement then LEVEL_PAREN else LEVEL_COND
|
||||
consequent:
|
||||
if isStatement
|
||||
@body.ast o, LEVEL_TOP
|
||||
else
|
||||
@bodyNode().ast o, LEVEL_TOP
|
||||
alternate:
|
||||
if @isChain
|
||||
@elseBody.unwrap().ast o, if isStatement then LEVEL_TOP else LEVEL_COND
|
||||
else
|
||||
@elseBody?.ast(o, LEVEL_TOP) ? null
|
||||
postfix: !!@postfix
|
||||
inverted: @type is 'unless'
|
||||
|
||||
# Constants
|
||||
# ---------
|
||||
|
||||
|
|
|
@ -2321,48 +2321,151 @@ test "AST as expected for Switch node", ->
|
|||
|
||||
# # TODO: File issue for compile error when using `then` or `;` where `\n` is rn.
|
||||
|
||||
# test "AST as expected for If node", ->
|
||||
# testExpression 'if maybe then yes',
|
||||
# type: 'If'
|
||||
# isChain: no
|
||||
# condition:
|
||||
# type: 'IdentifierLiteral'
|
||||
# body:
|
||||
# type: 'Value'
|
||||
# base:
|
||||
# type: 'BooleanLiteral'
|
||||
test "AST as expected for If node", ->
|
||||
testStatement 'if maybe then yes',
|
||||
type: 'IfStatement'
|
||||
test: ID 'maybe'
|
||||
consequent:
|
||||
type: 'BlockStatement'
|
||||
body: [
|
||||
type: 'ExpressionStatement'
|
||||
expression:
|
||||
type: 'BooleanLiteral'
|
||||
]
|
||||
alternate: null
|
||||
postfix: no
|
||||
inverted: no
|
||||
|
||||
# testExpression 'yes if maybe',
|
||||
# type: 'If'
|
||||
# isChain: no
|
||||
# condition:
|
||||
# type: 'IdentifierLiteral'
|
||||
# body:
|
||||
# type: 'Value'
|
||||
# base:
|
||||
# type: 'BooleanLiteral'
|
||||
testStatement 'yes if maybe',
|
||||
type: 'IfStatement'
|
||||
test: ID 'maybe'
|
||||
consequent:
|
||||
type: 'BlockStatement'
|
||||
body: [
|
||||
type: 'ExpressionStatement'
|
||||
expression:
|
||||
type: 'BooleanLiteral'
|
||||
]
|
||||
alternate: null
|
||||
postfix: yes
|
||||
inverted: no
|
||||
|
||||
# # TODO: Where's the post-if flag?
|
||||
testStatement 'unless x then x else if y then y else z',
|
||||
type: 'IfStatement'
|
||||
test: ID 'x'
|
||||
consequent:
|
||||
type: 'BlockStatement'
|
||||
body: [
|
||||
type: 'ExpressionStatement'
|
||||
expression: ID 'x'
|
||||
]
|
||||
alternate:
|
||||
type: 'IfStatement'
|
||||
test: ID 'y'
|
||||
consequent:
|
||||
type: 'BlockStatement'
|
||||
body: [
|
||||
type: 'ExpressionStatement'
|
||||
expression: ID 'y'
|
||||
]
|
||||
alternate:
|
||||
type: 'BlockStatement'
|
||||
body: [
|
||||
type: 'ExpressionStatement'
|
||||
expression: ID 'z'
|
||||
]
|
||||
postfix: no
|
||||
inverted: no
|
||||
postfix: no
|
||||
inverted: yes
|
||||
|
||||
# testExpression 'unless x then x else if y then y else z',
|
||||
# type: 'If'
|
||||
# isChain: yes
|
||||
# condition:
|
||||
# type: 'Op'
|
||||
# operator: '!'
|
||||
# originalOperator: '!'
|
||||
# flip: no
|
||||
# body:
|
||||
# type: 'Value'
|
||||
# elseBody:
|
||||
# type: 'If'
|
||||
# isChain: no
|
||||
# condition:
|
||||
# type: 'IdentifierLiteral'
|
||||
# body:
|
||||
# type: 'Value'
|
||||
# elseBody:
|
||||
# type: 'Value'
|
||||
# isDefaultValue: no
|
||||
testStatement '''
|
||||
if a
|
||||
b
|
||||
else
|
||||
if c
|
||||
d
|
||||
''',
|
||||
type: 'IfStatement'
|
||||
test: ID 'a'
|
||||
consequent:
|
||||
type: 'BlockStatement'
|
||||
body: [
|
||||
type: 'ExpressionStatement'
|
||||
expression: ID 'b'
|
||||
]
|
||||
alternate:
|
||||
type: 'BlockStatement'
|
||||
body: [
|
||||
type: 'IfStatement'
|
||||
test: ID 'c'
|
||||
consequent:
|
||||
type: 'BlockStatement'
|
||||
body: [
|
||||
type: 'ExpressionStatement'
|
||||
expression: ID 'd'
|
||||
]
|
||||
alternate: null
|
||||
postfix: no
|
||||
inverted: no
|
||||
]
|
||||
postfix: no
|
||||
inverted: no
|
||||
|
||||
# # TODO: AST generator should preserve use of `unless`.
|
||||
testExpression '''
|
||||
a =
|
||||
if b then c else if d then e
|
||||
''',
|
||||
type: 'AssignmentExpression'
|
||||
right:
|
||||
type: 'ConditionalExpression'
|
||||
test: ID 'b'
|
||||
consequent: ID 'c'
|
||||
alternate:
|
||||
type: 'ConditionalExpression'
|
||||
test: ID 'd'
|
||||
consequent: ID 'e'
|
||||
alternate: null
|
||||
postfix: no
|
||||
inverted: no
|
||||
postfix: no
|
||||
inverted: no
|
||||
|
||||
testExpression '''
|
||||
f(
|
||||
if b
|
||||
c
|
||||
d
|
||||
)
|
||||
''',
|
||||
type: 'CallExpression'
|
||||
arguments: [
|
||||
type: 'ConditionalExpression'
|
||||
test: ID 'b'
|
||||
consequent:
|
||||
type: 'BlockStatement'
|
||||
body: [
|
||||
type: 'ExpressionStatement'
|
||||
expression:
|
||||
ID 'c'
|
||||
,
|
||||
type: 'ExpressionStatement'
|
||||
expression:
|
||||
ID 'd'
|
||||
]
|
||||
postfix: no
|
||||
inverted: no
|
||||
]
|
||||
|
||||
testStatement 'a unless b',
|
||||
type: 'IfStatement'
|
||||
test: ID 'b'
|
||||
consequent:
|
||||
type: 'BlockStatement'
|
||||
body: [
|
||||
type: 'ExpressionStatement'
|
||||
expression: ID 'a'
|
||||
]
|
||||
alternate: null
|
||||
postfix: yes
|
||||
inverted: yes
|
||||
|
|
|
@ -3889,3 +3889,570 @@ test "AST as expected for AwaitReturn node", ->
|
|||
end:
|
||||
line: 1
|
||||
column: 15
|
||||
|
||||
test "AST as expected for If node", ->
|
||||
testAstLocationData 'if maybe then yes',
|
||||
type: 'IfStatement'
|
||||
test:
|
||||
start: 3
|
||||
end: 8
|
||||
range: [3, 8]
|
||||
loc:
|
||||
start:
|
||||
line: 1
|
||||
column: 3
|
||||
end:
|
||||
line: 1
|
||||
column: 8
|
||||
consequent:
|
||||
body: [
|
||||
expression:
|
||||
start: 14
|
||||
end: 17
|
||||
range: [14, 17]
|
||||
loc:
|
||||
start:
|
||||
line: 1
|
||||
column: 14
|
||||
end:
|
||||
line: 1
|
||||
column: 17
|
||||
start: 14
|
||||
end: 17
|
||||
range: [14, 17]
|
||||
loc:
|
||||
start:
|
||||
line: 1
|
||||
column: 14
|
||||
end:
|
||||
line: 1
|
||||
column: 17
|
||||
]
|
||||
start: 8
|
||||
end: 17
|
||||
range: [8, 17]
|
||||
loc:
|
||||
start:
|
||||
line: 1
|
||||
column: 8
|
||||
end:
|
||||
line: 1
|
||||
column: 17
|
||||
start: 0
|
||||
end: 17
|
||||
range: [0, 17]
|
||||
loc:
|
||||
start:
|
||||
line: 1
|
||||
column: 0
|
||||
end:
|
||||
line: 1
|
||||
column: 17
|
||||
|
||||
testAstLocationData 'yes if maybe',
|
||||
type: 'IfStatement'
|
||||
test:
|
||||
start: 7
|
||||
end: 12
|
||||
range: [7, 12]
|
||||
loc:
|
||||
start:
|
||||
line: 1
|
||||
column: 7
|
||||
end:
|
||||
line: 1
|
||||
column: 12
|
||||
consequent:
|
||||
body: [
|
||||
expression:
|
||||
start: 0
|
||||
end: 3
|
||||
range: [0, 3]
|
||||
loc:
|
||||
start:
|
||||
line: 1
|
||||
column: 0
|
||||
end:
|
||||
line: 1
|
||||
column: 3
|
||||
start: 0
|
||||
end: 3
|
||||
range: [0, 3]
|
||||
loc:
|
||||
start:
|
||||
line: 1
|
||||
column: 0
|
||||
end:
|
||||
line: 1
|
||||
column: 3
|
||||
]
|
||||
start: 0
|
||||
end: 3
|
||||
range: [0, 3]
|
||||
loc:
|
||||
start:
|
||||
line: 1
|
||||
column: 0
|
||||
end:
|
||||
line: 1
|
||||
column: 3
|
||||
start: 0
|
||||
end: 12
|
||||
range: [0, 12]
|
||||
loc:
|
||||
start:
|
||||
line: 1
|
||||
column: 0
|
||||
end:
|
||||
line: 1
|
||||
column: 12
|
||||
|
||||
testAstLocationData 'unless x then x else if y then y else z',
|
||||
type: 'IfStatement'
|
||||
test:
|
||||
start: 7
|
||||
end: 8
|
||||
range: [7, 8]
|
||||
loc:
|
||||
start:
|
||||
line: 1
|
||||
column: 7
|
||||
end:
|
||||
line: 1
|
||||
column: 8
|
||||
consequent:
|
||||
body: [
|
||||
expression:
|
||||
start: 14
|
||||
end: 15
|
||||
range: [14, 15]
|
||||
loc:
|
||||
start:
|
||||
line: 1
|
||||
column: 14
|
||||
end:
|
||||
line: 1
|
||||
column: 15
|
||||
start: 14
|
||||
end: 15
|
||||
range: [14, 15]
|
||||
loc:
|
||||
start:
|
||||
line: 1
|
||||
column: 14
|
||||
end:
|
||||
line: 1
|
||||
column: 15
|
||||
]
|
||||
start: 8
|
||||
end: 15
|
||||
range: [8, 15]
|
||||
loc:
|
||||
start:
|
||||
line: 1
|
||||
column: 8
|
||||
end:
|
||||
line: 1
|
||||
column: 15
|
||||
alternate:
|
||||
test:
|
||||
start: 24
|
||||
end: 25
|
||||
range: [24, 25]
|
||||
loc:
|
||||
start:
|
||||
line: 1
|
||||
column: 24
|
||||
end:
|
||||
line: 1
|
||||
column: 25
|
||||
consequent:
|
||||
body: [
|
||||
expression:
|
||||
start: 31
|
||||
end: 32
|
||||
range: [31, 32]
|
||||
loc:
|
||||
start:
|
||||
line: 1
|
||||
column: 31
|
||||
end:
|
||||
line: 1
|
||||
column: 32
|
||||
start: 31
|
||||
end: 32
|
||||
range: [31, 32]
|
||||
loc:
|
||||
start:
|
||||
line: 1
|
||||
column: 31
|
||||
end:
|
||||
line: 1
|
||||
column: 32
|
||||
]
|
||||
start: 25
|
||||
end: 32
|
||||
range: [25, 32]
|
||||
loc:
|
||||
start:
|
||||
line: 1
|
||||
column: 25
|
||||
end:
|
||||
line: 1
|
||||
column: 32
|
||||
alternate:
|
||||
body: [
|
||||
expression:
|
||||
start: 38
|
||||
end: 39
|
||||
range: [38, 39]
|
||||
loc:
|
||||
start:
|
||||
line: 1
|
||||
column: 38
|
||||
end:
|
||||
line: 1
|
||||
column: 39
|
||||
start: 38
|
||||
end: 39
|
||||
range: [38, 39]
|
||||
loc:
|
||||
start:
|
||||
line: 1
|
||||
column: 38
|
||||
end:
|
||||
line: 1
|
||||
column: 39
|
||||
]
|
||||
start: 37
|
||||
end: 39
|
||||
range: [37, 39]
|
||||
loc:
|
||||
start:
|
||||
line: 1
|
||||
column: 37
|
||||
end:
|
||||
line: 1
|
||||
column: 39
|
||||
start: 21
|
||||
end: 39
|
||||
range: [21, 39]
|
||||
loc:
|
||||
start:
|
||||
line: 1
|
||||
column: 21
|
||||
end:
|
||||
line: 1
|
||||
column: 39
|
||||
start: 0
|
||||
end: 39
|
||||
range: [0, 39]
|
||||
loc:
|
||||
start:
|
||||
line: 1
|
||||
column: 0
|
||||
end:
|
||||
line: 1
|
||||
column: 39
|
||||
|
||||
testAstLocationData '''
|
||||
if a
|
||||
b
|
||||
else
|
||||
if c
|
||||
d
|
||||
''',
|
||||
type: 'IfStatement'
|
||||
test:
|
||||
start: 3
|
||||
end: 4
|
||||
range: [3, 4]
|
||||
loc:
|
||||
start:
|
||||
line: 1
|
||||
column: 3
|
||||
end:
|
||||
line: 1
|
||||
column: 4
|
||||
consequent:
|
||||
body: [
|
||||
expression:
|
||||
start: 7
|
||||
end: 8
|
||||
range: [7, 8]
|
||||
loc:
|
||||
start:
|
||||
line: 2
|
||||
column: 2
|
||||
end:
|
||||
line: 2
|
||||
column: 3
|
||||
start: 7
|
||||
end: 8
|
||||
range: [7, 8]
|
||||
loc:
|
||||
start:
|
||||
line: 2
|
||||
column: 2
|
||||
end:
|
||||
line: 2
|
||||
column: 3
|
||||
]
|
||||
start: 5
|
||||
end: 8
|
||||
range: [5, 8]
|
||||
loc:
|
||||
start:
|
||||
line: 2
|
||||
column: 0
|
||||
end:
|
||||
line: 2
|
||||
column: 3
|
||||
alternate:
|
||||
body: [
|
||||
test:
|
||||
start: 19
|
||||
end: 20
|
||||
range: [19, 20]
|
||||
loc:
|
||||
start:
|
||||
line: 4
|
||||
column: 5
|
||||
end:
|
||||
line: 4
|
||||
column: 6
|
||||
consequent:
|
||||
body: [
|
||||
expression:
|
||||
start: 25
|
||||
end: 26
|
||||
range: [25, 26]
|
||||
loc:
|
||||
start:
|
||||
line: 5
|
||||
column: 4
|
||||
end:
|
||||
line: 5
|
||||
column: 5
|
||||
start: 25
|
||||
end: 26
|
||||
range: [25, 26]
|
||||
loc:
|
||||
start:
|
||||
line: 5
|
||||
column: 4
|
||||
end:
|
||||
line: 5
|
||||
column: 5
|
||||
]
|
||||
start: 21
|
||||
end: 26
|
||||
range: [21, 26]
|
||||
loc:
|
||||
start:
|
||||
line: 5
|
||||
column: 0
|
||||
end:
|
||||
line: 5
|
||||
column: 5
|
||||
start: 16
|
||||
end: 26
|
||||
range: [16, 26]
|
||||
loc:
|
||||
start:
|
||||
line: 4
|
||||
column: 2
|
||||
end:
|
||||
line: 5
|
||||
column: 5
|
||||
]
|
||||
start: 14
|
||||
end: 26
|
||||
range: [14, 26]
|
||||
loc:
|
||||
start:
|
||||
line: 4
|
||||
column: 0
|
||||
end:
|
||||
line: 5
|
||||
column: 5
|
||||
start: 0
|
||||
end: 26
|
||||
range: [0, 26]
|
||||
loc:
|
||||
start:
|
||||
line: 1
|
||||
column: 0
|
||||
end:
|
||||
line: 5
|
||||
column: 5
|
||||
|
||||
testAstLocationData '''
|
||||
a =
|
||||
if b then c else if d then e
|
||||
''',
|
||||
type: 'AssignmentExpression'
|
||||
right:
|
||||
test:
|
||||
start: 9
|
||||
end: 10
|
||||
range: [9, 10]
|
||||
loc:
|
||||
start:
|
||||
line: 2
|
||||
column: 5
|
||||
end:
|
||||
line: 2
|
||||
column: 6
|
||||
consequent:
|
||||
start: 16
|
||||
end: 17
|
||||
range: [16, 17]
|
||||
loc:
|
||||
start:
|
||||
line: 2
|
||||
column: 12
|
||||
end:
|
||||
line: 2
|
||||
column: 13
|
||||
alternate:
|
||||
test:
|
||||
start: 26
|
||||
end: 27
|
||||
range: [26, 27]
|
||||
loc:
|
||||
start:
|
||||
line: 2
|
||||
column: 22
|
||||
end:
|
||||
line: 2
|
||||
column: 23
|
||||
consequent:
|
||||
start: 33
|
||||
end: 34
|
||||
range: [33, 34]
|
||||
loc:
|
||||
start:
|
||||
line: 2
|
||||
column: 29
|
||||
end:
|
||||
line: 2
|
||||
column: 30
|
||||
start: 23
|
||||
end: 34
|
||||
range: [23, 34]
|
||||
loc:
|
||||
start:
|
||||
line: 2
|
||||
column: 19
|
||||
end:
|
||||
line: 2
|
||||
column: 30
|
||||
start: 6
|
||||
end: 34
|
||||
range: [6, 34]
|
||||
loc:
|
||||
start:
|
||||
line: 2
|
||||
column: 2
|
||||
end:
|
||||
line: 2
|
||||
column: 30
|
||||
start: 0
|
||||
end: 34
|
||||
range: [0, 34]
|
||||
loc:
|
||||
start:
|
||||
line: 1
|
||||
column: 0
|
||||
end:
|
||||
line: 2
|
||||
column: 30
|
||||
|
||||
testAstLocationData '''
|
||||
f(
|
||||
if b
|
||||
c
|
||||
d
|
||||
)
|
||||
''',
|
||||
type: 'CallExpression'
|
||||
arguments: [
|
||||
test:
|
||||
start: 8
|
||||
end: 9
|
||||
range: [8, 9]
|
||||
loc:
|
||||
start:
|
||||
line: 2
|
||||
column: 5
|
||||
end:
|
||||
line: 2
|
||||
column: 6
|
||||
consequent:
|
||||
body: [
|
||||
expression:
|
||||
start: 14
|
||||
end: 15
|
||||
range: [14, 15]
|
||||
loc:
|
||||
start:
|
||||
line: 3
|
||||
column: 4
|
||||
end:
|
||||
line: 3
|
||||
column: 5
|
||||
start: 14
|
||||
end: 15
|
||||
range: [14, 15]
|
||||
loc:
|
||||
start:
|
||||
line: 3
|
||||
column: 4
|
||||
end:
|
||||
line: 3
|
||||
column: 5
|
||||
,
|
||||
expression:
|
||||
start: 20
|
||||
end: 21
|
||||
range: [20, 21]
|
||||
loc:
|
||||
start:
|
||||
line: 4
|
||||
column: 4
|
||||
end:
|
||||
line: 4
|
||||
column: 5
|
||||
start: 20
|
||||
end: 21
|
||||
range: [20, 21]
|
||||
loc:
|
||||
start:
|
||||
line: 4
|
||||
column: 4
|
||||
end:
|
||||
line: 4
|
||||
column: 5
|
||||
]
|
||||
start: 10
|
||||
end: 21
|
||||
range: [10, 21]
|
||||
loc:
|
||||
start:
|
||||
line: 3
|
||||
column: 0
|
||||
end:
|
||||
line: 4
|
||||
column: 5
|
||||
]
|
||||
start: 0
|
||||
end: 23
|
||||
range: [0, 23]
|
||||
loc:
|
||||
start:
|
||||
line: 1
|
||||
column: 0
|
||||
end:
|
||||
line: 5
|
||||
column: 1
|
||||
|
|
Loading…
Reference in New Issue