From 2b0eb1f52c2ce7e826002550ebdab698c1b594cb Mon Sep 17 00:00:00 2001 From: Vladislav Rassokhin Date: Fri, 22 Jul 2016 20:13:27 +0300 Subject: [PATCH] Support multiline string literals in HCL only in HIL fragments --- decoder_test.go | 9 +++++++-- hcl/printer/testdata/multiline_string.golden | 4 ++-- hcl/printer/testdata/multiline_string.input | 4 ++-- hcl/scanner/scanner.go | 2 +- hcl/scanner/scanner_test.go | 3 ++- hcl/strconv/quote.go | 7 +++++++ hcl/strconv/quote_test.go | 4 ++++ test-fixtures/multiline_literal_with_hil.hcl | 2 ++ testhelper/unix2dos.go | 2 +- 9 files changed, 28 insertions(+), 9 deletions(-) create mode 100644 test-fixtures/multiline_literal_with_hil.hcl diff --git a/decoder_test.go b/decoder_test.go index b3428bb..11d5adb 100644 --- a/decoder_test.go +++ b/decoder_test.go @@ -82,9 +82,14 @@ func TestDecode_interface(t *testing.T) { }, { "multiline_literal.hcl", + true, + nil, + }, + { + "multiline_literal_with_hil.hcl", false, - map[string]interface{}{"multiline_literal": testhelper.Unix2dos(`hello - world`)}, + map[string]interface{}{"multiline_literal_with_hil": testhelper.Unix2dos(`${hello + world}`)}, }, { "multiline_no_marker.hcl", diff --git a/hcl/printer/testdata/multiline_string.golden b/hcl/printer/testdata/multiline_string.golden index a1e9949..3d10c74 100644 --- a/hcl/printer/testdata/multiline_string.golden +++ b/hcl/printer/testdata/multiline_string.golden @@ -1,7 +1,7 @@ resource "null_resource" "some_command" { provisioner "local-exec" { - command = "echo ' + command = "${echo ' some newlines -and additonal output'" +and additonal output'}" } } diff --git a/hcl/printer/testdata/multiline_string.input b/hcl/printer/testdata/multiline_string.input index a1e9949..3d10c74 100644 --- a/hcl/printer/testdata/multiline_string.input +++ b/hcl/printer/testdata/multiline_string.input @@ -1,7 +1,7 @@ resource "null_resource" "some_command" { provisioner "local-exec" { - command = "echo ' + command = "${echo ' some newlines -and additonal output'" +and additonal output'}" } } diff --git a/hcl/scanner/scanner.go b/hcl/scanner/scanner.go index d387794..6966236 100644 --- a/hcl/scanner/scanner.go +++ b/hcl/scanner/scanner.go @@ -480,7 +480,7 @@ func (s *Scanner) scanString() { // read character after quote ch := s.next() - if ch < 0 || ch == eof { + if (ch == '\n' && braces == 0) || ch < 0 || ch == eof { s.err("literal not terminated") return } diff --git a/hcl/scanner/scanner_test.go b/hcl/scanner/scanner_test.go index e92f650..d5334a0 100644 --- a/hcl/scanner/scanner_test.go +++ b/hcl/scanner/scanner_test.go @@ -494,7 +494,8 @@ func TestError(t *testing.T) { testError(t, `"`, "1:2", "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, `/foo`, "1:1", "expected '/' for comment", token.COMMENT) } diff --git a/hcl/strconv/quote.go b/hcl/strconv/quote.go index d578769..5f981ea 100644 --- a/hcl/strconv/quote.go +++ b/hcl/strconv/quote.go @@ -27,6 +27,9 @@ func Unquote(s string) (t string, err error) { if quote != '"' { return "", ErrSyntax } + if !contains(s, '$') && !contains(s, '{') && contains(s, '\n') { + return "", ErrSyntax + } // Is it trivial? Avoid allocation. 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) if err != nil { return "", err diff --git a/hcl/strconv/quote_test.go b/hcl/strconv/quote_test.go index 9de8c9f..65be375 100644 --- a/hcl/strconv/quote_test.go +++ b/hcl/strconv/quote_test.go @@ -40,6 +40,7 @@ var unquotetests = []unQuoteTest{ {`"echo ${var.region}${element(split(",",var.zones),0)}"`, `echo ${var.region}${element(split(",",var.zones),0)}`}, {`"${HH\\:mm\\:ss}"`, `${HH\\:mm\\:ss}`}, + {`"${\n}"`, `${\n}`}, } var misquoted = []string{ @@ -65,9 +66,12 @@ var misquoted = []string{ "`\"", `"\'"`, `'\"'`, + "\"\n\"", + "\"\\n\n\"", "'\n'", `"${"`, `"${foo{}"`, + "\"${foo}\n\"", } func TestUnquote(t *testing.T) { diff --git a/test-fixtures/multiline_literal_with_hil.hcl b/test-fixtures/multiline_literal_with_hil.hcl new file mode 100644 index 0000000..b55a361 --- /dev/null +++ b/test-fixtures/multiline_literal_with_hil.hcl @@ -0,0 +1,2 @@ +multiline_literal_with_hil = "${hello + world}" \ No newline at end of file diff --git a/testhelper/unix2dos.go b/testhelper/unix2dos.go index c689f73..827ac6f 100644 --- a/testhelper/unix2dos.go +++ b/testhelper/unix2dos.go @@ -12,4 +12,4 @@ func Unix2dos(unix string) string { } return strings.Replace(unix, "\n", "\r\n", -1) -} \ No newline at end of file +}