terraform-provider-google/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/structure_at_pos.go
Paddy 961c878e0d Switch to using Go modules. (#2679)
Switch to using Go modules.

This migrates our vendor.json to use Go 1.11's modules system, and
replaces the vendor folder with the output of go mod vendor.

The vendored code should remain basically the same; I believe some
tree shaking of packages and support scripts/licenses/READMEs/etc.
happened.

This also fixes Travis and our Makefile to no longer use govendor.
2018-12-20 17:22:22 -08:00

119 lines
3.5 KiB
Go

package hclsyntax
import (
"github.com/hashicorp/hcl2/hcl"
)
// -----------------------------------------------------------------------------
// The methods in this file are all optional extension methods that serve to
// implement the methods of the same name on *hcl.File when its root body
// is provided by this package.
// -----------------------------------------------------------------------------
// BlocksAtPos implements the method of the same name for an *hcl.File that
// is backed by a *Body.
func (b *Body) BlocksAtPos(pos hcl.Pos) []*hcl.Block {
list, _ := b.blocksAtPos(pos, true)
return list
}
// InnermostBlockAtPos implements the method of the same name for an *hcl.File
// that is backed by a *Body.
func (b *Body) InnermostBlockAtPos(pos hcl.Pos) *hcl.Block {
_, innermost := b.blocksAtPos(pos, false)
return innermost.AsHCLBlock()
}
// OutermostBlockAtPos implements the method of the same name for an *hcl.File
// that is backed by a *Body.
func (b *Body) OutermostBlockAtPos(pos hcl.Pos) *hcl.Block {
return b.outermostBlockAtPos(pos).AsHCLBlock()
}
// blocksAtPos is the internal engine of both BlocksAtPos and
// InnermostBlockAtPos, which both need to do the same logic but return a
// differently-shaped result.
//
// list is nil if makeList is false, avoiding an allocation. Innermost is
// always set, and if the returned list is non-nil it will always match the
// final element from that list.
func (b *Body) blocksAtPos(pos hcl.Pos, makeList bool) (list []*hcl.Block, innermost *Block) {
current := b
Blocks:
for current != nil {
for _, block := range current.Blocks {
wholeRange := hcl.RangeBetween(block.TypeRange, block.CloseBraceRange)
if wholeRange.ContainsPos(pos) {
innermost = block
if makeList {
list = append(list, innermost.AsHCLBlock())
}
current = block.Body
continue Blocks
}
}
// If we fall out here then none of the current body's nested blocks
// contain the position we are looking for, and so we're done.
break
}
return
}
// outermostBlockAtPos is the internal version of OutermostBlockAtPos that
// returns a hclsyntax.Block rather than an hcl.Block, allowing for further
// analysis if necessary.
func (b *Body) outermostBlockAtPos(pos hcl.Pos) *Block {
// This is similar to blocksAtPos, but simpler because we know it only
// ever needs to search the first level of nested blocks.
for _, block := range b.Blocks {
wholeRange := hcl.RangeBetween(block.TypeRange, block.CloseBraceRange)
if wholeRange.ContainsPos(pos) {
return block
}
}
return nil
}
// AttributeAtPos implements the method of the same name for an *hcl.File
// that is backed by a *Body.
func (b *Body) AttributeAtPos(pos hcl.Pos) *hcl.Attribute {
return b.attributeAtPos(pos).AsHCLAttribute()
}
// attributeAtPos is the internal version of AttributeAtPos that returns a
// hclsyntax.Block rather than an hcl.Block, allowing for further analysis if
// necessary.
func (b *Body) attributeAtPos(pos hcl.Pos) *Attribute {
searchBody := b
_, block := b.blocksAtPos(pos, false)
if block != nil {
searchBody = block.Body
}
for _, attr := range searchBody.Attributes {
if attr.SrcRange.ContainsPos(pos) {
return attr
}
}
return nil
}
// OutermostExprAtPos implements the method of the same name for an *hcl.File
// that is backed by a *Body.
func (b *Body) OutermostExprAtPos(pos hcl.Pos) hcl.Expression {
attr := b.attributeAtPos(pos)
if attr == nil {
return nil
}
if !attr.Expr.Range().ContainsPos(pos) {
return nil
}
return attr.Expr
}