Skip to content

Commit 024db9d

Browse files
committed
feat: impl go package to kcl files
Signed-off-by: peefy <[email protected]>
1 parent f4a0793 commit 024db9d

File tree

7 files changed

+561
-422
lines changed

7 files changed

+561
-422
lines changed

pkg/tools/gen/genkcl.go

-182
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,15 @@ package gen
22

33
import (
44
"errors"
5-
"fmt"
65
"io"
76
"path/filepath"
8-
"regexp"
9-
"strconv"
107
"strings"
118

129
"kcl-lang.io/kcl-go/pkg/loader"
13-
"kcl-lang.io/kcl-go/pkg/logger"
1410
)
1511

1612
type GenKclOptions struct {
1713
Mode Mode
18-
ParseFromTag bool
1914
CastingOption castingOption
2015
UseIntegersForNumbers bool
2116
}
@@ -104,180 +99,3 @@ func (k *kclGenerator) GenSchema(w io.Writer, filename string, src interface{})
10499
return errors.New("unknown mode")
105100
}
106101
}
107-
108-
func (k *kclGenerator) genSchemaFromGoStruct(w io.Writer, filename string, src interface{}) error {
109-
fmt.Fprintln(w)
110-
goStructs, err := ParseGoSourceCode(filename, src)
111-
if err != nil {
112-
return err
113-
}
114-
for _, goStruct := range goStructs {
115-
fmt.Fprintf(w, "schema %s:\n", goStruct.Name)
116-
if goStruct.StructComment != "" {
117-
fmt.Fprintf(w, " \"\"\"%s\"\"\"\n", goStruct.StructComment)
118-
}
119-
for _, field := range goStruct.Fields {
120-
kclFieldName, kclFieldType, err := k.GetTypeName(field)
121-
if err != nil {
122-
logger.GetLogger().Warningf("get struct tag key kcl info err: %s, will generate kcl schema from the struct field metadata data, field info %#v", err.Error(), field)
123-
kclFieldName, kclFieldType = k.GetKclTypeFromStructField(field)
124-
}
125-
fmt.Fprintf(w, " %s: %s\n", kclFieldName, kclFieldType)
126-
}
127-
fmt.Fprintf(w, "\n")
128-
}
129-
return nil
130-
}
131-
132-
func (k *kclGenerator) GetTypeName(f *GoStructField) (string, string, error) {
133-
if k.opts.ParseFromTag {
134-
return k.parserGoStructFieldTag(f.FieldTag)
135-
}
136-
fieldName, fieldType := k.GetKclTypeFromStructField(f)
137-
return fieldName, fieldType, nil
138-
}
139-
140-
func (k *kclGenerator) parserGoStructFieldTag(tag string) (string, string, error) {
141-
tagMap := make(map[string]string, 0)
142-
sp := strings.Split(tag, "`")
143-
if len(sp) == 1 {
144-
return "", "", errors.New("this field not found tag string like ``")
145-
}
146-
value, ok := k.Lookup(sp[1], "kcl")
147-
if !ok {
148-
return "", "", errors.New("not found tag key named kcl")
149-
}
150-
reg := "name=.*,type=.*"
151-
match, err := regexp.Match(reg, []byte(value))
152-
if err != nil {
153-
return "", "", err
154-
}
155-
if !match {
156-
return "", "", errors.New("don't match the kcl tag info, the tag info style is name=NAME,type=TYPE")
157-
}
158-
tagInfo := strings.Split(value, ",")
159-
for _, s := range tagInfo {
160-
t := strings.Split(s, "=")
161-
tagMap[t[0]] = t[1]
162-
}
163-
fieldType := tagMap["type"]
164-
if strings.Contains(tagMap["type"], ")|") {
165-
typeUnionList := strings.Split(tagMap["type"], "|")
166-
var ss []string
167-
for _, u := range typeUnionList {
168-
_, _, litValue := k.isLitType(u)
169-
ss = append(ss, litValue)
170-
}
171-
fieldType = strings.Join(ss, "|")
172-
}
173-
return tagMap["name"], fieldType, nil
174-
}
175-
176-
func (k *kclGenerator) GetKclTypeFromStructField(f *GoStructField) (string, string) {
177-
return f.FieldName, k.isLitGoType(f.FieldType)
178-
}
179-
180-
func (k *kclGenerator) isLitType(fieldType string) (ok bool, basicTyp, litValue string) {
181-
if !strings.HasSuffix(fieldType, ")") {
182-
return
183-
}
184-
185-
i := strings.Index(fieldType, "(") + 1
186-
j := strings.LastIndex(fieldType, ")")
187-
188-
switch {
189-
case strings.HasPrefix(fieldType, "bool("):
190-
return true, "bool", fieldType[i:j]
191-
case strings.HasPrefix(fieldType, "int("):
192-
return true, "int", fieldType[i:j]
193-
case strings.HasPrefix(fieldType, "float("):
194-
return true, "float", fieldType[i:j]
195-
case strings.HasPrefix(fieldType, "str("):
196-
return true, "str", strconv.Quote(fieldType[i:j])
197-
}
198-
return
199-
}
200-
201-
func (k *kclGenerator) isLitGoType(fieldType string) string {
202-
switch fieldType {
203-
case "int", "int32", "int64":
204-
return "int"
205-
case "float", "float64":
206-
return "float"
207-
case "string":
208-
return "str"
209-
case "bool":
210-
return "bool"
211-
case "interface{}":
212-
return "any"
213-
default:
214-
if strings.HasPrefix(fieldType, "*") {
215-
i := strings.Index(fieldType, "*") + 1
216-
return k.isLitGoType(fieldType[i:])
217-
}
218-
if strings.HasPrefix(fieldType, "map") {
219-
i := strings.Index(fieldType, "[") + 1
220-
j := strings.Index(fieldType, "]")
221-
return fmt.Sprintf("{%s:%s}", k.isLitGoType(fieldType[i:j]), k.isLitGoType(fieldType[j+1:]))
222-
}
223-
if strings.HasPrefix(fieldType, "[]") {
224-
i := strings.Index(fieldType, "]") + 1
225-
return fmt.Sprintf("[%s]", k.isLitGoType(fieldType[i:]))
226-
}
227-
return fieldType
228-
}
229-
}
230-
231-
func (k *kclGenerator) Lookup(tag, key string) (value string, ok bool) {
232-
// When modifying this code, also update the validateStructTag code
233-
// in cmd/vet/structtag.go.
234-
235-
for tag != "" {
236-
// Skip leading space.
237-
i := 0
238-
for i < len(tag) && tag[i] == ' ' {
239-
i++
240-
}
241-
tag = tag[i:]
242-
if tag == "" {
243-
break
244-
}
245-
246-
// Scan to colon. A space, a quote or a control character is a syntax error.
247-
// Strictly speaking, control chars include the range [0x7f, 0x9f], not just
248-
// [0x00, 0x1f], but in practice, we ignore the multi-byte control characters
249-
// as it is simpler to inspect the tag's bytes than the tag's runes.
250-
i = 0
251-
for i < len(tag) && tag[i] > ' ' && tag[i] != ':' && tag[i] != '"' && tag[i] != 0x7f {
252-
i++
253-
}
254-
if i == 0 || i+1 >= len(tag) || tag[i] != ':' || tag[i+1] != '"' {
255-
break
256-
}
257-
name := string(tag[:i])
258-
tag = tag[i+1:]
259-
260-
// Scan quoted string to find value.
261-
i = 1
262-
for i < len(tag) && tag[i] != '"' {
263-
if tag[i] == '\\' {
264-
i++
265-
}
266-
i++
267-
}
268-
if i >= len(tag) {
269-
break
270-
}
271-
qvalue := string(tag[:i+1])
272-
tag = tag[i+1:]
273-
274-
if key == name {
275-
value, err := strconv.Unquote(qvalue)
276-
if err != nil {
277-
break
278-
}
279-
return value, true
280-
}
281-
}
282-
return "", false
283-
}

0 commit comments

Comments
 (0)