mirror of https://github.com/databricks/cli.git
55 lines
1.3 KiB
Go
55 lines
1.3 KiB
Go
|
package schema
|
||
|
|
||
|
import (
|
||
|
"container/list"
|
||
|
"fmt"
|
||
|
"reflect"
|
||
|
)
|
||
|
|
||
|
type tracker struct {
|
||
|
// Types encountered in current path during the recursive traversal. Used to
|
||
|
// check for cycles
|
||
|
seenTypes map[reflect.Type]struct{}
|
||
|
|
||
|
// List of field names encountered in current path during the recursive traversal.
|
||
|
// Used to hydrate errors with path to the exact node where error occured.
|
||
|
//
|
||
|
// The field names here are the first tag in the json tags of struct field.
|
||
|
debugTrace *list.List
|
||
|
}
|
||
|
|
||
|
func newTracker() *tracker {
|
||
|
return &tracker{
|
||
|
seenTypes: map[reflect.Type]struct{}{},
|
||
|
debugTrace: list.New(),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (t *tracker) errWithTrace(prefix string) error {
|
||
|
traceString := "root"
|
||
|
curr := t.debugTrace.Front()
|
||
|
for curr != nil {
|
||
|
if curr.Value.(string) != "" {
|
||
|
traceString += " -> " + curr.Value.(string)
|
||
|
}
|
||
|
curr = curr.Next()
|
||
|
}
|
||
|
return fmt.Errorf("[ERROR] " + prefix + ". traversal trace: " + traceString)
|
||
|
}
|
||
|
|
||
|
func (t *tracker) hasCycle(golangType reflect.Type) bool {
|
||
|
_, ok := t.seenTypes[golangType]
|
||
|
return ok
|
||
|
}
|
||
|
|
||
|
func (t *tracker) push(nodeType reflect.Type, jsonName string) {
|
||
|
t.seenTypes[nodeType] = struct{}{}
|
||
|
t.debugTrace.PushBack(jsonName)
|
||
|
}
|
||
|
|
||
|
func (t *tracker) pop(nodeType reflect.Type) {
|
||
|
back := t.debugTrace.Back()
|
||
|
t.debugTrace.Remove(back)
|
||
|
delete(t.seenTypes, nodeType)
|
||
|
}
|