feat: skeleton
This commit is contained in:
151
internal/writer.go
Normal file
151
internal/writer.go
Normal file
@@ -0,0 +1,151 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/printer"
|
||||
"go/token"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/tools/go/ast/astutil"
|
||||
)
|
||||
|
||||
func ImplementServiceStruct(entityName string, file *ast.File, reimplement bool) {
|
||||
serviceName := entityName + "Service"
|
||||
isServiceStructDeclarated := false
|
||||
var insertPos int
|
||||
|
||||
for i, decl := range file.Decls {
|
||||
genDecl, ok := decl.(*ast.GenDecl)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if genDecl.Tok == token.IMPORT {
|
||||
insertPos = i + 1
|
||||
continue
|
||||
}
|
||||
if genDecl.Tok != token.TYPE {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, spec := range genDecl.Specs {
|
||||
typeSpec, ok := spec.(*ast.TypeSpec)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if _, ok := typeSpec.Type.(*ast.StructType); ok {
|
||||
if typeSpec.Name != nil && typeSpec.Name.Name == serviceName {
|
||||
isServiceStructDeclarated = true
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if isServiceStructDeclarated && !reimplement {
|
||||
return
|
||||
}
|
||||
|
||||
serviceStruct := &ast.GenDecl{
|
||||
Tok: token.TYPE,
|
||||
Specs: []ast.Spec{
|
||||
&ast.TypeSpec{
|
||||
Name: ast.NewIdent(serviceName),
|
||||
Type: &ast.StructType{
|
||||
Fields: &ast.FieldList{},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
file.Decls = append(file.Decls[:insertPos], append([]ast.Decl{serviceStruct}, file.Decls[insertPos:]...)...)
|
||||
}
|
||||
|
||||
func importExists(fset *token.FileSet, file *ast.File, importPath string) bool {
|
||||
for _, group := range astutil.Imports(fset, file) {
|
||||
for _, imp := range group {
|
||||
if imp.Name == nil && imp.Path.Value == `"`+importPath+`"` {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func MaintainImports(fileSet *token.FileSet, file *ast.File) error {
|
||||
for _, importPath := range ServiceImports {
|
||||
if !importExists(fileSet, file, importPath) {
|
||||
if !astutil.AddImport(fileSet, file, importPath) {
|
||||
err := fmt.Sprintf("%s: Failed to add import: %s", fileSet.Position(file.Pos()), importPath)
|
||||
return errors.New(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ImplementMethods(structName string, methodName string, template string, node ast.Node) {
|
||||
|
||||
}
|
||||
|
||||
func CreateServiceFileIfNotExists(filePath string) error {
|
||||
if _, err := os.Stat(filePath); err != nil {
|
||||
// file wasn't created
|
||||
f, err := os.Create(filePath)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create file: %s", filePath)
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = f.Write([]byte("package services\n"))
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to write file: %s", filePath)
|
||||
return err
|
||||
}
|
||||
|
||||
defer f.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ImplementService(mainPkgPath string, modelName string, reimplement bool) error {
|
||||
serviceRelativePath := fmt.Sprintf("services/%s.go", strings.ToLower(modelName))
|
||||
filePath := filepath.Join(mainPkgPath, serviceRelativePath)
|
||||
|
||||
err := CreateServiceFileIfNotExists(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fset := token.NewFileSet()
|
||||
serviceFile, err := parser.ParseFile(fset, filePath, nil, parser.ParseComments)
|
||||
if err != nil {
|
||||
log.Fatalf("Parsing error: %s: %v", mainPkgPath, err)
|
||||
return err
|
||||
}
|
||||
|
||||
err = MaintainImports(fset, serviceFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ImplementServiceStruct(modelName, serviceFile, reimplement)
|
||||
|
||||
file, err := os.Create(filePath)
|
||||
if err != nil {
|
||||
log.Fatalf("Error occured to open `%s` service file: %v", modelName, err)
|
||||
return err
|
||||
}
|
||||
|
||||
err = printer.Fprint(file, fset, serviceFile)
|
||||
if err != nil {
|
||||
log.Fatalf("Error occurred to writing changes in `%s` service file: %v", modelName, err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user