Support multiline string literals in HCL only in HIL fragments

This commit is contained in:
Vladislav Rassokhin 2016-07-22 20:13:27 +03:00 committed by Vladislav Rassokhin
parent 7cb7455c28
commit 2b0eb1f52c
9 changed files with 28 additions and 9 deletions

View File

@ -82,9 +82,14 @@ func TestDecode_interface(t *testing.T) {
}, },
{ {
"multiline_literal.hcl", "multiline_literal.hcl",
true,
nil,
},
{
"multiline_literal_with_hil.hcl",
false, false,
map[string]interface{}{"multiline_literal": testhelper.Unix2dos(`hello map[string]interface{}{"multiline_literal_with_hil": testhelper.Unix2dos(`${hello
world`)}, world}`)},
}, },
{ {
"multiline_no_marker.hcl", "multiline_no_marker.hcl",

View File

@ -1,7 +1,7 @@
resource "null_resource" "some_command" { resource "null_resource" "some_command" {
provisioner "local-exec" { provisioner "local-exec" {
command = "echo ' command = "${echo '
some newlines some newlines
and additonal output'" and additonal output'}"
} }
} }

View File

@ -1,7 +1,7 @@
resource "null_resource" "some_command" { resource "null_resource" "some_command" {
provisioner "local-exec" { provisioner "local-exec" {
command = "echo ' command = "${echo '
some newlines some newlines
and additonal output'" and additonal output'}"
} }
} }

View File

@ -480,7 +480,7 @@ func (s *Scanner) scanString() {
// read character after quote // read character after quote
ch := s.next() ch := s.next()
if ch < 0 || ch == eof { if (ch == '\n' && braces == 0) || ch < 0 || ch == eof {
s.err("literal not terminated") s.err("literal not terminated")
return return
} }

View File

@ -494,7 +494,8 @@ func TestError(t *testing.T) {
testError(t, `"`, "1:2", "literal not terminated", token.STRING) testError(t, `"`, "1:2", "literal not terminated", token.STRING)
testError(t, `"abc`, "1:5", "literal not terminated", token.STRING) testError(t, `"abc`, "1:5", "literal not terminated", token.STRING)
testError(t, `"abc`+"\n", "2:1", "literal not terminated", token.STRING) testError(t, `"abc`+"\n", "1:5", "literal not terminated", token.STRING)
testError(t, `"${abc`+"\n", "2:1", "literal not terminated", token.STRING)
testError(t, `/*/`, "1:4", "comment not terminated", token.COMMENT) testError(t, `/*/`, "1:4", "comment not terminated", token.COMMENT)
testError(t, `/foo`, "1:1", "expected '/' for comment", token.COMMENT) testError(t, `/foo`, "1:1", "expected '/' for comment", token.COMMENT)
} }

View File

@ -27,6 +27,9 @@ func Unquote(s string) (t string, err error) {
if quote != '"' { if quote != '"' {
return "", ErrSyntax return "", ErrSyntax
} }
if !contains(s, '$') && !contains(s, '{') && contains(s, '\n') {
return "", ErrSyntax
}
// Is it trivial? Avoid allocation. // Is it trivial? Avoid allocation.
if !contains(s, '\\') && !contains(s, quote) && !contains(s, '$') { if !contains(s, '\\') && !contains(s, quote) && !contains(s, '$') {
@ -84,6 +87,10 @@ func Unquote(s string) (t string, err error) {
} }
} }
if s[0] == '\n' {
return "", ErrSyntax
}
c, multibyte, ss, err := unquoteChar(s, quote) c, multibyte, ss, err := unquoteChar(s, quote)
if err != nil { if err != nil {
return "", err return "", err

View File

@ -40,6 +40,7 @@ var unquotetests = []unQuoteTest{
{`"echo ${var.region}${element(split(",",var.zones),0)}"`, {`"echo ${var.region}${element(split(",",var.zones),0)}"`,
`echo ${var.region}${element(split(",",var.zones),0)}`}, `echo ${var.region}${element(split(",",var.zones),0)}`},
{`"${HH\\:mm\\:ss}"`, `${HH\\:mm\\:ss}`}, {`"${HH\\:mm\\:ss}"`, `${HH\\:mm\\:ss}`},
{`"${\n}"`, `${\n}`},
} }
var misquoted = []string{ var misquoted = []string{
@ -65,9 +66,12 @@ var misquoted = []string{
"`\"", "`\"",
`"\'"`, `"\'"`,
`'\"'`, `'\"'`,
"\"\n\"",
"\"\\n\n\"",
"'\n'", "'\n'",
`"${"`, `"${"`,
`"${foo{}"`, `"${foo{}"`,
"\"${foo}\n\"",
} }
func TestUnquote(t *testing.T) { func TestUnquote(t *testing.T) {

View File

@ -0,0 +1,2 @@
multiline_literal_with_hil = "${hello
world}"

View File

@ -12,4 +12,4 @@ func Unix2dos(unix string) string {
} }
return strings.Replace(unix, "\n", "\r\n", -1) return strings.Replace(unix, "\n", "\r\n", -1)
} }