166 строки
3,1 КиБ
Go
166 строки
3,1 КиБ
Go
package service
|
|
|
|
import (
|
|
"go/ast"
|
|
)
|
|
|
|
type Class interface {
|
|
Name() string
|
|
String() 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()
|
|
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)
|
|
}
|