Preserve inherited source origins and transfer evidence
This commit is contained in:
@@ -8,34 +8,44 @@ import (
|
||||
)
|
||||
|
||||
type inheritanceWalker struct {
|
||||
root **document.Node
|
||||
limits projectionLimits
|
||||
transfers []inheritanceTransfer
|
||||
controls []inheritanceControl
|
||||
root **document.Node
|
||||
origins map[string]Origin
|
||||
limits projectionLimits
|
||||
transfers []inheritanceTransfer
|
||||
controls []inheritanceControl
|
||||
replacements []inheritanceReplacement
|
||||
}
|
||||
|
||||
// expandInheritanceTree resolves each destination scope after its enclosing
|
||||
// relationships. It remains a private, test-only operation until the loading
|
||||
// lifecycle also carries its complete provenance and inspection evidence.
|
||||
func expandInheritanceTree(input *document.Node, limits projectionLimits) (*inheritanceScope, []Diagnostic) {
|
||||
return expandInheritanceWithOrigins(input, nil, limits)
|
||||
}
|
||||
|
||||
func expandInheritanceWithOrigins(input *document.Node, inputOrigins map[string]Origin, limits projectionLimits) (*inheritanceScope, []Diagnostic) {
|
||||
if input == nil || input.Kind != document.Mapping {
|
||||
return nil, []Diagnostic{{Code: CodeInheritanceInvalid, Severity: SeverityError,
|
||||
Message: "inheritance requires a mapping document root"}}
|
||||
}
|
||||
root := input
|
||||
walker := inheritanceWalker{root: &root, limits: limits}
|
||||
walker := inheritanceWalker{root: &root, limits: limits, origins: cloneOriginIndex(inputOrigins)}
|
||||
if problem := walker.visit(&root, Path{}, true); problem != nil {
|
||||
return nil, []Diagnostic{*problem}
|
||||
}
|
||||
if problem := inheritanceFinalBudget(root, limits); problem != nil {
|
||||
return nil, []Diagnostic{*problem}
|
||||
}
|
||||
return &inheritanceScope{root: root, transfers: walker.transfers, controls: walker.controls}, nil
|
||||
return &inheritanceScope{
|
||||
root: root, origins: walker.origins, transfers: walker.transfers,
|
||||
controls: walker.controls, replacements: walker.replacements,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (w *inheritanceWalker) visit(node **document.Node, path Path, unscoped bool) *Diagnostic {
|
||||
switch (*node).Kind {
|
||||
case document.Mapping:
|
||||
original := *node
|
||||
if unscoped {
|
||||
reference, found := inheritanceDirective(*node)
|
||||
if found {
|
||||
@@ -49,16 +59,22 @@ func (w *inheritanceWalker) visit(node **document.Node, path Path, unscoped bool
|
||||
w.controls = append(w.controls, inheritanceControl{
|
||||
path: referencePath, locations: []Location{location}, cancelled: true,
|
||||
})
|
||||
deleteOriginSubtree(w.origins, referencePath, reference.Value)
|
||||
*node = withoutInheritanceDirective(*node)
|
||||
}
|
||||
}
|
||||
resolved, diagnostics := expandSiblingDefinitionsWithLimits(*node, path, w.limits)
|
||||
resolved, diagnostics := expandSiblingDefinitionsWithOrigins(*node, path, w.limits, w.origins)
|
||||
if len(diagnostics) != 0 {
|
||||
return &diagnostics[0]
|
||||
}
|
||||
*node = resolved.root
|
||||
deleteOriginSubtree(w.origins, path, original)
|
||||
for pointer, origin := range resolved.origins {
|
||||
w.origins[pointer] = origin
|
||||
}
|
||||
w.transfers = append(w.transfers, resolved.transfers...)
|
||||
w.controls = append(w.controls, resolved.controls...)
|
||||
w.replacements = append(w.replacements, resolved.replacements...)
|
||||
if !inheritanceLowerBoundWithin(*w.root, w.limits.nodes) {
|
||||
problem := inheritanceBudgetDiagnostic(path, (*node).Location)
|
||||
return &problem
|
||||
|
||||
Reference in New Issue
Block a user