cocago_builder.go 3.9 KB
Newer Older
1 2 3
package cocago

import (
P
Phodal Huang 已提交
4
	"fmt"
5
	. "github.com/phodal/coca/pkg/domain/core_domain"
6
	"go/ast"
P
Phodal Huang 已提交
7
	"reflect"
P
Phodal Huang 已提交
8
	"strings"
9 10
)

11
func BuildPropertyField(name string, field *ast.Field) *CodeProperty {
P
Phodal Huang 已提交
12 13
	var typeName string
	var typeType string
14 15
	var params []CodeProperty
	var results []CodeProperty
P
Phodal Huang 已提交
16 17 18 19 20 21 22 23 24 25 26 27
	switch x := field.Type.(type) {
	case *ast.Ident:
		typeType = "Identify"
		typeName = x.String()
	case *ast.ArrayType:
		typeType = "ArrayType"
		switch typeX := x.Elt.(type) {
		case *ast.Ident:
			typeName = typeX.String()
		case *ast.SelectorExpr:
			typeName = getSelectorName(*typeX)
		default:
P
Phodal Huang 已提交
28
			fmt.Fprintf(output, "BuildPropertyField ArrayType %s\n", reflect.TypeOf(x.Elt))
P
Phodal Huang 已提交
29 30 31 32
		}
	case *ast.FuncType:
		typeType = "Function"
		typeName = "func"
33 34 35 36 37 38
		if x.Params != nil {
			params = BuildFieldToProperty(x.Params.List)
		}
		if x.Results != nil {
			results = BuildFieldToProperty(x.Results.List)
		}
P
Phodal Huang 已提交
39 40 41 42 43 44
	case *ast.StarExpr:
		typeName = getStarExprName(*x)
		typeType = "Star"
	case *ast.SelectorExpr:
		typeName = getSelectorName(*x)
	default:
P
Phodal Huang 已提交
45
		fmt.Fprintf(output, "BuildPropertyField %s\n", reflect.TypeOf(x))
46
	}
P
Phodal Huang 已提交
47

48
	property := &CodeProperty{
49 50 51
		Modifiers:   nil,
		Name:        name,
		TypeType:    typeType,
52
		TypeValue:   typeName,
53 54
		ReturnTypes: results,
		Parameters:  params,
P
Phodal Huang 已提交
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
	}
	return property
}

func getSelectorName(typeX ast.SelectorExpr) string {
	return typeX.X.(*ast.Ident).String() + "." + typeX.Sel.Name
}

func getStarExprName(starExpr ast.StarExpr) string {
	switch x := starExpr.X.(type) {
	case *ast.Ident:
		return x.Name
	case *ast.SelectorExpr:
		return getSelectorName(*x)
	default:
		fmt.Println("getStarExprName", reflect.TypeOf(x))
		return ""
	}
}

75 76
func BuildFunction(x *ast.FuncDecl, file *CodeFile) *CodeFunction {
	codeFunc := &CodeFunction{
P
Phodal Huang 已提交
77 78 79 80 81 82 83 84
		Name: x.Name.String(),
	}

	if x.Type.Params != nil {
		codeFunc.Parameters = append(codeFunc.Parameters, BuildFieldToProperty(x.Type.Params.List)...)
	}

	if x.Type.Results != nil {
P
Phodal Huang 已提交
85
		codeFunc.MultipleReturns = append(codeFunc.Parameters, BuildFieldToProperty(x.Type.Results.List)...)
P
Phodal Huang 已提交
86 87
	}

88 89
	fields := file.Fields
	var localVars []CodeProperty
P
Phodal Huang 已提交
90
	for _, item := range x.Body.List {
P
Phodal Huang 已提交
91
		BuildMethodCall(codeFunc, item, fields, localVars, file.Imports)
92
	}
P
Phodal Huang 已提交
93
	return codeFunc
94
}
P
Phodal Huang 已提交
95

96 97
func BuildFieldToProperty(fieldList []*ast.Field) []CodeProperty {
	var properties []CodeProperty
98 99 100 101 102 103
	for _, field := range fieldList {
		property := BuildPropertyField(getFieldName(field), field)
		properties = append(properties, *property)
	}
	return properties
}
P
Phodal Huang 已提交
104

P
Phodal Huang 已提交
105
func BuildMethodCall(codeFunc *CodeFunction, item ast.Stmt, fields []CodeField, localVars []CodeProperty, imports []CodeImport) {
P
Phodal Huang 已提交
106 107
	switch it := item.(type) {
	case *ast.ExprStmt:
P
Phodal Huang 已提交
108
		BuildMethodCallExprStmt(it, codeFunc, fields, imports)
P
Phodal Huang 已提交
109 110 111 112 113
	default:
		fmt.Fprintf(output, "methodCall %s\n", reflect.TypeOf(it))
	}
}

P
Phodal Huang 已提交
114
func BuildMethodCallExprStmt(it *ast.ExprStmt, codeFunc *CodeFunction, fields []CodeField, imports []CodeImport) {
P
Phodal Huang 已提交
115 116 117
	switch expr := it.X.(type) {
	case *ast.CallExpr:
		selector, selName := BuildExpr(expr.Fun.(ast.Expr))
118
		target := ParseTarget(selector, fields)
P
Phodal Huang 已提交
119 120

		packageName := getCallPackageAndTarget(target, imports)
121
		call := CodeCall{
P
Phodal Huang 已提交
122 123
			Package:    packageName,
			Type:       target,
P
Phodal Huang 已提交
124 125 126 127 128 129
			NodeName:   selector,
			MethodName: selName,
		}

		for _, arg := range expr.Args {
			value, kind := BuildExpr(arg.(ast.Expr))
130
			property := &CodeProperty{
P
Phodal Huang 已提交
131 132 133 134 135 136 137 138 139 140
				TypeValue: value,
				TypeType:  kind,
			}

			call.Parameters = append(call.Parameters, *property)
		}

		codeFunc.MethodCalls = append(codeFunc.MethodCalls, call)
	}
}
141

P
Phodal Huang 已提交
142 143 144 145 146 147 148 149 150 151 152 153 154
func getCallPackageAndTarget(target string, imports []CodeImport) string {
	packageName := ""
	if strings.Contains(target, ".") {
		split := strings.Split(target, ".")
		for _, imp := range imports {
			if strings.HasSuffix(imp.Source, split[0]) {
				packageName = imp.Source
			}
		}
	}
	return packageName
}

155 156 157 158 159 160 161 162
func ParseTarget(selector string, fields []CodeField) string {
	for _, field := range fields {
		if field.TypeValue == selector {
			return field.TypeType
		}
	}
	return ""
}