Merge pull request #3524 from minodisk/master

Fix location data bug for string interpolations
This commit is contained in:
Michael Ficarra
2014-07-01 07:35:57 -07:00
3 changed files with 154 additions and 5 deletions

View File

@@ -193,7 +193,7 @@
};
Lexer.prototype.heredocToken = function() {
var doc, heredoc, match, quote;
var doc, heredoc, match, quote, strOffset;
if (!(match = HEREDOC.exec(this.chunk))) {
return 0;
}
@@ -204,9 +204,10 @@
indent: null
});
if (quote === '"' && 0 <= doc.indexOf('#{')) {
strOffset = match[2].charAt(0) === '\n' ? 4 : 3;
this.interpolateString(doc, {
heredoc: true,
strOffset: 3,
strOffset: strOffset,
lexedLength: heredoc.length
});
} else {
@@ -625,7 +626,7 @@
}
inner = expr.slice(1, -1);
if (inner.length) {
_ref2 = this.getLineAndColumnFromChunk(strOffset + i + 1), line = _ref2[0], column = _ref2[1];
_ref2 = this.getLineAndColumnFromChunk(strOffset + i + 2), line = _ref2[0], column = _ref2[1];
nested = new Lexer().tokenize(inner, {
line: line,
column: column,

View File

@@ -207,7 +207,8 @@ exports.Lexer = class Lexer
quote = heredoc.charAt 0
doc = @sanitizeHeredoc match[2], quote: quote, indent: null
if quote is '"' and 0 <= doc.indexOf '#{'
@interpolateString doc, heredoc: yes, strOffset: 3, lexedLength: heredoc.length
strOffset = if match[2].charAt(0) is '\n' then 4 else 3
@interpolateString doc, heredoc: yes, strOffset: strOffset, lexedLength: heredoc.length
else
@token 'STRING', @makeString(doc, quote, yes), 0, heredoc.length
heredoc.length
@@ -548,7 +549,7 @@ exports.Lexer = class Lexer
errorToken = @makeToken '', 'string interpolation', offsetInChunk + i + 1, 2
inner = expr[1...-1]
if inner.length
[line, column] = @getLineAndColumnFromChunk(strOffset + i + 1)
[line, column] = @getLineAndColumnFromChunk(strOffset + i + 2)
nested = new Lexer().tokenize inner, line: line, column: column, rewrite: off
popped = nested.pop()
popped = nested.shift() if nested[0]?[0] is 'TERMINATOR'

View File

@@ -59,6 +59,153 @@ test "Verify location of generated tokens (with indented first line)", ->
eq numberToken[2].last_line, 0
eq numberToken[2].last_column, 7
test "Verify locations in string interpolation", ->
tokens = CoffeeScript.tokens '"a#{b}c"'
eq tokens.length, 8
[openParen, a, firstPlus, b, secondPlus, c, closeParen] = tokens
eq a[2].first_line, 0
eq a[2].first_column, 1
eq a[2].last_line, 0
eq a[2].last_column, 1
eq b[2].first_line, 0
eq b[2].first_column, 4
eq b[2].last_line, 0
eq b[2].last_column, 4
eq c[2].first_line, 0
eq c[2].first_column, 6
eq c[2].last_line, 0
eq c[2].last_column, 6
test "Verify locations in string interpolation (single line with multiple interpolation)", ->
tokens = CoffeeScript.tokens '"#{a}b#{c}"'
eq tokens.length, 10
[{}, {}, {}, a, {}, b, {}, c] = tokens
eq a[2].first_line, 0
eq a[2].first_column, 3
eq a[2].last_line, 0
eq a[2].last_column, 3
eq b[2].first_line, 0
eq b[2].first_column, 5
eq b[2].last_line, 0
eq b[2].last_column, 5
eq c[2].first_line, 0
eq c[2].first_column, 8
eq c[2].last_line, 0
eq c[2].last_column, 8
test "Verify locations in string interpolation (multiline)", ->
tokens = CoffeeScript.tokens '"""a\n#{b}\nc"""'
eq tokens.length, 8
[{}, a, {}, b, {}, c, {}, {}] = tokens
eq a[2].first_line, 0
eq a[2].first_column, 3
eq a[2].last_line, 0
eq a[2].last_column, 4
eq b[2].first_line, 1
eq b[2].first_column, 2
eq b[2].last_line, 1
eq b[2].last_column, 2
eq c[2].first_line, 1
eq c[2].first_column, 4
eq c[2].last_line, 2
eq c[2].last_column, 0
test "Verify locations in string interpolation (multiline starting with a line break)", ->
tokens = CoffeeScript.tokens '"""\n#{b}\nc"""'
eq tokens.length, 8
[{}, a, {}, b, {}, c] = tokens
eq a[2].first_line, 0
eq a[2].first_column, 0
eq a[2].last_line, 0
eq a[2].last_column, 0
eq b[2].first_line, 1
eq b[2].first_column, 2
eq b[2].last_line, 1
eq b[2].last_column, 2
eq c[2].first_line, 1
eq c[2].first_column, 4
eq c[2].last_line, 2
eq c[2].last_column, 0
test "Verify locations in string interpolation (multiline starting with line breaks)", ->
tokens = CoffeeScript.tokens '"""\n\n#{b}\nc"""'
eq tokens.length, 8
[{}, a, {}, b, {}, c] = tokens
eq a[2].first_line, 1
eq a[2].first_column, 0
eq a[2].last_line, 1
eq a[2].last_column, 0
eq b[2].first_line, 2
eq b[2].first_column, 2
eq b[2].last_line, 2
eq b[2].last_column, 2
eq c[2].first_line, 2
eq c[2].first_column, 4
eq c[2].last_line, 3
eq c[2].last_column, 0
test "Verify locations in string interpolation (multiline with multiple interpolation)", ->
tokens = CoffeeScript.tokens '"""#{a}\nb\n#{c}"""'
eq tokens.length, 10
[{}, {}, {}, a, {}, b, {}, c] = tokens
eq a[2].first_line, 0
eq a[2].first_column, 5
eq a[2].last_line, 0
eq a[2].last_column, 5
eq b[2].first_line, 0
eq b[2].first_column, 7
eq b[2].last_line, 1
eq b[2].last_column, 1
eq c[2].first_line, 2
eq c[2].first_column, 2
eq c[2].last_line, 2
eq c[2].last_column, 2
test "Verify locations in string interpolation (multiline starting with multiple interpolation and line breaks)", ->
tokens = CoffeeScript.tokens '"""\n\n#{a}\nb\n#{c}"""'
eq tokens.length, 10
[{}, {}, {}, a, {}, b, {}, c] = tokens
eq a[2].first_line, 2
eq a[2].first_column, 2
eq a[2].last_line, 2
eq a[2].last_column, 2
eq b[2].first_line, 2
eq b[2].first_column, 4
eq b[2].last_line, 3
eq b[2].last_column, 1
eq c[2].first_line, 4
eq c[2].first_column, 2
eq c[2].last_line, 4
eq c[2].last_column, 2
test "Verify all tokens get a location", ->
doesNotThrow ->
tokens = CoffeeScript.tokens testScript