From: Daniel Martí Date: Wed, 6 Sep 2017 09:57:16 +0000 (+0200) Subject: text/template: fix pos info when trimming newlines X-Git-Tag: go1.10beta1~1200 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=9b8964bf2df0626530a0ca493e3e95d8dc3844dd;p=gostls13.git text/template: fix pos info when trimming newlines The lexer keeps the byte offset and the line for the rune it's currently on. This was simple enough up until whitespace trimming was introduced. With whitespace trimming, we might skip over newlines. In that case, the lexer wasn't properly updating the line counter. Fix it. Also, TestPos now checks that the line is correct too, which it was ignoring before. This was necessary to test this scenario in the lexer. Fixes #21778. Change-Id: I3880f3adf02662eac8f818d5caa6935cca9cb33b Reviewed-on: https://go-review.googlesource.com/61870 Run-TryBot: Daniel Martí Reviewed-by: Rob Pike TryBot-Result: Gobot Gobot --- diff --git a/src/text/template/parse/lex.go b/src/text/template/parse/lex.go index cdecd412ee..2cde4a2ca1 100644 --- a/src/text/template/parse/lex.go +++ b/src/text/template/parse/lex.go @@ -164,6 +164,7 @@ func (l *lexer) emit(t itemType) { // ignore skips over the pending input before this point. func (l *lexer) ignore() { + l.line += strings.Count(l.input[l.start:l.pos], "\n") l.start = l.pos } diff --git a/src/text/template/parse/lex_test.go b/src/text/template/parse/lex_test.go index 2c73bb623a..cb01cd98b6 100644 --- a/src/text/template/parse/lex_test.go +++ b/src/text/template/parse/lex_test.go @@ -404,6 +404,9 @@ func equal(i1, i2 []item, checkPos bool) bool { if checkPos && i1[k].pos != i2[k].pos { return false } + if checkPos && i1[k].line != i2[k].line { + return false + } } return true } @@ -452,7 +455,7 @@ func TestDelims(t *testing.T) { } var lexPosTests = []lexTest{ - {"empty", "", []item{tEOF}}, + {"empty", "", []item{{itemEOF, 0, "", 1}}}, {"punctuation", "{{,@%#}}", []item{ {itemLeftDelim, 0, "{{", 1}, {itemChar, 2, ",", 1}, @@ -470,6 +473,24 @@ var lexPosTests = []lexTest{ {itemText, 13, "xyz", 1}, {itemEOF, 16, "", 1}, }}, + {"trimafter", "{{x -}}\n{{y}}", []item{ + {itemLeftDelim, 0, "{{", 1}, + {itemIdentifier, 2, "x", 1}, + {itemRightDelim, 5, "}}", 1}, + {itemLeftDelim, 8, "{{", 2}, + {itemIdentifier, 10, "y", 2}, + {itemRightDelim, 11, "}}", 2}, + {itemEOF, 13, "", 2}, + }}, + {"trimbefore", "{{x}}\n{{- y}}", []item{ + {itemLeftDelim, 0, "{{", 1}, + {itemIdentifier, 2, "x", 1}, + {itemRightDelim, 3, "}}", 1}, + {itemLeftDelim, 6, "{{", 2}, + {itemIdentifier, 10, "y", 2}, + {itemRightDelim, 11, "}}", 2}, + {itemEOF, 13, "", 2}, + }}, } // The other tests don't check position, to make the test cases easier to construct. @@ -485,7 +506,8 @@ func TestPos(t *testing.T) { if !equal(items[i:i+1], test.items[i:i+1], true) { i1 := items[i] i2 := test.items[i] - t.Errorf("\t#%d: got {%v %d %q} expected {%v %d %q}", i, i1.typ, i1.pos, i1.val, i2.typ, i2.pos, i2.val) + t.Errorf("\t#%d: got {%v %d %q %d} expected {%v %d %q %d}", + i, i1.typ, i1.pos, i1.val, i1.line, i2.typ, i2.pos, i2.val, i2.line) } } }