d2ir: Implement lazy globs and triple glob
This finishes up the globs implementation! See tests for what I mean by lazy globs and what the triple glob does.
This commit is contained in:
parent
24a1e006d0
commit
bb6b176dee
10 changed files with 25522 additions and 741 deletions
|
|
@ -723,7 +723,43 @@ func (mk *Key) SetScalar(scalar ScalarBox) {
|
|||
}
|
||||
}
|
||||
|
||||
func (mk *Key) HasQueryGlob() bool {
|
||||
func (mk *Key) HasGlob() bool {
|
||||
if mk.Key.HasGlob() {
|
||||
return true
|
||||
}
|
||||
for _, e := range mk.Edges {
|
||||
if e.Src.HasGlob() || e.Dst.HasGlob() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
if mk.EdgeIndex != nil && mk.EdgeIndex.Glob {
|
||||
return true
|
||||
}
|
||||
if mk.EdgeKey.HasGlob() {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (mk *Key) HasTripleGlob() bool {
|
||||
if mk.Key.HasTripleGlob() {
|
||||
return true
|
||||
}
|
||||
for _, e := range mk.Edges {
|
||||
if e.Src.HasTripleGlob() || e.Dst.HasTripleGlob() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
if mk.EdgeIndex != nil && mk.EdgeIndex.Glob {
|
||||
return true
|
||||
}
|
||||
if mk.EdgeKey.HasTripleGlob() {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (mk *Key) SupportsGlobFilters() bool {
|
||||
if mk.Key.HasGlob() && len(mk.Edges) == 0 {
|
||||
return true
|
||||
}
|
||||
|
|
@ -736,6 +772,11 @@ func (mk *Key) HasQueryGlob() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (mk *Key) Copy() *Key {
|
||||
mk2 := *mk
|
||||
return &mk2
|
||||
}
|
||||
|
||||
type KeyPath struct {
|
||||
Range Range `json:"range"`
|
||||
Path []*StringBox `json:"path"`
|
||||
|
|
@ -763,16 +804,12 @@ func (kp *KeyPath) Copy() *KeyPath {
|
|||
return &kp2
|
||||
}
|
||||
|
||||
func (kp *KeyPath) HasDoubleGlob() bool {
|
||||
if kp == nil {
|
||||
return false
|
||||
}
|
||||
for _, el := range kp.Path {
|
||||
if el.UnquotedString != nil && el.ScalarString() == "**" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
func IsDoubleGlob(pattern []string) bool {
|
||||
return len(pattern) == 3 && pattern[0] == "*" && pattern[1] == "" && pattern[2] == "*"
|
||||
}
|
||||
|
||||
func IsTripleGlob(pattern []string) bool {
|
||||
return len(pattern) == 5 && pattern[0] == "*" && pattern[1] == "" && pattern[2] == "*" && pattern[3] == "" && pattern[4] == "*"
|
||||
}
|
||||
|
||||
func (kp *KeyPath) HasGlob() bool {
|
||||
|
|
@ -787,6 +824,30 @@ func (kp *KeyPath) HasGlob() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (kp *KeyPath) HasTripleGlob() bool {
|
||||
if kp == nil {
|
||||
return false
|
||||
}
|
||||
for _, el := range kp.Path {
|
||||
if el.UnquotedString != nil && IsTripleGlob(el.UnquotedString.Pattern) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (kp *KeyPath) HasMultiGlob() bool {
|
||||
if kp == nil {
|
||||
return false
|
||||
}
|
||||
for _, el := range kp.Path {
|
||||
if el.UnquotedString != nil && (IsDoubleGlob(el.UnquotedString.Pattern) || IsTripleGlob(el.UnquotedString.Pattern)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type Edge struct {
|
||||
Range Range `json:"range"`
|
||||
|
||||
|
|
|
|||
126
d2ir/compile.go
126
d2ir/compile.go
|
|
@ -5,14 +5,23 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
"oss.terrastruct.com/util-go/go2"
|
||||
|
||||
"oss.terrastruct.com/d2/d2ast"
|
||||
"oss.terrastruct.com/d2/d2format"
|
||||
"oss.terrastruct.com/d2/d2parser"
|
||||
"oss.terrastruct.com/d2/d2themes"
|
||||
"oss.terrastruct.com/d2/d2themes/d2themescatalog"
|
||||
"oss.terrastruct.com/util-go/go2"
|
||||
)
|
||||
|
||||
type globContext struct {
|
||||
refctx *RefContext
|
||||
// Set of BoardIDA that this glob has already applied to.
|
||||
appliedFields map[string]struct{}
|
||||
// Set of Edge IDs that this glob has already applied to.
|
||||
appliedEdges map[string]struct{}
|
||||
}
|
||||
|
||||
type compiler struct {
|
||||
err *d2parser.ParseError
|
||||
|
||||
|
|
@ -23,7 +32,12 @@ type compiler struct {
|
|||
importCache map[string]*Map
|
||||
utf16Pos bool
|
||||
|
||||
globStack []bool
|
||||
// Stack of globs that must be recomputed at each new object in and below the current scope.
|
||||
globContextStack [][]*globContext
|
||||
// Used to prevent field globs causing infinite loops.
|
||||
globRefContextStack []*RefContext
|
||||
// Used to check whether ampersands are allowed in the current map.
|
||||
mapRefContextStack []*RefContext
|
||||
}
|
||||
|
||||
type CompileOptions struct {
|
||||
|
|
@ -346,6 +360,52 @@ func (c *compiler) overlay(base *Map, f *Field) {
|
|||
}
|
||||
|
||||
func (c *compiler) compileMap(dst *Map, ast, scopeAST *d2ast.Map) {
|
||||
var globs []*globContext
|
||||
if len(c.globContextStack) > 0 {
|
||||
previousGlobs := c.globContextStack[len(c.globContextStack)-1]
|
||||
if NodeBoardKind(dst) == BoardLayer {
|
||||
for _, g := range previousGlobs {
|
||||
if g.refctx.Key.HasTripleGlob() {
|
||||
// Same as below but reset applied too.
|
||||
g2 := *g
|
||||
g2.refctx = g.refctx.Copy()
|
||||
g2.appliedFields = make(map[string]struct{})
|
||||
g2.appliedEdges = make(map[string]struct{})
|
||||
prefix := d2ast.MakeKeyPath(RelIDA(g2.refctx.ScopeMap, dst))
|
||||
g2.refctx.Key = g2.refctx.Key.Copy()
|
||||
if g2.refctx.Key.Key != nil {
|
||||
prefix.Path = append(prefix.Path, g2.refctx.Key.Key.Path...)
|
||||
}
|
||||
if len(prefix.Path) > 0 {
|
||||
g2.refctx.Key.Key = prefix
|
||||
}
|
||||
globs = append(globs, &g2)
|
||||
}
|
||||
}
|
||||
} else if NodeBoardKind(dst) != "" {
|
||||
// Make all globs relative to the scenario or step.
|
||||
for _, g := range previousGlobs {
|
||||
g2 := *g
|
||||
g2.refctx = g.refctx.Copy()
|
||||
prefix := d2ast.MakeKeyPath(RelIDA(g2.refctx.ScopeMap, dst))
|
||||
g2.refctx.Key = g2.refctx.Key.Copy()
|
||||
if g2.refctx.Key.Key != nil {
|
||||
prefix.Path = append(prefix.Path, g2.refctx.Key.Key.Path...)
|
||||
}
|
||||
if len(prefix.Path) > 0 {
|
||||
g2.refctx.Key.Key = prefix
|
||||
}
|
||||
globs = append(globs, &g2)
|
||||
}
|
||||
} else {
|
||||
globs = append(globs, previousGlobs...)
|
||||
}
|
||||
}
|
||||
c.globContextStack = append(c.globContextStack, globs)
|
||||
defer func() {
|
||||
c.globContextStack = c.globContextStack[:len(c.globContextStack)-1]
|
||||
}()
|
||||
|
||||
for _, n := range ast.Nodes {
|
||||
switch {
|
||||
case n.MapKey != nil:
|
||||
|
|
@ -403,7 +463,47 @@ func (c *compiler) compileMap(dst *Map, ast, scopeAST *d2ast.Map) {
|
|||
}
|
||||
}
|
||||
|
||||
func (c *compiler) globContexts() []*globContext {
|
||||
return c.globContextStack[len(c.globContextStack)-1]
|
||||
}
|
||||
|
||||
func (c *compiler) getGlobContext(refctx *RefContext) *globContext {
|
||||
for _, gctx := range c.globContexts() {
|
||||
if gctx.refctx.Equal(refctx) {
|
||||
return gctx
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *compiler) ensureGlobContext(refctx *RefContext) *globContext {
|
||||
gctx := c.getGlobContext(refctx)
|
||||
if gctx != nil {
|
||||
return gctx
|
||||
}
|
||||
gctx = &globContext{
|
||||
refctx: refctx,
|
||||
appliedFields: make(map[string]struct{}),
|
||||
appliedEdges: make(map[string]struct{}),
|
||||
}
|
||||
c.globContextStack[len(c.globContextStack)-1] = append(c.globContexts(), gctx)
|
||||
return gctx
|
||||
}
|
||||
|
||||
func (c *compiler) compileKey(refctx *RefContext) {
|
||||
if refctx.Key.HasGlob() {
|
||||
for _, refctx2 := range c.globRefContextStack {
|
||||
if refctx.Equal(refctx2) {
|
||||
// Break the infinite loop.
|
||||
return
|
||||
}
|
||||
}
|
||||
c.globRefContextStack = append(c.globRefContextStack, refctx)
|
||||
defer func() {
|
||||
c.globRefContextStack = c.globRefContextStack[:len(c.globRefContextStack)-1]
|
||||
}()
|
||||
c.ensureGlobContext(refctx)
|
||||
}
|
||||
if len(refctx.Key.Edges) == 0 {
|
||||
c.compileField(refctx.ScopeMap, refctx.Key.Key, refctx)
|
||||
} else {
|
||||
|
|
@ -416,7 +516,7 @@ func (c *compiler) compileField(dst *Map, kp *d2ast.KeyPath, refctx *RefContext)
|
|||
return
|
||||
}
|
||||
|
||||
fa, err := dst.EnsureField(kp, refctx, true)
|
||||
fa, err := dst.EnsureField(kp, refctx, true, c)
|
||||
if err != nil {
|
||||
c.err.Errors = append(c.err.Errors, err.(d2ast.Error))
|
||||
return
|
||||
|
|
@ -431,7 +531,7 @@ func (c *compiler) ampersandFilter(refctx *RefContext) bool {
|
|||
if !refctx.Key.Ampersand {
|
||||
return true
|
||||
}
|
||||
if len(c.globStack) == 0 || !c.globStack[len(c.globStack)-1] {
|
||||
if len(c.mapRefContextStack) == 0 || !c.mapRefContextStack[len(c.mapRefContextStack)-1].Key.SupportsGlobFilters() {
|
||||
c.errorf(refctx.Key, "glob filters cannot be used outside globs")
|
||||
return false
|
||||
}
|
||||
|
|
@ -439,7 +539,7 @@ func (c *compiler) ampersandFilter(refctx *RefContext) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
fa, err := refctx.ScopeMap.EnsureField(refctx.Key.Key, refctx, false)
|
||||
fa, err := refctx.ScopeMap.EnsureField(refctx.Key.Key, refctx, false, c)
|
||||
if err != nil {
|
||||
c.err.Errors = append(c.err.Errors, err.(d2ast.Error))
|
||||
return false
|
||||
|
|
@ -532,9 +632,9 @@ func (c *compiler) _compileField(f *Field, refctx *RefContext) {
|
|||
// If new board type, use that as the new scope AST, otherwise, carry on
|
||||
scopeAST = refctx.ScopeAST
|
||||
}
|
||||
c.globStack = append(c.globStack, refctx.Key.HasQueryGlob())
|
||||
c.mapRefContextStack = append(c.mapRefContextStack, refctx)
|
||||
c.compileMap(f.Map(), refctx.Key.Value.Map, scopeAST)
|
||||
c.globStack = c.globStack[:len(c.globStack)-1]
|
||||
c.mapRefContextStack = c.mapRefContextStack[:len(c.mapRefContextStack)-1]
|
||||
switch NodeBoardKind(f) {
|
||||
case BoardScenario, BoardStep:
|
||||
c.overlayClasses(f.Map())
|
||||
|
|
@ -692,7 +792,7 @@ func (c *compiler) compileEdges(refctx *RefContext) {
|
|||
return
|
||||
}
|
||||
|
||||
fa, err := refctx.ScopeMap.EnsureField(refctx.Key.Key, refctx, true)
|
||||
fa, err := refctx.ScopeMap.EnsureField(refctx.Key.Key, refctx, true, c)
|
||||
if err != nil {
|
||||
c.err.Errors = append(c.err.Errors, err.(d2ast.Error))
|
||||
return
|
||||
|
|
@ -728,7 +828,9 @@ func (c *compiler) _compileEdges(refctx *RefContext) {
|
|||
if eid.Index != nil || eid.Glob {
|
||||
ea = refctx.ScopeMap.GetEdges(eid, refctx)
|
||||
if len(ea) == 0 {
|
||||
c.errorf(refctx.Edge, "indexed edge does not exist")
|
||||
if !eid.Glob {
|
||||
c.errorf(refctx.Edge, "indexed edge does not exist")
|
||||
}
|
||||
continue
|
||||
}
|
||||
for _, e := range ea {
|
||||
|
|
@ -740,7 +842,7 @@ func (c *compiler) _compileEdges(refctx *RefContext) {
|
|||
}
|
||||
} else {
|
||||
var err error
|
||||
ea, err = refctx.ScopeMap.CreateEdge(eid, refctx)
|
||||
ea, err = refctx.ScopeMap.CreateEdge(eid, refctx, c)
|
||||
if err != nil {
|
||||
c.err.Errors = append(c.err.Errors, err.(d2ast.Error))
|
||||
continue
|
||||
|
|
@ -771,9 +873,9 @@ func (c *compiler) _compileEdges(refctx *RefContext) {
|
|||
parent: e,
|
||||
}
|
||||
}
|
||||
c.globStack = append(c.globStack, refctx.Key.HasQueryGlob())
|
||||
c.mapRefContextStack = append(c.mapRefContextStack, refctx)
|
||||
c.compileMap(e.Map_, refctx.Key.Value.Map, refctx.ScopeAST)
|
||||
c.globStack = c.globStack[:len(c.globStack)-1]
|
||||
c.mapRefContextStack = c.mapRefContextStack[:len(c.mapRefContextStack)-1]
|
||||
} else if refctx.Key.Value.ScalarBox().Unbox() != nil {
|
||||
e.Primary_ = &Scalar{
|
||||
parent: e,
|
||||
|
|
|
|||
128
d2ir/d2ir.go
128
d2ir/d2ir.go
|
|
@ -245,7 +245,11 @@ func NodeBoardKind(n Node) BoardKind {
|
|||
}
|
||||
f = ParentField(n)
|
||||
case *Map:
|
||||
f = ParentField(n)
|
||||
var ok bool
|
||||
f, ok = n.parent.(*Field)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
if f.Root() {
|
||||
return BoardLayer
|
||||
}
|
||||
|
|
@ -569,6 +573,10 @@ func (rc *RefContext) EdgeIndex() int {
|
|||
return -1
|
||||
}
|
||||
|
||||
func (rc *RefContext) Equal(rc2 *RefContext) bool {
|
||||
return rc.Edge == rc2.Edge && rc.Key.Equals(rc2.Key) && rc.Scope == rc2.Scope && rc.ScopeMap == rc2.ScopeMap && rc.ScopeAST == rc2.ScopeAST
|
||||
}
|
||||
|
||||
func (m *Map) FieldCountRecursive() int {
|
||||
if m == nil {
|
||||
return 0
|
||||
|
|
@ -667,7 +675,7 @@ func (m *Map) getField(ida []string) *Field {
|
|||
}
|
||||
|
||||
// EnsureField is a bit of a misnomer. It's more of a Query/Ensure combination function at this point.
|
||||
func (m *Map) EnsureField(kp *d2ast.KeyPath, refctx *RefContext, create bool) ([]*Field, error) {
|
||||
func (m *Map) EnsureField(kp *d2ast.KeyPath, refctx *RefContext, create bool, c *compiler) ([]*Field, error) {
|
||||
i := 0
|
||||
for kp.Path[i].Unbox().ScalarString() == "_" {
|
||||
m = ParentMap(m)
|
||||
|
|
@ -680,18 +688,47 @@ func (m *Map) EnsureField(kp *d2ast.KeyPath, refctx *RefContext, create bool) ([
|
|||
i++
|
||||
}
|
||||
|
||||
var gctx *globContext
|
||||
if refctx != nil && refctx.Key.HasGlob() && c != nil {
|
||||
gctx = c.getGlobContext(refctx)
|
||||
}
|
||||
|
||||
var fa []*Field
|
||||
err := m.ensureField(i, kp, refctx, create, &fa)
|
||||
return fa, err
|
||||
err := m.ensureField(i, kp, refctx, create, gctx, c, &fa)
|
||||
if err != nil {
|
||||
return fa, err
|
||||
}
|
||||
if len(fa) > 0 && create && c != nil {
|
||||
for _, gctx2 := range c.globContexts() {
|
||||
c.compileKey(gctx2.refctx)
|
||||
}
|
||||
}
|
||||
return fa, nil
|
||||
}
|
||||
|
||||
func (m *Map) ensureField(i int, kp *d2ast.KeyPath, refctx *RefContext, create bool, fa *[]*Field) error {
|
||||
func (m *Map) ensureField(i int, kp *d2ast.KeyPath, refctx *RefContext, create bool, gctx *globContext, c *compiler, fa *[]*Field) error {
|
||||
faAppend := func(fa2 ...*Field) {
|
||||
for _, f := range fa2 {
|
||||
if gctx != nil {
|
||||
// Always match all commons, sources and destinations for edge globs.
|
||||
if len(refctx.Key.Edges) == 0 || kp == refctx.Key.EdgeKey {
|
||||
ks := d2format.Format(d2ast.MakeKeyPath(BoardIDA(f)))
|
||||
if _, ok := gctx.appliedFields[ks]; ok {
|
||||
continue
|
||||
}
|
||||
gctx.appliedFields[ks] = struct{}{}
|
||||
}
|
||||
}
|
||||
*fa = append(*fa, f)
|
||||
}
|
||||
}
|
||||
|
||||
us, ok := kp.Path[i].Unbox().(*d2ast.UnquotedString)
|
||||
if ok && us.Pattern != nil {
|
||||
fa2, ok := m.doubleGlob(us.Pattern)
|
||||
fa2, ok := m.multiGlob(us.Pattern)
|
||||
if ok {
|
||||
if i == len(kp.Path)-1 {
|
||||
*fa = append(*fa, fa2...)
|
||||
faAppend(fa2...)
|
||||
} else {
|
||||
for _, f := range fa2 {
|
||||
if f.Map() == nil {
|
||||
|
|
@ -699,7 +736,7 @@ func (m *Map) ensureField(i int, kp *d2ast.KeyPath, refctx *RefContext, create b
|
|||
parent: f,
|
||||
}
|
||||
}
|
||||
err := f.Map().ensureField(i+1, kp, refctx, create, fa)
|
||||
err := f.Map().ensureField(i+1, kp, refctx, create, gctx, c, fa)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -710,14 +747,14 @@ func (m *Map) ensureField(i int, kp *d2ast.KeyPath, refctx *RefContext, create b
|
|||
for _, f := range m.Fields {
|
||||
if matchPattern(f.Name, us.Pattern) {
|
||||
if i == len(kp.Path)-1 {
|
||||
*fa = append(*fa, f)
|
||||
faAppend(f)
|
||||
} else {
|
||||
if f.Map() == nil {
|
||||
f.Composite = &Map{
|
||||
parent: f,
|
||||
}
|
||||
}
|
||||
err := f.Map().ensureField(i+1, kp, refctx, create, fa)
|
||||
err := f.Map().ensureField(i+1, kp, refctx, create, gctx, c, fa)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -763,7 +800,7 @@ func (m *Map) ensureField(i int, kp *d2ast.KeyPath, refctx *RefContext, create b
|
|||
}
|
||||
|
||||
if i+1 == len(kp.Path) {
|
||||
*fa = append(*fa, f)
|
||||
faAppend(f)
|
||||
return nil
|
||||
}
|
||||
if _, ok := f.Composite.(*Array); ok {
|
||||
|
|
@ -774,7 +811,7 @@ func (m *Map) ensureField(i int, kp *d2ast.KeyPath, refctx *RefContext, create b
|
|||
parent: f,
|
||||
}
|
||||
}
|
||||
return f.Map().ensureField(i+1, kp, refctx, create, fa)
|
||||
return f.Map().ensureField(i+1, kp, refctx, create, gctx, c, fa)
|
||||
}
|
||||
|
||||
if !create {
|
||||
|
|
@ -797,10 +834,12 @@ func (m *Map) ensureField(i int, kp *d2ast.KeyPath, refctx *RefContext, create b
|
|||
*fa = append(*fa, f)
|
||||
return nil
|
||||
}
|
||||
f.Composite = &Map{
|
||||
parent: f,
|
||||
if f.Composite == nil {
|
||||
f.Composite = &Map{
|
||||
parent: f,
|
||||
}
|
||||
}
|
||||
return f.Map().ensureField(i+1, kp, refctx, create, fa)
|
||||
return f.Map().ensureField(i+1, kp, refctx, create, gctx, c, fa)
|
||||
}
|
||||
|
||||
func (m *Map) DeleteEdge(eid *EdgeID) *Edge {
|
||||
|
|
@ -914,7 +953,7 @@ func (m *Map) getEdges(eid *EdgeID, refctx *RefContext, ea *[]*Edge) error {
|
|||
}
|
||||
}
|
||||
}
|
||||
fa, err := m.EnsureField(commonKP, nil, false)
|
||||
fa, err := m.EnsureField(commonKP, nil, false, nil)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -935,11 +974,11 @@ func (m *Map) getEdges(eid *EdgeID, refctx *RefContext, ea *[]*Edge) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
srcFA, err := refctx.ScopeMap.EnsureField(refctx.Edge.Src, nil, false)
|
||||
srcFA, err := refctx.ScopeMap.EnsureField(refctx.Edge.Src, nil, false, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dstFA, err := refctx.ScopeMap.EnsureField(refctx.Edge.Dst, nil, false)
|
||||
dstFA, err := refctx.ScopeMap.EnsureField(refctx.Edge.Dst, nil, false, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -957,12 +996,25 @@ func (m *Map) getEdges(eid *EdgeID, refctx *RefContext, ea *[]*Edge) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (m *Map) CreateEdge(eid *EdgeID, refctx *RefContext) ([]*Edge, error) {
|
||||
func (m *Map) CreateEdge(eid *EdgeID, refctx *RefContext, c *compiler) ([]*Edge, error) {
|
||||
var ea []*Edge
|
||||
return ea, m.createEdge(eid, refctx, &ea)
|
||||
var gctx *globContext
|
||||
if refctx != nil && refctx.Key.HasGlob() && c != nil {
|
||||
gctx = c.getGlobContext(refctx)
|
||||
}
|
||||
err := m.createEdge(eid, refctx, gctx, c, &ea)
|
||||
if err != nil {
|
||||
return ea, err
|
||||
}
|
||||
if len(ea) > 0 && c != nil {
|
||||
for _, gctx2 := range c.globContexts() {
|
||||
c.compileKey(gctx2.refctx)
|
||||
}
|
||||
}
|
||||
return ea, nil
|
||||
}
|
||||
|
||||
func (m *Map) createEdge(eid *EdgeID, refctx *RefContext, ea *[]*Edge) error {
|
||||
func (m *Map) createEdge(eid *EdgeID, refctx *RefContext, gctx *globContext, c *compiler, ea *[]*Edge) error {
|
||||
if ParentEdge(m) != nil {
|
||||
return d2parser.Errorf(refctx.Edge, "cannot create edge inside edge")
|
||||
}
|
||||
|
|
@ -983,7 +1035,7 @@ func (m *Map) createEdge(eid *EdgeID, refctx *RefContext, ea *[]*Edge) error {
|
|||
}
|
||||
}
|
||||
}
|
||||
fa, err := m.EnsureField(commonKP, nil, true)
|
||||
fa, err := m.EnsureField(commonKP, nil, true, c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -996,7 +1048,7 @@ func (m *Map) createEdge(eid *EdgeID, refctx *RefContext, ea *[]*Edge) error {
|
|||
parent: f,
|
||||
}
|
||||
}
|
||||
err = f.Map().createEdge(eid, refctx, ea)
|
||||
err = f.Map().createEdge(eid, refctx, gctx, c, ea)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -1022,11 +1074,11 @@ func (m *Map) createEdge(eid *EdgeID, refctx *RefContext, ea *[]*Edge) error {
|
|||
return d2parser.Errorf(refctx.Edge.Dst.Path[ij].Unbox(), "edge with board keyword alone doesn't make sense")
|
||||
}
|
||||
|
||||
srcFA, err := refctx.ScopeMap.EnsureField(refctx.Edge.Src, refctx, true)
|
||||
srcFA, err := refctx.ScopeMap.EnsureField(refctx.Edge.Src, refctx, true, c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dstFA, err := refctx.ScopeMap.EnsureField(refctx.Edge.Dst, refctx, true)
|
||||
dstFA, err := refctx.ScopeMap.EnsureField(refctx.Edge.Dst, refctx, true, c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -1038,21 +1090,21 @@ func (m *Map) createEdge(eid *EdgeID, refctx *RefContext, ea *[]*Edge) error {
|
|||
continue
|
||||
}
|
||||
|
||||
if refctx.Edge.Src.HasDoubleGlob() {
|
||||
if refctx.Edge.Src.HasMultiGlob() {
|
||||
// If src has a double glob we only select leafs, those without children.
|
||||
if src.Map().IsContainer() {
|
||||
continue
|
||||
}
|
||||
if ParentBoard(src) != ParentBoard(dst) {
|
||||
if NodeBoardKind(src) != "" || ParentBoard(src) != ParentBoard(dst) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
if refctx.Edge.Dst.HasDoubleGlob() {
|
||||
if refctx.Edge.Dst.HasMultiGlob() {
|
||||
// If dst has a double glob we only select leafs, those without children.
|
||||
if dst.Map().IsContainer() {
|
||||
continue
|
||||
}
|
||||
if ParentBoard(src) != ParentBoard(dst) {
|
||||
if NodeBoardKind(dst) != "" || ParentBoard(src) != ParentBoard(dst) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
|
@ -1060,17 +1112,20 @@ func (m *Map) createEdge(eid *EdgeID, refctx *RefContext, ea *[]*Edge) error {
|
|||
eid2 := eid.Copy()
|
||||
eid2.SrcPath = RelIDA(m, src)
|
||||
eid2.DstPath = RelIDA(m, dst)
|
||||
e, err := m.createEdge2(eid2, refctx, src, dst)
|
||||
|
||||
e, err := m.createEdge2(eid2, refctx, gctx, src, dst)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*ea = append(*ea, e)
|
||||
if e != nil {
|
||||
*ea = append(*ea, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Map) createEdge2(eid *EdgeID, refctx *RefContext, src, dst *Field) (*Edge, error) {
|
||||
func (m *Map) createEdge2(eid *EdgeID, refctx *RefContext, gctx *globContext, src, dst *Field) (*Edge, error) {
|
||||
if NodeBoardKind(src) != "" {
|
||||
return nil, d2parser.Errorf(refctx.Edge.Src, "cannot create edges between boards")
|
||||
}
|
||||
|
|
@ -1094,6 +1149,15 @@ func (m *Map) createEdge2(eid *EdgeID, refctx *RefContext, src, dst *Field) (*Ed
|
|||
Context: refctx,
|
||||
}},
|
||||
}
|
||||
|
||||
if gctx != nil {
|
||||
ks := e.String()
|
||||
if _, ok := gctx.appliedEdges[ks]; ok {
|
||||
return nil, nil
|
||||
}
|
||||
gctx.appliedEdges[ks] = struct{}{}
|
||||
}
|
||||
|
||||
m.Edges = append(m.Edges, e)
|
||||
|
||||
return e, nil
|
||||
|
|
|
|||
|
|
@ -3,19 +3,41 @@ package d2ir
|
|||
import (
|
||||
"strings"
|
||||
|
||||
"oss.terrastruct.com/d2/d2ast"
|
||||
"oss.terrastruct.com/d2/d2graph"
|
||||
)
|
||||
|
||||
func (m *Map) doubleGlob(pattern []string) ([]*Field, bool) {
|
||||
if !(len(pattern) == 3 && pattern[0] == "*" && pattern[1] == "" && pattern[2] == "*") {
|
||||
return nil, false
|
||||
}
|
||||
func (m *Map) multiGlob(pattern []string) ([]*Field, bool) {
|
||||
var fa []*Field
|
||||
m._doubleGlob(&fa)
|
||||
return fa, true
|
||||
if d2ast.IsDoubleGlob(pattern) {
|
||||
m._doubleGlob(&fa)
|
||||
return fa, true
|
||||
}
|
||||
if d2ast.IsTripleGlob(pattern) {
|
||||
m._tripleGlob(&fa)
|
||||
return fa, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (m *Map) _doubleGlob(fa *[]*Field) {
|
||||
for _, f := range m.Fields {
|
||||
if _, ok := d2graph.ReservedKeywords[f.Name]; ok {
|
||||
if f.Name == "layers" {
|
||||
continue
|
||||
}
|
||||
if _, ok := d2graph.BoardKeywords[f.Name]; !ok {
|
||||
continue
|
||||
}
|
||||
}
|
||||
*fa = append(*fa, f)
|
||||
if f.Map() != nil {
|
||||
f.Map()._doubleGlob(fa)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Map) _tripleGlob(fa *[]*Field) {
|
||||
for _, f := range m.Fields {
|
||||
if _, ok := d2graph.ReservedKeywords[f.Name]; ok {
|
||||
if _, ok := d2graph.BoardKeywords[f.Name]; !ok {
|
||||
|
|
@ -24,7 +46,7 @@ func (m *Map) _doubleGlob(fa *[]*Field) {
|
|||
}
|
||||
*fa = append(*fa, f)
|
||||
if f.Map() != nil {
|
||||
f.Map()._doubleGlob(fa)
|
||||
f.Map()._tripleGlob(fa)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -285,6 +285,31 @@ d
|
|||
assertQuery(t, m, 0, 0, nil, "(* -> *)[*]")
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "single-glob/defaults",
|
||||
run: func(t testing.TB) {
|
||||
m, err := compile(t, `wrapper.*: {
|
||||
shape: page
|
||||
}
|
||||
|
||||
wrapper.a
|
||||
wrapper.b
|
||||
wrapper.c
|
||||
wrapper.d
|
||||
|
||||
scenarios.x: { wrapper.p }
|
||||
layers.x: { wrapper.p }
|
||||
`)
|
||||
assert.Success(t, err)
|
||||
assertQuery(t, m, 26, 0, nil, "")
|
||||
assertQuery(t, m, 0, 0, "page", "wrapper.a.shape")
|
||||
assertQuery(t, m, 0, 0, "page", "wrapper.b.shape")
|
||||
assertQuery(t, m, 0, 0, "page", "wrapper.c.shape")
|
||||
assertQuery(t, m, 0, 0, "page", "wrapper.d.shape")
|
||||
assertQuery(t, m, 0, 0, "page", "scenarios.x.wrapper.p.shape")
|
||||
assertQuery(t, m, 0, 0, nil, "layers.x.wrapper.p")
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "double-glob/edge/1",
|
||||
run: func(t testing.TB) {
|
||||
|
|
@ -314,21 +339,81 @@ task.** -> fast
|
|||
assertQuery(t, m, 3, 1, nil, "")
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "double-glob/defaults",
|
||||
run: func(t testing.TB) {
|
||||
m, err := compile(t, `**: {
|
||||
shape: page
|
||||
}
|
||||
|
||||
a
|
||||
b
|
||||
c
|
||||
d
|
||||
|
||||
scenarios.x: { p }
|
||||
layers.x: { p }
|
||||
`)
|
||||
assert.Success(t, err)
|
||||
assertQuery(t, m, 25, 0, nil, "")
|
||||
assertQuery(t, m, 0, 0, "page", "a.shape")
|
||||
assertQuery(t, m, 0, 0, "page", "b.shape")
|
||||
assertQuery(t, m, 0, 0, "page", "c.shape")
|
||||
assertQuery(t, m, 0, 0, "page", "d.shape")
|
||||
assertQuery(t, m, 0, 0, "page", "scenarios.x.p.shape")
|
||||
assertQuery(t, m, 0, 0, nil, "layers.x.p")
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "triple-glob/defaults",
|
||||
run: func(t testing.TB) {
|
||||
m, err := compile(t, `***: {
|
||||
shape: page
|
||||
}
|
||||
|
||||
a
|
||||
b
|
||||
c
|
||||
d
|
||||
|
||||
scenarios.x: { p }
|
||||
layers.x: { p }
|
||||
`)
|
||||
assert.Success(t, err)
|
||||
assertQuery(t, m, 27, 0, nil, "")
|
||||
assertQuery(t, m, 0, 0, "page", "a.shape")
|
||||
assertQuery(t, m, 0, 0, "page", "b.shape")
|
||||
assertQuery(t, m, 0, 0, "page", "c.shape")
|
||||
assertQuery(t, m, 0, 0, "page", "d.shape")
|
||||
assertQuery(t, m, 0, 0, "page", "scenarios.x.p.shape")
|
||||
assertQuery(t, m, 0, 0, "page", "layers.x.p.shape")
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "triple-glob/edge-defaults",
|
||||
run: func(t testing.TB) {
|
||||
m, err := compile(t, `(*** -> ***)[*]: {
|
||||
target-arrowhead.shape: diamond
|
||||
}
|
||||
|
||||
a -> b
|
||||
c -> d
|
||||
|
||||
scenarios.x: { p -> q }
|
||||
layers.x: { j -> f }
|
||||
`)
|
||||
assert.Success(t, err)
|
||||
assertQuery(t, m, 28, 6, nil, "")
|
||||
assertQuery(t, m, 0, 0, "diamond", "(a -> b)[0].target-arrowhead.shape")
|
||||
assertQuery(t, m, 0, 0, "diamond", "(c -> d)[0].target-arrowhead.shape")
|
||||
assertQuery(t, m, 0, 0, "diamond", "scenarios.x.(a -> b)[0].target-arrowhead.shape")
|
||||
assertQuery(t, m, 0, 0, "diamond", "scenarios.x.(c -> d)[0].target-arrowhead.shape")
|
||||
assertQuery(t, m, 0, 0, "diamond", "scenarios.x.(p -> q)[0].target-arrowhead.shape")
|
||||
assertQuery(t, m, 4, 1, nil, "layers.x")
|
||||
assertQuery(t, m, 0, 0, "diamond", "layers.x.(j -> f)[0].target-arrowhead.shape")
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
runa(t, tca)
|
||||
|
||||
t.Run("errors", func(t *testing.T) {
|
||||
tca := []testCase{
|
||||
{
|
||||
name: "glob-edge-glob-index",
|
||||
run: func(t testing.TB) {
|
||||
_, err := compile(t, `(* -> b)[*].style.fill: red
|
||||
`)
|
||||
assert.ErrorString(t, err, `TestCompile/patterns/errors/glob-edge-glob-index.d2:1:2: indexed edge does not exist`)
|
||||
},
|
||||
},
|
||||
}
|
||||
runa(t, tca)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
2909
testdata/d2ir/TestCompile/patterns/double-glob/defaults.exp.json
generated
vendored
Normal file
2909
testdata/d2ir/TestCompile/patterns/double-glob/defaults.exp.json
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
667
testdata/d2ir/TestCompile/patterns/errors/glob-edge-glob-index.exp.json
generated
vendored
667
testdata/d2ir/TestCompile/patterns/errors/glob-edge-glob-index.exp.json
generated
vendored
|
|
@ -1,667 +1,4 @@
|
|||
{
|
||||
"fields": [
|
||||
{
|
||||
"name": "b",
|
||||
"references": [
|
||||
{
|
||||
"string": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:6:6-0:7:7",
|
||||
"value": [
|
||||
{
|
||||
"string": "b",
|
||||
"raw_string": "b"
|
||||
}
|
||||
]
|
||||
},
|
||||
"key_path": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:6:6-0:7:7",
|
||||
"path": [
|
||||
{
|
||||
"unquoted_string": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:6:6-0:7:7",
|
||||
"value": [
|
||||
{
|
||||
"string": "b",
|
||||
"raw_string": "b"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"context": {
|
||||
"edge": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:1:1-0:7:7",
|
||||
"src": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:1:1-0:2:2",
|
||||
"path": [
|
||||
{
|
||||
"unquoted_string": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:1:1-0:2:2",
|
||||
"value": [
|
||||
{
|
||||
"string": "*",
|
||||
"raw_string": "*"
|
||||
}
|
||||
],
|
||||
"pattern": [
|
||||
"*"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"src_arrow": "",
|
||||
"dst": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:6:6-0:7:7",
|
||||
"path": [
|
||||
{
|
||||
"unquoted_string": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:6:6-0:7:7",
|
||||
"value": [
|
||||
{
|
||||
"string": "b",
|
||||
"raw_string": "b"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"dst_arrow": ">"
|
||||
},
|
||||
"key": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:0:0-0:24:24",
|
||||
"edges": [
|
||||
{
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:1:1-0:7:7",
|
||||
"src": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:1:1-0:2:2",
|
||||
"path": [
|
||||
{
|
||||
"unquoted_string": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:1:1-0:2:2",
|
||||
"value": [
|
||||
{
|
||||
"string": "*",
|
||||
"raw_string": "*"
|
||||
}
|
||||
],
|
||||
"pattern": [
|
||||
"*"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"src_arrow": "",
|
||||
"dst": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:6:6-0:7:7",
|
||||
"path": [
|
||||
{
|
||||
"unquoted_string": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:6:6-0:7:7",
|
||||
"value": [
|
||||
{
|
||||
"string": "b",
|
||||
"raw_string": "b"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"dst_arrow": ">"
|
||||
}
|
||||
],
|
||||
"edge_key": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:9:9-0:19:19",
|
||||
"path": [
|
||||
{
|
||||
"unquoted_string": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:9:9-0:14:14",
|
||||
"value": [
|
||||
{
|
||||
"string": "style",
|
||||
"raw_string": "style"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"unquoted_string": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:15:15-0:19:19",
|
||||
"value": [
|
||||
{
|
||||
"string": "fill",
|
||||
"raw_string": "fill"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"primary": {},
|
||||
"value": {
|
||||
"unquoted_string": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:21:21-0:24:24",
|
||||
"value": [
|
||||
{
|
||||
"string": "red",
|
||||
"raw_string": "red"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"edges": [
|
||||
{
|
||||
"edge_id": {
|
||||
"src_path": [
|
||||
"b"
|
||||
],
|
||||
"src_arrow": false,
|
||||
"dst_path": [
|
||||
"b"
|
||||
],
|
||||
"dst_arrow": true,
|
||||
"index": 0,
|
||||
"glob": false
|
||||
},
|
||||
"map": {
|
||||
"fields": [
|
||||
{
|
||||
"name": "style",
|
||||
"composite": {
|
||||
"fields": [
|
||||
{
|
||||
"name": "fill",
|
||||
"primary": {
|
||||
"value": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:21:21-0:24:24",
|
||||
"value": [
|
||||
{
|
||||
"string": "red",
|
||||
"raw_string": "red"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"references": [
|
||||
{
|
||||
"string": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:15:15-0:19:19",
|
||||
"value": [
|
||||
{
|
||||
"string": "fill",
|
||||
"raw_string": "fill"
|
||||
}
|
||||
]
|
||||
},
|
||||
"key_path": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:9:9-0:19:19",
|
||||
"path": [
|
||||
{
|
||||
"unquoted_string": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:9:9-0:14:14",
|
||||
"value": [
|
||||
{
|
||||
"string": "style",
|
||||
"raw_string": "style"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"unquoted_string": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:15:15-0:19:19",
|
||||
"value": [
|
||||
{
|
||||
"string": "fill",
|
||||
"raw_string": "fill"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"context": {
|
||||
"edge": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:1:1-0:7:7",
|
||||
"src": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:1:1-0:2:2",
|
||||
"path": [
|
||||
{
|
||||
"unquoted_string": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:1:1-0:2:2",
|
||||
"value": [
|
||||
{
|
||||
"string": "*",
|
||||
"raw_string": "*"
|
||||
}
|
||||
],
|
||||
"pattern": [
|
||||
"*"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"src_arrow": "",
|
||||
"dst": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:6:6-0:7:7",
|
||||
"path": [
|
||||
{
|
||||
"unquoted_string": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:6:6-0:7:7",
|
||||
"value": [
|
||||
{
|
||||
"string": "b",
|
||||
"raw_string": "b"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"dst_arrow": ">"
|
||||
},
|
||||
"key": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:0:0-0:24:24",
|
||||
"edges": [
|
||||
{
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:1:1-0:7:7",
|
||||
"src": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:1:1-0:2:2",
|
||||
"path": [
|
||||
{
|
||||
"unquoted_string": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:1:1-0:2:2",
|
||||
"value": [
|
||||
{
|
||||
"string": "*",
|
||||
"raw_string": "*"
|
||||
}
|
||||
],
|
||||
"pattern": [
|
||||
"*"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"src_arrow": "",
|
||||
"dst": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:6:6-0:7:7",
|
||||
"path": [
|
||||
{
|
||||
"unquoted_string": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:6:6-0:7:7",
|
||||
"value": [
|
||||
{
|
||||
"string": "b",
|
||||
"raw_string": "b"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"dst_arrow": ">"
|
||||
}
|
||||
],
|
||||
"edge_key": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:9:9-0:19:19",
|
||||
"path": [
|
||||
{
|
||||
"unquoted_string": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:9:9-0:14:14",
|
||||
"value": [
|
||||
{
|
||||
"string": "style",
|
||||
"raw_string": "style"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"unquoted_string": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:15:15-0:19:19",
|
||||
"value": [
|
||||
{
|
||||
"string": "fill",
|
||||
"raw_string": "fill"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"primary": {},
|
||||
"value": {
|
||||
"unquoted_string": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:21:21-0:24:24",
|
||||
"value": [
|
||||
{
|
||||
"string": "red",
|
||||
"raw_string": "red"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"edges": null
|
||||
},
|
||||
"references": [
|
||||
{
|
||||
"string": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:9:9-0:14:14",
|
||||
"value": [
|
||||
{
|
||||
"string": "style",
|
||||
"raw_string": "style"
|
||||
}
|
||||
]
|
||||
},
|
||||
"key_path": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:9:9-0:19:19",
|
||||
"path": [
|
||||
{
|
||||
"unquoted_string": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:9:9-0:14:14",
|
||||
"value": [
|
||||
{
|
||||
"string": "style",
|
||||
"raw_string": "style"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"unquoted_string": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:15:15-0:19:19",
|
||||
"value": [
|
||||
{
|
||||
"string": "fill",
|
||||
"raw_string": "fill"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"context": {
|
||||
"edge": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:1:1-0:7:7",
|
||||
"src": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:1:1-0:2:2",
|
||||
"path": [
|
||||
{
|
||||
"unquoted_string": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:1:1-0:2:2",
|
||||
"value": [
|
||||
{
|
||||
"string": "*",
|
||||
"raw_string": "*"
|
||||
}
|
||||
],
|
||||
"pattern": [
|
||||
"*"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"src_arrow": "",
|
||||
"dst": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:6:6-0:7:7",
|
||||
"path": [
|
||||
{
|
||||
"unquoted_string": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:6:6-0:7:7",
|
||||
"value": [
|
||||
{
|
||||
"string": "b",
|
||||
"raw_string": "b"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"dst_arrow": ">"
|
||||
},
|
||||
"key": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:0:0-0:24:24",
|
||||
"edges": [
|
||||
{
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:1:1-0:7:7",
|
||||
"src": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:1:1-0:2:2",
|
||||
"path": [
|
||||
{
|
||||
"unquoted_string": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:1:1-0:2:2",
|
||||
"value": [
|
||||
{
|
||||
"string": "*",
|
||||
"raw_string": "*"
|
||||
}
|
||||
],
|
||||
"pattern": [
|
||||
"*"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"src_arrow": "",
|
||||
"dst": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:6:6-0:7:7",
|
||||
"path": [
|
||||
{
|
||||
"unquoted_string": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:6:6-0:7:7",
|
||||
"value": [
|
||||
{
|
||||
"string": "b",
|
||||
"raw_string": "b"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"dst_arrow": ">"
|
||||
}
|
||||
],
|
||||
"edge_key": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:9:9-0:19:19",
|
||||
"path": [
|
||||
{
|
||||
"unquoted_string": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:9:9-0:14:14",
|
||||
"value": [
|
||||
{
|
||||
"string": "style",
|
||||
"raw_string": "style"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"unquoted_string": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:15:15-0:19:19",
|
||||
"value": [
|
||||
{
|
||||
"string": "fill",
|
||||
"raw_string": "fill"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"primary": {},
|
||||
"value": {
|
||||
"unquoted_string": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:21:21-0:24:24",
|
||||
"value": [
|
||||
{
|
||||
"string": "red",
|
||||
"raw_string": "red"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"edges": null
|
||||
},
|
||||
"references": [
|
||||
{
|
||||
"context": {
|
||||
"edge": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:1:1-0:7:7",
|
||||
"src": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:1:1-0:2:2",
|
||||
"path": [
|
||||
{
|
||||
"unquoted_string": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:1:1-0:2:2",
|
||||
"value": [
|
||||
{
|
||||
"string": "*",
|
||||
"raw_string": "*"
|
||||
}
|
||||
],
|
||||
"pattern": [
|
||||
"*"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"src_arrow": "",
|
||||
"dst": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:6:6-0:7:7",
|
||||
"path": [
|
||||
{
|
||||
"unquoted_string": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:6:6-0:7:7",
|
||||
"value": [
|
||||
{
|
||||
"string": "b",
|
||||
"raw_string": "b"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"dst_arrow": ">"
|
||||
},
|
||||
"key": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:0:0-0:24:24",
|
||||
"edges": [
|
||||
{
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:1:1-0:7:7",
|
||||
"src": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:1:1-0:2:2",
|
||||
"path": [
|
||||
{
|
||||
"unquoted_string": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:1:1-0:2:2",
|
||||
"value": [
|
||||
{
|
||||
"string": "*",
|
||||
"raw_string": "*"
|
||||
}
|
||||
],
|
||||
"pattern": [
|
||||
"*"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"src_arrow": "",
|
||||
"dst": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:6:6-0:7:7",
|
||||
"path": [
|
||||
{
|
||||
"unquoted_string": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:6:6-0:7:7",
|
||||
"value": [
|
||||
{
|
||||
"string": "b",
|
||||
"raw_string": "b"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"dst_arrow": ">"
|
||||
}
|
||||
],
|
||||
"edge_key": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:9:9-0:19:19",
|
||||
"path": [
|
||||
{
|
||||
"unquoted_string": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:9:9-0:14:14",
|
||||
"value": [
|
||||
{
|
||||
"string": "style",
|
||||
"raw_string": "style"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"unquoted_string": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:15:15-0:19:19",
|
||||
"value": [
|
||||
{
|
||||
"string": "fill",
|
||||
"raw_string": "fill"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"primary": {},
|
||||
"value": {
|
||||
"unquoted_string": {
|
||||
"range": "TestCompile/patterns/errors/glob-edge-glob-index.d2,0:21:21-0:24:24",
|
||||
"value": [
|
||||
{
|
||||
"string": "red",
|
||||
"raw_string": "red"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
"fields": null,
|
||||
"edges": null
|
||||
}
|
||||
|
|
|
|||
4781
testdata/d2ir/TestCompile/patterns/single-glob/defaults.exp.json
generated
vendored
Normal file
4781
testdata/d2ir/TestCompile/patterns/single-glob/defaults.exp.json
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
3370
testdata/d2ir/TestCompile/patterns/triple-glob/defaults.exp.json
generated
vendored
Normal file
3370
testdata/d2ir/TestCompile/patterns/triple-glob/defaults.exp.json
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
14050
testdata/d2ir/TestCompile/patterns/triple-glob/edge-defaults.exp.json
generated
vendored
Normal file
14050
testdata/d2ir/TestCompile/patterns/triple-glob/edge-defaults.exp.json
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue