Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions ci/release/changelogs/next.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@
- Limit wildcard edge connections and selectors to bounded expansion work,
returning a clear error before excessive fanout consumes resources.
[#2926](https://github.com/d2lang/d2/pull/2926)
- Keep `sql_table` column types that match the column name, such as
`date: date`, instead of rendering an empty type. [#2950](https://github.com/d2lang/d2/pull/2950)
- Keep `class` field types and method return types that match the name, such
as `date: date`, instead of dropping them. [#2952](https://github.com/d2lang/d2/pull/2952)
- decoding and assets:
- Cap decompressed URL-encoded D2 input at 16 MiB. [#2902](https://github.com/d2lang/d2/pull/2902)
- Bound image references, locators, fetched and decoded bytes, cached data, and
Expand Down
22 changes: 15 additions & 7 deletions d2compiler/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,7 @@ type compiler struct {
err *d2parser.ParseError
activeClassMaps map[*d2ir.Map]struct{}
classMapsByRoot map[*d2ir.Map]map[string]*d2ir.Map
explicitLabels map[*d2graph.Attributes]struct{}
ctx context.Context
fatalErr error
}
Expand Down Expand Up @@ -793,6 +794,15 @@ func (c *compiler) compileLabel(attrs *d2graph.Attributes, f d2ir.Node) {
attrs.Label.Value = scalar.ScalarString()
}
attrs.Label.MapKey = f.LastPrimaryKey()
if c.explicitLabels == nil {
c.explicitLabels = make(map[*d2graph.Attributes]struct{})
}
c.explicitLabels[attrs] = struct{}{}
}

func (c *compiler) hasExplicitLabel(attrs *d2graph.Attributes) bool {
_, ok := c.explicitLabels[attrs]
return ok
}

func (c *compiler) compilePosition(attrs *d2graph.Attributes, f *d2ir.Field) {
Expand Down Expand Up @@ -1407,9 +1417,10 @@ func (c *compiler) compileClass(obj *d2graph.Object) {
}
}

// A field or method without an explicit label defaults it to its ID, which is not a type.
if !strings.Contains(f.IDVal, "(") {
typ := f.Label.Value
if typ == f.IDVal {
if !c.hasExplicitLabel(&f.Attributes) && typ == f.IDVal {
typ = ""
}
underline := f.Attributes.Style.Underline != nil && f.Attributes.Style.Underline.Value == "true"
Expand All @@ -1420,10 +1431,8 @@ func (c *compiler) compileClass(obj *d2graph.Object) {
Underline: underline,
})
} else {
// TODO: Not great, AST should easily allow specifying alternate primary field
// as an explicit label should change the name.
returnType := f.Label.Value
if returnType == f.IDVal {
if !c.hasExplicitLabel(&f.Attributes) && returnType == f.IDVal {
returnType = "void"
}
underline := f.Attributes.Style.Underline != nil && f.Attributes.Style.Underline.Value == "true"
Expand Down Expand Up @@ -1464,9 +1473,8 @@ func (c *compiler) compileSQLTable(obj *d2graph.Object) {
return
}
typ := col.Label.Value
if typ == col.IDVal {
// Not great, AST should easily allow specifying alternate primary field
// as an explicit label should change the name.
// A column without an explicit label defaults it to its ID, which is not a type.
if !c.hasExplicitLabel(&col.Attributes) && typ == col.IDVal {
typ = ""
}
d2Col := d2target.SQLColumn{
Expand Down
41 changes: 41 additions & 0 deletions d2compiler/compile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2857,6 +2857,47 @@ x.y -> a.b: {
assert.String(t, `Is()`, g.Objects[0].SQLTable.Columns[1].Name.Label)
},
},
{
name: "sql_column_type_matches_name",

text: `time: {
shape: sql_table
id
created {constraint: primary_key}
date: date
key: key
key {constraint: unique}
}
`,
assertions: func(t *testing.T, g *d2graph.Graph) {
cols := g.Objects[0].SQLTable.Columns
assert.String(t, ``, cols[0].Type.Label)
assert.String(t, ``, cols[1].Type.Label)
assert.String(t, `date`, cols[2].Type.Label)
assert.String(t, `key`, cols[3].Type.Label)
},
},
{
name: "class_field_type_matches_name",

text: `Event: {
shape: class
id
date: date
+status: status
save()
now(): now()
}
`,
assertions: func(t *testing.T, g *d2graph.Graph) {
class := g.Objects[0].Class
assert.String(t, ``, class.Fields[0].Type)
assert.String(t, `date`, class.Fields[1].Type)
assert.String(t, `status`, class.Fields[2].Type)
assert.String(t, `void`, class.Methods[0].Return)
assert.String(t, `now()`, class.Methods[1].Return)
},
},
{
name: "nested_sql",

Expand Down
Loading