Skip to content

Commit d84c94d

Browse files
authored
Merge pull request #4445 from alangpierce/upstream-fix-new-location-data
Properly update location data when setting a call to use `new`
2 parents 4f714cc + fbc77f7 commit d84c94d

File tree

3 files changed

+73
-0
lines changed

3 files changed

+73
-0
lines changed

lib/coffee-script/nodes.js

Lines changed: 17 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/nodes.coffee

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,13 +633,29 @@ exports.Call = class Call extends Base
633633

634634
children: ['variable', 'args']
635635

636+
# When setting the location, we sometimes need to update the start location to
637+
# account for a newly-discovered `new` operator to the left of us. This
638+
# expands the range on the left, but not the right.
639+
updateLocationDataIfMissing: (locationData) ->
640+
if @locationData and @needsUpdatedStartLocation
641+
@locationData.first_line = locationData.first_line
642+
@locationData.first_column = locationData.first_column
643+
base = @variable?.base or @variable
644+
if base.needsUpdatedStartLocation
645+
@variable.locationData.first_line = locationData.first_line
646+
@variable.locationData.first_column = locationData.first_column
647+
base.updateLocationDataIfMissing locationData
648+
delete @needsUpdatedStartLocation
649+
super
650+
636651
# Tag this invocation as creating a new instance.
637652
newInstance: ->
638653
base = @variable?.base or @variable
639654
if base instanceof Call and not base.isNew
640655
base.newInstance()
641656
else
642657
@isNew = true
658+
@needsUpdatedStartLocation = true
643659
this
644660

645661
# Soaked chained invocations unfold into if/else ternary structures.

test/parser.coffee

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,43 @@ test "operator precedence for binary ? operator", ->
3838
eq expression.second.first.base.value, 'b'
3939
eq expression.second.operator, '&&'
4040
eq expression.second.second.base.value, 'c'
41+
42+
test "new calls have a range including the new", ->
43+
source = '''
44+
a = new B().c(d)
45+
'''
46+
block = CoffeeScript.nodes source
47+
48+
assertColumnRange = (node, firstColumn, lastColumn) ->
49+
eq node.locationData.first_line, 0
50+
eq node.locationData.first_column, firstColumn
51+
eq node.locationData.last_line, 0
52+
eq node.locationData.last_column, lastColumn
53+
54+
[assign] = block.expressions
55+
outerCall = assign.value
56+
innerValue = outerCall.variable
57+
innerCall = innerValue.base
58+
59+
assertColumnRange assign, 0, 15
60+
assertColumnRange outerCall, 4, 15
61+
assertColumnRange innerValue, 4, 12
62+
assertColumnRange innerCall, 4, 10
63+
64+
test "location data is properly set for nested `new`", ->
65+
source = '''
66+
new new A()()
67+
'''
68+
block = CoffeeScript.nodes source
69+
70+
assertColumnRange = (node, firstColumn, lastColumn) ->
71+
eq node.locationData.first_line, 0
72+
eq node.locationData.first_column, firstColumn
73+
eq node.locationData.last_line, 0
74+
eq node.locationData.last_column, lastColumn
75+
76+
[outerCall] = block.expressions
77+
innerCall = outerCall.variable
78+
79+
assertColumnRange outerCall, 0, 12
80+
assertColumnRange innerCall, 4, 10

0 commit comments

Comments
 (0)