Repository: kcl-lang/kcl-go
Pull request #130 (2023-08-07 03:58:13)

feat: generate documentation comments from json schema
#### 1. Does this PR affect any open issues?(Y/N) and add issue references

- [ ] N
- [x] Y 

part of https://github.com/kcl-lang/kcl/issues/526


#### 2. What is the scope of this PR (e.g. component or file name):

pkg/tools/gen

#### 3. Provide a description of the PR(e.g. more details, effects, motivations or doc link):

<!-- You can choose a brief description here -->
- [ ] Affects user behaviors
- [ ] Contains syntax changes
- [ ] Contains variable changes
- [ ] Contains experimental features
- [ ] Performance regression: Consumes more CPU
- [ ] Performance regression: Consumes more Memory
- [x] Other

<!-- You can add more details here.
    e.g. 
    Call method "XXXX" to ..... in order to ....,
    More details: https://XXXX.com/doc......
-->

#### 4. Are there any breaking changes?(Y/N) and describe the breaking changes(e.g. more details, motivations or doc link):

- [x] N
- [ ] Y 

<!-- You can add more details here.
    e.g. 
    Calling method "XXXX" will cause the "XXXX", "XXXX" modules to be affected.
    More details: https://XXXX.com/doc......
-->

#### 5. Are there test cases for these changes?(Y/N) select and add more details, references or doc links:

<!-- You can choose a brief description here -->
- [x] Unit test
- [ ] Integration test
- [ ] Benchmark (add benchmark stats below)
- [ ] Manual test (add detailed scripts or steps below)
- [ ] Other

<!-- You can add more details here.
e.g. 
The test case in XXXX is used to .....
test cases in /src/tests/XXXXX
test cases https://github.com/XXX/pull/44
benchmark stats: time XXX ms
-->



