]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/variables.go
Upgrade to 0.12
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / hashicorp / hcl2 / hcl / hclsyntax / variables.go
1 package hclsyntax
2
3 import (
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.
11 func 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.
27 type variablesWalker struct {
28 Callback func(hcl.Traversal)
29 localScopes []map[string]struct{}
30 }
31
32 func (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
55 func (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.
73 type ChildScope struct {
74 LocalNames map[string]struct{}
75 Expr Expression
76 }
77
78 func (e ChildScope) walkChildNodes(w internalWalkFunc) {
79 w(e.Expr)
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.
84 func (e ChildScope) Range() hcl.Range {
85 return e.Expr.Range()
86 }