aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/variables.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/variables.go')
-rw-r--r--vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/variables.go86
1 files changed, 86 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/variables.go b/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/variables.go
new file mode 100644
index 0000000..eeee1a5
--- /dev/null
+++ b/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/variables.go
@@ -0,0 +1,86 @@
1package hclsyntax
2
3import (
4 "github.com/hashicorp/hcl2/hcl"
5)
6
7// Variables returns all of the variables referenced within a given experssion.
8//
9// This is the implementation of the "Variables" method on every native
10// expression.
11func Variables(expr Expression) []hcl.Traversal {
12 var vars []hcl.Traversal
13
14 walker := &variablesWalker{
15 Callback: func(t hcl.Traversal) {
16 vars = append(vars, t)
17 },
18 }
19
20 Walk(expr, walker)
21
22 return vars
23}
24
25// variablesWalker is a Walker implementation that calls its callback for any
26// root scope traversal found while walking.
27type variablesWalker struct {
28 Callback func(hcl.Traversal)
29 localScopes []map[string]struct{}
30}
31
32func (w *variablesWalker) Enter(n Node) hcl.Diagnostics {
33 switch tn := n.(type) {
34 case *ScopeTraversalExpr:
35 t := tn.Traversal
36
37 // Check if the given root name appears in any of the active
38 // local scopes. We don't want to return local variables here, since
39 // the goal of walking variables is to tell the calling application
40 // which names it needs to populate in the _root_ scope.
41 name := t.RootName()
42 for _, names := range w.localScopes {
43 if _, localized := names[name]; localized {
44 return nil
45 }
46 }
47
48 w.Callback(t)
49 case ChildScope:
50 w.localScopes = append(w.localScopes, tn.LocalNames)
51 }
52 return nil
53}
54
55func (w *variablesWalker) Exit(n Node) hcl.Diagnostics {
56 switch n.(type) {
57 case ChildScope:
58 // pop the latest local scope, assuming that the walker will
59 // behave symmetrically as promised.
60 w.localScopes = w.localScopes[:len(w.localScopes)-1]
61 }
62 return nil
63}
64
65// ChildScope is a synthetic AST node that is visited during a walk to
66// indicate that its descendent will be evaluated in a child scope, which
67// may mask certain variables from the parent scope as locals.
68//
69// ChildScope nodes don't really exist in the AST, but are rather synthesized
70// on the fly during walk. Therefore it doesn't do any good to transform them;
71// instead, transform either parent node that created a scope or the expression
72// that the child scope struct wraps.
73type ChildScope struct {
74 LocalNames map[string]struct{}
75 Expr *Expression // pointer because it can be replaced on walk
76}
77
78func (e ChildScope) walkChildNodes(w internalWalkFunc) {
79 *(e.Expr) = w(*(e.Expr)).(Expression)
80}
81
82// Range returns the range of the expression that the ChildScope is
83// encapsulating. It isn't really very useful to call Range on a ChildScope.
84func (e ChildScope) Range() hcl.Range {
85 return (*e.Expr).Range()
86}