Start of matching rule changes

This commit is contained in:
Ian Gulliver
2023-10-16 23:34:02 -07:00
parent 5cb5d1f0a7
commit ca83087159
12 changed files with 47 additions and 21 deletions

View File

@@ -1,6 +1,7 @@
package bkl
import (
"github.com/gopatchy/bkl/polyfill"
"go.jetpack.io/typeid"
)
@@ -27,13 +28,17 @@ func (d *Document) AddParents(parents ...*Document) {
}
func (d *Document) AllParents() []*Document {
ret := append([]*Document{}, d.Parents...)
parents := map[typeid.TypeID]*Document{}
for _, parent := range d.Parents {
ret = append(ret, parent.AllParents()...)
parents[parent.ID] = parent
for _, doc := range parent.AllParents() {
parents[doc.ID] = doc
}
}
return ret
return polyfill.MapsValues(parents)
}
func (d *Document) DataAsMap() map[string]any {

View File

@@ -9,7 +9,7 @@ tidy:
test:
{{go}} vet ./...
# golangci-lint run ./...
{{go}} test -race -coverprofile=cover.out -timeout=30s ./...
{{go}} test -race -coverprofile=cover.out -timeout=60s ./...
{{go}} tool cover -html=cover.out -o=cover.html
GOCMD={{go}} ./test

View File

@@ -29,7 +29,7 @@ func merge(dst any, src any) (any, error) {
default:
if src == dst {
return nil, fmt.Errorf("%v: %w", src, ErrUselessOverride)
return nil, fmt.Errorf("%#v: %w", src, ErrUselessOverride)
}
return src, nil

View File

@@ -12,6 +12,7 @@ import (
"os"
"github.com/gopatchy/bkl/polyfill"
"go.jetpack.io/typeid"
)
// A Parser reads input documents, merges layers, and generates outputs.
@@ -80,7 +81,7 @@ func (p *Parser) SetDebug(debug bool) {
// MergeDocument applies the supplied Document to the [Parser]'s current
// internal document state using bkl's merge semantics. If expand is true,
// documents without $match will append; otherwise this is an error.
func (p *Parser) MergeDocument(patch *Document, expand bool) error {
func (p *Parser) MergeDocument(patch *Document) error {
matched, err := p.mergePatchMatch(patch)
if err != nil {
return err
@@ -90,17 +91,31 @@ func (p *Parser) MergeDocument(patch *Document, expand bool) error {
return nil
}
if expand {
docIDs := map[typeid.TypeID]bool{}
for _, doc := range p.docs {
docIDs[doc.ID] = true
}
for _, parent := range patch.AllParents() {
if !docIDs[parent.ID] {
// Parent but not in the parser's state
continue
}
matched = true
err = mergeDocs(parent, patch)
if err != nil {
return err
}
}
if !matched {
p.docs = append(p.docs, patch)
return nil
}
// Don't require $match when there's only one document
if len(p.docs) == 1 {
return mergeDocs(p.docs[0], patch)
}
return fmt.Errorf("%v: %w", patch, ErrMissingMatch)
return nil
}
// mergePatchMatch attempts to apply the supplied patch to one or more
@@ -172,15 +187,12 @@ func (p *Parser) MergeFileLayers(path string) error {
// mergeFile applies an already-parsed file object into the [Parser]'s
// document state.
func (p *Parser) mergeFile(f *file) error {
// First file in an empty parser can append without $match
first := len(p.docs) == 0
p.log("[%s] merging", f)
for _, doc := range f.docs {
p.log("[%s] merging", doc)
err := p.MergeDocument(doc, first)
err := p.MergeDocument(doc)
if err != nil {
return fmt.Errorf("[%s:%s]: %w", f, doc, err)
}

View File

@@ -93,12 +93,12 @@ func ExampleParser_MergeDocument() {
doc2 := bkl.NewDocumentWithData(map[string]any{"b": 2})
doc2.AddParents(doc1)
err := b.MergeDocument(doc1, true)
err := b.MergeDocument(doc1)
if err != nil {
panic(err)
}
err = b.MergeDocument(doc2, false)
err = b.MergeDocument(doc2)
if err != nil {
panic(err)
}

View File

@@ -15,10 +15,13 @@ func MapsClone[M ~map[K]V, K comparable, V any](m M) M { //nolint:ireturn
}
func MapsKeys[M ~map[K]V, K comparable, V any](m M) []K { //nolint:ireturn
// Added to 1.21 maps then removed again
return xmaps.Keys(m)
}
func MapsValues[M ~map[K]V, K comparable, V any](m M) []V { //nolint:ireturn
return xmaps.Values(m)
}
func SlicesClone[S ~[]E, E any](s S) S { //nolint:ireturn
return slices.Clone(s)
}

View File

@@ -27,6 +27,10 @@ func MapsKeys[M ~map[K]V, K comparable, V any](m M) []K { //nolint:ireturn
return maps.Keys(m)
}
func MapsValues[M ~map[K]V, K comparable, V any](m M) []V { //nolint:ireturn
return maps.Values(m)
}
// Copied from go1.21 slices
func SlicesClone[S ~[]E, E any](s S) S { //nolint:ireturn
if s == nil {

View File

@@ -1,2 +1,3 @@
$match: {}
b: 10
c: 3

View File

@@ -1 +1,2 @@
$match: {}
b: 2