Activate ordinary source collection declarations
This commit is contained in:
@@ -264,3 +264,72 @@ func disabledDirectiveDiagnostics(node *document.Node, path Path) []Diagnostic {
|
||||
}
|
||||
return diagnostics
|
||||
}
|
||||
|
||||
func disabledRootImportDiagnostics(node *document.Node) []Diagnostic {
|
||||
if node == nil || node.Kind != document.Mapping {
|
||||
return nil
|
||||
}
|
||||
var rootDirective *document.Node
|
||||
var rootLocation document.Location
|
||||
var foundRootDirective bool
|
||||
for index := range node.Mapping {
|
||||
if node.Mapping[index].Key == directiveKey {
|
||||
rootDirective = node.Mapping[index].Value
|
||||
rootLocation = node.Mapping[index].KeyLocation
|
||||
foundRootDirective = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if foundRootDirective {
|
||||
if rootDirective == nil || rootDirective.Kind != document.Mapping {
|
||||
return disabledDirectiveDiagnostic(rootLocation)
|
||||
}
|
||||
for _, directive := range rootDirective.Mapping {
|
||||
if directive.Key == "imports" {
|
||||
return disabledDirectiveDiagnostic(rootLocation)
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, entry := range node.Mapping {
|
||||
if entry.Key == directiveKey {
|
||||
continue
|
||||
}
|
||||
if diagnostic := disabledNestedDirectiveDiagnostics(entry.Value, Path{}.Key(entry.Key)); len(diagnostic) != 0 {
|
||||
return diagnostic
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func disabledNestedDirectiveDiagnostics(node *document.Node, path Path) []Diagnostic {
|
||||
if node.Kind == document.Mapping {
|
||||
for _, entry := range node.Mapping {
|
||||
childPath := path.Key(entry.Key)
|
||||
if entry.Key == directiveKey {
|
||||
location := Location{SourceID: entry.KeyLocation.SourceID, Line: entry.KeyLocation.Line, Column: entry.KeyLocation.Column}
|
||||
return []Diagnostic{{
|
||||
Code: CodeImportDisabled, Severity: SeverityError, Path: childPath,
|
||||
Message: "configuration directives require imports to be enabled", Primary: &location,
|
||||
}}
|
||||
}
|
||||
if diagnostics := disabledNestedDirectiveDiagnostics(entry.Value, childPath); len(diagnostics) != 0 {
|
||||
return diagnostics
|
||||
}
|
||||
}
|
||||
} else if node.Kind == document.Sequence {
|
||||
for index, child := range node.Sequence {
|
||||
if diagnostics := disabledNestedDirectiveDiagnostics(child, path.Index(index)); len(diagnostics) != 0 {
|
||||
return diagnostics
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func disabledDirectiveDiagnostic(location document.Location) []Diagnostic {
|
||||
public := Location{SourceID: location.SourceID, Line: location.Line, Column: location.Column}
|
||||
return []Diagnostic{{
|
||||
Code: CodeImportDisabled, Severity: SeverityError, Path: Keys(directiveKey),
|
||||
Message: "configuration directives require imports to be enabled", Primary: &public,
|
||||
}}
|
||||
}
|
||||
|
||||
@@ -46,12 +46,13 @@ type importAccounting struct {
|
||||
}
|
||||
|
||||
type importTraversal struct {
|
||||
access *filesystemAccess
|
||||
accounting *importAccounting
|
||||
limits importLimits
|
||||
rule *VersionRule
|
||||
versionState *sourceVersionState
|
||||
defaults importDefaults
|
||||
access *filesystemAccess
|
||||
accounting *importAccounting
|
||||
limits importLimits
|
||||
rule *VersionRule
|
||||
versionState *sourceVersionState
|
||||
directiveContext rootDirectiveContext
|
||||
defaults importDefaults
|
||||
|
||||
scope acquisitionScope
|
||||
itemScope bool
|
||||
@@ -166,12 +167,17 @@ func loadImportedWithAccessTrackedAndProcessingPolicyDeferred(access *filesystem
|
||||
if versionState != nil {
|
||||
defaults = snapshotImportDefaults(versionState.importDefaults)
|
||||
}
|
||||
directiveContext := rootDirectiveContextImportsOnly
|
||||
if processing != nil && processing.directiveContext != 0 {
|
||||
directiveContext = processing.directiveContext
|
||||
}
|
||||
state := importTraversal{
|
||||
access: access, accounting: accounting, limits: limits, rule: rule, versionState: versionState,
|
||||
defaults: defaults,
|
||||
scope: acquisitionScope{owner: mainNodeKey, destination: destination.clone()},
|
||||
sources: []SourceInfo{mainInfo},
|
||||
active: make(map[resourceIdentity]int), visited: visited,
|
||||
directiveContext: directiveContext,
|
||||
defaults: defaults,
|
||||
scope: acquisitionScope{owner: mainNodeKey, destination: destination.clone()},
|
||||
sources: []SourceInfo{mainInfo},
|
||||
active: make(map[resourceIdentity]int), visited: visited,
|
||||
importGraph: newImportInclusionGraph(),
|
||||
}
|
||||
if mainIsItem {
|
||||
@@ -231,6 +237,7 @@ func loadImportedWithAccessTrackedAndProcessingPolicyDeferred(access *filesystem
|
||||
source: cloneSourceInfo(mainInfo), payload: body, document: placed,
|
||||
identity: mainNodeKey, role: importRoleMain, scopeOwner: mainNodeKey,
|
||||
destination: destination.clone(), processing: processing,
|
||||
sequenceDeclarations: cloneSequenceDeclarations(sequenceDeclarations),
|
||||
})
|
||||
diagnostics = state.walkDeclarations(basePath, declarations, 0, destination)
|
||||
}
|
||||
@@ -627,23 +634,34 @@ func (s *importTraversal) visitPath(candidate selectedImportCandidate, spec impo
|
||||
var sequenceDeclarations []sequenceDeclarationSpec
|
||||
var diagnostics []Diagnostic
|
||||
var processing *sourceVersionProcessingResult
|
||||
directiveContext := s.directiveContext
|
||||
if directiveContext == 0 {
|
||||
directiveContext = rootDirectiveContextImportsOnly
|
||||
}
|
||||
if s.versionState != nil && s.versionState.mode != sourceVersionModeDefault {
|
||||
versionDestination := destination
|
||||
if s.itemScope {
|
||||
versionDestination = appendDestination(s.itemPrefix.Index(0), destination)
|
||||
}
|
||||
processed, failures := s.versionState.process(root, sourceVersionContribution, versionDestination, sourceID, policy.placement)
|
||||
processed, failures := s.versionState.processWithDirectiveContext(root, sourceVersionContribution, versionDestination, sourceID, policy.placement, directiveContext)
|
||||
if len(failures) != 0 {
|
||||
return failures
|
||||
}
|
||||
processing = &processed
|
||||
body, declarations = processed.payload, processed.imports
|
||||
} else {
|
||||
body, declarations, diagnostics = splitImportDirectives(root)
|
||||
if len(diagnostics) != 0 {
|
||||
return diagnostics
|
||||
versionDestination := destination
|
||||
if s.itemScope {
|
||||
versionDestination = appendDestination(s.itemPrefix.Index(0), destination)
|
||||
}
|
||||
processed := processSourceVersionWithDirectiveContext(root, s.rule, sourceVersionContribution, versionDestination, sourceVersionModeDefault, directiveContext)
|
||||
if len(processed.diagnostics) != 0 {
|
||||
return processed.diagnostics
|
||||
}
|
||||
processing = &processed
|
||||
body, declarations = processed.payload, processed.imports
|
||||
}
|
||||
sequenceDeclarations = cloneSequenceDeclarations(processing.sequences)
|
||||
placementDestination := destination
|
||||
mode := placementModeMapping
|
||||
if policy.placement == placementModeSequenceItem {
|
||||
|
||||
@@ -35,6 +35,7 @@ type Options[T any] struct {
|
||||
placementMode placementMode
|
||||
sequencePolicy sequencePolicy
|
||||
deferAssembly bool
|
||||
directiveContext rootDirectiveContext
|
||||
importDefaultsValidated bool
|
||||
}
|
||||
|
||||
@@ -174,6 +175,7 @@ func executeLoadRequest[T any](request loadRequest[T], secrets SecretBinding, lo
|
||||
mainOptions.Overrides = request.overrides
|
||||
if request.ordinary {
|
||||
mainOptions.Overlay = request.overlay
|
||||
mainOptions.directiveContext = rootDirectiveContextSource
|
||||
}
|
||||
|
||||
var schema *schemaDescriptor
|
||||
|
||||
@@ -123,13 +123,43 @@ func assembleBaseInputTrackedForRole[T any](source Source, options Options[T], d
|
||||
}
|
||||
return input, diagnostics
|
||||
}
|
||||
directiveContext := options.directiveContext
|
||||
if directiveContext == 0 {
|
||||
directiveContext = rootDirectiveContextImportsOnly
|
||||
}
|
||||
if !options.Imports && parsed.document != nil {
|
||||
if diagnostics := disabledDirectiveDiagnostics(parsed.document, Path{}); len(diagnostics) != 0 {
|
||||
return input, diagnostics
|
||||
var directiveDiagnostics []Diagnostic
|
||||
if directiveContext == rootDirectiveContextSource {
|
||||
directiveDiagnostics = disabledRootImportDiagnostics(parsed.document)
|
||||
} else {
|
||||
directiveDiagnostics = disabledDirectiveDiagnostics(parsed.document, Path{})
|
||||
}
|
||||
if len(directiveDiagnostics) != 0 {
|
||||
return input, directiveDiagnostics
|
||||
}
|
||||
}
|
||||
var versionProcessing *sourceVersionProcessingResult
|
||||
if versionState != nil && versionState.mode != sourceVersionModeDefault {
|
||||
if directiveContext == rootDirectiveContextSource {
|
||||
var sourceID string
|
||||
if parsed.source != nil {
|
||||
sourceID = parsed.source.ID
|
||||
}
|
||||
var processed sourceVersionProcessingResult
|
||||
var failures []Diagnostic
|
||||
if versionState != nil {
|
||||
processed, failures = versionState.processWithDirectiveContext(parsed.document, role, destination, sourceID, options.placementMode, directiveContext)
|
||||
} else {
|
||||
processed = processSourceVersionWithDirectiveContext(parsed.document, options.Definition.Version, role, destination, sourceVersionModeDefault, directiveContext)
|
||||
failures = processed.diagnostics
|
||||
}
|
||||
if len(failures) != 0 {
|
||||
return input, failures
|
||||
}
|
||||
versionProcessing = &processed
|
||||
if role == sourceVersionMain && versionState != nil {
|
||||
versionState.mainProcessing = &processed
|
||||
}
|
||||
} else if versionState != nil && versionState.mode != sourceVersionModeDefault {
|
||||
var sourceID string
|
||||
if parsed.source != nil {
|
||||
sourceID = parsed.source.ID
|
||||
@@ -175,6 +205,10 @@ func assembleBaseInputTrackedForRole[T any](source Source, options Options[T], d
|
||||
localPayload := input.document
|
||||
input.document = placed
|
||||
identity := importKeyForMainSource(parsed.source)
|
||||
var sequenceDeclarations []sequenceDeclarationSpec
|
||||
if versionProcessing != nil {
|
||||
sequenceDeclarations = cloneSequenceDeclarations(versionProcessing.sequences)
|
||||
}
|
||||
input.acquisition = []acquisitionScope{{
|
||||
owner: identity,
|
||||
destination: destination.clone(),
|
||||
@@ -182,6 +216,7 @@ func assembleBaseInputTrackedForRole[T any](source Source, options Options[T], d
|
||||
source: cloneSourceInfo(*parsed.source), payload: localPayload,
|
||||
identity: identity, role: importRoleMain, scopeOwner: identity,
|
||||
document: placed, destination: destination.clone(), processing: versionProcessing,
|
||||
sequenceDeclarations: sequenceDeclarations,
|
||||
}},
|
||||
}}
|
||||
rawNodes := countInputNodes(parsed.document)
|
||||
@@ -273,6 +308,18 @@ func compositionForInputWithPolicy(input assembledInput, policy sequencePolicy)
|
||||
}
|
||||
return input.composition, nil
|
||||
}
|
||||
if len(input.acquisition) != 0 {
|
||||
acquired := &composedDocument{acquisition: cloneAcquisitionScopes(input.acquisition)}
|
||||
if input.accounting != nil {
|
||||
acquired.inputBytes = input.accounting.bytes
|
||||
acquired.inputNodes = input.accounting.nodes
|
||||
} else {
|
||||
acquired.inputBytes = input.parsed.bytes
|
||||
acquired.inputNodes = countInputNodes(input.parsed.document)
|
||||
}
|
||||
input.composition = acquired
|
||||
return composeAcquiredInputWithPolicy(input, policy)
|
||||
}
|
||||
if input.document == nil {
|
||||
return &composedDocument{root: &document.Node{Kind: document.Mapping}, origins: make(map[string]Origin)}, nil
|
||||
}
|
||||
|
||||
210
internal/engine/ordinary_sequence_test.go
Normal file
210
internal/engine/ordinary_sequence_test.go
Normal file
@@ -0,0 +1,210 @@
|
||||
package engine
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type ordinarySequenceItem struct {
|
||||
ID string `yaml:"id"`
|
||||
}
|
||||
|
||||
type ordinarySequenceRecord struct {
|
||||
ID string `yaml:"id"`
|
||||
Children []ordinarySequenceItem `yaml:"children"`
|
||||
}
|
||||
|
||||
type ordinarySequenceConfig struct {
|
||||
Items []ordinarySequenceItem `yaml:"items"`
|
||||
Catalog struct {
|
||||
Items []ordinarySequenceItem `yaml:"items"`
|
||||
} `yaml:"catalog"`
|
||||
Records []ordinarySequenceRecord `yaml:"records"`
|
||||
}
|
||||
|
||||
func TestOrdinaryLoadAcceptsDeclarationsWithoutImports(t *testing.T) {
|
||||
result, err := testLoad[ordinarySequenceConfig](Bytes("catalog.yml", []byte(`configkit:
|
||||
sequences:
|
||||
- destination: [items]
|
||||
key: id
|
||||
items:
|
||||
- id: prompt
|
||||
`)))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(result.Config.Items, []ordinarySequenceItem{{ID: "prompt"}}) {
|
||||
t.Fatalf("items = %#v", result.Config.Items)
|
||||
}
|
||||
if _, ok := result.Metadata().Lookup(Keys("configkit")); ok {
|
||||
t.Fatal("collection controls reached application metadata")
|
||||
}
|
||||
items, ok := result.Metadata().Lookup(Keys("items"))
|
||||
if !ok || !items.Explicit || len(items.Origin.Locations) != 1 {
|
||||
t.Fatalf("items metadata = %#v, %v", items, ok)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOrdinaryLoadKeepsDisabledImportRejection(t *testing.T) {
|
||||
_, err := testLoad[ordinarySequenceConfig](Bytes("disabled.yml", []byte(`configkit:
|
||||
imports: [{path: fragment.yml}]
|
||||
sequences: [{destination: [items], key: id}]
|
||||
`)))
|
||||
if err == nil {
|
||||
t.Fatal("source with disabled imports succeeded")
|
||||
}
|
||||
var loadError *LoadError
|
||||
if !errors.As(err, &loadError) || len(loadError.Diagnostics()) != 1 || loadError.Diagnostics()[0].Code != CodeImportDisabled {
|
||||
t.Fatalf("error = %#v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOrdinaryLoadValidatesSingletonCollectionIdentity(t *testing.T) {
|
||||
_, err := testLoad[ordinarySequenceConfig](Bytes("missing-identity.yml", []byte(`configkit:
|
||||
sequences:
|
||||
- destination: [items]
|
||||
key: id
|
||||
items: [{}]
|
||||
`)))
|
||||
if err == nil {
|
||||
t.Fatal("singleton sequence without identity succeeded")
|
||||
}
|
||||
var loadError *LoadError
|
||||
if !errors.As(err, &loadError) || len(loadError.Diagnostics()) != 1 || loadError.Diagnostics()[0].Code != CodeComposeInvalid {
|
||||
t.Fatalf("error = %#v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOrdinaryLoadCombinesImportedCollectionPeers(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
second string
|
||||
want []ordinarySequenceItem
|
||||
wantCode Code
|
||||
}{
|
||||
{name: "distinct identities", second: "items: [{id: second}]\n", want: []ordinarySequenceItem{{ID: "first"}, {ID: "second"}}},
|
||||
{name: "duplicate peer identity", second: "items: [{id: first}]\n", wantCode: CodeComposeConflict},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
directory := t.TempDir()
|
||||
mainPath := writeImportFile(t, directory, "main.yml", `configkit:
|
||||
imports:
|
||||
- path: first.yml
|
||||
- path: second.yml
|
||||
sequences:
|
||||
- destination: [items]
|
||||
key: id
|
||||
mode: append
|
||||
`)
|
||||
writeImportFile(t, directory, "first.yml", "items: [{id: first}]\n")
|
||||
writeImportFile(t, directory, "second.yml", test.second)
|
||||
|
||||
result, err := testLoad[ordinarySequenceConfig](File(mainPath), Options[ordinarySequenceConfig]{Imports: true})
|
||||
if test.wantCode != "" {
|
||||
if result != nil || err == nil {
|
||||
t.Fatalf("result, err = %#v, %v", result, err)
|
||||
}
|
||||
var loadError *LoadError
|
||||
if !errors.As(err, &loadError) || len(loadError.Diagnostics()) == 0 || loadError.Diagnostics()[0].Code != test.wantCode {
|
||||
t.Fatalf("error = %#v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
var loadError *LoadError
|
||||
if errors.As(err, &loadError) {
|
||||
t.Fatalf("diagnostics = %#v", loadError.Diagnostics())
|
||||
}
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(result.Config.Items, test.want) {
|
||||
t.Fatalf("items = %#v, want %#v", result.Config.Items, test.want)
|
||||
}
|
||||
inline, err := testLoad[ordinarySequenceConfig](Bytes("inline.yml", []byte(`configkit:
|
||||
sequences:
|
||||
- destination: [items]
|
||||
key: id
|
||||
mode: append
|
||||
items: [{id: first}, {id: second}]
|
||||
`)))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(result.Config.Items, inline.Config.Items) {
|
||||
t.Fatalf("imported items %#v differ from inline items %#v", result.Config.Items, inline.Config.Items)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestImportedCollectionDeclarationsUseRelativePlacement(t *testing.T) {
|
||||
directory := t.TempDir()
|
||||
mainPath := writeImportFile(t, directory, "main.yml", `configkit:
|
||||
imports:
|
||||
- path: first.yml
|
||||
destination: [catalog]
|
||||
- path: second.yml
|
||||
destination: [catalog]
|
||||
`)
|
||||
fragment := `configkit:
|
||||
sequences:
|
||||
- destination: [items]
|
||||
key: id
|
||||
mode: append
|
||||
items: [{id: ITEM}]
|
||||
`
|
||||
writeImportFile(t, directory, "first.yml", strings.ReplaceAll(fragment, "ITEM", "first"))
|
||||
writeImportFile(t, directory, "second.yml", strings.ReplaceAll(fragment, "ITEM", "second"))
|
||||
|
||||
result, err := testLoad[ordinarySequenceConfig](File(mainPath), Options[ordinarySequenceConfig]{Imports: true})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
want := []ordinarySequenceItem{{ID: "first"}, {ID: "second"}}
|
||||
if !reflect.DeepEqual(result.Config.Catalog.Items, want) {
|
||||
t.Fatalf("catalog items = %#v, want %#v", result.Config.Catalog.Items, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSequenceItemSourceAppliesItsCollectionDeclarations(t *testing.T) {
|
||||
directory := t.TempDir()
|
||||
mainPath := writeImportFile(t, directory, "main.yml", `configkit:
|
||||
imports:
|
||||
- path: item.yml
|
||||
destination: [records]
|
||||
placement: sequence-item
|
||||
`)
|
||||
writeImportFile(t, directory, "item.yml", `configkit:
|
||||
sequences:
|
||||
- destination: [children]
|
||||
key: id
|
||||
mode: append
|
||||
id: parent
|
||||
children: [{id: child}]
|
||||
`)
|
||||
result, err := testLoad[ordinarySequenceConfig](File(mainPath), Options[ordinarySequenceConfig]{Imports: true})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
want := []ordinarySequenceRecord{{ID: "parent", Children: []ordinarySequenceItem{{ID: "child"}}}}
|
||||
if !reflect.DeepEqual(result.Config.Records, want) {
|
||||
t.Fatalf("records = %#v, want %#v", result.Config.Records, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOrdinaryLoadAllowsDeclarationsWithoutValues(t *testing.T) {
|
||||
result, err := testLoad[ordinarySequenceConfig](Bytes("policy.yml", []byte(`configkit:
|
||||
sequences:
|
||||
- destination: [items]
|
||||
key: id
|
||||
`)))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if result.Config.Items != nil {
|
||||
t.Fatalf("items = %#v, want absent", result.Config.Items)
|
||||
}
|
||||
}
|
||||
@@ -118,11 +118,18 @@ func (state *sourceVersionState) process(root *document.Node, role sourceVersion
|
||||
if state == nil || state.mode == sourceVersionModeDefault {
|
||||
return sourceVersionProcessingResult{}, nil
|
||||
}
|
||||
return state.processWithDirectiveContext(root, role, destination, sourceID, placement, rootDirectiveContextImportsOnly)
|
||||
}
|
||||
|
||||
func (state *sourceVersionState) processWithDirectiveContext(root *document.Node, role sourceVersionRole, destination Path, sourceID string, placement placementMode, directiveContext rootDirectiveContext) (sourceVersionProcessingResult, []Diagnostic) {
|
||||
if state == nil {
|
||||
return sourceVersionProcessingResult{}, nil
|
||||
}
|
||||
projectedDestination := destination.clone()
|
||||
if placement == placementModeSequenceItem {
|
||||
projectedDestination = projectedDestination.Index(0)
|
||||
}
|
||||
result := processSourceVersion(root, state.localRule, role, projectedDestination, state.mode)
|
||||
result := processSourceVersionWithDirectiveContext(root, state.localRule, role, projectedDestination, state.mode, directiveContext)
|
||||
if result.evidence != nil {
|
||||
result.evidence.sourceID = sourceID
|
||||
state.evidence = append(state.evidence, result.evidence)
|
||||
@@ -139,11 +146,12 @@ func (state *sourceVersionState) process(root *document.Node, role sourceVersion
|
||||
}
|
||||
|
||||
type sourceVersionProcessingResult struct {
|
||||
payload *document.Node
|
||||
imports []importDeclarationSpec
|
||||
sequences []sequenceDeclarationSpec
|
||||
evidence *sourceVersionEvidence
|
||||
diagnostics []Diagnostic
|
||||
payload *document.Node
|
||||
imports []importDeclarationSpec
|
||||
sequences []sequenceDeclarationSpec
|
||||
directiveContext rootDirectiveContext
|
||||
evidence *sourceVersionEvidence
|
||||
diagnostics []Diagnostic
|
||||
}
|
||||
|
||||
func effectiveSourceVersionRule(local *VersionRule, destination Path, mode sourceVersionMode) *VersionRule {
|
||||
@@ -214,7 +222,7 @@ func processSourceVersionWithDirectiveContext(root *document.Node, rule *Version
|
||||
return sourceVersionProcessingResult{diagnostics: diagnostics}
|
||||
}
|
||||
result := sourceVersionProcessingResult{
|
||||
payload: extracted.body, imports: extracted.imports,
|
||||
payload: extracted.body, imports: extracted.imports, directiveContext: directiveContext,
|
||||
sequences: cloneSequenceDeclarations(extracted.sequences),
|
||||
}
|
||||
if mode == sourceVersionModeDefault {
|
||||
|
||||
Reference in New Issue
Block a user