4 "github.com/hashicorp/hcl2/hcl"
7 // -----------------------------------------------------------------------------
8 // The methods in this file are all optional extension methods that serve to
9 // implement the methods of the same name on *hcl.File when its root body
10 // is provided by this package.
11 // -----------------------------------------------------------------------------
13 // BlocksAtPos implements the method of the same name for an *hcl.File that
14 // is backed by a *Body.
15 func (b *Body) BlocksAtPos(pos hcl.Pos) []*hcl.Block {
16 list, _ := b.blocksAtPos(pos, true)
20 // InnermostBlockAtPos implements the method of the same name for an *hcl.File
21 // that is backed by a *Body.
22 func (b *Body) InnermostBlockAtPos(pos hcl.Pos) *hcl.Block {
23 _, innermost := b.blocksAtPos(pos, false)
24 return innermost.AsHCLBlock()
27 // OutermostBlockAtPos implements the method of the same name for an *hcl.File
28 // that is backed by a *Body.
29 func (b *Body) OutermostBlockAtPos(pos hcl.Pos) *hcl.Block {
30 return b.outermostBlockAtPos(pos).AsHCLBlock()
33 // blocksAtPos is the internal engine of both BlocksAtPos and
34 // InnermostBlockAtPos, which both need to do the same logic but return a
35 // differently-shaped result.
37 // list is nil if makeList is false, avoiding an allocation. Innermost is
38 // always set, and if the returned list is non-nil it will always match the
39 // final element from that list.
40 func (b *Body) blocksAtPos(pos hcl.Pos, makeList bool) (list []*hcl.Block, innermost *Block) {
45 for _, block := range current.Blocks {
46 wholeRange := hcl.RangeBetween(block.TypeRange, block.CloseBraceRange)
47 if wholeRange.ContainsPos(pos) {
50 list = append(list, innermost.AsHCLBlock())
57 // If we fall out here then none of the current body's nested blocks
58 // contain the position we are looking for, and so we're done.
65 // outermostBlockAtPos is the internal version of OutermostBlockAtPos that
66 // returns a hclsyntax.Block rather than an hcl.Block, allowing for further
67 // analysis if necessary.
68 func (b *Body) outermostBlockAtPos(pos hcl.Pos) *Block {
69 // This is similar to blocksAtPos, but simpler because we know it only
70 // ever needs to search the first level of nested blocks.
72 for _, block := range b.Blocks {
73 wholeRange := hcl.RangeBetween(block.TypeRange, block.CloseBraceRange)
74 if wholeRange.ContainsPos(pos) {
82 // AttributeAtPos implements the method of the same name for an *hcl.File
83 // that is backed by a *Body.
84 func (b *Body) AttributeAtPos(pos hcl.Pos) *hcl.Attribute {
85 return b.attributeAtPos(pos).AsHCLAttribute()
88 // attributeAtPos is the internal version of AttributeAtPos that returns a
89 // hclsyntax.Block rather than an hcl.Block, allowing for further analysis if
91 func (b *Body) attributeAtPos(pos hcl.Pos) *Attribute {
93 _, block := b.blocksAtPos(pos, false)
95 searchBody = block.Body
98 for _, attr := range searchBody.Attributes {
99 if attr.SrcRange.ContainsPos(pos) {
107 // OutermostExprAtPos implements the method of the same name for an *hcl.File
108 // that is backed by a *Body.
109 func (b *Body) OutermostExprAtPos(pos hcl.Pos) hcl.Expression {
110 attr := b.attributeAtPos(pos)
114 if !attr.Expr.Range().ContainsPos(pos) {