| package hclsyntax |
| |
| import ( |
| "testing" |
| |
| "github.com/go-test/deep" |
| "github.com/hashicorp/hcl/v2" |
| "github.com/zclconf/go-cty/cty" |
| ) |
| |
| func init() { |
| deep.MaxDepth = 999 |
| } |
| |
| func TestParseConfig(t *testing.T) { |
| tests := []struct { |
| input string |
| diagCount int |
| want *Body |
| }{ |
| { |
| ``, |
| 0, |
| &Body{ |
| Attributes: Attributes{}, |
| Blocks: Blocks{}, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| }, |
| }, |
| }, |
| |
| { |
| "block {}\n", |
| 0, |
| &Body{ |
| Attributes: Attributes{}, |
| Blocks: Blocks{ |
| &Block{ |
| Type: "block", |
| Labels: nil, |
| Body: &Body{ |
| Attributes: Attributes{}, |
| Blocks: Blocks{}, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 7, Byte: 6}, |
| End: hcl.Pos{Line: 1, Column: 9, Byte: 8}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 9, Byte: 8}, |
| End: hcl.Pos{Line: 1, Column: 9, Byte: 8}, |
| }, |
| }, |
| |
| TypeRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| }, |
| LabelRanges: nil, |
| OpenBraceRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 7, Byte: 6}, |
| End: hcl.Pos{Line: 1, Column: 8, Byte: 7}, |
| }, |
| CloseBraceRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 8, Byte: 7}, |
| End: hcl.Pos{Line: 1, Column: 9, Byte: 8}, |
| }, |
| }, |
| }, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 9}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 9}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 9}, |
| }, |
| }, |
| }, |
| { |
| "block {}", |
| 0, |
| &Body{ |
| Attributes: Attributes{}, |
| Blocks: Blocks{ |
| &Block{ |
| Type: "block", |
| Labels: nil, |
| Body: &Body{ |
| Attributes: Attributes{}, |
| Blocks: Blocks{}, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 7, Byte: 6}, |
| End: hcl.Pos{Line: 1, Column: 9, Byte: 8}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 9, Byte: 8}, |
| End: hcl.Pos{Line: 1, Column: 9, Byte: 8}, |
| }, |
| }, |
| |
| TypeRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| }, |
| LabelRanges: nil, |
| OpenBraceRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 7, Byte: 6}, |
| End: hcl.Pos{Line: 1, Column: 8, Byte: 7}, |
| }, |
| CloseBraceRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 8, Byte: 7}, |
| End: hcl.Pos{Line: 1, Column: 9, Byte: 8}, |
| }, |
| }, |
| }, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 9, Byte: 8}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 9, Byte: 8}, |
| End: hcl.Pos{Line: 1, Column: 9, Byte: 8}, |
| }, |
| }, |
| }, |
| { |
| "block {}block {}\n", |
| 1, // missing newline after block definition |
| &Body{ |
| Attributes: Attributes{}, |
| Blocks: Blocks{ |
| &Block{ |
| Type: "block", |
| Labels: nil, |
| Body: &Body{ |
| Attributes: Attributes{}, |
| Blocks: Blocks{}, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 7, Byte: 6}, |
| End: hcl.Pos{Line: 1, Column: 9, Byte: 8}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 9, Byte: 8}, |
| End: hcl.Pos{Line: 1, Column: 9, Byte: 8}, |
| }, |
| }, |
| |
| TypeRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| }, |
| LabelRanges: nil, |
| OpenBraceRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 7, Byte: 6}, |
| End: hcl.Pos{Line: 1, Column: 8, Byte: 7}, |
| }, |
| CloseBraceRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 8, Byte: 7}, |
| End: hcl.Pos{Line: 1, Column: 9, Byte: 8}, |
| }, |
| }, |
| }, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 17}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 17}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 17}, |
| }, |
| }, |
| }, |
| { |
| "block { block {} }\n", |
| 1, // can't nest another block in the single-line block syntax |
| &Body{ |
| Attributes: Attributes{}, |
| Blocks: Blocks{ |
| &Block{ |
| Type: "block", |
| Labels: nil, |
| Body: &Body{ |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 7, Byte: 6}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 19}, |
| }, |
| EndRange: hcl.Range{ // Parser recovery behavior leaves us after this whole construct, on the next line |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 19}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 19}, |
| }, |
| }, |
| |
| TypeRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| }, |
| LabelRanges: nil, |
| OpenBraceRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 7, Byte: 6}, |
| End: hcl.Pos{Line: 1, Column: 8, Byte: 7}, |
| }, |
| CloseBraceRange: hcl.Range{ // Parser recovery behavior leaves us after this whole construct, on the next line |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 19}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 19}, |
| }, |
| }, |
| }, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 19}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 19}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 19}, |
| }, |
| }, |
| }, |
| { |
| "block \"foo\" {}\n", |
| 0, |
| &Body{ |
| Attributes: Attributes{}, |
| Blocks: Blocks{ |
| &Block{ |
| Type: "block", |
| Labels: []string{"foo"}, |
| Body: &Body{ |
| Attributes: Attributes{}, |
| Blocks: Blocks{}, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 13, Byte: 12}, |
| End: hcl.Pos{Line: 1, Column: 15, Byte: 14}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 15, Byte: 14}, |
| End: hcl.Pos{Line: 1, Column: 15, Byte: 14}, |
| }, |
| }, |
| |
| TypeRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| }, |
| LabelRanges: []hcl.Range{ |
| { |
| Start: hcl.Pos{Line: 1, Column: 7, Byte: 6}, |
| End: hcl.Pos{Line: 1, Column: 12, Byte: 11}, |
| }, |
| }, |
| OpenBraceRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 13, Byte: 12}, |
| End: hcl.Pos{Line: 1, Column: 14, Byte: 13}, |
| }, |
| CloseBraceRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 14, Byte: 13}, |
| End: hcl.Pos{Line: 1, Column: 15, Byte: 14}, |
| }, |
| }, |
| }, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 15}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 15}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 15}, |
| }, |
| }, |
| }, |
| { |
| "block foo {}\n", |
| 0, |
| &Body{ |
| Attributes: Attributes{}, |
| Blocks: Blocks{ |
| &Block{ |
| Type: "block", |
| Labels: []string{"foo"}, |
| Body: &Body{ |
| Attributes: Attributes{}, |
| Blocks: Blocks{}, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 11, Byte: 10}, |
| End: hcl.Pos{Line: 1, Column: 13, Byte: 12}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 13, Byte: 12}, |
| End: hcl.Pos{Line: 1, Column: 13, Byte: 12}, |
| }, |
| }, |
| |
| TypeRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| }, |
| LabelRanges: []hcl.Range{ |
| { |
| Start: hcl.Pos{Line: 1, Column: 7, Byte: 6}, |
| End: hcl.Pos{Line: 1, Column: 10, Byte: 9}, |
| }, |
| }, |
| OpenBraceRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 11, Byte: 10}, |
| End: hcl.Pos{Line: 1, Column: 12, Byte: 11}, |
| }, |
| CloseBraceRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 12, Byte: 11}, |
| End: hcl.Pos{Line: 1, Column: 13, Byte: 12}, |
| }, |
| }, |
| }, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 13}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 13}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 13}, |
| }, |
| }, |
| }, |
| { |
| "block \"invalid ${not_allowed_here} foo\" {}\n", |
| 1, // Invalid string literal; Template sequences are not allowed in this string. |
| &Body{ |
| Attributes: Attributes{}, |
| Blocks: Blocks{ |
| &Block{ |
| Type: "block", |
| Labels: []string{"invalid ${ ... } foo"}, // invalid interpolation gets replaced with a placeholder here |
| Body: &Body{ |
| Attributes: Attributes{}, |
| Blocks: Blocks{}, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 41, Byte: 40}, |
| End: hcl.Pos{Line: 1, Column: 43, Byte: 42}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 43, Byte: 42}, |
| End: hcl.Pos{Line: 1, Column: 43, Byte: 42}, |
| }, |
| }, |
| |
| TypeRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| }, |
| LabelRanges: []hcl.Range{ |
| { |
| Start: hcl.Pos{Line: 1, Column: 7, Byte: 6}, |
| End: hcl.Pos{Line: 1, Column: 40, Byte: 39}, |
| }, |
| }, |
| OpenBraceRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 41, Byte: 40}, |
| End: hcl.Pos{Line: 1, Column: 42, Byte: 41}, |
| }, |
| CloseBraceRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 42, Byte: 41}, |
| End: hcl.Pos{Line: 1, Column: 43, Byte: 42}, |
| }, |
| }, |
| }, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 43}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 43}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 43}, |
| }, |
| }, |
| }, |
| { |
| ` |
| block "invalid" 1.2 {} |
| block "valid" {} |
| `, |
| 1, |
| &Body{ |
| Attributes: Attributes{}, |
| Blocks: Blocks{ |
| &Block{ |
| Type: "block", |
| Labels: []string{"invalid"}, |
| Body: &Body{ |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 1}, |
| End: hcl.Pos{Line: 2, Column: 6, Byte: 6}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 1}, |
| End: hcl.Pos{Line: 2, Column: 6, Byte: 6}, |
| }, |
| }, |
| |
| TypeRange: hcl.Range{ |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 1}, |
| End: hcl.Pos{Line: 2, Column: 6, Byte: 6}, |
| }, |
| LabelRanges: []hcl.Range{ |
| { |
| Start: hcl.Pos{Line: 2, Column: 7, Byte: 7}, |
| End: hcl.Pos{Line: 2, Column: 16, Byte: 16}, |
| }, |
| }, |
| |
| // Since we failed parsing before we got to the |
| // braces, the type range is used as a placeholder |
| // for these. |
| OpenBraceRange: hcl.Range{ |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 1}, |
| End: hcl.Pos{Line: 2, Column: 6, Byte: 6}, |
| }, |
| CloseBraceRange: hcl.Range{ |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 1}, |
| End: hcl.Pos{Line: 2, Column: 6, Byte: 6}, |
| }, |
| }, |
| |
| // Recovery behavior should allow us to still see this |
| // second block, even though the first was invalid. |
| &Block{ |
| Type: "block", |
| Labels: []string{"valid"}, |
| Body: &Body{ |
| Attributes: Attributes{}, |
| Blocks: Blocks{}, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 3, Column: 15, Byte: 38}, |
| End: hcl.Pos{Line: 3, Column: 17, Byte: 40}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 3, Column: 17, Byte: 40}, |
| End: hcl.Pos{Line: 3, Column: 17, Byte: 40}, |
| }, |
| }, |
| |
| TypeRange: hcl.Range{ |
| Start: hcl.Pos{Line: 3, Column: 1, Byte: 24}, |
| End: hcl.Pos{Line: 3, Column: 6, Byte: 29}, |
| }, |
| LabelRanges: []hcl.Range{ |
| { |
| Start: hcl.Pos{Line: 3, Column: 7, Byte: 30}, |
| End: hcl.Pos{Line: 3, Column: 14, Byte: 37}, |
| }, |
| }, |
| OpenBraceRange: hcl.Range{ |
| Start: hcl.Pos{Line: 3, Column: 15, Byte: 38}, |
| End: hcl.Pos{Line: 3, Column: 16, Byte: 39}, |
| }, |
| CloseBraceRange: hcl.Range{ |
| Start: hcl.Pos{Line: 3, Column: 16, Byte: 39}, |
| End: hcl.Pos{Line: 3, Column: 17, Byte: 40}, |
| }, |
| }, |
| }, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 4, Column: 1, Byte: 41}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 4, Column: 1, Byte: 41}, |
| End: hcl.Pos{Line: 4, Column: 1, Byte: 41}, |
| }, |
| }, |
| }, |
| { |
| `block "f\o" {} |
| `, |
| 1, // "\o" is not a valid escape sequence |
| &Body{ |
| Attributes: Attributes{}, |
| Blocks: Blocks{ |
| &Block{ |
| Type: "block", |
| Labels: []string{"fo"}, |
| Body: &Body{ |
| Attributes: map[string]*Attribute{}, |
| Blocks: []*Block{}, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 13, Byte: 12}, |
| End: hcl.Pos{Line: 1, Column: 15, Byte: 14}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 15, Byte: 14}, |
| End: hcl.Pos{Line: 1, Column: 15, Byte: 14}, |
| }, |
| }, |
| |
| TypeRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| }, |
| LabelRanges: []hcl.Range{ |
| { |
| Start: hcl.Pos{Line: 1, Column: 7, Byte: 6}, |
| End: hcl.Pos{Line: 1, Column: 12, Byte: 11}, |
| }, |
| }, |
| OpenBraceRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 13, Byte: 12}, |
| End: hcl.Pos{Line: 1, Column: 14, Byte: 13}, |
| }, |
| CloseBraceRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 14, Byte: 13}, |
| End: hcl.Pos{Line: 1, Column: 15, Byte: 14}, |
| }, |
| }, |
| }, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 15}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 15}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 15}, |
| }, |
| }, |
| }, |
| { |
| `block "f\n" {} |
| `, |
| 0, |
| &Body{ |
| Attributes: Attributes{}, |
| Blocks: Blocks{ |
| &Block{ |
| Type: "block", |
| Labels: []string{"f\n"}, |
| Body: &Body{ |
| Attributes: Attributes{}, |
| Blocks: Blocks{}, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 13, Byte: 12}, |
| End: hcl.Pos{Line: 1, Column: 15, Byte: 14}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 15, Byte: 14}, |
| End: hcl.Pos{Line: 1, Column: 15, Byte: 14}, |
| }, |
| }, |
| |
| TypeRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| }, |
| LabelRanges: []hcl.Range{ |
| { |
| Start: hcl.Pos{Line: 1, Column: 7, Byte: 6}, |
| End: hcl.Pos{Line: 1, Column: 12, Byte: 11}, |
| }, |
| }, |
| OpenBraceRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 13, Byte: 12}, |
| End: hcl.Pos{Line: 1, Column: 14, Byte: 13}, |
| }, |
| CloseBraceRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 14, Byte: 13}, |
| End: hcl.Pos{Line: 1, Column: 15, Byte: 14}, |
| }, |
| }, |
| }, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 15}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 15}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 15}, |
| }, |
| }, |
| }, |
| |
| { |
| "a = 1\n", |
| 0, |
| &Body{ |
| Attributes: Attributes{ |
| "a": { |
| Name: "a", |
| Expr: &LiteralValueExpr{ |
| Val: cty.NumberIntVal(1), |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, |
| End: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| }, |
| NameRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 2, Byte: 1}, |
| }, |
| EqualsRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 3, Byte: 2}, |
| End: hcl.Pos{Line: 1, Column: 4, Byte: 3}, |
| }, |
| }, |
| }, |
| Blocks: Blocks{}, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 6}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 6}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 6}, |
| }, |
| }, |
| }, |
| { |
| "a = 1", |
| 0, |
| &Body{ |
| Attributes: Attributes{ |
| "a": { |
| Name: "a", |
| Expr: &LiteralValueExpr{ |
| Val: cty.NumberIntVal(1), |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, |
| End: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| }, |
| NameRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 2, Byte: 1}, |
| }, |
| EqualsRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 3, Byte: 2}, |
| End: hcl.Pos{Line: 1, Column: 4, Byte: 3}, |
| }, |
| }, |
| }, |
| Blocks: Blocks{}, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| End: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| }, |
| }, |
| }, |
| { |
| "a = \"hello ${true}\"\n", |
| 0, |
| &Body{ |
| Attributes: Attributes{ |
| "a": { |
| Name: "a", |
| Expr: &TemplateExpr{ |
| Parts: []Expression{ |
| &LiteralValueExpr{ |
| Val: cty.StringVal("hello "), |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| End: hcl.Pos{Line: 1, Column: 12, Byte: 11}, |
| }, |
| }, |
| &LiteralValueExpr{ |
| Val: cty.True, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 14, Byte: 13}, |
| End: hcl.Pos{Line: 1, Column: 18, Byte: 17}, |
| }, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, |
| End: hcl.Pos{Line: 1, Column: 20, Byte: 19}, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 20, Byte: 19}, |
| }, |
| NameRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 2, Byte: 1}, |
| }, |
| EqualsRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 3, Byte: 2}, |
| End: hcl.Pos{Line: 1, Column: 4, Byte: 3}, |
| }, |
| }, |
| }, |
| Blocks: Blocks{}, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 20}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 20}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 20}, |
| }, |
| }, |
| }, |
| { |
| "a = \"hello $${true}\"\n", |
| 0, |
| &Body{ |
| Attributes: Attributes{ |
| "a": { |
| Name: "a", |
| Expr: &TemplateExpr{ |
| Parts: []Expression{ |
| &LiteralValueExpr{ |
| Val: cty.StringVal("hello "), |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| End: hcl.Pos{Line: 1, Column: 12, Byte: 11}, |
| }, |
| }, |
| &LiteralValueExpr{ |
| Val: cty.StringVal("${"), |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 12, Byte: 11}, |
| End: hcl.Pos{Line: 1, Column: 15, Byte: 14}, |
| }, |
| }, |
| &LiteralValueExpr{ |
| Val: cty.StringVal("true}"), |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 15, Byte: 14}, |
| End: hcl.Pos{Line: 1, Column: 20, Byte: 19}, |
| }, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, |
| End: hcl.Pos{Line: 1, Column: 21, Byte: 20}, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 21, Byte: 20}, |
| }, |
| NameRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 2, Byte: 1}, |
| }, |
| EqualsRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 3, Byte: 2}, |
| End: hcl.Pos{Line: 1, Column: 4, Byte: 3}, |
| }, |
| }, |
| }, |
| Blocks: Blocks{}, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 21}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 21}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 21}, |
| }, |
| }, |
| }, |
| { |
| "a = \"hello %%{true}\"\n", |
| 0, |
| &Body{ |
| Attributes: Attributes{ |
| "a": { |
| Name: "a", |
| Expr: &TemplateExpr{ |
| Parts: []Expression{ |
| &LiteralValueExpr{ |
| Val: cty.StringVal("hello "), |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| End: hcl.Pos{Line: 1, Column: 12, Byte: 11}, |
| }, |
| }, |
| &LiteralValueExpr{ |
| Val: cty.StringVal("%{"), |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 12, Byte: 11}, |
| End: hcl.Pos{Line: 1, Column: 15, Byte: 14}, |
| }, |
| }, |
| &LiteralValueExpr{ |
| Val: cty.StringVal("true}"), |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 15, Byte: 14}, |
| End: hcl.Pos{Line: 1, Column: 20, Byte: 19}, |
| }, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, |
| End: hcl.Pos{Line: 1, Column: 21, Byte: 20}, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 21, Byte: 20}, |
| }, |
| NameRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 2, Byte: 1}, |
| }, |
| EqualsRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 3, Byte: 2}, |
| End: hcl.Pos{Line: 1, Column: 4, Byte: 3}, |
| }, |
| }, |
| }, |
| Blocks: Blocks{}, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 21}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 21}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 21}, |
| }, |
| }, |
| }, |
| { |
| "a = \"hello $$\"\n", |
| 0, |
| &Body{ |
| Attributes: Attributes{ |
| "a": { |
| Name: "a", |
| Expr: &TemplateExpr{ |
| Parts: []Expression{ |
| &LiteralValueExpr{ |
| Val: cty.StringVal("hello "), |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| End: hcl.Pos{Line: 1, Column: 12, Byte: 11}, |
| }, |
| }, |
| // This parses oddly due to how the scanner |
| // handles escaping of the $ sequence, but it's |
| // functionally equivalent to a single literal. |
| &LiteralValueExpr{ |
| Val: cty.StringVal("$"), |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 12, Byte: 11}, |
| End: hcl.Pos{Line: 1, Column: 13, Byte: 12}, |
| }, |
| }, |
| &LiteralValueExpr{ |
| Val: cty.StringVal("$"), |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 13, Byte: 12}, |
| End: hcl.Pos{Line: 1, Column: 14, Byte: 13}, |
| }, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, |
| End: hcl.Pos{Line: 1, Column: 15, Byte: 14}, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 15, Byte: 14}, |
| }, |
| NameRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 2, Byte: 1}, |
| }, |
| EqualsRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 3, Byte: 2}, |
| End: hcl.Pos{Line: 1, Column: 4, Byte: 3}, |
| }, |
| }, |
| }, |
| Blocks: Blocks{}, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 15}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 15}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 15}, |
| }, |
| }, |
| }, |
| { |
| "a = \"hello $\"\n", |
| 0, // unterminated template interpolation sequence |
| &Body{ |
| Attributes: Attributes{ |
| "a": { |
| Name: "a", |
| Expr: &TemplateExpr{ |
| Parts: []Expression{ |
| &LiteralValueExpr{ |
| Val: cty.StringVal("hello "), |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| End: hcl.Pos{Line: 1, Column: 12, Byte: 11}, |
| }, |
| }, |
| &LiteralValueExpr{ |
| Val: cty.StringVal("$"), |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 12, Byte: 11}, |
| End: hcl.Pos{Line: 1, Column: 13, Byte: 12}, |
| }, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, |
| End: hcl.Pos{Line: 1, Column: 14, Byte: 13}, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 14, Byte: 13}, |
| }, |
| NameRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 2, Byte: 1}, |
| }, |
| EqualsRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 3, Byte: 2}, |
| End: hcl.Pos{Line: 1, Column: 4, Byte: 3}, |
| }, |
| }, |
| }, |
| Blocks: Blocks{}, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 14}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 14}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 14}, |
| }, |
| }, |
| }, |
| { |
| "a = \"hello %%\"\n", |
| 0, |
| &Body{ |
| Attributes: Attributes{ |
| "a": { |
| Name: "a", |
| Expr: &TemplateExpr{ |
| Parts: []Expression{ |
| &LiteralValueExpr{ |
| Val: cty.StringVal("hello "), |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| End: hcl.Pos{Line: 1, Column: 12, Byte: 11}, |
| }, |
| }, |
| // This parses oddly due to how the scanner |
| // handles escaping of the % sequence, but it's |
| // functionally equivalent to a single literal. |
| &LiteralValueExpr{ |
| Val: cty.StringVal("%"), |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 12, Byte: 11}, |
| End: hcl.Pos{Line: 1, Column: 13, Byte: 12}, |
| }, |
| }, |
| &LiteralValueExpr{ |
| Val: cty.StringVal("%"), |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 13, Byte: 12}, |
| End: hcl.Pos{Line: 1, Column: 14, Byte: 13}, |
| }, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, |
| End: hcl.Pos{Line: 1, Column: 15, Byte: 14}, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 15, Byte: 14}, |
| }, |
| NameRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 2, Byte: 1}, |
| }, |
| EqualsRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 3, Byte: 2}, |
| End: hcl.Pos{Line: 1, Column: 4, Byte: 3}, |
| }, |
| }, |
| }, |
| Blocks: Blocks{}, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 15}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 15}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 15}, |
| }, |
| }, |
| }, |
| { |
| "a = \"hello %\"\n", |
| 0, // unterminated template control sequence |
| &Body{ |
| Attributes: Attributes{ |
| "a": { |
| Name: "a", |
| Expr: &TemplateExpr{ |
| Parts: []Expression{ |
| &LiteralValueExpr{ |
| Val: cty.StringVal("hello "), |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| End: hcl.Pos{Line: 1, Column: 12, Byte: 11}, |
| }, |
| }, |
| &LiteralValueExpr{ |
| Val: cty.StringVal("%"), |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 12, Byte: 11}, |
| End: hcl.Pos{Line: 1, Column: 13, Byte: 12}, |
| }, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, |
| End: hcl.Pos{Line: 1, Column: 14, Byte: 13}, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 14, Byte: 13}, |
| }, |
| NameRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 2, Byte: 1}, |
| }, |
| EqualsRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 3, Byte: 2}, |
| End: hcl.Pos{Line: 1, Column: 4, Byte: 3}, |
| }, |
| }, |
| }, |
| Blocks: Blocks{}, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 14}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 14}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 14}, |
| }, |
| }, |
| }, |
| { |
| "a = \"hello!\"\n", |
| 0, |
| &Body{ |
| Attributes: Attributes{ |
| "a": { |
| Name: "a", |
| Expr: &TemplateExpr{ |
| Parts: []Expression{ |
| &LiteralValueExpr{ |
| Val: cty.StringVal("hello!"), |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| End: hcl.Pos{Line: 1, Column: 12, Byte: 11}, |
| }, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, |
| End: hcl.Pos{Line: 1, Column: 13, Byte: 12}, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 13, Byte: 12}, |
| }, |
| NameRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 2, Byte: 1}, |
| }, |
| EqualsRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 3, Byte: 2}, |
| End: hcl.Pos{Line: 1, Column: 4, Byte: 3}, |
| }, |
| }, |
| }, |
| Blocks: Blocks{}, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 13}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 13}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 13}, |
| }, |
| }, |
| }, |
| { |
| "a = \"\\u2022\"\n", |
| 0, |
| &Body{ |
| Attributes: Attributes{ |
| "a": { |
| Name: "a", |
| Expr: &TemplateExpr{ |
| Parts: []Expression{ |
| &LiteralValueExpr{ |
| Val: cty.StringVal("\u2022"), |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| End: hcl.Pos{Line: 1, Column: 12, Byte: 11}, |
| }, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, |
| End: hcl.Pos{Line: 1, Column: 13, Byte: 12}, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 13, Byte: 12}, |
| }, |
| NameRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 2, Byte: 1}, |
| }, |
| EqualsRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 3, Byte: 2}, |
| End: hcl.Pos{Line: 1, Column: 4, Byte: 3}, |
| }, |
| }, |
| }, |
| Blocks: Blocks{}, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 13}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 13}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 13}, |
| }, |
| }, |
| }, |
| { |
| "a = \"\\uu2022\"\n", |
| 1, // \u must be followed by four hex digits |
| &Body{ |
| Attributes: Attributes{ |
| "a": { |
| Name: "a", |
| Expr: &TemplateExpr{ |
| Parts: []Expression{ |
| &LiteralValueExpr{ |
| Val: cty.StringVal("\\uu2022"), |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| End: hcl.Pos{Line: 1, Column: 13, Byte: 12}, |
| }, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, |
| End: hcl.Pos{Line: 1, Column: 14, Byte: 13}, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 14, Byte: 13}, |
| }, |
| NameRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 2, Byte: 1}, |
| }, |
| EqualsRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 3, Byte: 2}, |
| End: hcl.Pos{Line: 1, Column: 4, Byte: 3}, |
| }, |
| }, |
| }, |
| Blocks: Blocks{}, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 14}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 14}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 14}, |
| }, |
| }, |
| }, |
| { |
| "a = \"\\U0001d11e\"\n", |
| 0, |
| &Body{ |
| Attributes: Attributes{ |
| "a": { |
| Name: "a", |
| Expr: &TemplateExpr{ |
| Parts: []Expression{ |
| &LiteralValueExpr{ |
| Val: cty.StringVal("\U0001d11e"), |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| End: hcl.Pos{Line: 1, Column: 16, Byte: 15}, |
| }, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, |
| End: hcl.Pos{Line: 1, Column: 17, Byte: 16}, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 17, Byte: 16}, |
| }, |
| NameRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 2, Byte: 1}, |
| }, |
| EqualsRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 3, Byte: 2}, |
| End: hcl.Pos{Line: 1, Column: 4, Byte: 3}, |
| }, |
| }, |
| }, |
| Blocks: Blocks{}, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 17}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 17}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 17}, |
| }, |
| }, |
| }, |
| { |
| "a = \"\\u0001d11e\"\n", |
| 0, // This is valid, but probably not what the user intended :( |
| &Body{ |
| Attributes: Attributes{ |
| "a": { |
| Name: "a", |
| Expr: &TemplateExpr{ |
| Parts: []Expression{ |
| &LiteralValueExpr{ |
| // Only the first four digits were used for the |
| // escape sequence, so the remaining four just |
| // get echoed out literally. |
| Val: cty.StringVal("\u0001d11e"), |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| End: hcl.Pos{Line: 1, Column: 16, Byte: 15}, |
| }, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, |
| End: hcl.Pos{Line: 1, Column: 17, Byte: 16}, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 17, Byte: 16}, |
| }, |
| NameRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 2, Byte: 1}, |
| }, |
| EqualsRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 3, Byte: 2}, |
| End: hcl.Pos{Line: 1, Column: 4, Byte: 3}, |
| }, |
| }, |
| }, |
| Blocks: Blocks{}, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 17}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 17}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 17}, |
| }, |
| }, |
| }, |
| { |
| "a = \"\\U2022\"\n", |
| 1, // Invalid escape sequence, since we need eight hex digits for \U |
| &Body{ |
| Attributes: Attributes{ |
| "a": { |
| Name: "a", |
| Expr: &TemplateExpr{ |
| Parts: []Expression{ |
| &LiteralValueExpr{ |
| Val: cty.StringVal("\\U2022"), |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| End: hcl.Pos{Line: 1, Column: 12, Byte: 11}, |
| }, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, |
| End: hcl.Pos{Line: 1, Column: 13, Byte: 12}, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 13, Byte: 12}, |
| }, |
| NameRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 2, Byte: 1}, |
| }, |
| EqualsRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 3, Byte: 2}, |
| End: hcl.Pos{Line: 1, Column: 4, Byte: 3}, |
| }, |
| }, |
| }, |
| Blocks: Blocks{}, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 13}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 13}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 13}, |
| }, |
| }, |
| }, |
| { |
| "a = \"\\u20m2\"\n", |
| 1, // Invalid escape sequence |
| &Body{ |
| Attributes: Attributes{ |
| "a": { |
| Name: "a", |
| Expr: &TemplateExpr{ |
| Parts: []Expression{ |
| &LiteralValueExpr{ |
| Val: cty.StringVal("\\u20m2"), |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| End: hcl.Pos{Line: 1, Column: 12, Byte: 11}, |
| }, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, |
| End: hcl.Pos{Line: 1, Column: 13, Byte: 12}, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 13, Byte: 12}, |
| }, |
| NameRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 2, Byte: 1}, |
| }, |
| EqualsRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 3, Byte: 2}, |
| End: hcl.Pos{Line: 1, Column: 4, Byte: 3}, |
| }, |
| }, |
| }, |
| Blocks: Blocks{}, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 13}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 13}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 13}, |
| }, |
| }, |
| }, |
| { |
| "a = \"\\U00300000\"\n", |
| 1, // Invalid unicode character (can't encode in UTF-8) |
| &Body{ |
| Attributes: Attributes{ |
| "a": { |
| Name: "a", |
| Expr: &TemplateExpr{ |
| Parts: []Expression{ |
| &LiteralValueExpr{ |
| Val: cty.StringVal("\\U00300000"), |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| End: hcl.Pos{Line: 1, Column: 16, Byte: 15}, |
| }, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, |
| End: hcl.Pos{Line: 1, Column: 17, Byte: 16}, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 17, Byte: 16}, |
| }, |
| NameRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 2, Byte: 1}, |
| }, |
| EqualsRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 3, Byte: 2}, |
| End: hcl.Pos{Line: 1, Column: 4, Byte: 3}, |
| }, |
| }, |
| }, |
| Blocks: Blocks{}, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 17}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 17}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 17}, |
| }, |
| }, |
| }, |
| { |
| "a = \"\\Ub2705550\"\n", |
| 1, // Invalid unicode character (can't encode in UTF-8) |
| &Body{ |
| Attributes: Attributes{ |
| "a": { |
| Name: "a", |
| Expr: &TemplateExpr{ |
| Parts: []Expression{ |
| &LiteralValueExpr{ |
| Val: cty.StringVal("\\Ub2705550"), |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| End: hcl.Pos{Line: 1, Column: 16, Byte: 15}, |
| }, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, |
| End: hcl.Pos{Line: 1, Column: 17, Byte: 16}, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 17, Byte: 16}, |
| }, |
| NameRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 2, Byte: 1}, |
| }, |
| EqualsRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 3, Byte: 2}, |
| End: hcl.Pos{Line: 1, Column: 4, Byte: 3}, |
| }, |
| }, |
| }, |
| Blocks: Blocks{}, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 17}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 17}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 17}, |
| }, |
| }, |
| }, |
| { |
| "a = <<EOT\nHello\nEOT\nb = \"Hi\"", |
| 0, |
| &Body{ |
| Attributes: Attributes{ |
| "a": { |
| Name: "a", |
| Expr: &TemplateExpr{ |
| Parts: []Expression{ |
| &LiteralValueExpr{ |
| Val: cty.StringVal("Hello\n"), |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 10}, |
| End: hcl.Pos{Line: 3, Column: 1, Byte: 16}, |
| }, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, |
| End: hcl.Pos{Line: 3, Column: 4, Byte: 19}, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 3, Column: 4, Byte: 19}, |
| }, |
| NameRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 2, Byte: 1}, |
| }, |
| EqualsRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 3, Byte: 2}, |
| End: hcl.Pos{Line: 1, Column: 4, Byte: 3}, |
| }, |
| }, |
| "b": { |
| Name: "b", |
| Expr: &TemplateExpr{ |
| Parts: []Expression{ |
| &LiteralValueExpr{ |
| Val: cty.StringVal("Hi"), |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 4, Column: 6, Byte: 25}, |
| End: hcl.Pos{Line: 4, Column: 8, Byte: 27}, |
| }, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 4, Column: 5, Byte: 24}, |
| End: hcl.Pos{Line: 4, Column: 9, Byte: 28}, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 4, Column: 1, Byte: 20}, |
| End: hcl.Pos{Line: 4, Column: 9, Byte: 28}, |
| }, |
| NameRange: hcl.Range{ |
| Start: hcl.Pos{Line: 4, Column: 1, Byte: 20}, |
| End: hcl.Pos{Line: 4, Column: 2, Byte: 21}, |
| }, |
| EqualsRange: hcl.Range{ |
| Start: hcl.Pos{Line: 4, Column: 3, Byte: 22}, |
| End: hcl.Pos{Line: 4, Column: 4, Byte: 23}, |
| }, |
| }, |
| }, |
| Blocks: Blocks{}, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 4, Column: 9, Byte: 28}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 4, Column: 9, Byte: 28}, |
| End: hcl.Pos{Line: 4, Column: 9, Byte: 28}, |
| }, |
| }, |
| }, |
| { |
| "a = foo.bar\n", |
| 0, |
| &Body{ |
| Attributes: Attributes{ |
| "a": { |
| Name: "a", |
| Expr: &ScopeTraversalExpr{ |
| Traversal: hcl.Traversal{ |
| hcl.TraverseRoot{ |
| Name: "foo", |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, |
| End: hcl.Pos{Line: 1, Column: 8, Byte: 7}, |
| }, |
| }, |
| hcl.TraverseAttr{ |
| Name: "bar", |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 8, Byte: 7}, |
| End: hcl.Pos{Line: 1, Column: 12, Byte: 11}, |
| }, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, |
| End: hcl.Pos{Line: 1, Column: 12, Byte: 11}, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 12, Byte: 11}, |
| }, |
| NameRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 2, Byte: 1}, |
| }, |
| EqualsRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 3, Byte: 2}, |
| End: hcl.Pos{Line: 1, Column: 4, Byte: 3}, |
| }, |
| }, |
| }, |
| Blocks: Blocks{}, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 12}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 12}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 12}, |
| }, |
| }, |
| }, |
| { |
| "a = foo.0.1.baz\n", |
| 1, // Chaining legacy index syntax is not supported |
| &Body{ |
| Attributes: Attributes{ |
| "a": { |
| Name: "a", |
| Expr: &ScopeTraversalExpr{ |
| Traversal: hcl.Traversal{ |
| hcl.TraverseRoot{ |
| Name: "foo", |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, |
| End: hcl.Pos{Line: 1, Column: 8, Byte: 7}, |
| }, |
| }, |
| hcl.TraverseIndex{ |
| Key: cty.DynamicVal, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 8, Byte: 7}, |
| End: hcl.Pos{Line: 1, Column: 12, Byte: 11}, |
| }, |
| }, |
| hcl.TraverseAttr{ |
| Name: "baz", |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 12, Byte: 11}, |
| End: hcl.Pos{Line: 1, Column: 16, Byte: 15}, |
| }, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, |
| End: hcl.Pos{Line: 1, Column: 16, Byte: 15}, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 16, Byte: 15}, |
| }, |
| NameRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 2, Byte: 1}, |
| }, |
| EqualsRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 3, Byte: 2}, |
| End: hcl.Pos{Line: 1, Column: 4, Byte: 3}, |
| }, |
| }, |
| }, |
| Blocks: Blocks{}, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 16}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 16}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 16}, |
| }, |
| }, |
| }, |
| { |
| "a = \"${var.public_subnets[count.index]}\"\n", |
| 0, |
| &Body{ |
| Attributes: Attributes{ |
| "a": { |
| Name: "a", |
| Expr: &TemplateWrapExpr{ |
| Wrapped: &IndexExpr{ |
| Collection: &ScopeTraversalExpr{ |
| Traversal: hcl.Traversal{ |
| hcl.TraverseRoot{ |
| Name: "var", |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 8, Byte: 7}, |
| End: hcl.Pos{Line: 1, Column: 11, Byte: 10}, |
| }, |
| }, |
| hcl.TraverseAttr{ |
| Name: "public_subnets", |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 11, Byte: 10}, |
| End: hcl.Pos{Line: 1, Column: 26, Byte: 25}, |
| }, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 8, Byte: 7}, |
| End: hcl.Pos{Line: 1, Column: 26, Byte: 25}, |
| }, |
| }, |
| Key: &ScopeTraversalExpr{ |
| Traversal: hcl.Traversal{ |
| hcl.TraverseRoot{ |
| Name: "count", |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 27, Byte: 26}, |
| End: hcl.Pos{Line: 1, Column: 32, Byte: 31}, |
| }, |
| }, |
| hcl.TraverseAttr{ |
| Name: "index", |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 32, Byte: 31}, |
| End: hcl.Pos{Line: 1, Column: 38, Byte: 37}, |
| }, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 27, Byte: 26}, |
| End: hcl.Pos{Line: 1, Column: 38, Byte: 37}, |
| }, |
| }, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 8, Byte: 7}, |
| End: hcl.Pos{Line: 1, Column: 39, Byte: 38}, |
| }, |
| OpenRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 26, Byte: 25}, |
| End: hcl.Pos{Line: 1, Column: 27, Byte: 26}, |
| }, |
| BracketRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 26, Byte: 25}, |
| End: hcl.Pos{Line: 1, Column: 39, Byte: 38}, |
| }, |
| }, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, |
| End: hcl.Pos{Line: 1, Column: 41, Byte: 40}, |
| }, |
| }, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 41, Byte: 40}, |
| }, |
| NameRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 2, Byte: 1}, |
| }, |
| EqualsRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 3, Byte: 2}, |
| End: hcl.Pos{Line: 1, Column: 4, Byte: 3}, |
| }, |
| }, |
| }, |
| Blocks: Blocks{}, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 41}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 41}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 41}, |
| }, |
| }, |
| }, |
| { |
| "a = \"${var.public_subnets[*]}\"\n", |
| 0, |
| &Body{ |
| Attributes: Attributes{ |
| "a": { |
| Name: "a", |
| Expr: &TemplateWrapExpr{ |
| Wrapped: &SplatExpr{ |
| Source: &ScopeTraversalExpr{ |
| Traversal: hcl.Traversal{ |
| hcl.TraverseRoot{ |
| Name: "var", |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 8, Byte: 7}, |
| End: hcl.Pos{Line: 1, Column: 11, Byte: 10}, |
| }, |
| }, |
| hcl.TraverseAttr{ |
| Name: "public_subnets", |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 11, Byte: 10}, |
| End: hcl.Pos{Line: 1, Column: 26, Byte: 25}, |
| }, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 8, Byte: 7}, |
| End: hcl.Pos{Line: 1, Column: 26, Byte: 25}, |
| }, |
| }, |
| Each: &AnonSymbolExpr{ |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 26, Byte: 25}, |
| End: hcl.Pos{Line: 1, Column: 29, Byte: 28}, |
| }, |
| }, |
| Item: &AnonSymbolExpr{ |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 26, Byte: 25}, |
| End: hcl.Pos{Line: 1, Column: 29, Byte: 28}, |
| }, |
| }, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 8, Byte: 7}, |
| End: hcl.Pos{Line: 1, Column: 29, Byte: 28}, |
| }, |
| MarkerRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 26, Byte: 25}, |
| End: hcl.Pos{Line: 1, Column: 29, Byte: 28}, |
| }, |
| }, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, |
| End: hcl.Pos{Line: 1, Column: 31, Byte: 30}, |
| }, |
| }, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 31, Byte: 30}, |
| }, |
| NameRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 2, Byte: 1}, |
| }, |
| EqualsRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 3, Byte: 2}, |
| End: hcl.Pos{Line: 1, Column: 4, Byte: 3}, |
| }, |
| }, |
| }, |
| Blocks: Blocks{}, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 31}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 31}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 31}, |
| }, |
| }, |
| }, |
| { |
| "a = 1 # line comment\n", |
| 0, |
| &Body{ |
| Attributes: Attributes{ |
| "a": { |
| Name: "a", |
| Expr: &LiteralValueExpr{ |
| Val: cty.NumberIntVal(1), |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, |
| End: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| }, |
| NameRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 2, Byte: 1}, |
| }, |
| EqualsRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 3, Byte: 2}, |
| End: hcl.Pos{Line: 1, Column: 4, Byte: 3}, |
| }, |
| }, |
| }, |
| Blocks: Blocks{}, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 21}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 21}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 21}, |
| }, |
| }, |
| }, |
| |
| { |
| "a = [for k, v in foo: v if true]\n", |
| 0, |
| &Body{ |
| Attributes: Attributes{ |
| "a": { |
| Name: "a", |
| Expr: &ForExpr{ |
| KeyVar: "k", |
| ValVar: "v", |
| |
| CollExpr: &ScopeTraversalExpr{ |
| Traversal: hcl.Traversal{ |
| hcl.TraverseRoot{ |
| Name: "foo", |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 18, Byte: 17}, |
| End: hcl.Pos{Line: 1, Column: 21, Byte: 20}, |
| }, |
| }, |
| }, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 18, Byte: 17}, |
| End: hcl.Pos{Line: 1, Column: 21, Byte: 20}, |
| }, |
| }, |
| ValExpr: &ScopeTraversalExpr{ |
| Traversal: hcl.Traversal{ |
| hcl.TraverseRoot{ |
| Name: "v", |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 23, Byte: 22}, |
| End: hcl.Pos{Line: 1, Column: 24, Byte: 23}, |
| }, |
| }, |
| }, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 23, Byte: 22}, |
| End: hcl.Pos{Line: 1, Column: 24, Byte: 23}, |
| }, |
| }, |
| CondExpr: &LiteralValueExpr{ |
| Val: cty.True, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 28, Byte: 27}, |
| End: hcl.Pos{Line: 1, Column: 32, Byte: 31}, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, |
| End: hcl.Pos{Line: 1, Column: 33, Byte: 32}, |
| }, |
| OpenRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, |
| End: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| }, |
| CloseRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 32, Byte: 31}, |
| End: hcl.Pos{Line: 1, Column: 33, Byte: 32}, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 33, Byte: 32}, |
| }, |
| NameRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 2, Byte: 1}, |
| }, |
| EqualsRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 3, Byte: 2}, |
| End: hcl.Pos{Line: 1, Column: 4, Byte: 3}, |
| }, |
| }, |
| }, |
| Blocks: Blocks{}, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 33}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 33}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 33}, |
| }, |
| }, |
| }, |
| { |
| "a = [for k, v in foo: k => v... if true]\n", |
| 2, // can't use => or ... in a tuple for |
| &Body{ |
| Attributes: Attributes{ |
| "a": { |
| Name: "a", |
| Expr: &ForExpr{ |
| KeyVar: "k", |
| ValVar: "v", |
| |
| CollExpr: &ScopeTraversalExpr{ |
| Traversal: hcl.Traversal{ |
| hcl.TraverseRoot{ |
| Name: "foo", |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 18, Byte: 17}, |
| End: hcl.Pos{Line: 1, Column: 21, Byte: 20}, |
| }, |
| }, |
| }, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 18, Byte: 17}, |
| End: hcl.Pos{Line: 1, Column: 21, Byte: 20}, |
| }, |
| }, |
| KeyExpr: &ScopeTraversalExpr{ |
| Traversal: hcl.Traversal{ |
| hcl.TraverseRoot{ |
| Name: "k", |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 23, Byte: 22}, |
| End: hcl.Pos{Line: 1, Column: 24, Byte: 23}, |
| }, |
| }, |
| }, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 23, Byte: 22}, |
| End: hcl.Pos{Line: 1, Column: 24, Byte: 23}, |
| }, |
| }, |
| ValExpr: &ScopeTraversalExpr{ |
| Traversal: hcl.Traversal{ |
| hcl.TraverseRoot{ |
| Name: "v", |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 28, Byte: 27}, |
| End: hcl.Pos{Line: 1, Column: 29, Byte: 28}, |
| }, |
| }, |
| }, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 28, Byte: 27}, |
| End: hcl.Pos{Line: 1, Column: 29, Byte: 28}, |
| }, |
| }, |
| CondExpr: &LiteralValueExpr{ |
| Val: cty.True, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 36, Byte: 35}, |
| End: hcl.Pos{Line: 1, Column: 40, Byte: 39}, |
| }, |
| }, |
| Group: true, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, |
| End: hcl.Pos{Line: 1, Column: 41, Byte: 40}, |
| }, |
| OpenRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, |
| End: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| }, |
| CloseRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 40, Byte: 39}, |
| End: hcl.Pos{Line: 1, Column: 41, Byte: 40}, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 41, Byte: 40}, |
| }, |
| NameRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 2, Byte: 1}, |
| }, |
| EqualsRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 3, Byte: 2}, |
| End: hcl.Pos{Line: 1, Column: 4, Byte: 3}, |
| }, |
| }, |
| }, |
| Blocks: Blocks{}, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 41}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 41}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 41}, |
| }, |
| }, |
| }, |
| |
| { |
| ` `, |
| 0, // the tab character is treated as a single whitespace character |
| &Body{ |
| Attributes: Attributes{}, |
| Blocks: Blocks{}, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 2, Byte: 1}, |
| End: hcl.Pos{Line: 1, Column: 2, Byte: 1}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 2, Byte: 1}, |
| End: hcl.Pos{Line: 1, Column: 2, Byte: 1}, |
| }, |
| }, |
| }, |
| { |
| `\x81`, |
| 2, // invalid UTF-8, and body item is required here |
| &Body{ |
| Attributes: Attributes{}, |
| Blocks: Blocks{}, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 2, Byte: 1}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 2, Byte: 1}, |
| End: hcl.Pos{Line: 1, Column: 2, Byte: 1}, |
| }, |
| }, |
| }, |
| { |
| "a = 1,", |
| 1, |
| &Body{ |
| Attributes: Attributes{ |
| "a": { |
| Name: "a", |
| Expr: &LiteralValueExpr{ |
| Val: cty.NumberIntVal(1), |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, |
| End: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| }, |
| }, |
| |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| }, |
| NameRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 2, Byte: 1}, |
| }, |
| EqualsRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 3, Byte: 2}, |
| End: hcl.Pos{Line: 1, Column: 4, Byte: 3}, |
| }, |
| }, |
| }, |
| Blocks: Blocks{}, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 7, Byte: 6}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 7, Byte: 6}, |
| End: hcl.Pos{Line: 1, Column: 7, Byte: 6}, |
| }, |
| }, |
| }, |
| { |
| "a = `str`", |
| 2, // Invalid character and expression |
| &Body{ |
| Attributes: Attributes{ |
| "a": { |
| Name: "a", |
| Expr: &LiteralValueExpr{ |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, |
| End: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| }, |
| }, |
| NameRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 2, Byte: 1}, |
| }, |
| EqualsRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 3, Byte: 2}, |
| End: hcl.Pos{Line: 1, Column: 4, Byte: 3}, |
| }, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 4, Byte: 3}, |
| }, |
| }, |
| }, |
| Blocks: Blocks{}, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 10, Byte: 9}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 10, Byte: 9}, |
| End: hcl.Pos{Line: 1, Column: 10, Byte: 9}, |
| }, |
| }, |
| }, |
| { |
| `a = 'str'`, |
| 2, // Invalid character and expression |
| &Body{ |
| Attributes: Attributes{ |
| "a": { |
| Name: "a", |
| Expr: &LiteralValueExpr{ |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, |
| End: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| }, |
| }, |
| NameRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 2, Byte: 1}, |
| }, |
| EqualsRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 3, Byte: 2}, |
| End: hcl.Pos{Line: 1, Column: 4, Byte: 3}, |
| }, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 4, Byte: 3}, |
| }, |
| }, |
| }, |
| Blocks: Blocks{}, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 10, Byte: 9}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 10, Byte: 9}, |
| End: hcl.Pos{Line: 1, Column: 10, Byte: 9}, |
| }, |
| }, |
| }, |
| { |
| "a = sort(data.first.ref.attr)[count.index]\n", |
| 0, |
| &Body{ |
| Attributes: Attributes{ |
| "a": { |
| Name: "a", |
| Expr: &IndexExpr{ |
| Collection: &FunctionCallExpr{ |
| Name: "sort", |
| Args: []Expression{ |
| &ScopeTraversalExpr{ |
| Traversal: hcl.Traversal{ |
| hcl.TraverseRoot{ |
| Name: "data", |
| SrcRange: hcl.Range{ |
| Filename: "", |
| Start: hcl.Pos{Line: 1, Column: 10, Byte: 9}, |
| End: hcl.Pos{Line: 1, Column: 14, Byte: 13}, |
| }, |
| }, |
| hcl.TraverseAttr{ |
| Name: "first", |
| SrcRange: hcl.Range{ |
| Filename: "", |
| Start: hcl.Pos{Line: 1, Column: 14, Byte: 13}, |
| End: hcl.Pos{Line: 1, Column: 20, Byte: 19}, |
| }, |
| }, |
| hcl.TraverseAttr{ |
| Name: "ref", |
| SrcRange: hcl.Range{ |
| Filename: "", |
| Start: hcl.Pos{Line: 1, Column: 20, Byte: 19}, |
| End: hcl.Pos{Line: 1, Column: 24, Byte: 23}, |
| }, |
| }, |
| hcl.TraverseAttr{ |
| Name: "attr", |
| SrcRange: hcl.Range{ |
| Filename: "", |
| Start: hcl.Pos{Line: 1, Column: 24, Byte: 23}, |
| End: hcl.Pos{Line: 1, Column: 29, Byte: 28}, |
| }, |
| }, |
| }, |
| SrcRange: hcl.Range{ |
| Filename: "", |
| Start: hcl.Pos{Line: 1, Column: 10, Byte: 9}, |
| End: hcl.Pos{Line: 1, Column: 29, Byte: 28}, |
| }, |
| }, |
| }, |
| ExpandFinal: false, |
| NameRange: hcl.Range{ |
| Filename: "", |
| Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, |
| End: hcl.Pos{Line: 1, Column: 9, Byte: 8}, |
| }, |
| OpenParenRange: hcl.Range{ |
| Filename: "", |
| Start: hcl.Pos{Line: 1, Column: 9, Byte: 8}, |
| End: hcl.Pos{Line: 1, Column: 10, Byte: 9}, |
| }, |
| CloseParenRange: hcl.Range{ |
| Filename: "", |
| Start: hcl.Pos{Line: 1, Column: 29, Byte: 28}, |
| End: hcl.Pos{Line: 1, Column: 30, Byte: 29}, |
| }, |
| }, |
| Key: &ScopeTraversalExpr{ |
| Traversal: hcl.Traversal{ |
| hcl.TraverseRoot{ |
| Name: "count", |
| SrcRange: hcl.Range{ |
| Filename: "", |
| Start: hcl.Pos{Line: 1, Column: 31, Byte: 30}, |
| End: hcl.Pos{Line: 1, Column: 36, Byte: 35}, |
| }, |
| }, |
| hcl.TraverseAttr{ |
| Name: "index", |
| SrcRange: hcl.Range{ |
| Filename: "", |
| Start: hcl.Pos{Line: 1, Column: 36, Byte: 35}, |
| End: hcl.Pos{Line: 1, Column: 42, Byte: 41}, |
| }, |
| }, |
| }, |
| SrcRange: hcl.Range{ |
| Filename: "", |
| Start: hcl.Pos{Line: 1, Column: 31, Byte: 30}, |
| End: hcl.Pos{Line: 1, Column: 42, Byte: 41}, |
| }, |
| }, |
| SrcRange: hcl.Range{ |
| Filename: "", |
| Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, |
| End: hcl.Pos{Line: 1, Column: 43, Byte: 42}, |
| }, |
| OpenRange: hcl.Range{ |
| Filename: "", |
| Start: hcl.Pos{Line: 1, Column: 30, Byte: 29}, |
| End: hcl.Pos{Line: 1, Column: 31, Byte: 30}, |
| }, |
| BracketRange: hcl.Range{ |
| Filename: "", |
| Start: hcl.Pos{Line: 1, Column: 30, Byte: 29}, |
| End: hcl.Pos{Line: 1, Column: 43, Byte: 42}, |
| }, |
| }, |
| SrcRange: hcl.Range{ |
| Filename: "", |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 43, Byte: 42}, |
| }, |
| NameRange: hcl.Range{ |
| Filename: "", |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 2, Byte: 1}, |
| }, |
| EqualsRange: hcl.Range{ |
| Filename: "", |
| Start: hcl.Pos{Line: 1, Column: 3, Byte: 2}, |
| End: hcl.Pos{Line: 1, Column: 4, Byte: 3}, |
| }, |
| }, |
| }, |
| Blocks: Blocks{}, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 43}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 2, Column: 1, Byte: 43}, |
| End: hcl.Pos{Line: 2, Column: 1, Byte: 43}, |
| }, |
| }, |
| }, |
| { |
| `block "unterminated_string "name" {}`, |
| 2, // "Invalid string literal" and "Invalid block definition" |
| &Body{ |
| Attributes: Attributes{}, |
| Blocks: Blocks{ |
| &Block{ |
| Type: "block", |
| Labels: []string{"unterminated_string ", "name", " {}"}, |
| Body: &Body{ |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| }, |
| }, |
| |
| TypeRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| }, |
| LabelRanges: []hcl.Range{ |
| { |
| Start: hcl.Pos{Line: 1, Column: 7, Byte: 6}, |
| End: hcl.Pos{Line: 1, Column: 29, Byte: 28}, |
| }, |
| { |
| Start: hcl.Pos{Line: 1, Column: 29, Byte: 28}, |
| End: hcl.Pos{Line: 1, Column: 33, Byte: 32}, |
| }, |
| { |
| Start: hcl.Pos{Line: 1, Column: 33, Byte: 32}, |
| End: hcl.Pos{Line: 1, Column: 37, Byte: 36}, |
| }, |
| }, |
| OpenBraceRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| }, |
| CloseBraceRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| }, |
| }, |
| }, |
| SrcRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 37, Byte: 36}, |
| }, |
| EndRange: hcl.Range{ |
| Start: hcl.Pos{Line: 1, Column: 37, Byte: 36}, |
| End: hcl.Pos{Line: 1, Column: 37, Byte: 36}, |
| }, |
| }, |
| }, |
| } |
| |
| for _, test := range tests { |
| t.Run(test.input, func(t *testing.T) { |
| t.Logf("\n%s", test.input) |
| file, diags := ParseConfig([]byte(test.input), "", hcl.Pos{Byte: 0, Line: 1, Column: 1}) |
| if len(diags) != test.diagCount { |
| t.Errorf("wrong number of diagnostics %d; want %d", len(diags), test.diagCount) |
| for _, diag := range diags { |
| t.Logf(" - %s", diag.Error()) |
| } |
| } |
| |
| got := file.Body |
| |
| if diff := deep.Equal(got, test.want); diff != nil { |
| for _, problem := range diff { |
| t.Errorf(problem) |
| } |
| } |
| }) |
| } |
| } |
| |
| func TestParseConfigDiagnostics(t *testing.T) { |
| // This test function is a variant of TestParseConfig which tests for |
| // specific error messages for certain kinds of invalid input where we |
| // intend to produce a particular helpful error message. |
| |
| tests := map[string]struct { |
| input string |
| want hcl.Diagnostics |
| }{ |
| "unclosed multi-line block (no contents)": { |
| "blah {\n", |
| hcl.Diagnostics{ |
| { |
| Severity: hcl.DiagError, |
| Summary: "Unclosed configuration block", |
| Detail: "There is no closing brace for this block before the end of the file. This may be caused by incorrect brace nesting elsewhere in this file.", |
| Subject: &hcl.Range{ |
| Filename: "test.hcl", |
| Start: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| End: hcl.Pos{Line: 1, Column: 7, Byte: 6}, |
| }, |
| }, |
| }, |
| }, |
| "unclosed multi-line block (after one argument)": { |
| "blah {\n a = 1\n", |
| hcl.Diagnostics{ |
| { |
| Severity: hcl.DiagError, |
| Summary: "Unclosed configuration block", |
| Detail: "There is no closing brace for this block before the end of the file. This may be caused by incorrect brace nesting elsewhere in this file.", |
| Subject: &hcl.Range{ |
| Filename: "test.hcl", |
| Start: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| End: hcl.Pos{Line: 1, Column: 7, Byte: 6}, |
| }, |
| }, |
| }, |
| }, |
| "unclosed single-line block (no contents)": { |
| "blah {", |
| hcl.Diagnostics{ |
| { |
| Severity: hcl.DiagError, |
| Summary: "Unclosed configuration block", |
| Detail: "There is no closing brace for this block before the end of the file. This may be caused by incorrect brace nesting elsewhere in this file.", |
| Subject: &hcl.Range{ |
| Filename: "test.hcl", |
| Start: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| End: hcl.Pos{Line: 1, Column: 7, Byte: 6}, |
| }, |
| }, |
| }, |
| }, |
| "unclosed single-line block (after its argument)": { |
| "blah { a = 1", |
| hcl.Diagnostics{ |
| { |
| Severity: hcl.DiagError, |
| Summary: "Unclosed configuration block", |
| Detail: "There is no closing brace for this block before the end of the file. This may be caused by incorrect brace nesting elsewhere in this file.", |
| Subject: &hcl.Range{ |
| Filename: "test.hcl", |
| Start: hcl.Pos{Line: 1, Column: 6, Byte: 5}, |
| End: hcl.Pos{Line: 1, Column: 7, Byte: 6}, |
| }, |
| Context: &hcl.Range{ // In this case we can also report a context because we detect this error in a more convenient place in the parser |
| Filename: "test.hcl", |
| Start: hcl.Pos{Line: 1, Column: 1, Byte: 0}, |
| End: hcl.Pos{Line: 1, Column: 7, Byte: 6}, |
| }, |
| }, |
| }, |
| }, |
| "unclosed object constructor (before element separator)": { |
| `foo = { a = 1`, |
| hcl.Diagnostics{ |
| { |
| Severity: hcl.DiagError, |
| Summary: "Unterminated object constructor expression", |
| Detail: "There is no corresponding closing brace before the end of the file. This may be caused by incorrect brace nesting elsewhere in this file.", |
| Subject: &hcl.Range{ |
| Filename: "test.hcl", |
| Start: hcl.Pos{Line: 1, Column: 7, Byte: 6}, |
| End: hcl.Pos{Line: 1, Column: 8, Byte: 7}, |
| }, |
| }, |
| }, |
| }, |
| "unclosed object constructor (before equals)": { |
| `foo = { a `, |
| hcl.Diagnostics{ |
| { |
| Severity: hcl.DiagError, |
| Summary: "Unterminated object constructor expression", |
| Detail: "There is no corresponding closing brace before the end of the file. This may be caused by incorrect brace nesting elsewhere in this file.", |
| Subject: &hcl.Range{ |
| Filename: "test.hcl", |
| Start: hcl.Pos{Line: 1, Column: 7, Byte: 6}, |
| End: hcl.Pos{Line: 1, Column: 8, Byte: 7}, |
| }, |
| }, |
| }, |
| }, |
| "unclosed tuple constructor (before element separator)": { |
| `foo = [ a`, |
| hcl.Diagnostics{ |
| { |
| Severity: hcl.DiagError, |
| Summary: "Unterminated tuple constructor expression", |
| Detail: "There is no corresponding closing bracket before the end of the file. This may be caused by incorrect bracket nesting elsewhere in this file.", |
| Subject: &hcl.Range{ |
| Filename: "test.hcl", |
| Start: hcl.Pos{Line: 1, Column: 7, Byte: 6}, |
| End: hcl.Pos{Line: 1, Column: 8, Byte: 7}, |
| }, |
| }, |
| }, |
| }, |
| "unclosed function call": { |
| `foo = boop("a"`, |
| hcl.Diagnostics{ |
| { |
| Severity: hcl.DiagError, |
| Summary: "Unterminated function call", |
| Detail: "There is no closing parenthesis for this function call before the end of the file. This may be caused by incorrect parethesis nesting elsewhere in this file.", |
| Subject: &hcl.Range{ |
| Filename: "test.hcl", |
| Start: hcl.Pos{Line: 1, Column: 7, Byte: 6}, |
| End: hcl.Pos{Line: 1, Column: 12, Byte: 11}, |
| }, |
| }, |
| }, |
| }, |
| "unclosed grouping parentheses": { |
| `foo = (1`, |
| hcl.Diagnostics{ |
| { |
| Severity: hcl.DiagError, |
| Summary: "Unbalanced parentheses", |
| Detail: "Expected a closing parenthesis to terminate the expression.", |
| Subject: &hcl.Range{ |
| Filename: "test.hcl", |
| Start: hcl.Pos{Line: 1, Column: 9, Byte: 8}, |
| End: hcl.Pos{Line: 1, Column: 9, Byte: 8}, |
| }, |
| Context: &hcl.Range{ |
| Filename: "test.hcl", |
| Start: hcl.Pos{Line: 1, Column: 7, Byte: 6}, |
| End: hcl.Pos{Line: 1, Column: 9, Byte: 8}, |
| }, |
| }, |
| }, |
| }, |
| "unclosed template interpolation at EOF": { |
| `foo = "${a`, |
| hcl.Diagnostics{ |
| { |
| Severity: hcl.DiagError, |
| Summary: "Unclosed template interpolation sequence", |
| Detail: "There is no closing brace for this interpolation sequence before the end of the file. This might be caused by incorrect nesting inside the given expression.", |
| Subject: &hcl.Range{ |
| Filename: "test.hcl", |
| Start: hcl.Pos{Line: 1, Column: 8, Byte: 7}, |
| End: hcl.Pos{Line: 1, Column: 10, Byte: 9}, |
| }, |
| }, |
| }, |
| }, |
| "unclosed quoted template interpolation at closing quote": { |
| `foo = "${a"`, |
| hcl.Diagnostics{ |
| { |
| Severity: hcl.DiagError, |
| Summary: "Unclosed template interpolation sequence", |
| Detail: "There is no closing brace for this interpolation sequence before the end of the quoted template. This might be caused by incorrect nesting inside the given expression.", |
| Subject: &hcl.Range{ |
| Filename: "test.hcl", |
| Start: hcl.Pos{Line: 1, Column: 8, Byte: 7}, |
| End: hcl.Pos{Line: 1, Column: 10, Byte: 9}, |
| }, |
| }, |
| }, |
| }, |
| "unclosed quoted template at literal part": { |
| `foo = "${a}`, |
| hcl.Diagnostics{ |
| { |
| Severity: hcl.DiagError, |
| Summary: "Unterminated template string", |
| Detail: "No closing marker was found for the string.", |
| Subject: &hcl.Range{ |
| Filename: "test.hcl", |
| Start: hcl.Pos{Line: 1, Column: 12, Byte: 11}, |
| End: hcl.Pos{Line: 1, Column: 12, Byte: 11}, |
| }, |
| Context: &hcl.Range{ |
| Filename: "test.hcl", |
| Start: hcl.Pos{Line: 1, Column: 8, Byte: 7}, |
| End: hcl.Pos{Line: 1, Column: 12, Byte: 11}, |
| }, |
| }, |
| }, |
| }, |
| |
| // Some of our "unclosed" situations happen at a less convenient time |
| // when we only know we're waiting for an expression, so those get |
| // an error message with much less context. |
| "unclosed object constructor (before any expression)": { |
| `foo = {`, |
| hcl.Diagnostics{ |
| { |
| Severity: hcl.DiagError, |
| Summary: "Missing expression", |
| Detail: "Expected the start of an expression, but found the end of the file.", |
| Subject: &hcl.Range{ |
| Filename: "test.hcl", |
| Start: hcl.Pos{Line: 1, Column: 8, Byte: 7}, |
| End: hcl.Pos{Line: 1, Column: 8, Byte: 7}, |
| }, |
| }, |
| }, |
| }, |
| "unclosed tuple constructor (before any expression)": { |
| `foo = [`, |
| hcl.Diagnostics{ |
| { |
| Severity: hcl.DiagError, |
| Summary: "Missing expression", |
| Detail: "Expected the start of an expression, but found the end of the file.", |
| Subject: &hcl.Range{ |
| Filename: "test.hcl", |
| Start: hcl.Pos{Line: 1, Column: 8, Byte: 7}, |
| End: hcl.Pos{Line: 1, Column: 8, Byte: 7}, |
| }, |
| }, |
| }, |
| }, |
| "unclosed function call (before any argument)": { |
| `foo = foo(`, |
| hcl.Diagnostics{ |
| { |
| Severity: hcl.DiagError, |
| Summary: "Missing expression", |
| Detail: "Expected the start of an expression, but found the end of the file.", |
| Subject: &hcl.Range{ |
| Filename: "test.hcl", |
| Start: hcl.Pos{Line: 1, Column: 11, Byte: 10}, |
| End: hcl.Pos{Line: 1, Column: 11, Byte: 10}, |
| }, |
| }, |
| }, |
| }, |
| } |
| |
| for name, test := range tests { |
| t.Run(name, func(t *testing.T) { |
| t.Logf("\n%s", test.input) |
| _, diags := ParseConfig([]byte(test.input), "test.hcl", hcl.InitialPos) |
| |
| if diff := deep.Equal(diags, test.want); diff != nil { |
| for _, problem := range diff { |
| t.Errorf(problem) |
| } |
| } |
| }) |
| } |
| } |