6c4344623b
The main HCL package is more visible this way, and so it's easier than having to pick it out from dozens of other package directories.
118 lines
3.0 KiB
Go
118 lines
3.0 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
|
|
"github.com/hashicorp/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
|
|
}
|