go-translator/pkg/service/class.go

171 строка
3,2 КиБ
Go

package service
import (
"go/ast"
)
type Class interface {
Name() string
String() string
MethodsString() string
AddMethod(*ast.FuncDecl)
}
var (
classDeclarations []Class
isInMethod = false
currentReceiverName = ""
)
type class struct {
name string
Struct *ast.StructType
methods []*ast.FuncDecl
}
func NewClass(name string) *class {
return &class{name: name}
}
func (c *class) Name() string {
return c.name
}
func (c *class) String() (code string) {
code += c.classDefinitionToString()
return
}
func (c *class) MethodsString() (code string) {
code += c.methodImplementationsToString()
return
}
func (c *class) classDefinitionToString() (code string) {
code = "class " + c.name + " {"
code += "public:\n"
code += c.structToString()
code += "\n"
code += c.methodDeclarationsToString()
code += "\n"
code += "};\n"
return
}
func (c *class) structToString() (code string) {
code += handleExpr(c.Struct)
code += "\n"
return
}
func (c *class) methodDeclarationsToString() (code string) {
for _, m := range c.methods {
code += c.methodDeclarationToString(m)
}
code += "\n"
return
}
func (c *class) methodDeclarationToString(m *ast.FuncDecl) (code string) {
code += " "
code += handleFuncDeclType(m.Type)
code += " "
code += m.Name.String() + "("
code += handleFuncDeclParams(m.Type)
code += ");"
code += "\n"
return
}
func (c *class) methodImplementationsToString() (code string) {
for _, m := range c.methods {
code += c.methodImplementationToString(m)
}
code += "\n"
return
}
func (c *class) methodImplementationToString(m *ast.FuncDecl) (code string) {
code += handleFuncDeclType(m.Type)
code += " "
code += c.name + "::"
code += m.Name.String() + "("
code += handleFuncDeclParams(m.Type)
code += ") {"
if len(m.Recv.List) > 0 {
n := m.Recv.List[0].Names
if len(n) > 0 {
isInMethod = true
currentReceiverName = n[0].Name
}
}
code += handleBlockStmt(m.Body)
isInMethod = false
code += "}"
code += "\n"
return
}
func (c *class) AddMethod(m *ast.FuncDecl) {
c.methods = append(c.methods, m)
}
// Handlers
func handleClass(name string, st *ast.StructType) string {
addClassFromStructType(name, st)
return ""
}
func addClassFromStructType(name string, s *ast.StructType) Class {
c := createClass(name)
c.Struct = s
return c
}
func handleMethodDeclaration(fd *ast.FuncDecl) string {
class := getOrCreateClassFromFuncDecl(fd)
class.AddMethod(fd)
return ""
}
func getOrCreateClassFromFuncDecl(fd *ast.FuncDecl) Class {
n := getClassNameFromReceiver(fd.Recv)
return getOrCreateClass(n)
}
func getClassNameFromReceiver(recv *ast.FieldList) string {
for _, f := range recv.List {
return getClassNameFromStarReceiver(f.Type)
}
return ""
}
func getClassNameFromStarReceiver(expr ast.Expr) string {
switch e := expr.(type) {
case *ast.StarExpr:
return handleExpr(e.X)
}
return ""
}
func getOrCreateClass(className string) Class {
for _, c := range classDeclarations {
if c.Name() == className {
return c
}
}
return createClass(className)
}
func createClass(className string) *class {
c := NewClass(className)
addClassDeclaration(c)
return c
}
func addClassDeclaration(c Class) {
dlock.Lock()
defer dlock.Unlock()
classDeclarations = append(classDeclarations, c)
}