1
0
Fork 0
mirror of https://github.com/jashkenas/coffeescript.git synced 2022-11-09 12:23:24 -05:00
jashkenas--coffeescript/test/parser.coffee
Alan Pierce fbc77f7445 Properly update location data when setting a call to use new
This is an upstream port of https://github.com/decaffeinate/coffeescript/pull/24

In a case like `new A().b(c)`, the jison structure ends up being different from
the resulting AST. To the jison parser, this is the `new` unary operator applied
to the expression `A().b(c)`. When the unary operator is applied, the
`Call.prototype.newInstance` function traverses into the leftmost function call
and sets the `isNew` flag to true, and the `Op` constructor returns the `Call`
node so that the call is used in place of the unary operator. However, the code
wasn't updating the node location data, so this commit fixes that.

It's sort of hard to get the location data in `newInstance`, so we set a flag on
every affected node in `newInstance` and override `updateLocationDataIfMissing`
(which is called with the location data after the fact) so that it updates just
the starting position.
2017-02-16 20:43:19 -08:00

80 lines
2.3 KiB
CoffeeScript

# Parser
# ---------
test "operator precedence for logical operators", ->
source = '''
a or b and c
'''
block = CoffeeScript.nodes source
[expression] = block.expressions
eq expression.first.base.value, 'a'
eq expression.operator, '||'
eq expression.second.first.base.value, 'b'
eq expression.second.operator, '&&'
eq expression.second.second.base.value, 'c'
test "operator precedence for bitwise operators", ->
source = '''
a | b ^ c & d
'''
block = CoffeeScript.nodes source
[expression] = block.expressions
eq expression.first.base.value, 'a'
eq expression.operator, '|'
eq expression.second.first.base.value, 'b'
eq expression.second.operator, '^'
eq expression.second.second.first.base.value, 'c'
eq expression.second.second.operator, '&'
eq expression.second.second.second.base.value, 'd'
test "operator precedence for binary ? operator", ->
source = '''
a ? b and c
'''
block = CoffeeScript.nodes source
[expression] = block.expressions
eq expression.first.base.value, 'a'
eq expression.operator, '?'
eq expression.second.first.base.value, 'b'
eq expression.second.operator, '&&'
eq expression.second.second.base.value, 'c'
test "new calls have a range including the new", ->
source = '''
a = new B().c(d)
'''
block = CoffeeScript.nodes source
assertColumnRange = (node, firstColumn, lastColumn) ->
eq node.locationData.first_line, 0
eq node.locationData.first_column, firstColumn
eq node.locationData.last_line, 0
eq node.locationData.last_column, lastColumn
[assign] = block.expressions
outerCall = assign.value
innerValue = outerCall.variable
innerCall = innerValue.base
assertColumnRange assign, 0, 15
assertColumnRange outerCall, 4, 15
assertColumnRange innerValue, 4, 12
assertColumnRange innerCall, 4, 10
test "location data is properly set for nested `new`", ->
source = '''
new new A()()
'''
block = CoffeeScript.nodes source
assertColumnRange = (node, firstColumn, lastColumn) ->
eq node.locationData.first_line, 0
eq node.locationData.first_column, firstColumn
eq node.locationData.last_line, 0
eq node.locationData.last_column, lastColumn
[outerCall] = block.expressions
innerCall = outerCall.variable
assertColumnRange outerCall, 0, 12
assertColumnRange innerCall, 4, 10