mirror of https://github.com/databricks/cli.git
fix: More ducmentation + tests
This commit is contained in:
parent
d27282c3a4
commit
13181fc5a7
|
@ -87,13 +87,13 @@ func buildAttributeTable(m *markdownRenderer, attributes []attributeNode) *markd
|
||||||
|
|
||||||
func formatDescription(a attributeNode) string {
|
func formatDescription(a attributeNode) string {
|
||||||
s := strings.ReplaceAll(a.Description, "\n", " ")
|
s := strings.ReplaceAll(a.Description, "\n", " ")
|
||||||
if a.Reference != "" {
|
if a.Link != "" {
|
||||||
if strings.HasSuffix(s, ".") {
|
if strings.HasSuffix(s, ".") {
|
||||||
s += " "
|
s += " "
|
||||||
} else if s != "" {
|
} else if s != "" {
|
||||||
s += ". "
|
s += ". "
|
||||||
}
|
}
|
||||||
s += fmt.Sprintf("See [_](#%s).", a.Reference)
|
s += fmt.Sprintf("See [_](#%s).", a.Link)
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ type attributeNode struct {
|
||||||
Title string
|
Title string
|
||||||
Type string
|
Type string
|
||||||
Description string
|
Description string
|
||||||
Reference string
|
Link string
|
||||||
}
|
}
|
||||||
|
|
||||||
type rootProp struct {
|
type rootProp struct {
|
||||||
|
@ -61,6 +61,7 @@ func buildNodes(s jsonschema.Schema, refs map[string]*jsonschema.Schema, ownFiel
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
visited[k] = true
|
visited[k] = true
|
||||||
|
|
||||||
v = resolveRefs(v, refs)
|
v = resolveRefs(v, refs)
|
||||||
node := rootNode{
|
node := rootNode{
|
||||||
Title: k,
|
Title: k,
|
||||||
|
@ -70,37 +71,56 @@ func buildNodes(s jsonschema.Schema, refs map[string]*jsonschema.Schema, ownFiel
|
||||||
Type: getHumanReadableType(v.Type),
|
Type: getHumanReadableType(v.Type),
|
||||||
}
|
}
|
||||||
|
|
||||||
node.Attributes = getAttributes(v.Properties, refs, ownFields, k, item.circular)
|
hasProperties := len(v.Properties) > 0
|
||||||
if !item.circular {
|
if hasProperties {
|
||||||
rootProps = append(rootProps, extractNodes(k, v.Properties, refs, ownFields)...)
|
node.Attributes = getAttributes(v.Properties, refs, ownFields, k, item.circular)
|
||||||
}
|
}
|
||||||
|
|
||||||
additionalProps, ok := v.AdditionalProperties.(*jsonschema.Schema)
|
mapValueType := getMapValueType(v, refs)
|
||||||
if ok {
|
if mapValueType != nil {
|
||||||
objectKeyType := resolveRefs(additionalProps, refs)
|
d := getDescription(mapValueType, true)
|
||||||
d := getDescription(objectKeyType, true)
|
|
||||||
if d != "" {
|
if d != "" {
|
||||||
node.Description = d
|
node.Description = d
|
||||||
}
|
}
|
||||||
if len(node.Example) == 0 {
|
if node.Example == "" {
|
||||||
node.Example = getExample(objectKeyType)
|
node.Example = getExample(mapValueType)
|
||||||
}
|
|
||||||
prefix := k + ".<name>"
|
|
||||||
node.ObjectKeyAttributes = getAttributes(objectKeyType.Properties, refs, ownFields, prefix, item.circular)
|
|
||||||
if !item.circular {
|
|
||||||
rootProps = append(rootProps, extractNodes(prefix, objectKeyType.Properties, refs, ownFields)...)
|
|
||||||
}
|
}
|
||||||
|
node.ObjectKeyAttributes = getAttributes(mapValueType.Properties, refs, ownFields, getMapKeyPrefix(k), item.circular)
|
||||||
}
|
}
|
||||||
|
|
||||||
if v.Items != nil {
|
arrayItemType := resolveRefs(v.Items, refs)
|
||||||
arrayItemType := resolveRefs(v.Items, refs)
|
if arrayItemType != nil {
|
||||||
node.ArrayItemAttributes = getAttributes(arrayItemType.Properties, refs, ownFields, k, item.circular)
|
node.ArrayItemAttributes = getAttributes(arrayItemType.Properties, refs, ownFields, k, item.circular)
|
||||||
if !item.circular {
|
|
||||||
rootProps = append(rootProps, extractNodes(k, arrayItemType.Properties, refs, ownFields)...)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nodes = append(nodes, node)
|
nodes = append(nodes, node)
|
||||||
|
|
||||||
|
// Whether we should add new root props from the children of the current JSON-schema node to include their definitions to this document
|
||||||
|
shouldAddNewProps := !item.circular
|
||||||
|
if shouldAddNewProps {
|
||||||
|
newProps := []rootProp{}
|
||||||
|
// Adds node with definition for the properties. Example:
|
||||||
|
// bundle:
|
||||||
|
// prop-name: <value>
|
||||||
|
if hasProperties {
|
||||||
|
newProps = append(newProps, extractNodes(k, v.Properties, refs, ownFields)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adds node with definition for the type of array item. Example:
|
||||||
|
// permissions:
|
||||||
|
// - <item>
|
||||||
|
if arrayItemType != nil {
|
||||||
|
newProps = append(newProps, extractNodes(k, arrayItemType.Properties, refs, ownFields)...)
|
||||||
|
}
|
||||||
|
// Adds node with definition for the type of the Map value. Example:
|
||||||
|
// targets:
|
||||||
|
// <key>: <value>
|
||||||
|
if mapValueType != nil {
|
||||||
|
newProps = append(newProps, extractNodes(getMapKeyPrefix(k), mapValueType.Properties, refs, ownFields)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
rootProps = append(rootProps, newProps...)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sort.Slice(nodes, func(i, j int) bool {
|
sort.Slice(nodes, func(i, j int) bool {
|
||||||
|
@ -109,6 +129,18 @@ func buildNodes(s jsonschema.Schema, refs map[string]*jsonschema.Schema, ownFiel
|
||||||
return nodes
|
return nodes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getMapValueType(v *jsonschema.Schema, refs map[string]*jsonschema.Schema) *jsonschema.Schema {
|
||||||
|
additionalProps, ok := v.AdditionalProperties.(*jsonschema.Schema)
|
||||||
|
if ok {
|
||||||
|
return resolveRefs(additionalProps, refs)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getMapKeyPrefix(s string) string {
|
||||||
|
return s + ".<name>"
|
||||||
|
}
|
||||||
|
|
||||||
func removePluralForm(s string) string {
|
func removePluralForm(s string) string {
|
||||||
if strings.HasSuffix(s, "s") {
|
if strings.HasSuffix(s, "s") {
|
||||||
return strings.TrimSuffix(s, "s")
|
return strings.TrimSuffix(s, "s")
|
||||||
|
@ -143,7 +175,7 @@ func getAttributes(props, refs map[string]*jsonschema.Schema, ownFields map[stri
|
||||||
Title: k,
|
Title: k,
|
||||||
Type: typeString,
|
Type: typeString,
|
||||||
Description: getDescription(v, true),
|
Description: getDescription(v, true),
|
||||||
Reference: reference,
|
Link: reference,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
sort.Slice(attributes, func(i, j int) bool {
|
sort.Slice(attributes, func(i, j int) bool {
|
||||||
|
@ -172,7 +204,7 @@ func shouldExtract(ref string, ownFields map[string]bool) bool {
|
||||||
func extractNodes(prefix string, props, refs map[string]*jsonschema.Schema, ownFields map[string]bool) []rootProp {
|
func extractNodes(prefix string, props, refs map[string]*jsonschema.Schema, ownFields map[string]bool) []rootProp {
|
||||||
nodes := []rootProp{}
|
nodes := []rootProp{}
|
||||||
for k, v := range props {
|
for k, v := range props {
|
||||||
if !shouldExtract(*v.Reference, ownFields) {
|
if v.Reference != nil && !shouldExtract(*v.Reference, ownFields) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
v = resolveRefs(v, refs)
|
v = resolveRefs(v, refs)
|
||||||
|
|
|
@ -0,0 +1,120 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/databricks/cli/libs/jsonschema"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestBuildNodes_ChildExpansion(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
schema jsonschema.Schema
|
||||||
|
refs map[string]*jsonschema.Schema
|
||||||
|
ownFields map[string]bool
|
||||||
|
wantNodes []rootNode
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "array expansion",
|
||||||
|
schema: jsonschema.Schema{
|
||||||
|
Type: "object",
|
||||||
|
Properties: map[string]*jsonschema.Schema{
|
||||||
|
"list": {
|
||||||
|
Type: "array",
|
||||||
|
Items: &jsonschema.Schema{
|
||||||
|
Type: "object",
|
||||||
|
Properties: map[string]*jsonschema.Schema{
|
||||||
|
"listSub": {Reference: strPtr("#/$defs/github.com/listSub")},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
refs: map[string]*jsonschema.Schema{
|
||||||
|
"github.com/listSub": {Type: "array", Items: &jsonschema.Schema{Type: "object", Properties: map[string]*jsonschema.Schema{"subField": {Type: "string"}}}},
|
||||||
|
},
|
||||||
|
ownFields: map[string]bool{"github.com/listSub": true},
|
||||||
|
wantNodes: []rootNode{
|
||||||
|
{
|
||||||
|
Title: "list",
|
||||||
|
TopLevel: true,
|
||||||
|
Type: "Sequence",
|
||||||
|
ArrayItemAttributes: []attributeNode{
|
||||||
|
{Title: "listSub", Type: "Sequence", Link: "list.listSub"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Title: "list.listSub",
|
||||||
|
Type: "Sequence",
|
||||||
|
ArrayItemAttributes: []attributeNode{
|
||||||
|
{Title: "subField", Type: "String"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "map expansion",
|
||||||
|
schema: jsonschema.Schema{
|
||||||
|
Type: "object",
|
||||||
|
Properties: map[string]*jsonschema.Schema{
|
||||||
|
"myMap": {
|
||||||
|
Type: "object",
|
||||||
|
AdditionalProperties: &jsonschema.Schema{
|
||||||
|
Reference: strPtr("#/$defs/github.com/myMap"),
|
||||||
|
Properties: map[string]*jsonschema.Schema{
|
||||||
|
"mapSub": {Type: "object", Reference: strPtr("#/$defs/github.com/mapSub")},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
refs: map[string]*jsonschema.Schema{
|
||||||
|
"github.com/myMap": {
|
||||||
|
Type: "object",
|
||||||
|
Properties: map[string]*jsonschema.Schema{
|
||||||
|
"mapSub": {Type: "boolean", Reference: strPtr("#/$defs/github.com/mapSub")},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"github.com/mapSub": {
|
||||||
|
Type: "object",
|
||||||
|
Properties: map[string]*jsonschema.Schema{
|
||||||
|
"deepSub": {Type: "boolean"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ownFields: map[string]bool{
|
||||||
|
"github.com/myMap": true,
|
||||||
|
"github.com/mapSub": true,
|
||||||
|
},
|
||||||
|
wantNodes: []rootNode{
|
||||||
|
{
|
||||||
|
Title: "myMap",
|
||||||
|
TopLevel: true,
|
||||||
|
Type: "Map",
|
||||||
|
ObjectKeyAttributes: []attributeNode{
|
||||||
|
{Title: "mapSub", Type: "Map", Link: "myMap.<name>.mapSub"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Title: "myMap.<name>.mapSub",
|
||||||
|
Type: "Map",
|
||||||
|
Attributes: []attributeNode{
|
||||||
|
{Title: "deepSub", Type: "Boolean"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got := buildNodes(tt.schema, tt.refs, tt.ownFields)
|
||||||
|
assert.Equal(t, tt.wantNodes, got)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func strPtr(s string) *string {
|
||||||
|
return &s
|
||||||
|
}
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"github.com/databricks/cli/libs/jsonschema"
|
"github.com/databricks/cli/libs/jsonschema"
|
||||||
)
|
)
|
||||||
|
|
||||||
func isReferenceType(v *jsonschema.Schema, refs map[string]*jsonschema.Schema, customFields map[string]bool) bool {
|
func isReferenceType(v *jsonschema.Schema, refs map[string]*jsonschema.Schema, ownFields map[string]bool) bool {
|
||||||
if v.Type != "object" && v.Type != "array" {
|
if v.Type != "object" && v.Type != "array" {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ func isReferenceType(v *jsonschema.Schema, refs map[string]*jsonschema.Schema, c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
props := resolveAdditionalProperties(v)
|
props := resolveAdditionalProperties(v)
|
||||||
if !isInOwnFields(props, customFields) {
|
if !isInOwnFields(props, ownFields) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if props != nil {
|
if props != nil {
|
||||||
|
@ -32,9 +32,9 @@ func isReferenceType(v *jsonschema.Schema, refs map[string]*jsonschema.Schema, c
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func isInOwnFields(node *jsonschema.Schema, customFields map[string]bool) bool {
|
func isInOwnFields(node *jsonschema.Schema, ownFields map[string]bool) bool {
|
||||||
if node != nil && node.Reference != nil {
|
if node != nil && node.Reference != nil {
|
||||||
return customFields[getRefType(node)]
|
return ownFields[getRefType(node)]
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -51,8 +51,11 @@ func resolveAdditionalProperties(v *jsonschema.Schema) *jsonschema.Schema {
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveRefs(s *jsonschema.Schema, schemas map[string]*jsonschema.Schema) *jsonschema.Schema {
|
func resolveRefs(s *jsonschema.Schema, schemas map[string]*jsonschema.Schema) *jsonschema.Schema {
|
||||||
node := s
|
if s == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
node := s
|
||||||
description := s.Description
|
description := s.Description
|
||||||
markdownDescription := s.MarkdownDescription
|
markdownDescription := s.MarkdownDescription
|
||||||
examples := s.Examples
|
examples := s.Examples
|
||||||
|
@ -62,6 +65,7 @@ func resolveRefs(s *jsonschema.Schema, schemas map[string]*jsonschema.Schema) *j
|
||||||
newNode, ok := schemas[ref]
|
newNode, ok := schemas[ref]
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Printf("schema %s not found", ref)
|
log.Printf("schema %s not found", ref)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if description == "" {
|
if description == "" {
|
||||||
|
|
Loading…
Reference in New Issue