Сценарий: Структура с методом
Этот коммит содержится в:
родитель
b6cb81fc11
коммит
5e7dec08df
6 изменённых файлов: 195 добавлений и 22 удалений
144
pkg/service/class.go
Обычный файл
144
pkg/service/class.go
Обычный файл
|
@ -0,0 +1,144 @@
|
||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/ast"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
classDeclarations []*Class
|
||||||
|
)
|
||||||
|
|
||||||
|
type Class struct {
|
||||||
|
Name string
|
||||||
|
Struct *ast.StructType
|
||||||
|
methods []*ast.FuncDecl
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewClass(className string) *Class {
|
||||||
|
return &Class{Name: className}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 += "void " + m.Name.String() + "();"
|
||||||
|
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 += "void "
|
||||||
|
code += c.Name + "::"
|
||||||
|
code += m.Name.String() + "("
|
||||||
|
|
||||||
|
code += ") {"
|
||||||
|
code += handleBlockStmt(m.Body)
|
||||||
|
code += "}"
|
||||||
|
|
||||||
|
code += "\n"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Class) AddMethod(m *ast.FuncDecl) {
|
||||||
|
c.methods = append(c.methods, m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handlers
|
||||||
|
func handleClass(t *ast.TypeSpec) string {
|
||||||
|
st, ok := t.Type.(*ast.StructType)
|
||||||
|
if !ok {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
addClassFromStructType(t.Name.String(), st)
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
func addClassFromStructType(name string, s *ast.StructType) {
|
||||||
|
c := createClass(name)
|
||||||
|
c.Struct = s
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
|
@ -79,3 +79,26 @@ public:
|
||||||
std::string c,d,e;
|
std::string c,d,e;
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
@f
|
||||||
|
Сценарий: Структура с методом
|
||||||
|
* Исходник:
|
||||||
|
```
|
||||||
|
package test
|
||||||
|
|
||||||
|
type device struct {
|
||||||
|
a int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *device) doSomething() {
|
||||||
|
}
|
||||||
|
```
|
||||||
|
* Результат:
|
||||||
|
```
|
||||||
|
class device {
|
||||||
|
public:
|
||||||
|
int a;
|
||||||
|
void doSomething();
|
||||||
|
};
|
||||||
|
void device::doSomething() {
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
|
@ -7,6 +7,12 @@ import (
|
||||||
|
|
||||||
func handleFuncDecl(decl ast.Decl) string {
|
func handleFuncDecl(decl ast.Decl) string {
|
||||||
fd := decl.(*ast.FuncDecl)
|
fd := decl.(*ast.FuncDecl)
|
||||||
|
if fd.Recv != nil {
|
||||||
|
return handleMethodDeclaration(fd)
|
||||||
|
}
|
||||||
|
return handleFunctionDeclaration(fd)
|
||||||
|
}
|
||||||
|
func handleFunctionDeclaration(fd *ast.FuncDecl) string {
|
||||||
if shouldSkipFunction(fd.Type) {
|
if shouldSkipFunction(fd.Type) {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"github.com/cucumber/godog/colors"
|
"github.com/cucumber/godog/colors"
|
||||||
|
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
|
gomega_format "github.com/onsi/gomega/format"
|
||||||
)
|
)
|
||||||
|
|
||||||
func InitializeScenario(ctx *godog.ScenarioContext) {
|
func InitializeScenario(ctx *godog.ScenarioContext) {
|
||||||
|
@ -47,6 +48,7 @@ func TestMain(t *testing.T) {
|
||||||
StopOnFailure: true,
|
StopOnFailure: true,
|
||||||
TestingT: t,
|
TestingT: t,
|
||||||
}
|
}
|
||||||
|
gomega_format.CharactersAroundMismatchToInclude = 100
|
||||||
|
|
||||||
godog.BindCommandLineFlags("godog.", &opts)
|
godog.BindCommandLineFlags("godog.", &opts)
|
||||||
godog.TestSuite{
|
godog.TestSuite{
|
||||||
|
|
|
@ -86,6 +86,7 @@ func (s *defaultService) Start() error {
|
||||||
dst[i] = make(chan string, 1)
|
dst[i] = make(chan string, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
classDeclarations = nil
|
||||||
funcDeclarations = nil
|
funcDeclarations = nil
|
||||||
helpersForDeclarations = nil
|
helpersForDeclarations = nil
|
||||||
|
|
||||||
|
@ -103,6 +104,7 @@ func (s *defaultService) Start() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
s.printIncludeHeaders()
|
s.printIncludeHeaders()
|
||||||
|
s.printClassDeclarations()
|
||||||
s.printFunctionDeclarations()
|
s.printFunctionDeclarations()
|
||||||
s.printGoHelperDeclarations()
|
s.printGoHelperDeclarations()
|
||||||
|
|
||||||
|
@ -128,6 +130,19 @@ func (s *defaultService) printIncludeHeaders() {
|
||||||
h := "#include <Arduino.h>\n\n"
|
h := "#include <Arduino.h>\n\n"
|
||||||
s.out.Write([]byte(h))
|
s.out.Write([]byte(h))
|
||||||
}
|
}
|
||||||
|
func (s *defaultService) printClassDeclarations() {
|
||||||
|
dlock.Lock()
|
||||||
|
defer dlock.Unlock()
|
||||||
|
|
||||||
|
for _, c := range classDeclarations {
|
||||||
|
d := c.String()
|
||||||
|
s.out.Write([]byte(d + "\n"))
|
||||||
|
if s.header != nil {
|
||||||
|
s.header.Write([]byte(d + "\n"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.out.Write([]byte("\n"))
|
||||||
|
}
|
||||||
func (s *defaultService) printFunctionDeclarations() {
|
func (s *defaultService) printFunctionDeclarations() {
|
||||||
dlock.Lock()
|
dlock.Lock()
|
||||||
defer dlock.Unlock()
|
defer dlock.Unlock()
|
||||||
|
|
|
@ -4,31 +4,14 @@ import (
|
||||||
"go/ast"
|
"go/ast"
|
||||||
)
|
)
|
||||||
|
|
||||||
func handleTypeSpec(spec ast.Spec) string {
|
func handleTypeSpec(spec ast.Spec) (code string) {
|
||||||
s := spec.(*ast.TypeSpec)
|
s := spec.(*ast.TypeSpec)
|
||||||
code := "class"
|
handleClass(s)
|
||||||
code += " "
|
return
|
||||||
code += s.Name.String()
|
|
||||||
code += " "
|
|
||||||
code += "{\n"
|
|
||||||
code += handleClass(s.Type)
|
|
||||||
// spew.Dump(s.TypeParams)
|
|
||||||
code += "};\n"
|
|
||||||
return code
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleClass(e ast.Expr) string {
|
func handleStructType(s *ast.StructType) (code string) {
|
||||||
code := ""
|
return handleFieldList(s.Fields)
|
||||||
code += "public:\n"
|
|
||||||
code += handleExpr(e)
|
|
||||||
// spew.Dump(e)
|
|
||||||
return code
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleStructType(s *ast.StructType) string {
|
|
||||||
code := ""
|
|
||||||
code += handleFieldList(s.Fields)
|
|
||||||
return code
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleFieldList(l *ast.FieldList) string {
|
func handleFieldList(l *ast.FieldList) string {
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче