fix: Missing array types

This commit is contained in:
Ilya Kuznetsov 2025-01-10 12:52:20 +01:00
parent f9278c2b4d
commit 6c5268aaaa
2 changed files with 70 additions and 13 deletions

View File

@ -27,6 +27,7 @@ type attributeNode struct {
Title string Title string
Type string Type string
Description string Description string
Reference string
} }
type rootProp struct { type rootProp struct {
@ -35,17 +36,25 @@ type rootProp struct {
topLevel bool topLevel bool
} }
const MapType = "Map"
func getNodes(s jsonschema.Schema, refs map[string]jsonschema.Schema, customFields map[string]bool) []rootNode { func getNodes(s jsonschema.Schema, refs map[string]jsonschema.Schema, customFields map[string]bool) []rootNode {
rootProps := []rootProp{} rootProps := []rootProp{}
for k, v := range s.Properties { for k, v := range s.Properties {
rootProps = append(rootProps, rootProp{k, v, true}) rootProps = append(rootProps, rootProp{k, v, true})
} }
nodes := make([]rootNode, 0, len(rootProps)) nodes := make([]rootNode, 0, len(rootProps))
visited := make(map[string]bool)
for i := 0; i < len(rootProps); i++ { for i := 0; i < len(rootProps); i++ {
item := rootProps[i] item := rootProps[i]
k := item.k k := item.k
v := item.v v := item.v
if visited[k] {
continue
}
visited[k] = true
v = resolveRefs(v, refs) v = resolveRefs(v, refs)
node := rootNode{ node := rootNode{
Title: k, Title: k,
@ -55,25 +64,27 @@ func getNodes(s jsonschema.Schema, refs map[string]jsonschema.Schema, customFiel
Type: getHumanReadableType(v.Type), Type: getHumanReadableType(v.Type),
} }
node.Attributes = getAttributes(v.Properties, refs) node.Attributes = getAttributes(v.Properties, refs, k)
rootProps = append(rootProps, extractNodes(k, v.Properties, refs, customFields)...) rootProps = append(rootProps, extractNodes(k, v.Properties, refs, customFields)...)
additionalProps, ok := v.AdditionalProperties.(*jsonschema.Schema) additionalProps, ok := v.AdditionalProperties.(*jsonschema.Schema)
if ok { if ok {
objectKeyType := resolveRefs(additionalProps, refs) objectKeyType := resolveRefs(additionalProps, refs)
if node.Description == "" { d := getDescription(objectKeyType, true)
node.Description = getDescription(objectKeyType, true) if d != "" {
node.Description = d
} }
if len(node.Example) == 0 { if len(node.Example) == 0 {
node.Example = getExample(objectKeyType) node.Example = getExample(objectKeyType)
} }
node.ObjectKeyAttributes = getAttributes(objectKeyType.Properties, refs) node.ObjectKeyAttributes = getAttributes(objectKeyType.Properties, refs, k)
rootProps = append(rootProps, extractNodes(k, objectKeyType.Properties, refs, customFields)...) rootProps = append(rootProps, extractNodes(k, objectKeyType.Properties, refs, customFields)...)
} }
if v.Items != nil { if v.Items != nil {
arrayItemType := resolveRefs(v.Items, refs) arrayItemType := resolveRefs(v.Items, refs)
node.ArrayItemAttributes = getAttributes(arrayItemType.Properties, refs) node.ArrayItemAttributes = getAttributes(arrayItemType.Properties, refs, k)
// rootProps = append(rootProps, extractNodes(k, arrayItemType.Properties, refs, customFields)...)
} }
isEmpty := len(node.Attributes) == 0 && len(node.ObjectKeyAttributes) == 0 && len(node.ArrayItemAttributes) == 0 isEmpty := len(node.Attributes) == 0 && len(node.ObjectKeyAttributes) == 0 && len(node.ArrayItemAttributes) == 0
@ -167,8 +178,18 @@ func buildAttributeTable(m *md.Markdown, attributes []attributeNode) *md.Markdow
// return m // return m
} }
func formatDescription(s string) string { func formatDescription(a attributeNode) string {
return strings.ReplaceAll(s, "\n", " ") s := strings.ReplaceAll(a.Description, "\n", " ")
return s
if a.Reference != "" {
if strings.HasSuffix(s, ".") {
s += " "
} else if s != "" {
s += ". "
}
s += fmt.Sprintf("See %s.", md.Link("_", "#"+a.Reference))
}
return s
} }
// Build a custom table which we use in Databricks website // Build a custom table which we use in Databricks website
@ -186,7 +207,7 @@ func buildCustomAttributeTable(m *md.Markdown, attributes []attributeNode) *md.M
for _, a := range attributes { for _, a := range attributes {
m = m.PlainText(" * - " + fmt.Sprintf("`%s`", a.Title)) m = m.PlainText(" * - " + fmt.Sprintf("`%s`", a.Title))
m = m.PlainText(" - " + a.Type) m = m.PlainText(" - " + a.Type)
m = m.PlainText(" - " + formatDescription(a.Description)) m = m.PlainText(" - " + formatDescription(a))
m = m.LF() m = m.LF()
} }
return m return m
@ -203,7 +224,7 @@ func getHumanReadableType(t jsonschema.Type) string {
return typesMapping[string(t)] return typesMapping[string(t)]
} }
func getAttributes(props map[string]*jsonschema.Schema, refs map[string]jsonschema.Schema) []attributeNode { func getAttributes(props map[string]*jsonschema.Schema, refs map[string]jsonschema.Schema, prefix string) []attributeNode {
attributes := []attributeNode{} attributes := []attributeNode{}
for k, v := range props { for k, v := range props {
v = resolveRefs(v, refs) v = resolveRefs(v, refs)
@ -211,10 +232,15 @@ func getAttributes(props map[string]*jsonschema.Schema, refs map[string]jsonsche
if typeString == "" { if typeString == "" {
typeString = "Any" typeString = "Any"
} }
var reference string
if isReferenceType(v, refs) {
reference = prefix + "." + k
}
attributes = append(attributes, attributeNode{ attributes = append(attributes, attributeNode{
Title: k, Title: k,
Type: typeString, Type: typeString,
Description: getDescription(v, true), Description: getDescription(v, true),
Reference: reference,
}) })
} }
sort.Slice(attributes, func(i, j int) bool { sort.Slice(attributes, func(i, j int) bool {
@ -223,6 +249,35 @@ func getAttributes(props map[string]*jsonschema.Schema, refs map[string]jsonsche
return attributes return attributes
} }
func isReferenceType(v *jsonschema.Schema, refs map[string]jsonschema.Schema) bool {
if len(v.Properties) > 0 {
return true
}
if v.Items != nil {
items := resolveRefs(v.Items, refs)
if items != nil && items.Type == "object" {
return true
}
}
props := resolveAdditionaProperties(v, refs)
if props != nil && props.Type == "object" {
return true
}
return false
}
func resolveAdditionaProperties(v *jsonschema.Schema, refs map[string]jsonschema.Schema) *jsonschema.Schema {
if v.AdditionalProperties == nil {
return nil
}
additionalProps, ok := v.AdditionalProperties.(*jsonschema.Schema)
if !ok {
return nil
}
return resolveRefs(additionalProps, refs)
}
func getDescription(s *jsonschema.Schema, allowMarkdown bool) string { func getDescription(s *jsonschema.Schema, allowMarkdown bool) string {
if allowMarkdown && s.MarkdownDescription != "" { if allowMarkdown && s.MarkdownDescription != "" {
return s.MarkdownDescription return s.MarkdownDescription
@ -265,8 +320,10 @@ func resolveRefs(s *jsonschema.Schema, schemas map[string]jsonschema.Schema) *js
} }
func shouldExtract(ref string, customFields map[string]bool) bool { func shouldExtract(ref string, customFields map[string]bool) bool {
refKey := strings.TrimPrefix(ref, "#/$defs/") if i := strings.Index(ref, "github.com"); i >= 0 {
_, isCustomField := customFields[refKey] ref = ref[i:]
}
_, isCustomField := customFields[ref]
return isCustomField return isCustomField
} }
@ -277,7 +334,7 @@ func extractNodes(prefix string, props map[string]*jsonschema.Schema, refs map[s
continue continue
} }
v = resolveRefs(v, refs) v = resolveRefs(v, refs)
if v.Type == "object" { if v.Type == "object" || v.Type == "array" {
nodes = append(nodes, rootProp{prefix + "." + k, v, false}) nodes = append(nodes, rootProp{prefix + "." + k, v, false})
} }
} }

View File

@ -63,7 +63,7 @@ func main() {
log.Fatal(err) log.Fatal(err)
} }
err = generateDocs( err = generateDocs(
[]string{path.Join(annotationDir, "annotations_openapi.yml"), path.Join(annotationDir, "annotations_openapi_overrides.yml")}, []string{path.Join(annotationDir, "annotations_openapi.yml"), path.Join(annotationDir, "annotations_openapi_overrides.yml"), path.Join(annotationDir, "annotations.yml")},
path.Join(outputDir, resourcesFileName), path.Join(outputDir, resourcesFileName),
reflect.TypeOf(config.Resources{}), reflect.TypeOf(config.Resources{}),
resourcesHeader, resourcesHeader,