Patch:
diff --git a/pkg/tools/gen/genkcl_jsonschema.go b/pkg/tools/gen/genkcl_jsonschema.go
index 2a58f28..e4981be 100644
--- a/pkg/tools/gen/genkcl_jsonschema.go
+++ b/pkg/tools/gen/genkcl_jsonschema.go
@@ -78,6 +78,8 @@ func convertSchemaFromJsonSchema(ctx convertContext, s *jsonschema.Schema, name
 	required := make(map[string]struct{})
 	for _, k := range s.OrderedKeywords {
 		switch v := s.Keywords[k].(type) {
+		case *jsonschema.Title:
+		case *jsonschema.Comment:
 		case *jsonschema.SchemaURI:
 		case *jsonschema.ID:
 			// if the schema has ID, use it as the name
@@ -85,12 +87,8 @@ func convertSchemaFromJsonSchema(ctx convertContext, s *jsonschema.Schema, name
 			if lastSlashIndex != -1 {
 				result.Name = strings.Trim(string(*v)[lastSlashIndex+1:], ".json")
 			}
-		case *jsonschema.Title:
-			result.Description += string(*v)
 		case *jsonschema.Description:
-			result.Description += string(*v)
-		case *jsonschema.Comment:
-			result.Description += string(*v)
+			result.Description = string(*v)
 		case *jsonschema.Type:
 			if len(v.Vals) == 1 {
 				switch v.Vals[0] {
diff --git a/pkg/tools/gen/template.go b/pkg/tools/gen/template.go
index 38f53da..3f38b03 100644
--- a/pkg/tools/gen/template.go
+++ b/pkg/tools/gen/template.go
@@ -4,10 +4,13 @@ import (
 	_ "embed"
 	"fmt"
 	"io"
+	"strings"
 	"text/template"
 )
 
 var (
+	//go:embed templates/document.gotmpl
+	documentTmpl string
 	//go:embed templates/header.gotmpl
 	headerTmpl string
 	//go:embed templates/validator.gotmpl
@@ -20,10 +23,12 @@ var funcs = template.FuncMap{
 	"formatType":  formatType,
 	"formatValue": formatValue,
 	"formatName":  formatName,
+	"formatDoc":   formatDoc,
 }
 
 func (k *kclGenerator) genKclSchema(w io.Writer, s kclSchema) error {
 	tmpl := &template.Template{}
+	tmpl = addTemplate(tmpl, "document", documentTmpl)
 	tmpl = addTemplate(tmpl, "header", headerTmpl)
 	tmpl = addTemplate(tmpl, "validator", validatorTmpl)
 	tmpl = addTemplate(tmpl, "schema", schemaTmpl)
@@ -59,3 +64,8 @@ func formatValue(v interface{}) string {
 func formatName(name string) string {
 	return name
 }
+
+func formatDoc(doc, indent string) string {
+	doc = strings.Replace(doc, "\r\n", "\n", -1)
+	return indent + strings.Replace(doc, "\n", "\n"+indent, -1)
+}
diff --git a/pkg/tools/gen/templates/document.gotmpl b/pkg/tools/gen/templates/document.gotmpl
new file mode 100644
index 0000000..23441ee
--- /dev/null
+++ b/pkg/tools/gen/templates/document.gotmpl
@@ -0,0 +1,17 @@
+{{- if .Description }}
+    {{- formatDoc .Description "    " }}
+{{- else }}
+    {{- formatDoc .Name "    " }}
+{{- end }}
+
+{{- if .Properties }}
+
+    Attributes
+    ----------
+  {{- range .Properties }}
+    {{ formatName .Name }} : {{ formatType .Type }}, {{ if .Required }}required{{ else }}optional{{ end }}
+    {{- if .HasDefault }}, default is {{ formatValue .DefaultValue }}{{ end }}
+    {{- if .Description }}{{ "\n" }}{{ formatDoc .Description "        " }}{{ end }}
+  {{- end -}}
+
+{{- end -}}
diff --git a/pkg/tools/gen/templates/schema.gotmpl b/pkg/tools/gen/templates/schema.gotmpl
index 6be42e6..bf6f343 100644
--- a/pkg/tools/gen/templates/schema.gotmpl
+++ b/pkg/tools/gen/templates/schema.gotmpl
@@ -1,6 +1,10 @@
 {{ template "header" . }}
 {{ range .Schemas -}}
 schema {{ formatName .Name }}:
+    """{{- "\n" }}
+    {{- template "document" . }}
+    """{{- "\n" }}
+
 	{{- range .Properties }}
     {{ formatName .Name }}{{ if not .Required }}?{{ end }}: {{ formatType .Type }}{{ if .HasDefault }} = {{ formatValue .DefaultValue }}{{ end }}
     {{- end }}


Test patch:
diff --git a/pkg/tools/gen/testdata/jsonschema/basic/expect.k b/pkg/tools/gen/testdata/jsonschema/basic/expect.k
index 508ec76..dcd051c 100644
--- a/pkg/tools/gen/testdata/jsonschema/basic/expect.k
+++ b/pkg/tools/gen/testdata/jsonschema/basic/expect.k
@@ -4,6 +4,18 @@ Editing this file might prove futile when you re-run the KCL auto-gen generate c
 """
 
 schema Book:
+    """
+    Book
+
+    Attributes
+    ----------
+    title : str, required
+    authors : [str], optional
+    price : float, optional
+    available : bool, optional, default is True
+    category : "Fiction" | "Science" | "History", optional
+    """
+
     title: str
     authors?: [str]
     price?: float
diff --git a/pkg/tools/gen/testdata/jsonschema/document/expect.k b/pkg/tools/gen/testdata/jsonschema/document/expect.k
new file mode 100644
index 0000000..b085951
--- /dev/null
+++ b/pkg/tools/gen/testdata/jsonschema/document/expect.k
@@ -0,0 +1,24 @@
+"""
+This file was generated by the KCL auto-gen tool. DO NOT EDIT.
+Editing this file might prove futile when you re-run the KCL auto-gen generate command.
+"""
+
+schema MyOrder:
+    """
+    Schema for representing an order information.
+    It contains the order number, list of items and the current status.
+
+    Attributes
+    ----------
+    id : str, required
+        The unique order number.
+    items : [str], optional
+        List of items in the order.
+    status : "processing" | "done", required, default is "processing"
+        Current status of the order.
+    """
+
+    id: str
+    items?: [str]
+    status: "processing" | "done" = "processing"
+
diff --git a/pkg/tools/gen/testdata/jsonschema/document/input.json b/pkg/tools/gen/testdata/jsonschema/document/input.json
new file mode 100644
index 0000000..2edcb85
--- /dev/null
+++ b/pkg/tools/gen/testdata/jsonschema/document/input.json
@@ -0,0 +1,28 @@
+{
+	"$schema": "http://json-schema.org/draft-07/schema#",
+	"$id": "https://example.com/schemas/my-order.json",
+	"title": "My Order",
+	"description": "Schema for representing an order information.\r\nIt contains the order number, list of items and the current status.",
+	"type": "object",
+	"properties": {
+		"id": {
+			"description": "The unique order number.",
+			"type": "string"
+		},
+		"items": {
+			"description": "List of items in the order.",
+			"type": "array",
+			"items": {
+				"type": "string"
+			}
+		},
+		"status": {
+			"description": "Current status of the order.",
+			"enum": ["processing", "done"],
+			"default": "processing"
+		}
+	},
+	"required": [
+		"id", "status"
+	]
+}
diff --git a/pkg/tools/gen/testdata/jsonschema/nested/expect.k b/pkg/tools/gen/testdata/jsonschema/nested/expect.k
index ecb42a0..fdb6618 100644
--- a/pkg/tools/gen/testdata/jsonschema/nested/expect.k
+++ b/pkg/tools/gen/testdata/jsonschema/nested/expect.k
@@ -4,10 +4,28 @@ Editing this file might prove futile when you re-run the KCL auto-gen generate c
 """
 
 schema Book:
+    """
+    Book
+
+    Attributes
+    ----------
+    title : str, optional
+    author : Author, optional
+    """
+
     title?: str
     author?: Author
 
 schema Author:
+    """
+    Author
+
+    Attributes
+    ----------
+    name : str, optional
+    address : str, optional
+    """
+
     name?: str
     address?: str
 
diff --git a/pkg/tools/gen/testdata/jsonschema/validation/expect.k b/pkg/tools/gen/testdata/jsonschema/validation/expect.k
index dad7c7a..5ab6316 100644
--- a/pkg/tools/gen/testdata/jsonschema/validation/expect.k
+++ b/pkg/tools/gen/testdata/jsonschema/validation/expect.k
@@ -4,6 +4,16 @@ Editing this file might prove futile when you re-run the KCL auto-gen generate c
 """
 
 schema Book:
+    """
+    Book
+
+    Attributes
+    ----------
+    title : str, required
+    price : float, optional
+    quantity : int, optional
+    """
+
     title: str
     price?: float
     quantity?: int