Simplify empty import selection evidence
This commit is contained in:
@@ -46,21 +46,21 @@ func fromEngineSourceInfo(value engine.SourceInfo) SourceInfo {
|
||||
return SourceInfo{
|
||||
ID: value.ID, Label: value.Label, Path: value.Path, Destination: fromEnginePath(value.Destination),
|
||||
PlacementMode: PlacementMode(engine.SourceInfoPlacementModeForFacade(value)),
|
||||
DestinationUnresolved: engine.SourceInfoDestinationUnresolvedForFacade(value),
|
||||
DestinationIsFallback: engine.SourceInfoDestinationUnresolvedForFacade(value),
|
||||
Layer: Layer(value.Layer), Kind: SourceKind(value.Kind), UnderlayIndex: value.UnderlayIndex,
|
||||
ImportedFrom: fromEngineLocationPointer(value.ImportedFrom), VersionEvidence: fromEngineSourceVersionEvidence(value.VersionCheck),
|
||||
ImportSelections: fromEngineImportSelections(engine.SourceInfoImportSelectionsForFacade(value)),
|
||||
EmptyImportSelections: fromEngineEmptyImportSelections(engine.SourceInfoImportSelectionsForFacade(value)),
|
||||
}
|
||||
}
|
||||
func fromEngineImportSelections(values []engine.ImportSelectionForFacade) []ImportSelection {
|
||||
func fromEngineEmptyImportSelections(values []engine.ImportSelectionForFacade) []EmptyImportSelection {
|
||||
if values == nil {
|
||||
return nil
|
||||
}
|
||||
result := make([]ImportSelection, len(values))
|
||||
result := make([]EmptyImportSelection, len(values))
|
||||
for index, value := range values {
|
||||
result[index] = ImportSelection{
|
||||
result[index] = EmptyImportSelection{
|
||||
Path: fromEnginePath(value.Path), Location: fromEngineLocation(value.Location),
|
||||
Selector: ImportSelector(value.Selector), Outcome: ImportSelectionOutcome(value.Outcome),
|
||||
Selector: ImportSelector(value.Selector),
|
||||
}
|
||||
}
|
||||
return result
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Pre-v1 Public API Cleanup Implementation Plan
|
||||
|
||||
Status: in progress; Stages 1–2 are complete and Stages 3–11 are pending.
|
||||
Status: in progress; Stages 1–3 are complete and Stages 4–11 are pending.
|
||||
Baseline: `07e4ae5d9236935389e81b207d4a8f00543fafce`.
|
||||
Audience: a Luna coding agent executing the stages sequentially.
|
||||
|
||||
@@ -161,7 +161,7 @@ with existing version behavior intact.
|
||||
|
||||
## Stage 3 — Simplify Empty-Selection And Destination Evidence
|
||||
|
||||
Status: pending. Implements D4 and D5.
|
||||
Status: complete. Implements D4 and D5.
|
||||
|
||||
1. Replace root `ImportSelection` with `EmptyImportSelection` and
|
||||
`SourceInfo.ImportSelections` with `EmptyImportSelections`. Retain `Path`,
|
||||
|
||||
@@ -24,8 +24,8 @@ func Example_identifiedPromptCatalog() {
|
||||
}
|
||||
emptySearches := 0
|
||||
for _, source := range result.Sources() {
|
||||
for _, selection := range source.ImportSelections {
|
||||
if selection.Selector == configkit.ImportSelectorDirectory && selection.Outcome == configkit.ImportSelectionNone {
|
||||
for _, selection := range source.EmptyImportSelections {
|
||||
if selection.Selector == configkit.ImportSelectorDirectory {
|
||||
emptySearches++
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ func TestImportDefaultsPreserveEmptyPatternAndRequiredness(t *testing.T) {
|
||||
t.Fatalf("empty pattern = %#v, %v", empty, err)
|
||||
}
|
||||
emptySources := empty.Sources()
|
||||
if len(emptySources) != 1 || len(emptySources[0].ImportSelections) != 1 || emptySources[0].ImportSelections[0].Path.String() != "/configkit/imports/0" || emptySources[0].ImportSelections[0].Selector != ImportSelectorDirectory || emptySources[0].ImportSelections[0].Outcome != ImportSelectionNone {
|
||||
if len(emptySources) != 1 || len(emptySources[0].EmptyImportSelections) != 1 || emptySources[0].EmptyImportSelections[0].Path.String() != "/configkit/imports/0" || emptySources[0].EmptyImportSelections[0].Selector != ImportSelectorDirectory {
|
||||
t.Fatalf("empty-pattern evidence = %#v", emptySources)
|
||||
}
|
||||
required := true
|
||||
@@ -120,7 +120,7 @@ func TestImportDefaultsPreserveEmptyPatternAndRequiredness(t *testing.T) {
|
||||
if !errors.As(err, &loadError) || len(loadError.Diagnostics()) != 1 || loadError.Diagnostics()[0].Code != CodeImportMissing {
|
||||
t.Fatalf("required empty selection error = %T %v", err, err)
|
||||
}
|
||||
if sources := loadError.Sources(); len(sources) != 1 || len(sources[0].ImportSelections) != 0 {
|
||||
if sources := loadError.Sources(); len(sources) != 1 || len(sources[0].EmptyImportSelections) != 0 {
|
||||
t.Fatalf("required empty selection was recorded as optional: %#v", sources)
|
||||
}
|
||||
}
|
||||
@@ -230,15 +230,15 @@ value: loaded
|
||||
callbackPath := ""
|
||||
loaded, err := Load(File(mainPath), Options[config]{Imports: true, Definition: Definition[config]{Resolve: func(_ *config, resolution *Resolution) error {
|
||||
first, ok := resolution.Source("source-1")
|
||||
if !ok || len(first.ImportSelections) != 1 {
|
||||
if !ok || len(first.EmptyImportSelections) != 1 {
|
||||
t.Fatalf("resolution source = %#v, %v", first, ok)
|
||||
}
|
||||
first.ImportSelections[0].Path = Keys("callback mutation")
|
||||
first.EmptyImportSelections[0].Path = Keys("callback mutation")
|
||||
second, ok := resolution.Source("source-1")
|
||||
if !ok || second.ImportSelections[0].Path.String() != "/configkit/imports/0" {
|
||||
if !ok || second.EmptyImportSelections[0].Path.String() != "/configkit/imports/0" {
|
||||
t.Fatalf("resolution snapshot changed after mutation: %#v", second)
|
||||
}
|
||||
callbackPath = second.ImportSelections[0].Path.String()
|
||||
callbackPath = second.EmptyImportSelections[0].Path.String()
|
||||
return nil
|
||||
}}})
|
||||
if err != nil {
|
||||
@@ -248,11 +248,11 @@ value: loaded
|
||||
t.Fatalf("callback path = %q", callbackPath)
|
||||
}
|
||||
sources := loaded.Sources()
|
||||
if len(sources) != 1 || len(sources[0].ImportSelections) != 1 || sources[0].ImportSelections[0].Location.SourceID != sources[0].ID || sources[0].ImportSelections[0].Selector != ImportSelectorDirectory {
|
||||
if len(sources) != 1 || len(sources[0].EmptyImportSelections) != 1 || sources[0].EmptyImportSelections[0].Location.SourceID != sources[0].ID || sources[0].EmptyImportSelections[0].Selector != ImportSelectorDirectory {
|
||||
t.Fatalf("result source evidence = %#v", sources)
|
||||
}
|
||||
sources[0].ImportSelections[0].Path = Keys("result mutation")
|
||||
if got := loaded.Sources()[0].ImportSelections[0].Path.String(); got != "/configkit/imports/0" {
|
||||
sources[0].EmptyImportSelections[0].Path = Keys("result mutation")
|
||||
if got := loaded.Sources()[0].EmptyImportSelections[0].Path.String(); got != "/configkit/imports/0" {
|
||||
t.Fatalf("result snapshot changed after mutation: %q", got)
|
||||
}
|
||||
|
||||
@@ -268,11 +268,11 @@ value: loaded
|
||||
t.Fatalf("failed load error = %T %v", err, err)
|
||||
}
|
||||
errorSources := loadError.Sources()
|
||||
if len(errorSources) != 1 || len(errorSources[0].ImportSelections) != 1 || errorSources[0].ImportSelections[0].Path.String() != "/configkit/imports/0" {
|
||||
if len(errorSources) != 1 || len(errorSources[0].EmptyImportSelections) != 1 || errorSources[0].EmptyImportSelections[0].Path.String() != "/configkit/imports/0" {
|
||||
t.Fatalf("error source evidence = %#v", errorSources)
|
||||
}
|
||||
errorSources[0].ImportSelections[0].Path = Keys("error mutation")
|
||||
if got := loadError.Sources()[0].ImportSelections[0].Path.String(); got != "/configkit/imports/0" {
|
||||
errorSources[0].EmptyImportSelections[0].Path = Keys("error mutation")
|
||||
if got := loadError.Sources()[0].EmptyImportSelections[0].Path.String(); got != "/configkit/imports/0" {
|
||||
t.Fatalf("error snapshot changed after mutation: %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,7 +211,7 @@ func TestFacadeSequencePlacementControlsAcrossLoadEntryPoints(t *testing.T) {
|
||||
if got := ordinary.Config["entries"].([]any); len(got) != 1 || got[0].(map[string]any)["id"] != "one" {
|
||||
t.Fatalf("ordinary item placement = %#v", ordinary.Config)
|
||||
}
|
||||
if sources := ordinary.Sources(); len(sources) != 1 || sources[0].PlacementMode != configkit.PlacementModeSequenceItem || sources[0].Destination.String() != "/entries" || sources[0].DestinationUnresolved {
|
||||
if sources := ordinary.Sources(); len(sources) != 1 || sources[0].PlacementMode != configkit.PlacementModeSequenceItem || sources[0].Destination.String() != "/entries" || sources[0].DestinationIsFallback {
|
||||
t.Fatalf("ordinary item source = %#v", sources)
|
||||
}
|
||||
|
||||
@@ -230,7 +230,7 @@ func TestFacadeSequencePlacementControlsAcrossLoadEntryPoints(t *testing.T) {
|
||||
t.Fatalf("layered item placement = %#v", layered.Config)
|
||||
}
|
||||
for _, source := range layered.Sources() {
|
||||
if source.PlacementMode != configkit.PlacementModeSequenceItem || source.Destination.String() != "/entries" || source.DestinationUnresolved {
|
||||
if source.PlacementMode != configkit.PlacementModeSequenceItem || source.Destination.String() != "/entries" || source.DestinationIsFallback {
|
||||
t.Errorf("layered item source = %#v", source)
|
||||
}
|
||||
}
|
||||
@@ -334,7 +334,7 @@ items:
|
||||
t.Fatalf("callback snapshots = %#v, contexts %#v", callbackSources, callbackContexts)
|
||||
}
|
||||
for index, source := range callbackSources {
|
||||
if source.PlacementMode != configkit.PlacementModeSequenceItem || source.Destination.String() != "/items" || source.DestinationUnresolved {
|
||||
if source.PlacementMode != configkit.PlacementModeSequenceItem || source.Destination.String() != "/items" || source.DestinationIsFallback {
|
||||
t.Errorf("callback source = %#v", source)
|
||||
}
|
||||
if callbackContexts[index].FS == nil || callbackContexts[index].BaseDir != "records" {
|
||||
@@ -349,7 +349,7 @@ items:
|
||||
t.Errorf("shifted item origin at %s = %#v, %v", path.String(), info, ok)
|
||||
}
|
||||
}
|
||||
if got := result.Sources(); len(got) != 3 || got[1].Destination.String() != "/items" || got[1].DestinationUnresolved {
|
||||
if got := result.Sources(); len(got) != 3 || got[1].Destination.String() != "/items" || got[1].DestinationIsFallback {
|
||||
t.Fatalf("final item sources = %#v", got)
|
||||
}
|
||||
}
|
||||
@@ -372,9 +372,9 @@ func TestFacadeItemDestinationFallbackEvidenceSurvivesFailures(t *testing.T) {
|
||||
t.Fatalf("early failure = %v", err)
|
||||
}
|
||||
sources := loadError.Sources()
|
||||
if len(sources) != 2 || sources[0].Destination.String() != "/items" || sources[0].DestinationUnresolved ||
|
||||
if len(sources) != 2 || sources[0].Destination.String() != "/items" || sources[0].DestinationIsFallback ||
|
||||
sources[0].PlacementMode != configkit.PlacementModeSequenceItem ||
|
||||
sources[1].Destination.String() != "/items" || !sources[1].DestinationUnresolved ||
|
||||
sources[1].Destination.String() != "/items" || !sources[1].DestinationIsFallback ||
|
||||
sources[1].PlacementMode != configkit.PlacementModeMapping {
|
||||
t.Fatalf("early source snapshots = %#v", sources)
|
||||
}
|
||||
@@ -399,13 +399,13 @@ func TestFacadeItemDestinationFallbackEvidenceSurvivesFailures(t *testing.T) {
|
||||
t.Fatalf("post-placement failure = %v", err)
|
||||
}
|
||||
sources = loadError.Sources()
|
||||
if len(sources) != 2 || sources[0].Destination.String() != "/items" || sources[0].DestinationUnresolved ||
|
||||
sources[1].Destination.String() != "/items/0/metadata" || sources[1].DestinationUnresolved {
|
||||
if len(sources) != 2 || sources[0].Destination.String() != "/items" || sources[0].DestinationIsFallback ||
|
||||
sources[1].Destination.String() != "/items/0/metadata" || sources[1].DestinationIsFallback {
|
||||
t.Fatalf("post-placement source snapshots = %#v", sources)
|
||||
}
|
||||
firstSnapshot := sources[1]
|
||||
sources[1].Destination = configkit.Keys("mutated")
|
||||
if again := loadError.Sources(); len(again) != 2 || again[1].Destination.String() != firstSnapshot.Destination.String() || again[1].DestinationUnresolved {
|
||||
if again := loadError.Sources(); len(again) != 2 || again[1].Destination.String() != firstSnapshot.Destination.String() || again[1].DestinationIsFallback {
|
||||
t.Fatalf("failure source snapshots were aliased: %#v", again)
|
||||
}
|
||||
|
||||
@@ -420,7 +420,7 @@ func TestFacadeItemDestinationFallbackEvidenceSurvivesFailures(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("successful item load: %v", err)
|
||||
}
|
||||
if callback.Destination.String() != "/items/0/metadata" || callback.DestinationUnresolved || callback.PlacementMode != configkit.PlacementModeMapping {
|
||||
if callback.Destination.String() != "/items/0/metadata" || callback.DestinationIsFallback || callback.PlacementMode != configkit.PlacementModeMapping {
|
||||
t.Fatalf("callback source snapshot = %#v", callback)
|
||||
}
|
||||
}
|
||||
@@ -450,13 +450,13 @@ func TestFacadeNestedItemFallbackUsesNearestResolvedContainer(t *testing.T) {
|
||||
if len(sources) != 3 {
|
||||
t.Fatalf("nested source snapshots = %#v", sources)
|
||||
}
|
||||
if got := sources[0]; got.Destination.String() != "/groups" || got.DestinationUnresolved || got.PlacementMode != configkit.PlacementModeSequenceItem {
|
||||
if got := sources[0]; got.Destination.String() != "/groups" || got.DestinationIsFallback || got.PlacementMode != configkit.PlacementModeSequenceItem {
|
||||
t.Errorf("outer item snapshot = %#v", got)
|
||||
}
|
||||
if got := sources[1]; got.Destination.String() != "/groups" || !got.DestinationUnresolved || got.PlacementMode != configkit.PlacementModeSequenceItem {
|
||||
if got := sources[1]; got.Destination.String() != "/groups" || !got.DestinationIsFallback || got.PlacementMode != configkit.PlacementModeSequenceItem {
|
||||
t.Errorf("nested item fallback = %#v", got)
|
||||
}
|
||||
if got := sources[2]; got.Destination.String() != "/groups" || !got.DestinationUnresolved || got.PlacementMode != configkit.PlacementModeMapping {
|
||||
if got := sources[2]; got.Destination.String() != "/groups" || !got.DestinationIsFallback || got.PlacementMode != configkit.PlacementModeMapping {
|
||||
t.Errorf("nested helper fallback = %#v", got)
|
||||
}
|
||||
}
|
||||
@@ -496,7 +496,7 @@ func TestFacadeSequenceIdentityRegistrationIsDetached(t *testing.T) {
|
||||
|
||||
func TestFacadeSourceInfoPlacementCopiesAndZeroValues(t *testing.T) {
|
||||
zero := configkit.SourceInfo{}
|
||||
if zero.PlacementMode != configkit.PlacementModeMapping || zero.DestinationUnresolved {
|
||||
if zero.PlacementMode != configkit.PlacementModeMapping || zero.DestinationIsFallback {
|
||||
t.Fatalf("zero source info = %#v", zero)
|
||||
}
|
||||
loaded, err := configkit.Load[map[string]any](configkit.Mapping("mapping", map[string]any{"value": true}))
|
||||
@@ -504,12 +504,12 @@ func TestFacadeSourceInfoPlacementCopiesAndZeroValues(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
sources := loaded.Sources()
|
||||
if len(sources) != 1 || sources[0].PlacementMode != configkit.PlacementModeMapping || sources[0].DestinationUnresolved {
|
||||
if len(sources) != 1 || sources[0].PlacementMode != configkit.PlacementModeMapping || sources[0].DestinationIsFallback {
|
||||
t.Fatalf("mapping source evidence = %#v", sources)
|
||||
}
|
||||
first := sources[0]
|
||||
first.Destination = configkit.Keys("caller")
|
||||
if again := loaded.Sources(); len(again) != 1 || again[0].Destination.String() != "" || again[0].DestinationUnresolved {
|
||||
if again := loaded.Sources(); len(again) != 1 || again[0].Destination.String() != "" || again[0].DestinationIsFallback {
|
||||
t.Fatalf("source evidence changed after caller mutation: %#v", again)
|
||||
}
|
||||
}
|
||||
@@ -646,7 +646,7 @@ entries:
|
||||
t.Fatalf("callback sources = %#v; contexts = %#v", callbackItems, callbackContexts)
|
||||
}
|
||||
for _, source := range callbackItems {
|
||||
if source.PlacementMode != configkit.PlacementModeSequenceItem || source.Destination.String() != "/entries" || source.DestinationUnresolved {
|
||||
if source.PlacementMode != configkit.PlacementModeSequenceItem || source.Destination.String() != "/entries" || source.DestinationIsFallback {
|
||||
t.Errorf("callback item source = %#v", source)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,7 +289,7 @@ func (s *importTraversal) recordEmptyImportSelection(sourceIndex int, spec impor
|
||||
// missing-source rollback, unlike a pointer into the source slice.
|
||||
s.sources[sourceIndex].importSelections = append(s.sources[sourceIndex].importSelections, importSelectionEvidence{
|
||||
path: spec.path.clone(), location: spec.location,
|
||||
selector: spec.selector, outcome: importSelectionNone,
|
||||
selector: spec.selector,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ func TestBroadEmptyImportSelectionsKeepDeclaringSourceOwnership(t *testing.T) {
|
||||
}
|
||||
for selectionIndex, selection := range source.importSelections {
|
||||
if selection.path.String() != wantPaths[selectionIndex] || selection.location.SourceID != source.ID ||
|
||||
selection.selector != importSelectorPath || selection.outcome != importSelectionNone {
|
||||
selection.selector != importSelectorPath {
|
||||
t.Errorf("source %s selection %d = %#v", source.ID, selectionIndex, selection)
|
||||
}
|
||||
}
|
||||
@@ -90,7 +90,7 @@ func TestOptionalEmptyImportSelectionsRemainSourceLocalAndDetached(t *testing.T)
|
||||
}
|
||||
for index, selection := range evidence {
|
||||
if selection.path.String() != wantPaths[index] || selection.location.SourceID != sources[0].ID ||
|
||||
selection.selector != wantSelectors[index] || selection.outcome != importSelectionNone {
|
||||
selection.selector != wantSelectors[index] {
|
||||
t.Errorf("selection %d = %#v", index, selection)
|
||||
}
|
||||
}
|
||||
@@ -137,7 +137,7 @@ value: main
|
||||
t.Fatalf("failed-load sources = %#v", sources)
|
||||
}
|
||||
selection := sources[0].importSelections[0]
|
||||
if selection.path.String() != "/configkit/imports/0" || selection.location.SourceID != sources[0].ID || selection.selector != importSelectorGlob || selection.outcome != importSelectionNone {
|
||||
if selection.path.String() != "/configkit/imports/0" || selection.location.SourceID != sources[0].ID || selection.selector != importSelectorGlob {
|
||||
t.Fatalf("retained selection = %#v", selection)
|
||||
}
|
||||
sources[0].importSelections[0].path.segments[0].key = "changed"
|
||||
|
||||
@@ -9,13 +9,6 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
type importSelectionOutcome uint8
|
||||
|
||||
const (
|
||||
importSelectionNone importSelectionOutcome = iota
|
||||
importSelectionHasCandidates
|
||||
)
|
||||
|
||||
type selectedImportCandidate struct {
|
||||
path string
|
||||
accessPath string
|
||||
|
||||
@@ -206,7 +206,6 @@ type importSelectionEvidence struct {
|
||||
path Path
|
||||
location Location
|
||||
selector importSelector
|
||||
outcome importSelectionOutcome
|
||||
}
|
||||
|
||||
// ImportSelectionForFacade is a root-converted source-selection transport
|
||||
@@ -215,7 +214,6 @@ type ImportSelectionForFacade struct {
|
||||
Path Path // source-local import declaration path
|
||||
Location Location // authored location and declaring source ID
|
||||
Selector string // path, dir, or glob
|
||||
Outcome string // none for a completed empty optional selection
|
||||
}
|
||||
|
||||
// SourceInfoImportSelectionsForFacade returns detached selection records for
|
||||
@@ -229,7 +227,6 @@ func SourceInfoImportSelectionsForFacade(source SourceInfo) []ImportSelectionFor
|
||||
result[index] = ImportSelectionForFacade{
|
||||
Path: selection.path.clone(), Location: selection.location,
|
||||
Selector: importSelectorString(selection.selector),
|
||||
Outcome: importSelectionOutcomeString(selection.outcome),
|
||||
}
|
||||
}
|
||||
return result
|
||||
@@ -250,13 +247,6 @@ func importSelectorString(value importSelector) string {
|
||||
}
|
||||
}
|
||||
|
||||
func importSelectionOutcomeString(value importSelectionOutcome) string {
|
||||
if value == importSelectionNone {
|
||||
return "none"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// SourceInfoPlacementModeForFacade converts private placement evidence to its
|
||||
// root-owned numeric representation.
|
||||
func SourceInfoPlacementModeForFacade(source SourceInfo) uint8 {
|
||||
|
||||
25
records.go
25
records.go
@@ -192,16 +192,16 @@ type SourceInfo struct {
|
||||
Label string
|
||||
Path string
|
||||
// Destination is the effective mapping or sequence-container path. It is a
|
||||
// detached snapshot. A fallback container is marked by DestinationUnresolved.
|
||||
// detached snapshot. A fallback container is marked by DestinationIsFallback.
|
||||
Destination Path
|
||||
// PlacementMode describes how this source was placed. Mapping is the zero
|
||||
// value; CLI and overlay sources report mapping placement unless item placement
|
||||
// was applied to that source.
|
||||
PlacementMode PlacementMode
|
||||
// DestinationUnresolved marks Destination as the nearest resolved enclosing
|
||||
// DestinationIsFallback marks Destination as the nearest resolved enclosing
|
||||
// container when an enclosing item index is not yet assigned. It is false for
|
||||
// exact destinations, including an item source's own sequence container.
|
||||
DestinationUnresolved bool
|
||||
DestinationIsFallback bool
|
||||
Layer Layer
|
||||
Kind SourceKind
|
||||
UnderlayIndex int
|
||||
@@ -212,12 +212,12 @@ type SourceInfo struct {
|
||||
// and failed loads, text is conservatively withheld; successful final source
|
||||
// records reflect completed sensitivity classification.
|
||||
VersionEvidence *SourceVersionEvidence
|
||||
// ImportSelections records completed optional declarations that selected no
|
||||
// EmptyImportSelections records completed optional declarations that selected no
|
||||
// sources, in declaration order. Paths are local to this declaring source.
|
||||
// Each record identifies the declaration mapping, selector, and empty outcome;
|
||||
// Each record identifies the declaration mapping and selector;
|
||||
// it does not list candidates or explain why a path was absent. Result, error,
|
||||
// and callback snapshots detach these records and their paths.
|
||||
ImportSelections []ImportSelection
|
||||
EmptyImportSelections []EmptyImportSelection
|
||||
}
|
||||
|
||||
// ImportSelector identifies the selector used by an import declaration.
|
||||
@@ -232,22 +232,13 @@ const (
|
||||
ImportSelectorGlob ImportSelector = "glob"
|
||||
)
|
||||
|
||||
// ImportSelectionOutcome identifies the established result of import selection.
|
||||
type ImportSelectionOutcome string
|
||||
|
||||
const (
|
||||
// ImportSelectionNone means the optional declaration selected no sources.
|
||||
ImportSelectionNone ImportSelectionOutcome = "none"
|
||||
)
|
||||
|
||||
// ImportSelection records an optional import declaration that selected no
|
||||
// EmptyImportSelection records an optional import declaration that selected no
|
||||
// sources. Path is local to the declaring source; Location identifies its
|
||||
// declaration mapping and source ID.
|
||||
type ImportSelection struct {
|
||||
type EmptyImportSelection struct {
|
||||
Path Path
|
||||
Location Location
|
||||
Selector ImportSelector
|
||||
Outcome ImportSelectionOutcome
|
||||
}
|
||||
|
||||
// SourceVersionEvidence describes a source-local version declaration observed
|
||||
|
||||
@@ -35,7 +35,7 @@ func TestSourceInfoDestinationConversion(t *testing.T) {
|
||||
}
|
||||
internal := engineSourceInfoFromLoad(t, path, "source-1", options)
|
||||
converted := fromEngineSourceInfo(internal)
|
||||
if converted.Destination.String() != destination.String() || converted.PlacementMode != PlacementModeSequenceItem || converted.DestinationUnresolved {
|
||||
if converted.Destination.String() != destination.String() || converted.PlacementMode != PlacementModeSequenceItem || converted.DestinationIsFallback {
|
||||
t.Fatalf("public source evidence = %#v", converted)
|
||||
}
|
||||
}
|
||||
@@ -70,18 +70,15 @@ func TestImportSelectionConversion(t *testing.T) {
|
||||
file := writeRecordConfig(t, "configkit:\n imports:\n - glob: absent/*.yml\nvalue: main\n")
|
||||
internal := engineSourceInfoFromLoad(t, file, "source-1", engine.Options[recordConfig]{Imports: true})
|
||||
converted := fromEngineSourceInfo(internal)
|
||||
if len(converted.ImportSelections) != 1 || converted.ImportSelections[0].Path.String() != "/configkit/imports/0" ||
|
||||
converted.ImportSelections[0].Location.SourceID != internal.ID || converted.ImportSelections[0].Location.Line != 3 ||
|
||||
converted.ImportSelections[0].Selector != ImportSelectorGlob || converted.ImportSelections[0].Outcome != ImportSelectionNone {
|
||||
t.Fatalf("converted selection evidence = %#v", converted.ImportSelections)
|
||||
if len(converted.EmptyImportSelections) != 1 || converted.EmptyImportSelections[0].Path.String() != "/configkit/imports/0" ||
|
||||
converted.EmptyImportSelections[0].Location.SourceID != internal.ID || converted.EmptyImportSelections[0].Location.Line != 3 ||
|
||||
converted.EmptyImportSelections[0].Selector != ImportSelectorGlob {
|
||||
t.Fatalf("converted selection evidence = %#v", converted.EmptyImportSelections)
|
||||
}
|
||||
if converted.ImportSelections[0].Outcome != ImportSelectionNone {
|
||||
t.Fatalf("source selection outcome = %q", converted.ImportSelections[0].Outcome)
|
||||
}
|
||||
if fromEngineImportSelections(nil) != nil {
|
||||
if fromEngineEmptyImportSelections(nil) != nil {
|
||||
t.Fatal("converting nil engine selections returned a non-nil slice")
|
||||
}
|
||||
if fromEngineImportSelections([]engine.ImportSelectionForFacade{}) == nil {
|
||||
if fromEngineEmptyImportSelections([]engine.ImportSelectionForFacade{}) == nil {
|
||||
t.Fatal("converting an empty engine selection slice returned nil")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user