diff --git a/hclsyntax/expression.go b/hclsyntax/expression.go index 963ed77..0821ce3 100644 --- a/hclsyntax/expression.go +++ b/hclsyntax/expression.go @@ -615,8 +615,9 @@ type IndexExpr struct { Collection Expression Key Expression - SrcRange hcl.Range - OpenRange hcl.Range + SrcRange hcl.Range + OpenRange hcl.Range + BracketRange hcl.Range } func (e *IndexExpr) walkChildNodes(w internalWalkFunc) { @@ -631,7 +632,7 @@ func (e *IndexExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { diags = append(diags, collDiags...) diags = append(diags, keyDiags...) - val, indexDiags := hcl.Index(coll, key, &e.SrcRange) + val, indexDiags := hcl.Index(coll, key, &e.BracketRange) setDiagEvalContext(indexDiags, e, ctx) diags = append(diags, indexDiags...) return val, diags diff --git a/hclsyntax/parser.go b/hclsyntax/parser.go index 6fb284a..f67d989 100644 --- a/hclsyntax/parser.go +++ b/hclsyntax/parser.go @@ -760,7 +760,7 @@ Traversal: Each: travExpr, Item: itemExpr, - SrcRange: hcl.RangeBetween(dot.Range, lastRange), + SrcRange: hcl.RangeBetween(from.Range(), lastRange), MarkerRange: hcl.RangeBetween(dot.Range, marker.Range), } @@ -819,7 +819,7 @@ Traversal: Each: travExpr, Item: itemExpr, - SrcRange: hcl.RangeBetween(open.Range, travExpr.Range()), + SrcRange: hcl.RangeBetween(from.Range(), travExpr.Range()), MarkerRange: hcl.RangeBetween(open.Range, close.Range), } @@ -867,8 +867,9 @@ Traversal: Collection: ret, Key: keyExpr, - SrcRange: rng, - OpenRange: open.Range, + SrcRange: hcl.RangeBetween(from.Range(), rng), + OpenRange: open.Range, + BracketRange: rng, } } } @@ -899,7 +900,7 @@ func makeRelativeTraversal(expr Expression, next hcl.Traverser, rng hcl.Range) E return &RelativeTraversalExpr{ Source: expr, Traversal: hcl.Traversal{next}, - SrcRange: rng, + SrcRange: hcl.RangeBetween(expr.Range(), rng), } } } diff --git a/hclsyntax/parser_test.go b/hclsyntax/parser_test.go index 3df29b7..45b5645 100644 --- a/hclsyntax/parser_test.go +++ b/hclsyntax/parser_test.go @@ -1834,13 +1834,17 @@ block "valid" {} }, }, SrcRange: hcl.Range{ - Start: hcl.Pos{Line: 1, Column: 26, Byte: 25}, + 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}, @@ -1872,6 +1876,91 @@ block "valid" {} }, }, }, + { + "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, @@ -2353,7 +2442,7 @@ block "valid" {} }, SrcRange: hcl.Range{ Filename: "", - Start: hcl.Pos{Line: 1, Column: 30, Byte: 29}, + Start: hcl.Pos{Line: 1, Column: 5, Byte: 4}, End: hcl.Pos{Line: 1, Column: 43, Byte: 42}, }, OpenRange: hcl.Range{ @@ -2361,6 +2450,11 @@ block "valid" {} 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: "", diff --git a/hclwrite/parser_test.go b/hclwrite/parser_test.go index 8ac82f5..28b5380 100644 --- a/hclwrite/parser_test.go +++ b/hclwrite/parser_test.go @@ -555,6 +555,150 @@ func TestParse(t *testing.T) { }, }, }, + { + "a = foo[bar]\n", + TestTreeNode{ + Type: "Body", + Children: []TestTreeNode{ + { + Type: "Attribute", + Children: []TestTreeNode{ + { + Type: "comments", + }, + { + Type: "identifier", + Val: "a", + }, + { + Type: "Tokens", + Val: " =", + }, + { + Type: "Expression", + Children: []TestTreeNode{ + { + Type: "Traversal", + Children: []TestTreeNode{ + { + Type: "TraverseName", + Children: []TestTreeNode{ + { + Type: "identifier", + Val: " foo", + }, + }, + }, + }, + }, + { + Type: "Tokens", + Val: "[", + }, + { + Type: "Traversal", + Children: []TestTreeNode{ + { + Type: "TraverseName", + Children: []TestTreeNode{ + { + Type: "identifier", + Val: "bar", + }, + }, + }, + }, + }, + { + Type: "Tokens", + Val: "]", + }, + }, + }, + { + Type: "comments", + }, + { + Type: "Tokens", + Val: "\n", + }, + }, + }, + }, + }, + }, + { + "a = foo[bar].baz\n", + TestTreeNode{ + Type: "Body", + Children: []TestTreeNode{ + { + Type: "Attribute", + Children: []TestTreeNode{ + { + Type: "comments", + }, + { + Type: "identifier", + Val: "a", + }, + { + Type: "Tokens", + Val: " =", + }, + { + Type: "Expression", + Children: []TestTreeNode{ + { + Type: "Traversal", + Children: []TestTreeNode{ + { + Type: "TraverseName", + Children: []TestTreeNode{ + { + Type: "identifier", + Val: " foo", + }, + }, + }, + }, + }, + { + Type: "Tokens", + Val: "[", + }, + { + Type: "Traversal", + Children: []TestTreeNode{ + { + Type: "TraverseName", + Children: []TestTreeNode{ + { + Type: "identifier", + Val: "bar", + }, + }, + }, + }, + }, + { + Type: "Tokens", + Val: "].baz", + }, + }, + }, + { + Type: "comments", + }, + { + Type: "Tokens", + Val: "\n", + }, + }, + }, + }, + }, + }, } for _, test := range tests {