Remove unused commands from the development tools
Signed-off-by: Snider <snider@lt.hn>
This commit is contained in:
parent
5d4e081143
commit
e0cf77c64a
3 changed files with 0 additions and 302 deletions
|
|
@ -1,185 +0,0 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/doc"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/leaanthony/clir"
|
||||
)
|
||||
|
||||
func AddDocGenCommand(parent *clir.Command) {
|
||||
cmd := parent.NewSubCommand("docgen", "Generates Markdown documentation for the public API of the services.")
|
||||
cmd.Action(func() error {
|
||||
return runDocGen()
|
||||
})
|
||||
}
|
||||
|
||||
func runDocGen() error {
|
||||
const pkgDir = "pkg"
|
||||
const outDir = "docs/services"
|
||||
|
||||
if err := os.MkdirAll(outDir, 0755); err != nil {
|
||||
return fmt.Errorf("failed to create output directory: %w", err)
|
||||
}
|
||||
|
||||
dirs, err := os.ReadDir(pkgDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read pkg directory: %w", err)
|
||||
}
|
||||
|
||||
for _, dir := range dirs {
|
||||
if !dir.IsDir() {
|
||||
continue
|
||||
}
|
||||
serviceName := dir.Name()
|
||||
servicePath := filepath.Join(pkgDir, serviceName)
|
||||
|
||||
if err := generateDocsForService(servicePath, serviceName, outDir); err != nil {
|
||||
fmt.Printf("Warning: Could not generate docs for service '%s': %v\n", serviceName, err)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("Documentation generated successfully in", outDir)
|
||||
return nil
|
||||
}
|
||||
|
||||
func generateDocsForService(servicePath, serviceName, outDir string) error {
|
||||
fset := token.NewFileSet()
|
||||
filter := func(info os.FileInfo) bool {
|
||||
return !strings.HasSuffix(info.Name(), "_test.go")
|
||||
}
|
||||
pkgs, err := parser.ParseDir(fset, servicePath, filter, parser.ParseComments)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse directory %s: %w", servicePath, err)
|
||||
}
|
||||
|
||||
internalPath := filepath.Join(servicePath, "internal")
|
||||
if _, err := os.Stat(internalPath); err == nil {
|
||||
pkgs, err = parser.ParseDir(fset, internalPath, nil, parser.ParseComments)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse internal directory %s: %w", internalPath, err)
|
||||
}
|
||||
}
|
||||
|
||||
var pkg *ast.Package
|
||||
for _, p := range pkgs {
|
||||
pkg = p
|
||||
break
|
||||
}
|
||||
if pkg == nil {
|
||||
return fmt.Errorf("no package found in %s", servicePath)
|
||||
}
|
||||
|
||||
docPkg := doc.New(pkg, "./", doc.AllDecls)
|
||||
|
||||
md, err := generateMarkdown(docPkg)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to generate markdown: %w", err)
|
||||
}
|
||||
|
||||
outFile := filepath.Join(outDir, serviceName+".md")
|
||||
return os.WriteFile(outFile, []byte(md), 0644)
|
||||
}
|
||||
|
||||
const docTemplate = `---
|
||||
title: {{ .Name }}
|
||||
---
|
||||
# Service: ` + "`" + `{{ .Name }}` + "`" + `
|
||||
|
||||
{{ .Doc }}
|
||||
|
||||
{{if .Consts}}
|
||||
## Constants
|
||||
{{range .Consts}}
|
||||
` + "```go" + `
|
||||
{{- range .Names }}{{ . }}{{ end }}
|
||||
` + "```" + `
|
||||
{{ .Doc }}
|
||||
{{end}}{{end}}
|
||||
|
||||
{{if .Types}}
|
||||
## Types
|
||||
{{range .Types}}
|
||||
### ` + "`" + `type {{ .Name }}` + "`" + `
|
||||
` + "```go" + `
|
||||
type {{ .Name }} {{.Decl | formatNode}}
|
||||
` + "```" + `
|
||||
{{ .Doc }}
|
||||
|
||||
{{if .Methods}}
|
||||
#### Methods
|
||||
{{range .Methods}}
|
||||
- ` + "`" + `{{ .Name }}({{ .Decl.Type.Params | formatParams }}) {{ .Decl.Type.Results | formatParams }}` + "`" + `: {{ .Doc | oneLine }}
|
||||
{{end}}{{end}}
|
||||
|
||||
{{end}}{{end}}
|
||||
|
||||
{{if .Funcs}}
|
||||
## Functions
|
||||
{{range .Funcs}}
|
||||
- ` + "`" + `{{ .Name }}({{ .Decl.Type.Params | formatParams }}) {{ .Decl.Type.Results | formatParams }}` + "`" + `: {{ .Doc | oneLine }}
|
||||
{{end}}{{end}}
|
||||
`
|
||||
|
||||
func generateMarkdown(pkg *doc.Package) (string, error) {
|
||||
funcMap := template.FuncMap{
|
||||
"oneLine": func(s string) string {
|
||||
return strings.TrimSpace(strings.Replace(s, "\n", " ", -1))
|
||||
},
|
||||
"formatNode": func(decl *ast.GenDecl) string {
|
||||
if len(decl.Specs) == 0 {
|
||||
return ""
|
||||
}
|
||||
spec := decl.Specs[0].(*ast.TypeSpec)
|
||||
return nodeToString(spec.Type)
|
||||
},
|
||||
"formatParams": func(fieldList *ast.FieldList) string {
|
||||
if fieldList == nil {
|
||||
return ""
|
||||
}
|
||||
var params []string
|
||||
for _, p := range fieldList.List {
|
||||
var names []string
|
||||
for _, name := range p.Names {
|
||||
names = append(names, name.Name)
|
||||
}
|
||||
typeStr := nodeToString(p.Type)
|
||||
if len(names) > 0 {
|
||||
params = append(params, strings.Join(names, ", ")+" "+typeStr)
|
||||
} else {
|
||||
params = append(params, typeStr)
|
||||
}
|
||||
}
|
||||
return strings.Join(params, ", ")
|
||||
},
|
||||
}
|
||||
|
||||
tmpl, err := template.New("doc").Funcs(funcMap).Parse(docTemplate)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err := tmpl.Execute(&buf, pkg); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
func nodeToString(node ast.Node) string {
|
||||
var buf bytes.Buffer
|
||||
err := ast.Fprint(&buf, token.NewFileSet(), node, nil)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
|
@ -67,9 +67,7 @@ func Execute() error {
|
|||
// Add the top-level commands
|
||||
devCmd := app.NewSubCommand("dev", "Development tools for Core Framework")
|
||||
AddAPICommands(devCmd)
|
||||
AddTestGenCommand(devCmd)
|
||||
AddSyncCommand(devCmd)
|
||||
AddDocGenCommand(devCmd)
|
||||
AddBuildCommand(app)
|
||||
AddTviewCommand(app)
|
||||
// Run the application
|
||||
|
|
|
|||
|
|
@ -1,115 +0,0 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"text/template"
|
||||
|
||||
"github.com/leaanthony/clir"
|
||||
"golang.org/x/text/cases"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
// AddTestGenCommand adds the 'test-gen' command to the given parent command.
|
||||
func AddTestGenCommand(parent *clir.Command) {
|
||||
testGenCmd := parent.NewSubCommand("test-gen", "Generates baseline test files for public service APIs.")
|
||||
testGenCmd.LongDescription("This command scans for public services and generates a standard set of API contract tests for each one.")
|
||||
testGenCmd.Action(func() error {
|
||||
if err := runTestGen(); err != nil {
|
||||
return fmt.Errorf("Error during test generation: %w", err)
|
||||
}
|
||||
fmt.Println("API test files generated successfully.")
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
const testFileTemplate = `package {{.ServiceName}}_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/Snider/Core/{{.ServiceName}}"
|
||||
"github.com/Snider/Core/pkg/core"
|
||||
)
|
||||
|
||||
// TestNew ensures that the public constructor New is available.
|
||||
func TestNew(t *testing.T) {
|
||||
if {{.ServiceName}}.New == nil {
|
||||
t.Fatal("{{.ServiceName}}.New constructor is nil")
|
||||
}
|
||||
// Note: This is a basic check. Some services may require a core instance
|
||||
// or other arguments. This test can be expanded as needed.
|
||||
}
|
||||
|
||||
// TestRegister ensures that the public factory Register is available.
|
||||
func TestRegister(t *testing.T) {
|
||||
if {{.ServiceName}}.Register == nil {
|
||||
t.Fatal("{{.ServiceName}}.Register factory is nil")
|
||||
}
|
||||
}
|
||||
|
||||
// TestInterfaceCompliance ensures that the public Service type correctly
|
||||
// implements the public {{.InterfaceName}} interface. This is a compile-time check.
|
||||
func TestInterfaceCompliance(t *testing.T) {
|
||||
// This is a compile-time check. If it compiles, the test passes.
|
||||
var _ core.{{.InterfaceName}} = (*{{.ServiceName}}.Service)(nil)
|
||||
}
|
||||
`
|
||||
|
||||
func runTestGen() error {
|
||||
pkgDir := "pkg"
|
||||
internalDirs, err := os.ReadDir(pkgDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read pkg directory: %w", err)
|
||||
}
|
||||
|
||||
for _, dir := range internalDirs {
|
||||
if !dir.IsDir() || dir.Name() == "core" {
|
||||
continue
|
||||
}
|
||||
|
||||
serviceName := dir.Name()
|
||||
publicDir := serviceName
|
||||
|
||||
// Check if a corresponding top-level public API directory exists.
|
||||
if _, err := os.Stat(publicDir); os.IsNotExist(err) {
|
||||
continue // Not a public service, so we skip it.
|
||||
}
|
||||
|
||||
testFilePath := filepath.Join(publicDir, serviceName+"_test.go")
|
||||
fmt.Printf("Generating test file for service '%s' at %s\n", serviceName, testFilePath)
|
||||
|
||||
if err := generateTestFile(testFilePath, serviceName); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Warning: could not generate test for service '%s': %v\n", serviceName, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func generateTestFile(path, serviceName string) error {
|
||||
tmpl, err := template.New("test").Parse(testFileTemplate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tcaser := cases.Title(language.English)
|
||||
interfaceName := tcaser.String(serviceName)
|
||||
|
||||
data := struct {
|
||||
ServiceName string
|
||||
InterfaceName string
|
||||
}{
|
||||
ServiceName: serviceName,
|
||||
InterfaceName: interfaceName,
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err := tmpl.Execute(&buf, data); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return os.WriteFile(path, buf.Bytes(), 0644)
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue