forked from hashicorp/hcl
/
traversals.go
117 lines (101 loc) · 2.99 KB
/
traversals.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package main
import (
"fmt"
"reflect"
"github.com/apio-project/hcl/v2"
)
func findTraversalSpec(got hcl.Traversal, candidates []*TestFileExpectTraversal) *TestFileExpectTraversal {
for _, candidate := range candidates {
if traversalsAreEquivalent(candidate.Traversal, got) {
return candidate
}
}
return nil
}
func findTraversalForSpec(want *TestFileExpectTraversal, have []hcl.Traversal) hcl.Traversal {
for _, candidate := range have {
if traversalsAreEquivalent(candidate, want.Traversal) {
return candidate
}
}
return nil
}
func traversalsAreEquivalent(a, b hcl.Traversal) bool {
if len(a) != len(b) {
return false
}
for i := range a {
aStep := a[i]
bStep := b[i]
if reflect.TypeOf(aStep) != reflect.TypeOf(bStep) {
return false
}
// We can now assume that both are of the same type.
switch ts := aStep.(type) {
case hcl.TraverseRoot:
if bStep.(hcl.TraverseRoot).Name != ts.Name {
return false
}
case hcl.TraverseAttr:
if bStep.(hcl.TraverseAttr).Name != ts.Name {
return false
}
case hcl.TraverseIndex:
if !bStep.(hcl.TraverseIndex).Key.RawEquals(ts.Key) {
return false
}
default:
return false
}
}
return true
}
// checkTraversalsMatch determines if a given traversal matches the given
// expectation, which must've been produced by an earlier call to
// findTraversalSpec for the same traversal.
func checkTraversalsMatch(got hcl.Traversal, filename string, match *TestFileExpectTraversal) hcl.Diagnostics {
var diags hcl.Diagnostics
gotRng := got.SourceRange()
wantRng := match.Range
if got, want := gotRng.Filename, filename; got != want {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Incorrect filename in detected traversal",
Detail: fmt.Sprintf(
"Filename was reported as %q, but was expecting %q.",
got, want,
),
Subject: match.Traversal.SourceRange().Ptr(),
})
return diags
}
// If we have the expected filename then we'll use that to construct the
// full "want range" here so that we can use it to point to the appropriate
// location in the remaining diagnostics.
wantRng.Filename = filename
if got, want := gotRng.Start, wantRng.Start; got != want {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Incorrect start position in detected traversal",
Detail: fmt.Sprintf(
"Start position was reported as line %d column %d byte %d, but was expecting line %d column %d byte %d.",
got.Line, got.Column, got.Byte,
want.Line, want.Column, want.Byte,
),
Subject: &wantRng,
})
}
if got, want := gotRng.End, wantRng.End; got != want {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Incorrect end position in detected traversal",
Detail: fmt.Sprintf(
"End position was reported as line %d column %d byte %d, but was expecting line %d column %d byte %d.",
got.Line, got.Column, got.Byte,
want.Line, want.Column, want.Byte,
),
Subject: &wantRng,
})
}
return diags
}