Skip to content

Commit 0b41f99

Browse files
committed
refactor: better go module import impl
1 parent 1460c5c commit 0b41f99

File tree

10 files changed

+1008
-474
lines changed

10 files changed

+1008
-474
lines changed

pkg/tools/gen/genkcl_gostruct.go

+102-52
Original file line numberDiff line numberDiff line change
@@ -100,21 +100,34 @@ func (ctx *genKclTypeContext) typeName(defName string, fieldName string, ty type
100100
return ctx.typeName(defName, fieldName, ty.Elem())
101101
case *types.Named:
102102
obj := ty.Obj()
103-
switch {
104-
case obj.Pkg().Path() == "time" && obj.Name() == "Time":
105-
return typePrimitive(typStr)
106-
case obj.Pkg().Path() == "time" && obj.Name() == "Duration":
107-
return typePrimitive(typInt)
108-
case obj.Pkg().Path() == "math/big" && obj.Name() == "Int":
109-
return typePrimitive(typInt)
110-
default:
111-
if _, ok := ctx.goStructs[obj]; !ok {
112-
return ctx.typeName(defName, fieldName, ty.Underlying())
113-
} else {
114-
return typeCustom{
115-
Name: obj.Name(),
103+
if obj != nil {
104+
pkg := obj.Pkg()
105+
switch {
106+
case pkg != nil && pkg.Path() == "time" && obj.Name() == "Time":
107+
return typePrimitive(typStr)
108+
case pkg != nil && pkg.Path() == "time" && obj.Name() == "Duration":
109+
return typePrimitive(typInt)
110+
case pkg != nil && pkg.Path() == "math/big" && obj.Name() == "Int":
111+
return typePrimitive(typInt)
112+
default:
113+
// Struct from external package in the Go module
114+
if _, ok := ctx.goStructs[obj]; !ok {
115+
if pkg != nil {
116+
ty := ctx.typeName(strcase.ToCamel(pkg.Name()), obj.Name(), ty.Underlying())
117+
return ty
118+
} else {
119+
ty := ctx.typeName(defName, obj.Name(), ty.Underlying())
120+
return ty
121+
}
122+
} else {
123+
// Struct from current package
124+
return typeCustom{
125+
Name: obj.Name(),
126+
}
116127
}
117128
}
129+
} else {
130+
return typePrimitive(typAny)
118131
}
119132
case *types.Array:
120133
return typeArray{
@@ -137,13 +150,29 @@ func (ctx *genKclTypeContext) typeName(defName string, fieldName string, ty type
137150
for i := 0; i < ty.NumFields(); i++ {
138151
sf := ty.Field(i)
139152
typeName := ctx.typeName(schemaName, sf.Name(), sf.Type())
153+
fieldName := formatName(sf.Name())
154+
// TODO: get description and tag name from external AST files.
155+
fieldDescription := ""
156+
description := ""
157+
// Use alias name and type defined in the `kcl` or `json`` tag
158+
tagName, tagTy, err := parserGoStructFieldTag("")
159+
if err == nil {
160+
if tagName != "" {
161+
fieldName = tagName
162+
}
163+
if tagTy != nil {
164+
typeName = tagTy
165+
}
166+
}
167+
result.schema.Description = description
140168
result.schema.Name = schemaName
141169
result.schema.Properties = append(result.Properties, property{
142-
Name: formatName(sf.Name()),
143-
Type: typeName,
170+
Name: fieldName,
171+
Type: typeName,
172+
Description: fieldDescription,
144173
})
145-
ctx.resultMap[schemaName] = result
146174
}
175+
ctx.resultMap[schemaName] = result
147176
}
148177
return typeCustom{
149178
Name: schemaName,
@@ -185,13 +214,19 @@ func (ctx *genKclTypeContext) convertSchemaFromGoPackage() ([]convertResult, err
185214
result := convertResult{IsSchema: true}
186215
result.schema.Name = name
187216
result.schema.Description = s.doc
217+
ctx.resultMap[name] = result
188218
for _, field := range s.fields {
189219
typeName := ctx.typeName(name, field.name, field.ty)
190220
fieldName := formatName(field.name)
221+
// Use alias name and type defined in the `kcl` or `json`` tag
191222
tagName, tagTy, err := parserGoStructFieldTag(field.tag)
192-
if err == nil && tagName != "" && tagTy != nil {
193-
fieldName = tagName
194-
typeName = tagTy
223+
if err == nil {
224+
if tagName != "" {
225+
fieldName = tagName
226+
}
227+
if tagTy != nil {
228+
typeName = tagTy
229+
}
195230
}
196231
result.schema.Properties = append(result.Properties, property{
197232
Name: fieldName,
@@ -219,24 +254,28 @@ func fetchStructs(pkgPath string) (map[*types.TypeName]goStruct, error) {
219254
}
220255
structs := make(map[*types.TypeName]goStruct)
221256
for _, pkg := range pkgs {
257+
if len(pkg.Errors) > 0 {
258+
return nil, errors.New(pkg.Errors[0].Error())
259+
}
222260
astFiles := pkg.Syntax
223261
scope := pkg.Types.Scope()
224262
for _, name := range scope.Names() {
225263
obj := scope.Lookup(name)
226264
if obj, ok := obj.(*types.TypeName); ok {
227-
named, _ := obj.Type().(*types.Named)
228-
if structType, ok := named.Underlying().(*types.Struct); ok {
229-
structDoc := getStructDoc(name, astFiles)
230-
fields, fieldDocs := getStructFieldsAndDocs(structType, name, astFiles)
231-
pkgPath := named.Obj().Pkg().Path()
232-
pkgName := named.Obj().Pkg().Name()
233-
structs[named.Obj()] = goStruct{
234-
pkgPath: pkgPath,
235-
pkgName: pkgName,
236-
name: name,
237-
fields: fields,
238-
doc: structDoc,
239-
fieldDocs: fieldDocs,
265+
if named, ok := obj.Type().(*types.Named); ok {
266+
if structType, ok := named.Underlying().(*types.Struct); ok {
267+
structDoc := getStructDoc(name, astFiles)
268+
pkgPath := named.Obj().Pkg().Path()
269+
pkgName := named.Obj().Pkg().Name()
270+
fields, fieldDocs := getStructFieldsAndDocs(structType, pkgName, name, astFiles)
271+
structs[named.Obj()] = goStruct{
272+
pkgPath: pkgPath,
273+
pkgName: pkgName,
274+
name: name,
275+
fields: fields,
276+
doc: structDoc,
277+
fieldDocs: fieldDocs,
278+
}
240279
}
241280
}
242281
}
@@ -262,26 +301,28 @@ func getStructDoc(structName string, astFiles []*ast.File) string {
262301
return ""
263302
}
264303

265-
func getStructFieldsAndDocs(structType *types.Struct, structName string, astFiles []*ast.File) ([]field, map[string]string) {
304+
func getStructFieldsAndDocs(structType *types.Struct, pkgName string, structName string, astFiles []*ast.File) ([]field, map[string]string) {
266305
fieldDocs := make(map[string]string)
267306
var fields []field
268307
for i := 0; i < structType.NumFields(); i++ {
269308
f := structType.Field(i)
270309
var tag string
271310
for _, file := range astFiles {
272-
for _, decl := range file.Decls {
273-
if genDecl, ok := decl.(*ast.GenDecl); ok && genDecl.Tok == token.TYPE {
274-
for _, spec := range genDecl.Specs {
275-
if typeSpec, ok := spec.(*ast.TypeSpec); ok && typeSpec.Name.Name == structName {
276-
if structType, ok := typeSpec.Type.(*ast.StructType); ok {
277-
for _, field := range structType.Fields.List {
278-
for _, fieldName := range field.Names {
279-
if fieldName.Name == f.Name() {
280-
if field.Doc != nil {
281-
fieldDocs[fieldName.Name] = field.Doc.Text()
282-
}
283-
if field.Tag != nil {
284-
tag = field.Tag.Value
311+
if pkgName == "" || file.Name.Name == pkgName {
312+
for _, decl := range file.Decls {
313+
if genDecl, ok := decl.(*ast.GenDecl); ok && genDecl.Tok == token.TYPE {
314+
for _, spec := range genDecl.Specs {
315+
if typeSpec, ok := spec.(*ast.TypeSpec); ok && typeSpec.Name.Name == structName {
316+
if structType, ok := typeSpec.Type.(*ast.StructType); ok {
317+
for _, field := range structType.Fields.List {
318+
for _, fieldName := range field.Names {
319+
if fieldName.Name == f.Name() {
320+
if field.Doc != nil {
321+
fieldDocs[fieldName.Name] = field.Doc.Text()
322+
}
323+
if field.Tag != nil {
324+
tag = field.Tag.Value
325+
}
285326
}
286327
}
287328
}
@@ -293,7 +334,7 @@ func getStructFieldsAndDocs(structType *types.Struct, structName string, astFile
293334
}
294335
}
295336
if f.Embedded() {
296-
embeddedFields, embeddedFieldDocs := getEmbeddedFieldsAndDocs(f.Type(), astFiles, structName)
337+
embeddedFields, embeddedFieldDocs := getEmbeddedFieldsAndDocs(f.Type(), astFiles, "", structName)
297338
fields = append(fields, embeddedFields...)
298339
for k, v := range embeddedFieldDocs {
299340
fieldDocs[k] = v
@@ -311,18 +352,18 @@ func getStructFieldsAndDocs(structType *types.Struct, structName string, astFile
311352
return fields, fieldDocs
312353
}
313354

314-
func getEmbeddedFieldsAndDocs(t types.Type, astFiles []*ast.File, structName string) ([]field, map[string]string) {
355+
func getEmbeddedFieldsAndDocs(t types.Type, astFiles []*ast.File, pkgName, structName string) ([]field, map[string]string) {
315356
fieldDocs := make(map[string]string)
316357
var fields []field
317358
switch t := t.(type) {
318359
case *types.Pointer:
319-
fields, fieldDocs = getEmbeddedFieldsAndDocs(t.Elem(), astFiles, structName)
360+
fields, fieldDocs = getEmbeddedFieldsAndDocs(t.Elem(), astFiles, pkgName, structName)
320361
case *types.Named:
321362
if structType, ok := t.Underlying().(*types.Struct); ok {
322-
fields, fieldDocs = getStructFieldsAndDocs(structType, structName, astFiles)
363+
fields, fieldDocs = getStructFieldsAndDocs(structType, pkgName, structName, astFiles)
323364
}
324365
case *types.Struct:
325-
fields, fieldDocs = getStructFieldsAndDocs(t, structName, astFiles)
366+
fields, fieldDocs = getStructFieldsAndDocs(t, pkgName, structName, astFiles)
326367
}
327368
return fields, fieldDocs
328369
}
@@ -335,7 +376,16 @@ func parserGoStructFieldTag(tag string) (string, typeInterface, error) {
335376
}
336377
value, ok := lookupTag(sp[1], "kcl")
337378
if !ok {
338-
return "", nil, errors.New("not found tag key named kcl")
379+
value, ok = lookupTag(sp[1], "json")
380+
if !ok {
381+
return "", nil, errors.New("not found tag key named json or kcl")
382+
}
383+
tagInfos := strings.Split(value, ",")
384+
if len(tagInfos) > 0 {
385+
return tagInfos[0], nil, nil
386+
} else {
387+
return "", nil, errors.New("invalid tag key named json")
388+
}
339389
}
340390
reg := "name=.*,type=.*"
341391
match, err := regexp.Match(reg, []byte(value))

0 commit comments

Comments
 (0)