diff options
Diffstat (limited to 'vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/structure_at_pos.go')
-rw-r--r-- | vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/structure_at_pos.go | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/structure_at_pos.go b/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/structure_at_pos.go new file mode 100644 index 0000000..d8f023b --- /dev/null +++ b/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/structure_at_pos.go | |||
@@ -0,0 +1,118 @@ | |||
1 | package hclsyntax | ||
2 | |||
3 | import ( | ||
4 | "github.com/hashicorp/hcl2/hcl" | ||
5 | ) | ||
6 | |||
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 | // ----------------------------------------------------------------------------- | ||
12 | |||
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) | ||
17 | return list | ||
18 | } | ||
19 | |||
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() | ||
25 | } | ||
26 | |||
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() | ||
31 | } | ||
32 | |||
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. | ||
36 | // | ||
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) { | ||
41 | current := b | ||
42 | |||
43 | Blocks: | ||
44 | for current != nil { | ||
45 | for _, block := range current.Blocks { | ||
46 | wholeRange := hcl.RangeBetween(block.TypeRange, block.CloseBraceRange) | ||
47 | if wholeRange.ContainsPos(pos) { | ||
48 | innermost = block | ||
49 | if makeList { | ||
50 | list = append(list, innermost.AsHCLBlock()) | ||
51 | } | ||
52 | current = block.Body | ||
53 | continue Blocks | ||
54 | } | ||
55 | } | ||
56 | |||
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. | ||
59 | break | ||
60 | } | ||
61 | |||
62 | return | ||
63 | } | ||
64 | |||
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. | ||
71 | |||
72 | for _, block := range b.Blocks { | ||
73 | wholeRange := hcl.RangeBetween(block.TypeRange, block.CloseBraceRange) | ||
74 | if wholeRange.ContainsPos(pos) { | ||
75 | return block | ||
76 | } | ||
77 | } | ||
78 | |||
79 | return nil | ||
80 | } | ||
81 | |||
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() | ||
86 | } | ||
87 | |||
88 | // attributeAtPos is the internal version of AttributeAtPos that returns a | ||
89 | // hclsyntax.Block rather than an hcl.Block, allowing for further analysis if | ||
90 | // necessary. | ||
91 | func (b *Body) attributeAtPos(pos hcl.Pos) *Attribute { | ||
92 | searchBody := b | ||
93 | _, block := b.blocksAtPos(pos, false) | ||
94 | if block != nil { | ||
95 | searchBody = block.Body | ||
96 | } | ||
97 | |||
98 | for _, attr := range searchBody.Attributes { | ||
99 | if attr.SrcRange.ContainsPos(pos) { | ||
100 | return attr | ||
101 | } | ||
102 | } | ||
103 | |||
104 | return nil | ||
105 | } | ||
106 | |||
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) | ||
111 | if attr == nil { | ||
112 | return nil | ||
113 | } | ||
114 | if !attr.Expr.Range().ContainsPos(pos) { | ||
115 | return nil | ||
116 | } | ||
117 | return attr.Expr | ||
118 | } | ||