diff --git a/d2ir/compile.go b/d2ir/compile.go index 4a4d5f9fce..e991431aaa 100644 --- a/d2ir/compile.go +++ b/d2ir/compile.go @@ -362,9 +362,14 @@ func (c *compiler) overlay(base *Map, f *Field) { f.Composite = base } -func (g *globContext) prefixed(dst *Map) *globContext { +func (g *globContext) copy() *globContext { g2 := *g g2.refctx = g.root.refctx.Copy() + return &g2 +} + +func (g *globContext) prefixed(dst *Map) *globContext { + g2 := g.copy() prefix := d2ast.MakeKeyPath(RelIDA(g2.refctx.ScopeMap, dst)) g2.refctx.Key = g2.refctx.Key.Copy() if g2.refctx.Key.Key != nil { @@ -373,7 +378,7 @@ func (g *globContext) prefixed(dst *Map) *globContext { if len(prefix.Path) > 0 { g2.refctx.Key.Key = prefix } - return &g2 + return g2 } func (c *compiler) ampersandFilterMap(dst *Map, ast, scopeAST *d2ast.Map) bool { @@ -427,6 +432,7 @@ func (c *compiler) compileMap(dst *Map, ast, scopeAST *d2ast.Map) { } c.globContextStack = append(c.globContextStack, globs) defer func() { + dst.globs = c.globContexts() c.globContextStack = c.globContextStack[:len(c.globContextStack)-1] }() @@ -464,6 +470,20 @@ func (c *compiler) compileMap(dst *Map, ast, scopeAST *d2ast.Map) { c.errorf(n.Import, "cannot spread import non map into map") continue } + + for _, gctx := range impn.Map().globs { + if !gctx.refctx.Key.HasTripleGlob() { + continue + } + if gctx.refctx.ScopeMap != impn.Map() { + continue + } + gctx2 := gctx.copy() + gctx2.refctx.ScopeMap = dst + c.compileKey(gctx2.refctx) + c.ensureGlobContext(gctx2.refctx) + } + OverlayMap(dst, impn.Map()) if impnf, ok := impn.(*Field); ok { @@ -474,6 +494,13 @@ func (c *compiler) compileMap(dst *Map, ast, scopeAST *d2ast.Map) { } } } + + for _, gctx2 := range c.globContexts() { + old := c.lazyGlobBeingApplied + c.lazyGlobBeingApplied = true + c.compileKey(gctx2.refctx) + c.lazyGlobBeingApplied = old + } } } } diff --git a/d2ir/d2ir.go b/d2ir/d2ir.go index 95401c1e7c..72bcc116d1 100644 --- a/d2ir/d2ir.go +++ b/d2ir/d2ir.go @@ -170,6 +170,8 @@ type Map struct { parent Node Fields []*Field `json:"fields"` Edges []*Edge `json:"edges"` + + globs []*globContext } func (m *Map) initRoot() { diff --git a/d2ir/pattern_test.go b/d2ir/pattern_test.go index 7301af806a..e60ec0b11d 100644 --- a/d2ir/pattern_test.go +++ b/d2ir/pattern_test.go @@ -734,6 +734,22 @@ two assertQuery(t, m, 12, 0, nil, "") }, }, + { + name: "import-glob", + run: func(t testing.TB) { + m, err := compileFS(t, "index.d2", map[string]string{ + "index.d2": "before; ...@globs.d2; after", + "globs.d2": `*: jingle +**: true +***: meow`, + }) + assert.Success(t, err) + + assertQuery(t, m, 2, 0, nil, "") + assertQuery(t, m, 0, 0, "meow", "before") + assertQuery(t, m, 0, 0, "meow", "after") + }, + }, } runa(t, tca) diff --git a/testdata/d2ir/TestCompile/patterns/import-glob.exp.json b/testdata/d2ir/TestCompile/patterns/import-glob.exp.json new file mode 100644 index 0000000000..7c0aa92b03 --- /dev/null +++ b/testdata/d2ir/TestCompile/patterns/import-glob.exp.json @@ -0,0 +1,143 @@ +{ + "fields": [ + { + "name": "before", + "primary": { + "value": { + "range": "globs.d2,2:5:24-2:9:28", + "value": [ + { + "string": "meow", + "raw_string": "meow" + } + ] + } + }, + "references": [ + { + "string": { + "range": "index.d2,0:0:0-0:6:6", + "value": [ + { + "string": "before", + "raw_string": "before" + } + ] + }, + "key_path": { + "range": "index.d2,0:0:0-0:6:6", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:6:6", + "value": [ + { + "string": "before", + "raw_string": "before" + } + ] + } + } + ] + }, + "context": { + "edge": null, + "key": { + "range": "index.d2,0:0:0-0:6:6", + "key": { + "range": "index.d2,0:0:0-0:6:6", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:6:6", + "value": [ + { + "string": "before", + "raw_string": "before" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + }, + "due_to_glob": false, + "due_to_lazy_glob": false + } + ] + }, + { + "name": "after", + "primary": { + "value": { + "range": "globs.d2,2:5:24-2:9:28", + "value": [ + { + "string": "meow", + "raw_string": "meow" + } + ] + } + }, + "references": [ + { + "string": { + "range": "index.d2,0:22:22-0:27:27", + "value": [ + { + "string": "after", + "raw_string": "after" + } + ] + }, + "key_path": { + "range": "index.d2,0:22:22-0:27:27", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:22:22-0:27:27", + "value": [ + { + "string": "after", + "raw_string": "after" + } + ] + } + } + ] + }, + "context": { + "edge": null, + "key": { + "range": "index.d2,0:22:22-0:27:27", + "key": { + "range": "index.d2,0:22:22-0:27:27", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:22:22-0:27:27", + "value": [ + { + "string": "after", + "raw_string": "after" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + }, + "due_to_glob": false, + "due_to_lazy_glob": false + } + ] + } + ], + "edges": null +}