diff --git a/pkg/tools/gen/genkcl.go b/pkg/tools/gen/genkcl.go
index 30fb3dcf..20b7f1a4 100644
--- a/pkg/tools/gen/genkcl.go
+++ b/pkg/tools/gen/genkcl.go
@@ -2,20 +2,15 @@ package gen
 
 import (
 	"errors"
-	"fmt"
 	"io"
 	"path/filepath"
-	"regexp"
-	"strconv"
 	"strings"
 
 	"kcl-lang.io/kcl-go/pkg/loader"
-	"kcl-lang.io/kcl-go/pkg/logger"
 )
 
 type GenKclOptions struct {
 	Mode                  Mode
-	ParseFromTag          bool
 	CastingOption         castingOption
 	UseIntegersForNumbers bool
 }
@@ -104,180 +99,3 @@ func (k *kclGenerator) GenSchema(w io.Writer, filename string, src interface{})
 		return errors.New("unknown mode")
 	}
 }
-
-func (k *kclGenerator) genSchemaFromGoStruct(w io.Writer, filename string, src interface{}) error {
-	fmt.Fprintln(w)
-	goStructs, err := ParseGoSourceCode(filename, src)
-	if err != nil {
-		return err
-	}
-	for _, goStruct := range goStructs {
-		fmt.Fprintf(w, "schema %s:\n", goStruct.Name)
-		if goStruct.StructComment != "" {
-			fmt.Fprintf(w, "    \"\"\"%s\"\"\"\n", goStruct.StructComment)
-		}
-		for _, field := range goStruct.Fields {
-			kclFieldName, kclFieldType, err := k.GetTypeName(field)
-			if err != nil {
-				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)
-				kclFieldName, kclFieldType = k.GetKclTypeFromStructField(field)
-			}
-			fmt.Fprintf(w, "    %s: %s\n", kclFieldName, kclFieldType)
-		}
-		fmt.Fprintf(w, "\n")
-	}
-	return nil
-}
-
-func (k *kclGenerator) GetTypeName(f *GoStructField) (string, string, error) {
-	if k.opts.ParseFromTag {
-		return k.parserGoStructFieldTag(f.FieldTag)
-	}
-	fieldName, fieldType := k.GetKclTypeFromStructField(f)
-	return fieldName, fieldType, nil
-}
-
-func (k *kclGenerator) parserGoStructFieldTag(tag string) (string, string, error) {
-	tagMap := make(map[string]string, 0)
-	sp := strings.Split(tag, "`")
-	if len(sp) == 1 {
-		return "", "", errors.New("this field not found tag string like ``")
-	}
-	value, ok := k.Lookup(sp[1], "kcl")
-	if !ok {
-		return "", "", errors.New("not found tag key named kcl")
-	}
-	reg := "name=.*,type=.*"
-	match, err := regexp.Match(reg, []byte(value))
-	if err != nil {
-		return "", "", err
-	}
-	if !match {
-		return "", "", errors.New("don't match the kcl tag info, the tag info style is name=NAME,type=TYPE")
-	}
-	tagInfo := strings.Split(value, ",")
-	for _, s := range tagInfo {
-		t := strings.Split(s, "=")
-		tagMap[t[0]] = t[1]
-	}
-	fieldType := tagMap["type"]
-	if strings.Contains(tagMap["type"], ")|") {
-		typeUnionList := strings.Split(tagMap["type"], "|")
-		var ss []string
-		for _, u := range typeUnionList {
-			_, _, litValue := k.isLitType(u)
-			ss = append(ss, litValue)
-		}
-		fieldType = strings.Join(ss, "|")
-	}
-	return tagMap["name"], fieldType, nil
-}
-
-func (k *kclGenerator) GetKclTypeFromStructField(f *GoStructField) (string, string) {
-	return f.FieldName, k.isLitGoType(f.FieldType)
-}
-
-func (k *kclGenerator) isLitType(fieldType string) (ok bool, basicTyp, litValue string) {
-	if !strings.HasSuffix(fieldType, ")") {
-		return
-	}
-
-	i := strings.Index(fieldType, "(") + 1
-	j := strings.LastIndex(fieldType, ")")
-
-	switch {
-	case strings.HasPrefix(fieldType, "bool("):
-		return true, "bool", fieldType[i:j]
-	case strings.HasPrefix(fieldType, "int("):
-		return true, "int", fieldType[i:j]
-	case strings.HasPrefix(fieldType, "float("):
-		return true, "float", fieldType[i:j]
-	case strings.HasPrefix(fieldType, "str("):
-		return true, "str", strconv.Quote(fieldType[i:j])
-	}
-	return
-}
-
-func (k *kclGenerator) isLitGoType(fieldType string) string {
-	switch fieldType {
-	case "int", "int32", "int64":
-		return "int"
-	case "float", "float64":
-		return "float"
-	case "string":
-		return "str"
-	case "bool":
-		return "bool"
-	case "interface{}":
-		return "any"
-	default:
-		if strings.HasPrefix(fieldType, "*") {
-			i := strings.Index(fieldType, "*") + 1
-			return k.isLitGoType(fieldType[i:])
-		}
-		if strings.HasPrefix(fieldType, "map") {
-			i := strings.Index(fieldType, "[") + 1
-			j := strings.Index(fieldType, "]")
-			return fmt.Sprintf("{%s:%s}", k.isLitGoType(fieldType[i:j]), k.isLitGoType(fieldType[j+1:]))
-		}
-		if strings.HasPrefix(fieldType, "[]") {
-			i := strings.Index(fieldType, "]") + 1
-			return fmt.Sprintf("[%s]", k.isLitGoType(fieldType[i:]))
-		}
-		return fieldType
-	}
-}
-
-func (k *kclGenerator) Lookup(tag, key string) (value string, ok bool) {
-	// When modifying this code, also update the validateStructTag code
-	// in cmd/vet/structtag.go.
-
-	for tag != "" {
-		// Skip leading space.
-		i := 0
-		for i < len(tag) && tag[i] == ' ' {
-			i++
-		}
-		tag = tag[i:]
-		if tag == "" {
-			break
-		}
-
-		// Scan to colon. A space, a quote or a control character is a syntax error.
-		// Strictly speaking, control chars include the range [0x7f, 0x9f], not just
-		// [0x00, 0x1f], but in practice, we ignore the multi-byte control characters
-		// as it is simpler to inspect the tag's bytes than the tag's runes.
-		i = 0
-		for i < len(tag) && tag[i] > ' ' && tag[i] != ':' && tag[i] != '"' && tag[i] != 0x7f {
-			i++
-		}
-		if i == 0 || i+1 >= len(tag) || tag[i] != ':' || tag[i+1] != '"' {
-			break
-		}
-		name := string(tag[:i])
-		tag = tag[i+1:]
-
-		// Scan quoted string to find value.
-		i = 1
-		for i < len(tag) && tag[i] != '"' {
-			if tag[i] == '\\' {
-				i++
-			}
-			i++
-		}
-		if i >= len(tag) {
-			break
-		}
-		qvalue := string(tag[:i+1])
-		tag = tag[i+1:]
-
-		if key == name {
-			value, err := strconv.Unquote(qvalue)
-			if err != nil {
-				break
-			}
-			return value, true
-		}
-	}
-	return "", false
-}
diff --git a/pkg/tools/gen/genkcl_gostruct.go b/pkg/tools/gen/genkcl_gostruct.go
new file mode 100644
index 00000000..26dcb41a
--- /dev/null
+++ b/pkg/tools/gen/genkcl_gostruct.go
@@ -0,0 +1,442 @@
+package gen
+
+import (
+	"errors"
+	"fmt"
+	"go/ast"
+	"go/token"
+	"go/types"
+	"io"
+	"regexp"
+	"strconv"
+	"strings"
+
+	"github.com/iancoleman/strcase"
+	"golang.org/x/tools/go/packages"
+)
+
+type goStruct struct {
+	pkgPath   string
+	pkgName   string
+	name      string
+	fields    []field
+	doc       string
+	fieldDocs map[string]string
+}
+
+type field struct {
+	name string
+	ty   types.Type
+	tag  string
+}
+
+type genKclTypeContext struct {
+	context
+	// Go package path.
+	pkgPath   string
+	goStructs map[*types.TypeName]goStruct
+	oneFile   bool
+}
+
+func (k *kclGenerator) genSchemaFromGoStruct(w io.Writer, filename string, _ interface{}) error {
+	ctx := genKclTypeContext{
+		pkgPath: filename,
+		context: context{
+			resultMap: make(map[string]convertResult),
+			imports:   make(map[string]struct{}),
+			paths:     []string{},
+		},
+		oneFile: true,
+	}
+	results, err := ctx.convertSchemaFromGoPackage()
+	if err != nil {
+		return err
+	}
+	kclSch := kclFile{
+		Schemas: []schema{},
+	}
+	for _, result := range results {
+		if result.IsSchema {
+			kclSch.Schemas = append(kclSch.Schemas, result.schema)
+		}
+	}
+	// generate kcl schema code
+	return k.genKcl(w, kclSch)
+}
+
+func (ctx *genKclTypeContext) typeName(defName string, fieldName string, ty types.Type) typeInterface {
+	switch ty := ty.(type) {
+	case *types.Basic:
+		switch ty.Kind() {
+		case types.Bool, types.UntypedBool:
+			return typePrimitive(typBool)
+		case types.Int,
+			types.Int8,
+			types.Int16,
+			types.Int32,
+			types.Int64,
+			types.Uint,
+			types.Uint8,
+			types.Uint16,
+			types.Uint32,
+			types.Uint64,
+			types.Uintptr,
+			types.UnsafePointer,
+			types.UntypedInt:
+			return typePrimitive(typInt)
+		case types.Float32,
+			types.Float64,
+			types.Complex64,
+			types.Complex128,
+			types.UntypedFloat,
+			types.UntypedComplex:
+			return typePrimitive(typFloat)
+		case types.String, types.UntypedString, types.UntypedRune:
+			return typePrimitive(typStr)
+		default:
+			return typePrimitive(typAny)
+		}
+	case *types.Pointer:
+		return ctx.typeName(defName, fieldName, ty.Elem())
+	case *types.Named:
+		obj := ty.Obj()
+		switch {
+		case obj.Pkg().Path() == "time" && obj.Name() == "Time":
+			return typePrimitive(typStr)
+		case obj.Pkg().Path() == "time" && obj.Name() == "Duration":
+			return typePrimitive(typInt)
+		case obj.Pkg().Path() == "math/big" && obj.Name() == "Int":
+			return typePrimitive(typInt)
+		default:
+			if _, ok := ctx.goStructs[obj]; !ok {
+				return ctx.typeName(defName, fieldName, ty.Underlying())
+			} else {
+				return typeCustom{
+					Name: obj.Name(),
+				}
+			}
+		}
+	case *types.Array:
+		return typeArray{
+			Items: ctx.typeName(defName, fieldName, ty.Elem()),
+		}
+	case *types.Slice:
+		return typeArray{
+			Items: ctx.typeName(defName, fieldName, ty.Elem()),
+		}
+	case *types.Map:
+		return typeDict{
+			Key:   ctx.typeName(defName, fieldName, ty.Key()),
+			Value: ctx.typeName(defName, fieldName, ty.Elem()),
+		}
+	case *types.Struct:
+		schemaName := fmt.Sprintf("%s%s", defName, strcase.ToCamel(fieldName))
+		if _, ok := ctx.resultMap[schemaName]; !ok {
+			result := convertResult{IsSchema: true}
+			ctx.resultMap[schemaName] = result
+			for i := 0; i < ty.NumFields(); i++ {
+				sf := ty.Field(i)
+				typeName := ctx.typeName(schemaName, sf.Name(), sf.Type())
+				result.schema.Name = schemaName
+				result.schema.Properties = append(result.Properties, property{
+					Name: formatName(sf.Name()),
+					Type: typeName,
+				})
+				ctx.resultMap[schemaName] = result
+			}
+		}
+		return typeCustom{
+			Name: schemaName,
+		}
+	case *types.Union:
+		var types []typeInterface
+		for i := 0; i < ty.Len(); i++ {
+			types = append(types, ctx.typeName(defName, fieldName, ty.Term(i).Type()))
+		}
+		return typeUnion{
+			Items: types,
+		}
+	case *types.Interface:
+		if !ty.IsComparable() {
+			return typePrimitive(typAny)
+		}
+		var types []typeInterface
+		for i := 0; i < ty.NumEmbeddeds(); i++ {
+			types = append(types, ctx.typeName(defName, fieldName, ty.EmbeddedType(i)))
+		}
+		return typeUnion{
+			Items: types,
+		}
+	default:
+		return typePrimitive(typAny)
+	}
+}
+
+func (ctx *genKclTypeContext) convertSchemaFromGoPackage() ([]convertResult, error) {
+	structs, error := fetchStructs(ctx.pkgPath)
+	ctx.goStructs = structs
+	if error != nil {
+		return nil, error
+	}
+	var results []convertResult
+	for _, s := range structs {
+		name := s.name
+		if _, ok := ctx.resultMap[name]; !ok {
+			result := convertResult{IsSchema: true}
+			ctx.resultMap[name] = result
+			for _, field := range s.fields {
+				typeName := ctx.typeName(name, field.name, field.ty)
+				fieldName := formatName(field.name)
+				tagName, tagTy, err := parserGoStructFieldTag(field.tag)
+				if err == nil && tagName != "" && tagTy != nil {
+					fieldName = tagName
+					typeName = tagTy
+				}
+				result.schema.Name = name
+				result.schema.Description = s.doc
+				result.schema.Properties = append(result.Properties, property{
+					Name:        fieldName,
+					Type:        typeName,
+					Description: s.fieldDocs[field.name],
+				})
+				ctx.resultMap[name] = result
+			}
+		}
+	}
+	// Append anonymous structs
+	for _, key := range getSortedKeys(ctx.resultMap) {
+		if ctx.resultMap[key].IsSchema {
+			results = append(results, ctx.resultMap[key])
+		}
+	}
+	return results, nil
+}
+
+func fetchStructs(pkgPath string) (map[*types.TypeName]goStruct, error) {
+	cfg := &packages.Config{Mode: packages.NeedTypes | packages.NeedDeps | packages.NeedSyntax | packages.NeedTypesInfo}
+	pkgs, err := packages.Load(cfg, pkgPath)
+	if err != nil {
+		return nil, err
+	}
+	structs := make(map[*types.TypeName]goStruct)
+	for _, pkg := range pkgs {
+		astFiles := pkg.Syntax
+		scope := pkg.Types.Scope()
+		for _, name := range scope.Names() {
+			obj := scope.Lookup(name)
+			if obj, ok := obj.(*types.TypeName); ok {
+				named, _ := obj.Type().(*types.Named)
+				if structType, ok := named.Underlying().(*types.Struct); ok {
+					structDoc := getStructDoc(name, astFiles)
+					fields, fieldDocs := getStructFieldsAndDocs(structType, name, astFiles)
+					pkgPath := named.Obj().Pkg().Path()
+					pkgName := named.Obj().Pkg().Name()
+					structs[named.Obj()] = goStruct{
+						pkgPath:   pkgPath,
+						pkgName:   pkgName,
+						name:      name,
+						fields:    fields,
+						doc:       structDoc,
+						fieldDocs: fieldDocs,
+					}
+				}
+			}
+		}
+	}
+	return structs, nil
+}
+
+func getStructDoc(structName string, astFiles []*ast.File) string {
+	for _, file := range astFiles {
+		for _, decl := range file.Decls {
+			if genDecl, ok := decl.(*ast.GenDecl); ok && genDecl.Tok == token.TYPE {
+				for _, spec := range genDecl.Specs {
+					if typeSpec, ok := spec.(*ast.TypeSpec); ok && typeSpec.Name.Name == structName {
+						if genDecl.Doc != nil {
+							return genDecl.Doc.Text()
+						}
+					}
+				}
+			}
+		}
+	}
+	return ""
+}
+
+func getStructFieldsAndDocs(structType *types.Struct, structName string, astFiles []*ast.File) ([]field, map[string]string) {
+	fieldDocs := make(map[string]string)
+	var fields []field
+	for i := 0; i < structType.NumFields(); i++ {
+		f := structType.Field(i)
+		var tag string
+		for _, file := range astFiles {
+			for _, decl := range file.Decls {
+				if genDecl, ok := decl.(*ast.GenDecl); ok && genDecl.Tok == token.TYPE {
+					for _, spec := range genDecl.Specs {
+						if typeSpec, ok := spec.(*ast.TypeSpec); ok && typeSpec.Name.Name == structName {
+							if structType, ok := typeSpec.Type.(*ast.StructType); ok {
+								for _, field := range structType.Fields.List {
+									for _, fieldName := range field.Names {
+										if fieldName.Name == f.Name() {
+											if field.Doc != nil {
+												fieldDocs[fieldName.Name] = field.Doc.Text()
+											}
+											if field.Tag != nil {
+												tag = field.Tag.Value
+											}
+										}
+									}
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+		if f.Embedded() {
+			embeddedFields, embeddedFieldDocs := getEmbeddedFieldsAndDocs(f.Type(), astFiles, structName)
+			fields = append(fields, embeddedFields...)
+			for k, v := range embeddedFieldDocs {
+				fieldDocs[k] = v
+			}
+		} else {
+			if f.Exported() {
+				fields = append(fields, field{
+					name: f.Name(),
+					ty:   f.Type(),
+					tag:  tag,
+				})
+			}
+		}
+	}
+	return fields, fieldDocs
+}
+
+func getEmbeddedFieldsAndDocs(t types.Type, astFiles []*ast.File, structName string) ([]field, map[string]string) {
+	fieldDocs := make(map[string]string)
+	var fields []field
+	switch t := t.(type) {
+	case *types.Pointer:
+		fields, fieldDocs = getEmbeddedFieldsAndDocs(t.Elem(), astFiles, structName)
+	case *types.Named:
+		if structType, ok := t.Underlying().(*types.Struct); ok {
+			fields, fieldDocs = getStructFieldsAndDocs(structType, structName, astFiles)
+		}
+	case *types.Struct:
+		fields, fieldDocs = getStructFieldsAndDocs(t, structName, astFiles)
+	}
+	return fields, fieldDocs
+}
+
+func parserGoStructFieldTag(tag string) (string, typeInterface, error) {
+	tagMap := make(map[string]string, 0)
+	sp := strings.Split(tag, "`")
+	if len(sp) == 1 {
+		return "", nil, errors.New("this field not found tag string like ``")
+	}
+	value, ok := lookupTag(sp[1], "kcl")
+	if !ok {
+		return "", nil, errors.New("not found tag key named kcl")
+	}
+	reg := "name=.*,type=.*"
+	match, err := regexp.Match(reg, []byte(value))
+	if err != nil {
+		return "", nil, err
+	}
+	if !match {
+		return "", nil, errors.New("don't match the kcl tag info, the tag info style is name=NAME,type=TYPE")
+	}
+	tagInfo := strings.Split(value, ",")
+	for _, s := range tagInfo {
+		t := strings.Split(s, "=")
+		tagMap[t[0]] = t[1]
+	}
+	fieldType := tagMap["type"]
+	if strings.Contains(tagMap["type"], ")|") {
+		typeUnionList := strings.Split(tagMap["type"], "|")
+		var ss []string
+		for _, u := range typeUnionList {
+			_, _, litValue := isLitType(u)
+			ss = append(ss, litValue)
+		}
+		fieldType = strings.Join(ss, "|")
+	}
+	return tagMap["name"], typeCustom{
+		Name: fieldType,
+	}, nil
+}
+
+func isLitType(fieldType string) (ok bool, basicTyp, litValue string) {
+	if !strings.HasSuffix(fieldType, ")") {
+		return
+	}
+
+	i := strings.Index(fieldType, "(") + 1
+	j := strings.LastIndex(fieldType, ")")
+
+	switch {
+	case strings.HasPrefix(fieldType, "bool("):
+		return true, "bool", fieldType[i:j]
+	case strings.HasPrefix(fieldType, "int("):
+		return true, "int", fieldType[i:j]
+	case strings.HasPrefix(fieldType, "float("):
+		return true, "float", fieldType[i:j]
+	case strings.HasPrefix(fieldType, "str("):
+		return true, "str", strconv.Quote(fieldType[i:j])
+	}
+	return
+}
+
+func lookupTag(tag, key string) (value string, ok bool) {
+	// When modifying this code, also update the validateStructTag code
+	// in cmd/vet/structtag.go.
+
+	for tag != "" {
+		// Skip leading space.
+		i := 0
+		for i < len(tag) && tag[i] == ' ' {
+			i++
+		}
+		tag = tag[i:]
+		if tag == "" {
+			break
+		}
+
+		// Scan to colon. A space, a quote or a control character is a syntax error.
+		// Strictly speaking, control chars include the range [0x7f, 0x9f], not just
+		// [0x00, 0x1f], but in practice, we ignore the multi-byte control characters
+		// as it is simpler to inspect the tag's bytes than the tag's runes.
+		i = 0
+		for i < len(tag) && tag[i] > ' ' && tag[i] != ':' && tag[i] != '"' && tag[i] != 0x7f {
+			i++
+		}
+		if i == 0 || i+1 >= len(tag) || tag[i] != ':' || tag[i+1] != '"' {
+			break
+		}
+		name := string(tag[:i])
+		tag = tag[i+1:]
+
+		// Scan quoted string to find value.
+		i = 1
+		for i < len(tag) && tag[i] != '"' {
+			if tag[i] == '\\' {
+				i++
+			}
+			i++
+		}
+		if i >= len(tag) {
+			break
+		}
+		qvalue := string(tag[:i+1])
+		tag = tag[i+1:]
+
+		if key == name {
+			value, err := strconv.Unquote(qvalue)
+			if err != nil {
+				break
+			}
+			return value, true
+		}
+	}
+	return "", false
+}
diff --git a/pkg/tools/gen/genkcl_jsonschema.go b/pkg/tools/gen/genkcl_jsonschema.go
index 27e14956..2e38df42 100644
--- a/pkg/tools/gen/genkcl_jsonschema.go
+++ b/pkg/tools/gen/genkcl_jsonschema.go
@@ -24,15 +24,19 @@ const (
 	camelCase
 )
 
+type context struct {
+	imports       map[string]struct{}
+	resultMap     map[string]convertResult
+	paths         []string
+	castingOption castingOption
+}
+
 type convertContext struct {
+	context
 	rootSchema *jsonschema.Schema
-	imports    map[string]struct{}
-	resultMap  map[string]convertResult
-	paths      []string
 	// pathObjects is used to avoid infinite loop when converting recursive schema
 	// TODO: support recursive schema
-	pathObjects   []*jsonschema.Schema
-	castingOption castingOption
+	pathObjects []*jsonschema.Schema
 }
 
 type convertResult struct {
@@ -66,10 +70,12 @@ func (k *kclGenerator) genSchemaFromJsonSchema(w io.Writer, filename string, src
 
 	// convert json schema to kcl schema
 	ctx := convertContext{
-		rootSchema:  js,
-		resultMap:   make(map[string]convertResult),
-		imports:     make(map[string]struct{}),
-		paths:       []string{},
+		rootSchema: js,
+		context: context{
+			resultMap: make(map[string]convertResult),
+			imports:   make(map[string]struct{}),
+			paths:     []string{},
+		},
 		pathObjects: []*jsonschema.Schema{},
 	}
 	result := convertSchemaFromJsonSchema(&ctx, js,
diff --git a/pkg/tools/gen/genkcl_test.go b/pkg/tools/gen/genkcl_test.go
index 7f0ff4cc..f8156034 100644
--- a/pkg/tools/gen/genkcl_test.go
+++ b/pkg/tools/gen/genkcl_test.go
@@ -2,7 +2,6 @@ package gen
 
 import (
 	"bytes"
-	"fmt"
 	"log"
 	"os"
 	"path/filepath"
@@ -14,97 +13,105 @@ import (
 
 func TestGenKcl(t *testing.T) {
 	var buf bytes.Buffer
-	opts := &GenKclOptions{
-		ParseFromTag: false,
-	}
+	opts := &GenKclOptions{}
 	err := GenKcl(&buf, "./testdata/genkcldata.go", nil, opts)
 	// err := GenKcl(&buf, "demo", code, opts)
 	if err != nil {
 		log.Fatal(err)
 	}
 	kclCode := buf.String()
-	fmt.Println("###############")
-	fmt.Print(kclCode)
-	expectedKclCodeFromTag := `
-schema Person:
-    """Person Example"""
-    name: str
-    age: int
-    friends: [str]
-    movies: {str:Movie}
-    MapInterface: {str:{str:any}}
-    Ep: employee
-    Com: Company
-    StarInt: int
-    StarMap: {str:str}
-    Inter: any
+	expectedKclCodeFromField := `"""
+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 Company:
+    r"""
+    Company
+
+    Attributes
+    ----------
+    name : str, optional
+    employees : [Employee], optional
+    persons : Person, optional
+    """
+
+    name?: str
+    employees?: [Employee]
+    persons?: Person
+
+schema Employee:
+    r"""
+    Employee
+
+    Attributes
+    ----------
+    name : str, optional
+    age : int, optional
+    friends : [str], optional
+    movies : {str:Movie}, optional
+    bankCard : int, optional
+    nationality : str, optional
+    """
+
+    name?: str
+    age?: int
+    friends?: [str]
+    movies?: {str:Movie}
+    bankCard?: int
+    nationality?: str
 
 schema Movie:
-    desc: str
-    size: units.NumberMultiplier
+    r"""
+    Movie
+
+    Attributes
+    ----------
+    Desc : str, optional
+    size : units.NumberMultiplier, optional
+    kind : "Superhero"|"War"|"Unknown", optional
+    unknown1 : int|str, optional
+    unknown2 : any, optional
+    """
+
+    Desc?: str
+    size?: units.NumberMultiplier
     kind?: "Superhero"|"War"|"Unknown"
     unknown1?: int|str
     unknown2?: any
 
-schema employee:
-    name: str
-    age: int
-    friends: [str]
-    movies: {str:Movie}
-    bankCard: int
-    nationality: str
-
-schema Company:
-    name: str
-    employees: [employee]
-    persons: Person
-
-`
-	expectedKclCodeFromField := `
 schema Person:
-    """Person Example"""
-    name: str
-    age: int
-    friends: [str]
-    movies: {str:Movie}
-    MapInterface: {str:{str:any}}
-    Ep: employee
-    Com: Company
-    StarInt: int
-    StarMap: {str:str}
-    Inter: any
-
-schema Movie:
-    desc: str
-    size: int
-    kind: str
-    unknown1: any
-    unknown2: any
-
-schema employee:
-    name: str
-    age: int
-    friends: [str]
-    movies: {str:Movie}
-    bankCard: int
-    nationality: str
-
-schema Company:
-    name: str
-    employees: [employee]
-    persons: Person
+    r"""
+    Person Example
+
+
+    Attributes
+    ----------
+    name : str, optional
+    age : int, optional
+    friends : [str], optional
+    movies : {str:Movie}, optional
+    MapInterface : {str:{str:any}}, optional
+    Ep : Employee, optional
+    Com : Company, optional
+    StarInt : int, optional
+    StarMap : {str:str}, optional
+    Inter : any, optional
+    """
+
+    name?: str
+    age?: int
+    friends?: [str]
+    movies?: {str:Movie}
+    MapInterface?: {str:{str:any}}
+    Ep?: Employee
+    Com?: Company
+    StarInt?: int
+    StarMap?: {str:str}
+    Inter?: any
 
 `
-	if opts.ParseFromTag {
-		if kclCode != expectedKclCodeFromTag {
-			panic(fmt.Sprintf("test failed, expected %s got %s", expectedKclCodeFromTag, kclCode))
-		}
-	} else {
-		if kclCode != expectedKclCodeFromField {
-			panic(fmt.Sprintf("test failed, expected %s got %s", expectedKclCodeFromField, kclCode))
-		}
-	}
-
+	assert2.Equal(t, strings.ReplaceAll(kclCode, "\r\n", "\n"), strings.ReplaceAll(expectedKclCodeFromField, "\r\n", "\n"))
 }
 
 func TestGenKclFromJsonSchema(t *testing.T) {
diff --git a/pkg/tools/gen/gotypes.go b/pkg/tools/gen/gotypes.go
deleted file mode 100644
index 00a61716..00000000
--- a/pkg/tools/gen/gotypes.go
+++ /dev/null
@@ -1,107 +0,0 @@
-package gen
-
-import (
-	"fmt"
-	"go/ast"
-	"go/parser"
-	"go/token"
-	"strings"
-)
-
-type GoStruct struct {
-	Name          string
-	Fields        []*GoStructField
-	FieldNum      int
-	StructComment string
-}
-
-type GoStructField struct {
-	FieldName    string
-	FieldType    string
-	FieldTag     string
-	FieldTagKind string
-	FieldComment string
-}
-
-// ParseGoSourceCode parse go source code from .go file path or source code
-func ParseGoSourceCode(filename string, src interface{}) ([]*GoStruct, error) {
-	fset := token.NewFileSet()
-	f, err := parser.ParseFile(fset, filename, src, parser.ParseComments)
-	if err != nil {
-		return nil, err
-	}
-	goStructList := make([]*GoStruct, 0)
-	for _, v := range f.Decls {
-		goStruct := &GoStruct{}
-		if stc, ok := v.(*ast.GenDecl); ok && stc.Tok == token.TYPE {
-			if stc.Doc != nil {
-				goStruct.StructComment = strings.TrimRight(stc.Doc.Text(), "\n")
-			}
-			for _, spec := range stc.Specs {
-				goStructFields := make([]*GoStructField, 0)
-				if tp, ok := spec.(*ast.TypeSpec); ok {
-					goStruct.Name = tp.Name.Name
-					if stp, ok := tp.Type.(*ast.StructType); ok {
-						if !stp.Struct.IsValid() {
-							continue
-						}
-						goStruct.FieldNum = stp.Fields.NumFields()
-						for _, field := range stp.Fields.List {
-							goStructField := &GoStructField{}
-
-							// get field name
-							if len(field.Names) == 1 {
-								goStructField.FieldName = field.Names[0].Name
-							} else if len(field.Names) > 1 {
-								for _, name := range field.Names {
-									goStructField.FieldName = goStructField.FieldName + name.String() + ","
-								}
-							}
-
-							// get tag
-							if field.Tag != nil {
-								goStructField.FieldTag = field.Tag.Value
-								goStructField.FieldTagKind = field.Tag.Kind.String()
-							}
-
-							// get comment
-							if field.Comment != nil {
-								goStructField.FieldComment = strings.TrimRight(field.Comment.Text(), "")
-							}
-
-							// get field type
-							goStructField.FieldType = getTypeName(field.Type)
-							goStructFields = append(goStructFields, goStructField)
-						}
-					}
-					goStruct.Fields = goStructFields
-				}
-			}
-			goStructList = append(goStructList, goStruct)
-		}
-	}
-	return goStructList, nil
-}
-
-func getTypeName(f ast.Expr) string {
-	if ft, ok := f.(*ast.Ident); ok {
-		return ft.Name
-	}
-	if ft, ok := f.(*ast.ArrayType); ok {
-		item := getTypeName(ft.Elt)
-		return fmt.Sprintf("[]%s", item)
-	}
-	if ft, ok := f.(*ast.MapType); ok {
-		key := getTypeName(ft.Key)
-		value := getTypeName(ft.Value)
-		return fmt.Sprintf("map[%s]%s", key, value)
-	}
-	if ft, ok := f.(*ast.StarExpr); ok {
-		value := getTypeName(ft.X)
-		return fmt.Sprintf("*%s", value)
-	}
-	if _, ok := f.(*ast.InterfaceType); ok {
-		return "interface{}"
-	}
-	return ""
-}
diff --git a/pkg/tools/gen/gotypes_test.go b/pkg/tools/gen/gotypes_test.go
deleted file mode 100644
index 891b285c..00000000
--- a/pkg/tools/gen/gotypes_test.go
+++ /dev/null
@@ -1,27 +0,0 @@
-package gen
-
-import (
-	"fmt"
-	"testing"
-)
-
-func TestParseGoFiles(t *testing.T) {
-	goStructs, err := ParseGoSourceCode("./testdata/genkcldata.go", nil)
-	if err != nil {
-		t.Fatalf("parse go source code err: %s", err.Error())
-	}
-	t.Logf("%#v", goStructs)
-	for _, v := range goStructs {
-		fmt.Printf("Struct Name: %s\n", v.Name)
-		fmt.Printf("struct Num: %d\n", v.FieldNum)
-		fmt.Printf("struct Comment: %s\n", v.StructComment)
-		for _, f := range v.Fields {
-			fmt.Printf("\tFieldName: %s\n", f.FieldName)
-			fmt.Printf("\tFieldType: %s\n", f.FieldType)
-			fmt.Printf("\tFieldTag: %s\n", f.FieldTag)
-			fmt.Printf("\tFieldTagKind: %s\n", f.FieldTagKind)
-			fmt.Printf("\tFieldComment: %s\n", f.FieldComment)
-			fmt.Printf("\t\n")
-		}
-	}
-}
diff --git a/pkg/tools/gen/testdata/genkcldata.go b/pkg/tools/gen/testdata/genkcldata.go
index 25391715..c3fa3bb5 100644
--- a/pkg/tools/gen/testdata/genkcldata.go
+++ b/pkg/tools/gen/testdata/genkcldata.go
@@ -2,12 +2,12 @@ package testdata
 
 // Person Example
 type Person struct {
-	name         string            `kcl:"name=name,type=str"`           // kcl-type: str
-	age          int               `kcl:"name=age,type=int"`            // kcl-type: int
-	friends      []string          `kcl:"name=friends,type=[str]"`      // kcl-type: [str]
-	movies       map[string]*Movie `kcl:"name=movies,type={str:Movie}"` // kcl-type: {str:Movie}
+	Name         string            `kcl:"name=name,type=str"`           // kcl-type: str
+	Age          int               `kcl:"name=age,type=int"`            // kcl-type: int
+	Friends      []string          `kcl:"name=friends,type=[str]"`      // kcl-type: [str]
+	Movies       map[string]*Movie `kcl:"name=movies,type={str:Movie}"` // kcl-type: {str:Movie}
 	MapInterface map[string]map[string]interface{}
-	Ep           *employee
+	Ep           *Employee
 	Com          Company
 	StarInt      *int
 	StarMap      map[string]string
@@ -15,24 +15,24 @@ type Person struct {
 }
 
 type Movie struct {
-	desc     string      `kcl:"nam=desc,type=str"`                                    // kcl-type: str
-	size     int         `kcl:"name=size,type=units.NumberMultiplier"`                // kcl-type: units.NumberMultiplier
-	kind     string      `kcl:"name=kind?,type=str(Superhero)|str(War)|str(Unknown)"` // kcl-type: "Superhero"|"War"|"Unknown"
-	unknown1 interface{} `kcl:"name=unknown1?,type=int|str"`                          // kcl-type: int|str
-	unknown2 interface{} `kcl:"name=unknown2?,type=any"`                              // kcl-type: any
+	Desc     string      `kcl:"nam=desc,type=str"`                                   // kcl-type: str
+	Size     int         `kcl:"name=size,type=units.NumberMultiplier"`               // kcl-type: units.NumberMultiplier
+	Kind     string      `kcl:"name=kind,type=str(Superhero)|str(War)|str(Unknown)"` // kcl-type: "Superhero"|"War"|"Unknown"
+	Unknown1 interface{} `kcl:"name=unknown1,type=int|str"`                          // kcl-type: int|str
+	Unknown2 interface{} `kcl:"name=unknown2,type=any"`                              // kcl-type: any
 }
 
-type employee struct {
-	name        string            `kcl:"name=name,type=str"`           // kcl-type: str
-	age         int               `kcl:"name=age,type=int"`            // kcl-type: int
-	friends     []string          `kcl:"name=friends,type=[str]"`      // kcl-type: [str]
-	movies      map[string]*Movie `kcl:"name=movies,type={str:Movie}"` // kcl-type: {str:Movie}
-	bankCard    int               `kcl:"name=bankCard,type=int"`       // kcl-type: int
-	nationality string            `kcl:"name=nationality,type=str"`    // kcl-type: str
+type Employee struct {
+	Name        string            `kcl:"name=name,type=str"`           // kcl-type: str
+	Age         int               `kcl:"name=age,type=int"`            // kcl-type: int
+	Friends     []string          `kcl:"name=friends,type=[str]"`      // kcl-type: [str]
+	Movies      map[string]*Movie `kcl:"name=movies,type={str:Movie}"` // kcl-type: {str:Movie}
+	BankCard    int               `kcl:"name=bankCard,type=int"`       // kcl-type: int
+	Nationality string            `kcl:"name=nationality,type=str"`    // kcl-type: str
 }
 
 type Company struct {
-	name      string      `kcl:"name=name,type=str"`             // kcl-type: str
-	employees []*employee `kcl:"name=employees,type=[employee]"` // kcl-type: [employee]
-	persons   *Person     `kcl:"name=persons,type=Person"`       // kcl-type: Person
+	Name      string      `kcl:"name=name,type=str"`             // kcl-type: str
+	Employees []*Employee `kcl:"name=employees,type=[Employee]"` // kcl-type: [Employee]
+	Persons   *Person     `kcl:"name=persons,type=Person"`       // kcl-type: Person
 }