Fix wrong location issue in "string" interpolation

This commit is contained in:
minodisk
2014-07-03 00:33:57 +09:00
parent 2bab1b6aa1
commit 5920939e23
3 changed files with 136 additions and 17 deletions

View File

@@ -166,7 +166,7 @@
};
Lexer.prototype.stringToken = function() {
var octalEsc, quote, string, trimmed;
var inner, innerLen, numBreak, octalEsc, pos, quote, string, trimmed;
switch (quote = this.chunk.charAt(0)) {
case "'":
string = (SIMPLESTR.exec(this.chunk) || [])[0];
@@ -177,10 +177,16 @@
if (!string) {
return 0;
}
trimmed = this.removeNewlines(string.slice(1, -1));
inner = string.slice(1, -1);
trimmed = this.removeNewlines(inner);
if (quote === '"' && 0 < string.indexOf('#{', 1)) {
numBreak = pos = 0;
innerLen = inner.length;
while (inner.charAt(pos++) === '\n' && pos < innerLen) {
numBreak++;
}
this.interpolateString(trimmed, {
strOffset: 1,
strOffset: 1 + numBreak,
lexedLength: string.length
});
} else {

View File

@@ -190,9 +190,13 @@ exports.Lexer = class Lexer
when "'" then [string] = SIMPLESTR.exec(@chunk) || []
when '"' then string = @balancedString @chunk, '"'
return 0 unless string
trimmed = @removeNewlines string[1...-1]
inner = string[1...-1]
trimmed = @removeNewlines inner
if quote is '"' and 0 < string.indexOf '#{', 1
@interpolateString trimmed, strOffset: 1, lexedLength: string.length
numBreak = pos = 0
innerLen = inner.length
numBreak++ while inner.charAt(pos++) is '\n' and pos < innerLen
@interpolateString trimmed, strOffset: 1 + numBreak, lexedLength: string.length
else
@token 'STRING', quote + @escapeLines(trimmed) + quote, 0, string.length
if octalEsc = /^(?:\\.|[^\\])*\\(?:0[0-7]|[1-7])/.test string

View File

@@ -59,7 +59,7 @@ 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", ->
test 'Verify locations in string interpolation (in "string")', ->
tokens = CoffeeScript.tokens '"a#{b}c"'
eq tokens.length, 8
@@ -80,7 +80,7 @@ test "Verify locations in string interpolation", ->
eq c[2].last_line, 0
eq c[2].last_column, 6
test "Verify locations in string interpolation (single line with multiple interpolation)", ->
test 'Verify locations in string interpolation (in "string", multiple interpolation)', ->
tokens = CoffeeScript.tokens '"#{a}b#{c}"'
eq tokens.length, 10
@@ -101,7 +101,95 @@ test "Verify locations in string interpolation (single line with multiple interp
eq c[2].last_line, 0
eq c[2].last_column, 8
test "Verify locations in string interpolation (multiline)", ->
test 'Verify locations in string interpolation (in "string", multiple interpolation and line breaks)', ->
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, 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, 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 (in "string", multiple interpolation and starting with line breaks)', ->
tokens = CoffeeScript.tokens '"\n#{a}\nb\n#{c}"'
eq tokens.length, 10
[{}, {}, {}, a, {}, b, {}, c] = tokens
console.log a
console.log b
console.log c
eq a[2].first_line, 1
eq a[2].first_column, 2
eq a[2].last_line, 1
eq a[2].last_column, 2
eq b[2].first_line, 1
eq b[2].first_column, 4
eq b[2].last_line, 2
eq b[2].last_column, 1
eq c[2].first_line, 3
eq c[2].first_column, 2
eq c[2].last_line, 3
eq c[2].last_column, 2
test 'Verify locations in string interpolation (in "string", multiple interpolation and starting with line breaks)', ->
tokens = CoffeeScript.tokens '"\n\n#{a}\n\nb\n\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, 5
eq b[2].last_column, 0
eq c[2].first_line, 6
eq c[2].first_column, 2
eq c[2].last_line, 6
eq c[2].last_column, 2
test 'Verify locations in string interpolation (in "string", multiple interpolation and starting with line breaks)', ->
tokens = CoffeeScript.tokens '"\n\n\n#{a}\n\n\nb\n\n\n#{c}"'
eq tokens.length, 10
[{}, {}, {}, a, {}, b, {}, c] = tokens
eq a[2].first_line, 3
eq a[2].first_column, 2
eq a[2].last_line, 3
eq a[2].last_column, 2
eq b[2].first_line, 3
eq b[2].first_column, 4
eq b[2].last_line, 8
eq b[2].last_column, 0
eq c[2].first_line, 9
eq c[2].first_column, 2
eq c[2].last_line, 9
eq c[2].last_column, 2
test 'Verify locations in string interpolation (in """string""", line breaks)', ->
tokens = CoffeeScript.tokens '"""a\n#{b}\nc"""'
eq tokens.length, 8
@@ -122,7 +210,7 @@ test "Verify locations in string interpolation (multiline)", ->
eq c[2].last_line, 2
eq c[2].last_column, 0
test "Verify locations in string interpolation (multiline starting with a line break)", ->
test 'Verify locations in string interpolation (in """string""", starting with a line break)', ->
tokens = CoffeeScript.tokens '"""\n#{b}\nc"""'
eq tokens.length, 8
@@ -143,7 +231,7 @@ test "Verify locations in string interpolation (multiline starting with a line b
eq c[2].last_line, 2
eq c[2].last_column, 0
test "Verify locations in string interpolation (multiline starting with line breaks)", ->
test 'Verify locations in string interpolation (in """string""", starting with line breaks)', ->
tokens = CoffeeScript.tokens '"""\n\n#{b}\nc"""'
eq tokens.length, 8
@@ -164,7 +252,7 @@ test "Verify locations in string interpolation (multiline starting with line bre
eq c[2].last_line, 3
eq c[2].last_column, 0
test "Verify locations in string interpolation (multiline with multiple interpolation)", ->
test 'Verify locations in string interpolation (in """string""", multiple interpolation)', ->
tokens = CoffeeScript.tokens '"""#{a}\nb\n#{c}"""'
eq tokens.length, 10
@@ -185,8 +273,8 @@ test "Verify locations in string interpolation (multiline with multiple interpol
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}"""'
test 'Verify locations in string interpolation (in """string""", multiple interpolation, and starting with line breaks)', ->
tokens = CoffeeScript.tokens '"""\n\n#{a}\n\nb\n\n#{c}"""'
eq tokens.length, 10
[{}, {}, {}, a, {}, b, {}, c] = tokens
@@ -198,12 +286,33 @@ test "Verify locations in string interpolation (multiline starting with multiple
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 b[2].last_line, 5
eq b[2].last_column, 0
eq c[2].first_line, 4
eq c[2].first_line, 6
eq c[2].first_column, 2
eq c[2].last_line, 4
eq c[2].last_line, 6
eq c[2].last_column, 2
test 'Verify locations in string interpolation (in """string""", multiple interpolation, and starting with line breaks)', ->
tokens = CoffeeScript.tokens '"""\n\n\n#{a}\n\n\nb\n\n\n#{c}"""'
eq tokens.length, 10
[{}, {}, {}, a, {}, b, {}, c] = tokens
eq a[2].first_line, 3
eq a[2].first_column, 2
eq a[2].last_line, 3
eq a[2].last_column, 2
eq b[2].first_line, 3
eq b[2].first_column, 4
eq b[2].last_line, 8
eq b[2].last_column, 0
eq c[2].first_line, 9
eq c[2].first_column, 2
eq c[2].last_line, 9
eq c[2].last_column, 2
test "Verify all tokens get a location", ->