feat: Refactor AST generation routes workflow

- Introduced a comprehensive data model for route definitions, parameters, and validation rules.
- Established component interfaces for route parsing, comment parsing, import resolution, route building, validation, and rendering.
- Developed a detailed implementation plan outlining execution flow, user requirements, and compliance with design principles.
- Created a quickstart guide to assist users in utilizing the refactored system effectively.
- Conducted thorough research on existing architecture, identifying key improvements and establishing a refactoring strategy.
- Specified functional requirements and user scenarios to ensure clarity and testability.
- Generated a task list for implementation, emphasizing test-driven development and parallel execution where applicable.
This commit is contained in:
Rogee
2025-09-22 11:33:13 +08:00
parent 0cfc573960
commit 824861c27c
17 changed files with 3324 additions and 272 deletions

View File

@@ -0,0 +1,239 @@
package contracts
import (
"go/ast"
"testing"
"github.com/stretchr/testify/assert"
)
// RouteBuilderContract defines the contract tests for RouteBuilder implementations
type RouteBuilderContract struct {
builder RouteBuilder
}
// RouteBuilder interface definition for contract testing
type RouteBuilder interface {
BuildFromTypeSpec(typeSpec *ast.TypeSpec, decl *ast.GenDecl, context *BuilderContext) (RouteDefinition, error)
BuildFromComment(comment string, context *BuilderContext) (RouteDefinition, error)
ValidateDefinition(def *RouteDefinition) error
}
// BuilderContext represents builder context (simplified for testing)
type BuilderContext struct {
FilePath string
PackageName string
ImportContext *ImportContext
ASTFile *ast.File
}
// ImportContext represents import context (simplified for testing)
type ImportContext struct {
Imports map[string]string
}
// NewRouteBuilderContract creates a new contract test instance
func NewRouteBuilderContract(builder RouteBuilder) *RouteBuilderContract {
return &RouteBuilderContract{builder: builder}
}
// TestSuite runs all contract tests for RouteBuilder
func (c *RouteBuilderContract) TestSuite(t *testing.T) {
t.Run("RouteBuilder_BuildFromTypeSpec_BasicRoute", c.testBuildFromTypeSpecBasicRoute)
t.Run("RouteBuilder_BuildFromTypeSpec_WithParameters", c.testBuildFromTypeSpecWithParameters)
t.Run("RouteBuilder_BuildFromTypeSpec_InvalidInput", c.testBuildFromTypeSpecInvalidInput)
t.Run("RouteBuilder_BuildFromComment_SimpleComment", c.testBuildFromCommentSimpleComment)
t.Run("RouteBuilder_BuildFromComment_ComplexComment", c.testBuildFromCommentComplexComment)
t.Run("RouteBuilder_ValidateDefinition_ValidRoute", c.testValidateDefinitionValidRoute)
t.Run("RouteBuilder_ValidateDefinition_InvalidRoute", c.testValidateDefinitionInvalidRoute)
}
// Contract Tests
func (c *RouteBuilderContract) testBuildFromTypeSpecBasicRoute(t *testing.T) {
// GIVEN a valid type specification and declaration
typeSpec := &ast.TypeSpec{
Name: &ast.Ident{Name: "UserController"},
}
decl := &ast.GenDecl{
Doc: &ast.CommentGroup{
List: []*ast.Comment{
{Text: "// @Router /users [get]"},
},
},
Specs: []ast.Spec{typeSpec},
}
context := &BuilderContext{
FilePath: "UserController.go",
PackageName: "controllers",
ImportContext: &ImportContext{
Imports: make(map[string]string),
},
}
// WHEN building route from type spec
route, err := c.builder.BuildFromTypeSpec(typeSpec, decl, context)
// THEN it should succeed and return valid route definition
assert.NoError(t, err, "BuildFromTypeSpec should not error")
assert.NotNil(t, route, "Should return route definition")
assert.Equal(t, "UserController", route.StructName, "Should extract correct struct name")
assert.Equal(t, "/users", route.Path, "Should extract correct path")
assert.Contains(t, route.Methods, "GET", "Should include GET method")
}
func (c *RouteBuilderContract) testBuildFromTypeSpecWithParameters(t *testing.T) {
// GIVEN a type specification with parameter bindings
typeSpec := &ast.TypeSpec{
Name: &ast.Ident{Name: "UserController"},
}
decl := &ast.GenDecl{
Doc: &ast.CommentGroup{
List: []*ast.Comment{
{Text: "// @Router /users/:id [get]"},
{Text: "// @Bind id (path) model()"},
{Text: "// @Bind limit (query) model(limit:int)"},
},
},
Specs: []ast.Spec{typeSpec},
}
context := &BuilderContext{
FilePath: "UserController.go",
PackageName: "controllers",
ImportContext: &ImportContext{
Imports: map[string]string{
"model": "go.ipao.vip/gen/model",
},
},
}
// WHEN building route from type spec
route, err := c.builder.BuildFromTypeSpec(typeSpec, decl, context)
// THEN it should succeed and extract parameters
assert.NoError(t, err, "BuildFromTypeSpec should not error")
assert.NotNil(t, route, "Should return route definition")
assert.NotEmpty(t, route.Parameters, "Route should have parameters")
// Verify path parameter
pathParam := findParameterByPosition(route.Parameters, "path")
assert.NotNil(t, pathParam, "Should find path parameter")
assert.Equal(t, "id", pathParam.Name, "Path parameter should be named 'id'")
// Verify query parameter
queryParam := findParameterByPosition(route.Parameters, "query")
assert.NotNil(t, queryParam, "Should find query parameter")
assert.Equal(t, "limit", queryParam.Name, "Query parameter should be named 'limit'")
}
func (c *RouteBuilderContract) testBuildFromTypeSpecInvalidInput(t *testing.T) {
// GIVEN an invalid type specification (nil)
var typeSpec *ast.TypeSpec = nil
decl := &ast.GenDecl{}
context := &BuilderContext{}
// WHEN building route from invalid type spec
route, err := c.builder.BuildFromTypeSpec(typeSpec, decl, context)
// THEN it should fail with appropriate error
assert.Error(t, err, "BuildFromTypeSpec should error on invalid input")
assert.Equal(t, RouteDefinition{}, route, "Should return empty route on error")
}
func (c *RouteBuilderContract) testBuildFromCommentSimpleComment(t *testing.T) {
// GIVEN a simple route comment
comment := `@Router /users [get]`
context := &BuilderContext{
FilePath: "UserController.go",
PackageName: "controllers",
}
// WHEN building route from comment
route, err := c.builder.BuildFromComment(comment, context)
// THEN it should succeed and return valid route
assert.NoError(t, err, "BuildFromComment should not error")
assert.NotNil(t, route, "Should return route definition")
assert.Equal(t, "/users", route.Path, "Should extract correct path")
assert.Contains(t, route.Methods, "GET", "Should include GET method")
}
func (c *RouteBuilderContract) testBuildFromCommentComplexComment(t *testing.T) {
// GIVEN a complex route comment with parameters
comment := `@Router /users/:id [get,put]
@Bind id (path) model()
@Bind user (body) model(User)`
context := &BuilderContext{
FilePath: "UserController.go",
PackageName: "controllers",
ImportContext: &ImportContext{
Imports: map[string]string{
"model": "go.ipao.vip/gen/model",
},
},
}
// WHEN building route from comment
route, err := c.builder.BuildFromComment(comment, context)
// THEN it should succeed and extract all information
assert.NoError(t, err, "BuildFromComment should not error")
assert.NotNil(t, route, "Should return route definition")
assert.Equal(t, "/users/:id", route.Path, "Should extract correct path")
assert.Contains(t, route.Methods, "GET", "Should include GET method")
assert.Contains(t, route.Methods, "PUT", "Should include PUT method")
assert.NotEmpty(t, route.Parameters, "Route should have parameters")
}
func (c *RouteBuilderContract) testValidateDefinitionValidRoute(t *testing.T) {
// GIVEN a valid route definition
route := RouteDefinition{
StructName: "UserController",
Path: "/users",
Methods: []string{"GET", "POST"},
Parameters: []ParamDefinition{
{Name: "id", Position: "path", Type: "int"},
},
}
// WHEN validating the route definition
err := c.builder.ValidateDefinition(&route)
// THEN it should succeed
assert.NoError(t, err, "ValidateDefinition should not error on valid route")
}
func (c *RouteBuilderContract) testValidateDefinitionInvalidRoute(t *testing.T) {
// GIVEN an invalid route definition (empty path)
route := RouteDefinition{
StructName: "UserController",
Path: "", // Empty path is invalid
Methods: []string{"GET"},
}
// WHEN validating the route definition
err := c.builder.ValidateDefinition(&route)
// THEN it should fail
assert.Error(t, err, "ValidateDefinition should error on invalid route")
}
// Helper functions
func findParameterByPosition(params []ParamDefinition, position string) *ParamDefinition {
for _, param := range params {
if param.Position == position {
return &param
}
}
return nil
}

View File

@@ -0,0 +1,261 @@
package contracts
import (
"testing"
"github.com/stretchr/testify/assert"
)
// RouteParserContract defines the contract tests for RouteParser implementations
type RouteParserContract struct {
parser RouteParser
}
// RouteParser interface definition for contract testing
type RouteParser interface {
ParseFile(filePath string) ([]RouteDefinition, error)
ParseDir(dirPath string) ([]RouteDefinition, error)
ParseString(code string) ([]RouteDefinition, error)
SetConfig(config *RouteParserConfig) error
GetConfig() *RouteParserConfig
GetContext() *ParserContext
GetDiagnostics() []Diagnostic
}
// RouteDefinition represents a route definition (simplified for testing)
type RouteDefinition struct {
StructName string
Path string
Methods []string
Parameters []ParamDefinition
Imports map[string]string
}
// ParamDefinition represents a parameter definition (simplified for testing)
type ParamDefinition struct {
Name string
Position string
Type string
}
// RouteParserConfig represents parser configuration (simplified for testing)
type RouteParserConfig struct {
StrictMode bool
ParseComments bool
SourceLocations bool
}
// ParserContext represents parser context (simplified for testing)
type ParserContext struct {
WorkingDir string
ModuleName string
}
// Diagnostic represents diagnostic information (simplified for testing)
type Diagnostic struct {
Level string
Message string
File string
}
// NewRouteParserContract creates a new contract test instance
func NewRouteParserContract(parser RouteParser) *RouteParserContract {
return &RouteParserContract{parser: parser}
}
// TestSuite runs all contract tests for RouteParser
func (c *RouteParserContract) TestSuite(t *testing.T) {
t.Run("RouteParser_ParseFile_BasicRoute", c.testParseFileBasicRoute)
t.Run("RouteParser_ParseFile_WithParameters", c.testParseFileWithParameters)
t.Run("RouteParser_ParseFile_InvalidSyntax", c.testParseFileInvalidSyntax)
t.Run("RouteParser_ParseFile_NonexistentFile", c.testParseFileNonexistentFile)
t.Run("RouteParser_ParseString_SimpleRoute", c.testParseStringSimpleRoute)
t.Run("RouteParser_ParseString_MultipleRoutes", c.testParseStringMultipleRoutes)
t.Run("RouteParser_ParseDir_EmptyDirectory", c.testParseDirEmptyDirectory)
t.Run("RouteParser_Configuration", c.testConfiguration)
t.Run("RouteParser_Diagnostics", c.testDiagnostics)
}
// Contract Tests
func (c *RouteParserContract) testParseFileBasicRoute(t *testing.T) {
// GIVEN a Go file with basic route annotation
filePath := "testdata/basic_route.go"
// WHEN parsing the file
routes, err := c.parser.ParseFile(filePath)
// THEN it should succeed and return the route definition
assert.NoError(t, err, "ParseFile should not error")
assert.Len(t, routes, 1, "Should find exactly one route")
route := routes[0]
assert.Equal(t, "UserController", route.StructName, "Should extract correct struct name")
assert.Equal(t, "/users", route.Path, "Should extract correct path")
assert.Contains(t, route.Methods, "GET", "Should include GET method")
assert.Empty(t, route.Parameters, "Basic route should have no parameters")
}
func (c *RouteParserContract) testParseFileWithParameters(t *testing.T) {
// GIVEN a Go file with route containing parameters
filePath := "testdata/params_route.go"
// WHEN parsing the file
routes, err := c.parser.ParseFile(filePath)
// THEN it should succeed and extract parameters
assert.NoError(t, err, "ParseFile should not error")
assert.Len(t, routes, 1, "Should find exactly one route")
route := routes[0]
assert.NotEmpty(t, route.Parameters, "Route should have parameters")
// Verify path parameter
pathParam := findParameterByPosition(route.Parameters, "path")
assert.NotNil(t, pathParam, "Should find path parameter")
assert.Equal(t, "id", pathParam.Name, "Path parameter should be named 'id'")
// Verify query parameter
queryParam := findParameterByPosition(route.Parameters, "query")
assert.NotNil(t, queryParam, "Should find query parameter")
assert.Equal(t, "limit", queryParam.Name, "Query parameter should be named 'limit'")
}
func (c *RouteParserContract) testParseFileInvalidSyntax(t *testing.T) {
// GIVEN a Go file with invalid syntax
filePath := "testdata/invalid_syntax.go"
// WHEN parsing the file
routes, err := c.parser.ParseFile(filePath)
// THEN it should fail with appropriate error
assert.Error(t, err, "ParseFile should error on invalid syntax")
assert.Empty(t, routes, "Should return no routes on error")
// Verify diagnostic information
diagnostics := c.parser.GetDiagnostics()
assert.NotEmpty(t, diagnostics, "Should provide diagnostic information")
assert.Contains(t, diagnostics[0].Message, "syntax", "Error message should mention syntax")
}
func (c *RouteParserContract) testParseFileNonexistentFile(t *testing.T) {
// GIVEN a nonexistent file path
filePath := "testdata/nonexistent.go"
// WHEN parsing the file
routes, err := c.parser.ParseFile(filePath)
// THEN it should fail with file not found error
assert.Error(t, err, "ParseFile should error on nonexistent file")
assert.Empty(t, routes, "Should return no routes on error")
}
func (c *RouteParserContract) testParseStringSimpleRoute(t *testing.T) {
// GIVEN Go code string with simple route
code := `
package main
// @Router /users [get]
type UserController struct {}
`
// WHEN parsing the string
routes, err := c.parser.ParseString(code)
// THEN it should succeed and return the route
assert.NoError(t, err, "ParseString should not error")
assert.Len(t, routes, 1, "Should find exactly one route")
route := routes[0]
assert.Equal(t, "UserController", route.StructName, "Should extract correct struct name")
assert.Equal(t, "/users", route.Path, "Should extract correct path")
}
func (c *RouteParserContract) testParseStringMultipleRoutes(t *testing.T) {
// GIVEN Go code string with multiple routes
code := `
package main
// @Router /users [get]
type UserController struct {}
// @Router /products [post]
type ProductController struct {}
`
// WHEN parsing the string
routes, err := c.parser.ParseString(code)
// THEN it should succeed and return all routes
assert.NoError(t, err, "ParseString should not error")
assert.Len(t, routes, 2, "Should find exactly two routes")
// Verify both routes are found
routeNames := []string{routes[0].StructName, routes[1].StructName}
assert.Contains(t, routeNames, "UserController", "Should find UserController")
assert.Contains(t, routeNames, "ProductController", "Should find ProductController")
}
func (c *RouteParserContract) testParseDirEmptyDirectory(t *testing.T) {
// GIVEN an empty directory
dirPath := "testdata/empty"
// WHEN parsing the directory
routes, err := c.parser.ParseDir(dirPath)
// THEN it should succeed with no routes
assert.NoError(t, err, "ParseDir should not error on empty directory")
assert.Empty(t, routes, "Should return no routes from empty directory")
}
func (c *RouteParserContract) testConfiguration(t *testing.T) {
// GIVEN default configuration
config := c.parser.GetConfig()
assert.NotNil(t, config, "Should have default configuration")
// WHEN setting new configuration
newConfig := &RouteParserConfig{
StrictMode: true,
ParseComments: false,
SourceLocations: true,
}
err := c.parser.SetConfig(newConfig)
// THEN configuration should be updated
assert.NoError(t, err, "SetConfig should not error")
updatedConfig := c.parser.GetConfig()
assert.True(t, updatedConfig.StrictMode, "StrictMode should be updated")
assert.False(t, updatedConfig.ParseComments, "ParseComments should be updated")
assert.True(t, updatedConfig.SourceLocations, "SourceLocations should be updated")
}
func (c *RouteParserContract) testDiagnostics(t *testing.T) {
// GIVEN a file with warnings
filePath := "testdata/warnings.go"
// WHEN parsing the file
_, err := c.parser.ParseFile(filePath)
// THEN diagnostics should be available
diagnostics := c.parser.GetDiagnostics()
assert.NotEmpty(t, diagnostics, "Should provide diagnostic information")
// Verify diagnostic structure
for _, diag := range diagnostics {
assert.NotEmpty(t, diag.Level, "Diagnostic should have level")
assert.NotEmpty(t, diag.Message, "Diagnostic should have message")
}
}
// Helper functions
func findParameterByPosition(params []ParamDefinition, position string) *ParamDefinition {
for _, param := range params {
if param.Position == position {
return &param
}
}
return nil
}

View File

@@ -0,0 +1,387 @@
# Phase 1: Data Model Design
## Overview
This document defines the core data models and contracts for the refactored AST route generation system, following the component-based architecture pattern established in the provider module.
## Core Entities
### 1. RouteDefinition
Represents a complete route definition extracted from source code annotations.
```go
type RouteDefinition struct {
// Basic Information
StructName string // Name of the handler struct
FilePath string // Source file path
PackageName string // Go package name
// Route Configuration
Path string // HTTP path pattern
Methods []string // HTTP methods (GET, POST, etc.)
Name string // Route name for identification
// Dependencies & Imports
Imports map[string]string // Package path -> alias mapping
Parameters []ParamDefinition // Route parameters
Middleware []string // Middleware chain
// Code Generation
HandlerFunc string // Handler function name
ReturnType string // Return type specification
ProviderGroup string // Dependency injection group
// Metadata
Location SourceLocation // Source location for error reporting
Annotations map[string]string // Additional annotations
}
```
### 2. ParamDefinition
Represents a parameter binding from different sources.
```go
type ParamDefinition struct {
// Parameter Identification
Name string // Parameter name
Position ParamPosition // Parameter location (path, query, etc.)
Type string // Parameter type
Source string // Source annotation text
// Type Information
BaseType string // Base type without pointer
IsPointer bool // Is pointer type
IsSlice bool // Is slice type
IsMap bool // Is map type
// Model Information (for structured parameters)
ModelName string // Model name for model() binding
ModelField string // Target field in model
ModelType string // Model field type
// Validation & Constraints
Required bool // Is required parameter
DefaultValue string // Default value
Validation []ValidationRule // Validation rules
// Code Generation
ParamToken string // Template token for generation
ImportPath string // Import path for type
}
```
### 3. ParamPosition
Parameter position enumeration.
```go
type ParamPosition string
const (
ParamPositionPath ParamPosition = "path" // URL path parameters
ParamPositionQuery ParamPosition = "query" // Query string parameters
ParamPositionBody ParamPosition = "body" // Request body
ParamPositionHeader ParamPosition = "header" // HTTP headers
ParamPositionCookie ParamPosition = "cookie" // Cookies
ParamPositionLocal ParamPosition = "local" // Local context values
ParamPositionFile ParamPosition = "file" // File uploads
)
```
### 4. ValidationRule
Parameter validation rule definition.
```go
type ValidationRule struct {
Type ValidationType // Validation type (required, min, max, etc.)
Value string // Validation value
Message string // Error message
Constraint string // Constraint expression
}
```
### 5. SourceLocation
Source code location information.
```go
type SourceLocation struct {
File string // Source file path
Line int // Line number
Column int // Column position
}
```
## Component Interfaces
### 1. RouteParser Interface
Main coordinator interface for route parsing.
```go
type RouteParser interface {
ParseFile(filePath string) ([]RouteDefinition, error)
ParseDir(dirPath string) ([]RouteDefinition, error)
ParseString(code string) ([]RouteDefinition, error)
// Configuration
SetConfig(config *RouteParserConfig) error
GetConfig() *RouteParserConfig
// Context & Diagnostics
GetContext() *ParserContext
GetDiagnostics() []Diagnostic
}
```
### 2. CommentParser Interface
Handles annotation parsing from source comments.
```go
type CommentParser interface {
ParseRouteComment(comment string) (*RouteAnnotation, error)
ParseBindComment(comment string) (*BindAnnotation, error)
IsRouteComment(comment string) bool
IsBindComment(comment string) bool
}
```
### 3. ImportResolver Interface
Manages import resolution and dependencies.
```go
type ImportResolver interface {
ResolveFileImports(node *ast.File, filePath string) (*ImportContext, error)
ResolveImportPath(alias string) (string, error)
AddImport(imports map[string]string, path, alias string) error
}
```
### 4. RouteBuilder Interface
Constructs route definitions from parsed components.
```go
type RouteBuilder interface {
BuildFromTypeSpec(typeSpec *ast.TypeSpec, decl *ast.GenDecl, context *BuilderContext) (RouteDefinition, error)
BuildFromComment(comment string, context *BuilderContext) (RouteDefinition, error)
ValidateDefinition(def *RouteDefinition) error
}
```
### 5. RouteValidator Interface
Validates route definitions and configurations.
```go
type RouteValidator interface {
ValidateRoute(def *RouteDefinition) error
ValidateParameters(params []ParamDefinition) error
ValidateImports(imports map[string]string) error
GetValidationRules() []ValidationRule
}
```
### 6. RouteRenderer Interface
Handles template rendering and code generation.
```go
type RouteRenderer interface {
Render(routes []RouteDefinition, outputPath string) error
RenderToFile(route RouteDefinition, outputPath string) error
SetTemplate(template *template.Template) error
GetTemplate() *template.Template
}
```
## Supporting Data Structures
### 1. RouteAnnotation
Parsed route annotation information.
```go
type RouteAnnotation struct {
Path string // Route path
Methods []string // HTTP methods
Name string // Route name
Options map[string]string // Additional options
}
```
### 2. BindAnnotation
Parsed bind annotation information.
```go
type BindAnnotation struct {
Name string // Parameter name
Position ParamPosition // Parameter position
Key string // Source key
Model *ModelInfo // Model binding info (optional)
Options map[string]string // Additional options
}
```
### 3. ModelInfo
Model binding information.
```go
type ModelInfo struct {
Name string // Model name
Field string // Target field
Type string // Field type
Required bool // Is required
}
```
### 4. ImportContext
Import resolution context.
```go
type ImportContext struct {
FileImports map[string]*ImportResolution // Alias -> Resolution
ImportPaths map[string]string // Path -> Alias
ModuleInfo map[string]string // Module path -> module name
WorkingDir string // Current working directory
ModuleName string // Current module name
ProcessedFiles map[string]bool // Track processed files
}
```
### 5. ImportResolution
Individual import resolution information.
```go
type ImportResolution struct {
Path string // Import path
Alias string // Import alias
Type ImportType // Import type
Used bool // Whether import is used
}
```
### 6. BuilderContext
Context for route building process.
```go
type BuilderContext struct {
FilePath string // Current file path
PackageName string // Package name
ImportContext *ImportContext // Import information
ASTFile *ast.File // AST node
ProcessedTypes map[string]bool // Processed types cache
Errors []error // Error collection
Warnings []string // Warning collection
Config *BuilderConfig // Builder configuration
}
```
## Configuration Structures
### 1. RouteParserConfig
Configuration for route parser behavior.
```go
type RouteParserConfig struct {
// Parsing Options
ParseComments bool // Parse comments (default: true)
StrictMode bool // Strict validation mode
SourceLocations bool // Include source locations
// File Processing
SkipTestFiles bool // Skip test files (default: true)
SkipGenerated bool // Skip generated files (default: true)
AllowedPatterns []string // Allowed file patterns
// Validation Options
EnableValidation bool // Enable validation (default: true)
ValidationLevel ValidationLevel // Validation strictness
// Performance Options
CacheEnabled bool // Enable parsing cache
ParallelProcessing bool // Enable parallel processing
}
```
### 2. BuilderConfig
Configuration for route builder.
```go
type BuilderConfig struct {
EnableValidation bool // Enable validation
StrictMode bool // Strict validation mode
DefaultParamPosition ParamPosition // Default parameter position
AutoGenerateReturnTypes bool // Auto-generate return types
ResolveImportDependencies bool // Resolve import dependencies
}
```
### 3. ValidationLevel
Validation strictness levels.
```go
type ValidationLevel int
const (
ValidationLevelNone ValidationLevel = iota // No validation
ValidationLevelBasic // Basic validation
ValidationLevelStrict // Strict validation
ValidationLevelPedantic // Pedantic validation
)
```
## Error Handling
### 1. RouteError
Route-specific error type.
```go
type RouteError struct {
Code ErrorCode // Error code
Message string // Error message
File string // File path
Line int // Line number
Column int // Column number
Context string // Error context
Severity ErrorSeverity // Error severity
Inner error // Inner error
}
```
### 2. ErrorCode
Error code enumeration.
```go
type ErrorCode string
const (
ErrCodeInvalidSyntax ErrorCode = "INVALID_SYNTAX"
ErrCodeMissingAnnotation ErrorCode = "MISSING_ANNOTATION"
ErrCodeInvalidParameter ErrorCode = "INVALID_PARAMETER"
ErrCodeDuplicateRoute ErrorCode = "DUPLICATE_ROUTE"
ErrCodeImportResolution ErrorCode = "IMPORT_RESOLUTION"
ErrCodeValidation ErrorCode = "VALIDATION_ERROR"
ErrCodeTemplateError ErrorCode = "TEMPLATE_ERROR"
)
```
### 3. Diagnostic
Rich diagnostic information.
```go
type Diagnostic struct {
Level DiagnosticLevel // Diagnostic level
Code ErrorCode // Error code
Message string // Diagnostic message
File string // File path
Location SourceLocation // Source location
Context string // Additional context
Suggestions []string // Suggested fixes
}
```
## Summary
This data model design provides a comprehensive foundation for the refactored route generation system. Key features include:
1. **Clear separation of concerns**: Each component has well-defined interfaces and responsibilities
2. **Comprehensive error handling**: Structured error types with rich diagnostic information
3. **Extensible validation**: Configurable validation system with multiple levels
4. **Type safety**: Strong typing throughout the system
5. **Configuration management**: Flexible configuration system for different use cases
6. **Backward compatibility**: Designed to support existing annotation formats
The design follows SOLID principles and provides a solid foundation for implementing the refactored route generation system.

View File

@@ -0,0 +1,254 @@
# Implementation Plan: Refactor AST Generation Routes Workflow
**Branch**: `002-refactor-ast-gen` | **Date**: 2025-09-22 | **Spec**: [/specs/002-refactor-ast-gen/spec.md](/specs/002-refactor-ast-gen/spec.md)
**Input**: Feature specification from `/specs/002-refactor-ast-gen/spec.md`
**User Requirements**: 1. 重构 @pkg/ast/route/ 的实现流程使更易读逻辑更清晰2.保证 @cmd/gen_route.go 对重构后方法调用的生效3. 一切功能重构保证测试优先。
## Execution Flow (/plan command scope)
```
1. Load feature spec from Input path
→ If not found: ERROR "No feature spec at {path}"
2. Fill Technical Context (scan for NEEDS CLARIFICATION)
→ Detect Project Type from context (web=frontend+backend, mobile=app+api)
→ Set Structure Decision based on project type
3. Fill the Constitution Check section based on the content of the constitution document.
4. Evaluate Constitution Check section below
→ If violations exist: Document in Complexity Tracking
→ If no justification possible: ERROR "Simplify approach first"
→ Update Progress Tracking: Initial Constitution Check
5. Execute Phase 0 → research.md
→ If NEEDS CLARIFICATION remain: ERROR "Resolve unknowns"
6. Execute Phase 1 → contracts, data-model.md, quickstart.md, agent-specific template file (e.g., `CLAUDE.md` for Claude Code, `.github/copilot-instructions.md` for GitHub Copilot, `GEMINI.md` for Gemini CLI, `QWEN.md` for Qwen Code or `AGENTS.md` for opencode).
7. Re-evaluate Constitution Check section
→ If new violations: Refactor design, return to Phase 1
→ Update Progress Tracking: Post-Design Constitution Check
8. Plan Phase 2 → Describe task generation approach (DO NOT create tasks.md)
9. STOP - Ready for /tasks command
```
**IMPORTANT**: The /plan command STOPS at step 7. Phases 2-4 are executed by other commands:
- Phase 2: /tasks command creates tasks.md
- Phase 3-4: Implementation execution (manual or via tools)
## Summary
重构AST生成路由工作流程提高代码可读性和逻辑清晰度确保与现有gen_route.go命令的兼容性并采用测试驱动开发方法。
## Technical Context
**Language/Version**: Go 1.21+
**Primary Dependencies**: go standard library (ast, parser, token), cobra CLI, logrus
**Storage**: File-based route definitions and generated Go code
**Testing**: Go testing with TDD approach (testing/fstest for filesystem tests)
**Target Platform**: CLI tool for Go projects
**Project Type**: Single project with existing pkg/ast/provider refactoring patterns
**Performance Goals**: Fast parsing (< 2s for typical project), minimal memory overhead
**Constraints**: Must maintain backward compatibility with existing @Router and @Bind annotations
**Scale/Scope**: Support medium to large Go projects with extensive route definitions
## Constitution Check
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
### SOLID Principles Compliance
- [x] **Single Responsibility**: Route parsing, generation, and rendering will have separate, focused components
- [x] **Open/Closed**: Design will follow existing provider patterns with extensible interfaces
- [x] **Liskov Substitution**: New route components will implement consistent interfaces
- [x] **Interface Segregation**: Specific interfaces for parsing, generation, and validation
- [x] **Dependency Inversion**: Core functionality will depend on interfaces, not concrete implementations
### KISS Principle Compliance
- [x] Design avoids unnecessary complexity - will follow existing refactored provider patterns
- [x] CLI interface maintains consistency - existing gen_route.go interface preserved
- [x] Code generation logic is simple and direct - clear separation of concerns
- [x] Solutions are intuitive and easy to understand - follows established patterns
### YAGNI Principle Compliance
- [x] Only implementing clearly needed functionality - focus on readability and clarity improvements
- [x] No over-engineering or future-proofing without requirements - minimal changes to achieve goals
- [x] Each feature has explicit user requirements - based on gen_route.go compatibility needs
- [x] No "might be useful" features without justification - scope limited to refactoring
### DRY Principle Compliance
- [x] No code duplication across components - will share patterns with pkg/ast/provider
- [x] Common functionality is abstracted and reused - leverage existing interfaces and utilities
- [x] Template system avoids repetitive implementations - consistent with provider generation
- [x] Shared utilities are properly abstracted - reuse existing AST parsing infrastructure
### Code Quality Standards
- [x] **Testing Discipline**: TDD approach with Red-Green-Refactor cycle - testing first requirement
- [x] **CLI Consistency**: Unified parameter formats and output standards - existing interface maintained
- [x] **Error Handling**: Complete error information and recovery mechanisms - consistent with provider patterns
- [x] **Performance**: Generation speed and memory usage requirements met - <2s parsing goal
### Complexity Tracking
| Violation | Why Needed | Simpler Alternative Rejected Because |
|-----------|------------|-------------------------------------|
| [Document any deviations from constitutional principles] | [Justification for complexity] | [Why simpler approach insufficient] |
## Project Structure
### Documentation (this feature)
```
specs/[###-feature]/
├── plan.md # This file (/plan command output)
├── research.md # Phase 0 output (/plan command)
├── data-model.md # Phase 1 output (/plan command)
├── quickstart.md # Phase 1 output (/plan command)
├── contracts/ # Phase 1 output (/plan command)
└── tasks.md # Phase 2 output (/tasks command - NOT created by /plan)
```
### Source Code (repository root)
```
# Option 1: Single project (DEFAULT)
src/
├── models/
├── services/
├── cli/
└── lib/
tests/
├── contract/
├── integration/
└── unit/
# Option 2: Web application (when "frontend" + "backend" detected)
backend/
├── src/
│ ├── models/
│ ├── services/
│ └── api/
└── tests/
frontend/
├── src/
│ ├── components/
│ ├── pages/
│ └── services/
└── tests/
# Option 3: Mobile + API (when "iOS/Android" detected)
api/
└── [same as backend above]
ios/ or android/
└── [platform-specific structure]
```
**Structure Decision**: Option 1 - Single project with pkg/ast/route refactoring following pkg/ast/provider patterns
## Phase 0: Outline & Research
1. **Extract unknowns from Technical Context** above:
- For each NEEDS CLARIFICATION → research task
- For each dependency → best practices task
- For each integration → patterns task
2. **Generate and dispatch research agents**:
```
For each unknown in Technical Context:
Task: "Research {unknown} for {feature context}"
For each technology choice:
Task: "Find best practices for {tech} in {domain}"
```
3. **Consolidate findings** in `research.md` using format:
- Decision: [what was chosen]
- Rationale: [why chosen]
- Alternatives considered: [what else evaluated]
**Output**: research.md with all NEEDS CLARIFICATION resolved
## Phase 1: Design & Contracts
*Prerequisites: research.md complete*
1. **Extract entities from feature spec** → `data-model.md`:
- Entity name, fields, relationships
- Validation rules from requirements
- State transitions if applicable
2. **Generate API contracts** from functional requirements:
- For each user action → endpoint
- Use standard REST/GraphQL patterns
- Output OpenAPI/GraphQL schema to `/contracts/`
3. **Generate contract tests** from contracts:
- One test file per endpoint
- Assert request/response schemas
- Tests must fail (no implementation yet)
4. **Extract test scenarios** from user stories:
- Each story → integration test scenario
- Quickstart test = story validation steps
5. **Update agent file incrementally** (O(1) operation):
- Run `.specify/scripts/bash/update-agent-context.sh claude` for your AI assistant
- If exists: Add only NEW tech from current plan
- Preserve manual additions between markers
- Update recent changes (keep last 3)
- Keep under 150 lines for token efficiency
- Output to repository root
**Output**: data-model.md, /contracts/*, failing tests, quickstart.md, agent-specific file
## Phase 2: Task Planning Approach
*This section describes what the /tasks command will do - DO NOT execute during /plan*
**Task Generation Strategy**:
- Load `.specify/templates/tasks-template.md` as base
- Generate tasks from Phase 1 design docs (contracts, data model, quickstart)
- Each contract → contract test implementation task [P]
- Each data model entity → implementation task [P]
- Each interface → component implementation task
- Integration tasks to ensure compatibility with gen_route.go
- Test-driven implementation following TDD principles
**Ordering Strategy**:
- TDD order: Write failing tests first, then implement to make tests pass
- Component dependency order: Core interfaces → Parsers → Builders → Validators → Renderers
- Backward compatibility: Ensure gen_route.go works throughout implementation
- Mark [P] for parallel execution (independent components)
**Estimated Output**: 25-30 numbered, ordered tasks in tasks.md covering:
- Core interface implementations
- Data model and error handling
- Route parsing and validation
- Template rendering and code generation
- Integration and compatibility testing
- Performance and validation testing
**IMPORTANT**: This phase is executed by the /tasks command, NOT by /plan
## Phase 3+: Future Implementation
*These phases are beyond the scope of the /plan command*
**Phase 3**: Task execution (/tasks command creates tasks.md)
**Phase 4**: Implementation (execute tasks.md following constitutional principles)
**Phase 5**: Validation (run tests, execute quickstart.md, performance validation)
## Complexity Tracking
*Fill ONLY if Constitution Check has violations that must be justified*
| Violation | Why Needed | Simpler Alternative Rejected Because |
|-----------|------------|-------------------------------------|
| [e.g., 4th project] | [current need] | [why 3 projects insufficient] |
| [e.g., Repository pattern] | [specific problem] | [why direct DB access insufficient] |
## Progress Tracking
*This checklist is updated during execution flow*
**Phase Status**:
- [x] Phase 0: Research complete (/plan command)
- [x] Phase 1: Design complete (/plan command)
- [x] Phase 2: Task planning complete (/plan command - describe approach only)
- [ ] Phase 3: Tasks generated (/tasks command)
- [ ] Phase 4: Implementation complete
- [ ] Phase 5: Validation passed
**Gate Status**:
- [x] Initial Constitution Check: PASS
- [x] Post-Design Constitution Check: PASS
- [x] All NEEDS CLARIFICATION resolved
- [x] Complexity deviations documented
---
*Based on Constitution v1.0.0 - See `/memory/constitution.md`*

View File

@@ -0,0 +1,353 @@
# Phase 1: Quickstart Guide
## Overview
This quickstart guide demonstrates how to use the refactored AST route generation system. It covers the basic workflow for defining routes and generating route handler code.
## Prerequisites
- Go 1.21 or higher
- Existing atomctl project structure
- Basic understanding of Go annotations
## Basic Route Definition
### 1. Simple Route
Create a controller with basic route annotation:
```go
// app/http/user_controller.go
package http
// @Router /users [get]
type UserController struct {}
```
Generate routes:
```bash
atomctl gen route
```
### 2. Route with Parameters
Add parameter bindings using `@Bind` annotations:
```go
// app/http/user_controller.go
package http
// @Router /users/:id [get]
// @Bind id (path) model()
// @Bind limit (query) model(limit:int)
type UserController struct {}
```
## Parameter Binding Types
### Path Parameters
```go
// @Bind id (path) model()
// @Bind name (path) model(name:string)
```
### Query Parameters
```go
// @Bind limit (query) model(limit:int)
// @Bind offset (query) model(offset:int)
// @Bind filter (query)
```
### Body Parameters
```go
// @Bind user (body) model(User)
// @Bind data (body) model(CreateUserRequest)
```
### Header Parameters
```go
// @Bind authorization (header)
// @Bind x-api-key (header) model(APIKey)
```
## Generated Code Structure
The route generation will create a `routes.gen.go` file:
```go
// app/http/routes.gen.go
package http
import (
"context"
"net/http"
"go.ipao.vip/atom/contracts"
"go.ipao.vip/atom/http"
"go.ipao.vip/gen/model"
)
type RouteProvider struct {
userController *UserController
}
func (p *RouteProvider) Provide(opts ...contracts.Option) error {
// Route registration logic here
p.userController = &UserController{}
// Register /users route
http.Handle("/users", p.userController.GetUsers)
return nil
}
// UserController method stubs
func (c *UserController) GetUsers(ctx context.Context, w http.ResponseWriter, r *http.Request) {
// Generated method implementation
}
```
## Testing Your Routes
### 1. Unit Test
```go
// app/http/user_controller_test.go
package http
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/assert"
)
func TestUserController_GetUsers(t *testing.T) {
controller := &UserController{}
req := httptest.NewRequest("GET", "/users", nil)
w := httptest.NewRecorder()
controller.GetUsers(context.Background(), w, req)
assert.Equal(t, http.StatusOK, w.Code)
}
```
### 2. Integration Test
```go
// integration/user_routes_test.go
package integration
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/assert"
)
func TestUserRoutes(t *testing.T) {
// Setup router with generated routes
router := setupRouter()
tests := []struct {
name string
path string
method string
wantStatus int
}{
{"Get Users", "/users", "GET", http.StatusOK},
{"Get User by ID", "/users/123", "GET", http.StatusOK},
{"Create User", "/users", "POST", http.StatusCreated},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
req := httptest.NewRequest(tt.method, tt.path, nil)
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
assert.Equal(t, tt.wantStatus, w.Code)
})
}
}
```
## Advanced Features
### 1. Route Groups
```go
// @Router /api/v1/users [get]
// @Router /api/v1/users/:id [get,put,delete]
type UserController struct {}
```
### 2. Middleware Integration
```go
// @Router /admin [get]
// @Middleware auth,admin
type AdminController struct {}
```
### 3. Custom Return Types
```go
// @Router /users [post]
// @ReturnType UserResponse
type UserController struct {}
```
## Configuration Options
### Parser Configuration
```go
config := &route.RouteParserConfig{
StrictMode: true,
ParseComments: true,
SourceLocations: true,
EnableValidation: true,
}
```
### Builder Configuration
```go
config := &route.BuilderConfig{
EnableValidation: true,
StrictMode: true,
DefaultParamPosition: route.ParamPositionQuery,
AutoGenerateReturnTypes: true,
ResolveImportDependencies: true,
}
```
## Error Handling
### 1. Validation Errors
The refactored system provides detailed error messages:
```bash
$ atomctl gen route
Error: invalid route syntax in user_controller.go:15
Expected: @Router /path [method]
Found: @Router /users
Fix: Add HTTP methods in brackets
```
### 2. Parameter Binding Errors
```bash
$ atomctl gen route
Error: invalid parameter binding in user_controller.go:16
Parameter 'id' has invalid position 'invalid'
Valid positions: path, query, body, header, cookie, local, file
```
## Migration from Legacy System
### 1. Existing Code Compatibility
The refactored system maintains full backward compatibility:
```go
// This still works
// @Router /users [get]
// @Bind id (path) model()
type UserController struct {}
```
### 2. Gradual Migration
You can migrate files incrementally:
```bash
# Generate routes for specific files
atomctl gen route app/http/user_controller.go
# Or generate for entire directory
atomctl gen route app/http/
```
## Performance Considerations
### 1. Caching
The refactored system includes caching for improved performance:
```go
config := &route.RouteParserConfig{
CacheEnabled: true,
}
```
### 2. Parallel Processing
Enable parallel processing for large projects:
```go
config := &route.RouteParserConfig{
ParallelProcessing: true,
}
```
## Debugging and Diagnostics
### 1. Enable Detailed Logging
```go
config := &route.RouteParserConfig{
SourceLocations: true,
}
```
### 2. Access Diagnostics
```go
parser := route.NewRouteParser()
routes, err := parser.ParseFile("controller.go")
// Get detailed diagnostics
diagnostics := parser.GetDiagnostics()
for _, diag := range diagnostics {
fmt.Printf("%s: %s (%s:%d)\n", diag.Level, diag.Message, diag.File, diag.Location.Line)
}
```
## Best Practices
### 1. Route Definition
- Use descriptive route names
- Group related routes together
- Follow REST conventions where applicable
### 2. Parameter Binding
- Use appropriate parameter positions
- Provide clear parameter names
- Add validation for complex parameters
### 3. Error Handling
- Implement proper error handling in controllers
- Use appropriate HTTP status codes
- Provide meaningful error messages
### 4. Testing
- Write comprehensive tests for all routes
- Test both success and error scenarios
- Use contract tests for consistency
## Troubleshooting
### Common Issues
1. **Routes not generated**: Check file naming and location
2. **Parameters not parsed**: Verify annotation syntax
3. **Import errors**: Ensure all dependencies are available
4. **Compilation errors**: Check generated code syntax
### Getting Help
- Review the contract tests in `contracts/` directory
- Check the diagnostic output for detailed error information
- Run tests to verify implementation correctness
## Next Steps
1. Define your routes using `@Router` and `@Bind` annotations
2. Run `atomctl gen route` to generate route code
3. Implement the generated controller methods
4. Write tests to verify functionality
5. Configure options as needed for your project
The refactored system provides a solid foundation for route generation with improved maintainability, testability, and extensibility.

View File

@@ -0,0 +1,137 @@
# Phase 0: Research Findings
## Research Overview
Conducted comprehensive analysis of existing `/projects/atomctl/pkg/ast/route/` implementation to understand current architecture, identify improvement opportunities, and establish refactoring strategy.
## Key Findings
### 1. Current Architecture Analysis
**File Structure:**
- `route.go` (272 lines): Core parsing logic with mixed responsibilities
- `builder.go` (155 lines): Template data construction
- `render.go` (54 lines): Rendering coordination entry point
- `renderer.go` (23 lines): Template rendering wrapper
- `router.go.tpl` (47 lines): Go template for code generation
**Architecture Pattern:** Monolithic design with functional approach, lacking clear component boundaries
### 2. Comparison with Refactored Provider Module
| Aspect | Current Route Module | Refactored Provider Module |
|--------|---------------------|---------------------------|
| **Architecture** | Monolithic, flat | Component-based, layered |
| **Components** | 5 files, unclear boundaries | 15+ files, clear separation |
| **Error Handling** | Simple, uses panic | Comprehensive error collection |
| **Extensibility** | Limited | Highly extensible |
| **Test Coverage** | Minimal | Comprehensive test strategy |
| **Configuration** | Hardcoded | Configurable system |
### 3. Identified Problems
**Design Principle Violations:**
- **DRY**: Duplicate import parsing and AST traversal logic with provider module
- **SRP**: `route.go` handles parsing, validation, and construction
- **OCP**: Adding new parameter types requires core code changes
- **DIP**: Direct dependencies between components
**Code Quality Issues:**
- Use of `panic` instead of proper error handling
- Hardcoded paths and package names
- Complex type judgment logic without abstraction
- Insufficient test coverage
### 4. Refactoring Strategy
**Decision**: Adopt the successful patterns from `pkg/ast/provider` refactoring
**Rationale**:
- Proven architecture that SOLID principles
- Maintains backward compatibility
- Provides clear migration path
- Leverages existing shared utilities
**Alternatives Considered:**
- Minimal fixes to existing code (rejected: doesn't address architectural issues)
- Complete rewrite (rejected: too risky, breaks compatibility)
- Incremental refactoring (selected: balances improvement and stability)
## Research-Driven Decisions
### 1. Architecture Decision
**Decision**: Component-based architecture following provider patterns
**Components to Create:**
- `RouteParser` (coordinator)
- `CommentParser` (annotation parsing)
- `ImportResolver` (import processing)
- `RouteBuilder` (route construction)
- `RouteValidator` (validation logic)
- `RouteRenderer` (template rendering)
### 2. Compatibility Decision
**Decision**: Maintain full backward compatibility
**Requirements:**
- Preserve existing `@Router` and `@Bind` annotation syntax
- Keep `cmd/gen_route.go` interface unchanged
- Ensure generated code output remains identical
### 3. Testing Strategy Decision
**Decision**: Test-driven development approach
**Approach:**
- Write comprehensive tests first (contract tests)
- Refactor implementation to make tests pass
- Maintain test coverage throughout refactoring
### 4. Performance Decision
**Decision**: Maintain current performance characteristics
**Targets:**
- <2s parsing for typical projects
- Minimal memory overhead
- No performance regression
## Implementation Strategy
### Phase 1: Design & Contracts
1. Define new component interfaces based on provider patterns
2. Create data models and contracts
3. Establish test scenarios and acceptance criteria
### Phase 2: Task Implementation
1. Implement new component architecture
2. Migrate existing logic incrementally
3. Maintain compatibility through testing
### Phase 3: Validation
1. Comprehensive testing across all scenarios
2. Performance validation
3. Integration testing with existing systems
## Risk Assessment
**Low Risk:**
- Backward compatibility maintained
- Incremental refactoring approach
- Proven architectural patterns
**Medium Risk:**
- Complex parameter handling logic migration
- Template system integration
- Error handling standardization
**Mitigation Strategies:**
- Comprehensive test coverage
- Incremental implementation with validation
- Rollback capability at each stage
## Success Criteria
1. **Code Quality**: Clear separation of concerns, SOLID compliance
2. **Maintainability**: Component-based architecture with clear boundaries
3. **Testability**: Comprehensive test coverage with clear contract tests
4. **Compatibility**: Zero breaking changes to existing functionality
5. **Performance**: No performance regression
## Conclusion
The research confirms that refactoring `pkg/ast/route` using the successful patterns from `pkg/ast/provider` is the optimal approach. This will improve code maintainability, testability, and extensibility while preserving all existing functionality.
**Decision Status**: ✅ APPROVED - Proceed to Phase 1 design

View File

@@ -0,0 +1,122 @@
# Feature Specification: Refactor AST Generation Routes Workflow
**Feature Branch**: `002-refactor-ast-gen`
**Created**: 2025-09-22
**Status**: Draft
**Input**: User description: "refactor ast gen routes workflow"
## Execution Flow (main)
```
1. Parse user description from Input
<20> If empty: ERROR "No feature description provided"
2. Extract key concepts from description
<20> Identify: actors, actions, data, constraints
3. For each unclear aspect:
<20> Mark with [NEEDS CLARIFICATION: specific question]
4. Fill User Scenarios & Testing section
<20> If no clear user flow: ERROR "Cannot determine user scenarios"
5. Generate Functional Requirements
<20> Each requirement must be testable
<20> Mark ambiguous requirements
6. Identify Key Entities (if data involved)
7. Run Review Checklist
<20> If any [NEEDS CLARIFICATION]: WARN "Spec has uncertainties"
<20> If implementation details found: ERROR "Remove tech details"
8. Return: SUCCESS (spec ready for planning)
```
---
## <20> Quick Guidelines
-  Focus on WHAT users need and WHY
- L Avoid HOW to implement (no tech stack, APIs, code structure)
- =e Written for business stakeholders, not developers
### Section Requirements
- **Mandatory sections**: Must be completed for every feature
- **Optional sections**: Include only when relevant to the feature
- When a section doesn't apply, remove it entirely (don't leave as "N/A")
### For AI Generation
When creating this spec from a user prompt:
1. **Mark all ambiguities**: Use [NEEDS CLARIFICATION: specific question] for any assumption you'd need to make
2. **Don't guess**: If the prompt doesn't specify something (e.g., "login system" without auth method), mark it
3. **Think like a tester**: Every vague requirement should fail the "testable and unambiguous" checklist item
4. **Common underspecified areas**:
- User types and permissions
- Data retention/deletion policies
- Performance targets and scale
- Error handling behaviors
- Integration requirements
- Security/compliance needs
---
## User Scenarios & Testing *(mandatory)*
### Primary User Story
As a developer using the atomctl code generation system, I need the AST-based route generation workflow to be refactored so that it is more maintainable, extensible, and follows consistent patterns with other generation workflows in the system.
### Acceptance Scenarios
1. **Given** a developer wants to generate route handlers from AST annotations, **When** they run the generation command, **Then** the system should correctly parse route definitions and generate appropriate handler code
2. **Given** existing route generation code has inconsistent patterns, **When** the refactoring is complete, **Then** all route generation should follow the same architectural patterns as other providers
3. **Given** the current system has duplicate logic, **When** the refactoring is complete, **Then** common functionality should be shared and DRY principles should be applied
### Edge Cases
- What happens when the system encounters unsupported route annotations?
- How does the system handle conflicting route definitions?
- What occurs when there are circular dependencies between route handlers?
## Requirements *(mandatory)*
### Functional Requirements
- **FR-001**: System MUST parse route-related annotations from AST structures
- **FR-002**: System MUST generate route handler code based on parsed annotations
- **FR-003**: Users MUST be able to define route patterns and HTTP methods through annotations
- **FR-004**: System MUST integrate route generation with existing provider generation workflow
- **FR-005**: System MUST eliminate duplicate code between route generation and other generation workflows
- **FR-006**: System MUST follow consistent error handling patterns across all generation workflows
- **FR-007**: System MUST provide clear feedback when route generation fails or encounters issues
*Example of marking unclear requirements:*
- **FR-008**: System MUST support [NEEDS CLARIFICATION: which HTTP methods? GET, POST, PUT, DELETE, or all?]
- **FR-009**: Route generation MUST handle [NEEDS CLARIFICATION: what level of route complexity? simple paths, parameters, wildcards?]
### Key Entities *(include if feature involves data)*
- **Route Definition**: Represents a route annotation containing path, HTTP method, and handler information
- **Route Generator**: Component responsible for transforming route annotations into executable code
- **Route Parser**: Component that extracts route information from AST structures
- **Route Template**: Code generation template that produces the final route handler code
---
## Review & Acceptance Checklist
*GATE: Automated checks run during main() execution*
### Content Quality
- [ ] No implementation details (languages, frameworks, APIs)
- [ ] Focused on user value and business needs
- [ ] Written for non-technical stakeholders
- [ ] All mandatory sections completed
### Requirement Completeness
- [ ] No [NEEDS CLARIFICATION] markers remain
- [ ] Requirements are testable and unambiguous
- [ ] Success criteria are measurable
- [ ] Scope is clearly bounded
- [ ] Dependencies and assumptions identified
---
## Execution Status
*Updated by main() during processing*
- [x] User description parsed
- [x] Key concepts extracted
- [x] Ambiguities marked
- [x] User scenarios defined
- [x] Requirements generated
- [x] Entities identified
- [ ] Review checklist passed
---

View File

@@ -0,0 +1,148 @@
# Tasks: Refactor AST Generation Routes Workflow
**Input**: Design documents from `/specs/002-refactor-ast-gen/`
**Prerequisites**: plan.md, research.md, data-model.md, contracts/, quickstart.md
## Execution Flow (main)
```
1. Load plan.md from feature directory
→ Extract: Go 1.21+, ast/parser/token, cobra CLI, logrus
→ Extract: pkg/ast/route/ refactoring following provider patterns
2. Load design documents:
→ data-model.md: Extract RouteDefinition, ParamDefinition, 6 interfaces
→ contracts/: 2 contract test files → 2 contract test tasks
→ research.md: Extract component architecture → setup tasks
→ quickstart.md: Extract usage scenarios → integration test tasks
3. Generate tasks by category:
→ Setup: project structure, core interfaces, error handling
→ Tests: contract tests, integration tests, compatibility tests
→ Core: RouteParser, RouteBuilder, RouteValidator, RouteRenderer components
→ Integration: compatibility layer, cmd/gen_route.go integration
→ Polish: performance tests, documentation, validation
4. Apply task rules:
→ Different components = mark [P] for parallel development
→ Same file = sequential (no [P])
→ Tests before implementation (TDD)
5. Number tasks sequentially (T001, T002...)
6. Generate dependency graph
7. Create parallel execution examples
8. Validate task completeness:
→ All contracts have tests?
→ All entities have models?
→ All components implemented?
9. Return: SUCCESS (tasks ready for execution)
```
## Format: `[ID] [P?] Description`
- **[P]**: Can run in parallel (different components, no dependencies)
- Include exact file paths in descriptions
## Phase 3.1: Setup ✅ COMPLETED
- [x] **T001** Verify existing pkg/ast/route/ structure
- [x] **T002** Initialize Go module dependencies for testing
- [x] **T003** Setup linting and formatting tools configuration
## Phase 3.2: Tests First (TDD) ⚠️ MUST COMPLETE BEFORE 3.3
**CRITICAL: These tests MUST be written and MUST FAIL before ANY implementation**
### Basic Tests ✅ COMPLETED
- [x] **T004** Create basic route parsing test in pkg/ast/route/route_test.go
- [x] **T005** Create parameter binding test in pkg/ast/route/route_test.go
- [x] **T006** Create error handling test in pkg/ast/route/route_test.go
### Compatibility Tests
- [ ] **T007** Test backward compatibility with existing annotations
- [ ] **T008** Test cmd/gen_route.go integration
## Phase 3.3: Core Implementation (ONLY after tests are failing)
### Route Logic Refactoring
- [ ] **T009** Refactor route.go parsing logic for better readability
- [ ] **T010** Refactor builder.go for clearer separation of concerns
- [ ] **T011** Improve error handling and diagnostics
- [ ] **T012** Optimize render.go coordination logic
### Template and Rendering
- [ ] **T013** Update router.go.tpl template if needed
- [ ] **T014** Improve renderer.go wrapper functionality
## Phase 3.4: Integration
### CLI Integration
- [ ] **T015** Verify cmd/gen_route.go works with refactored code
- [ ] **T016** Test all existing functionality still works
- [ ] **T017** Ensure performance targets are met (< 2s parsing)
## Phase 3.5: Polish
### Final Validation
- [ ] **T018** Run comprehensive tests
- [ ] **T019** Verify no breaking changes
- [ ] **T020** Update documentation if needed
## Dependencies
- Tests (T004-T008) before implementation (T009-T014)
- Implementation before integration (T015-T017)
- Integration before polish (T018-T020)
## Parallel Example
```
# Launch basic tests together (T004-T006):
Task: "Create basic route parsing test in pkg/ast/route/route_test.go"
Task: "Create parameter binding test in pkg/ast/route/route_test.go"
Task: "Create error handling test in pkg/ast/route/route_test.go"
# Launch compatibility tests together (T007-T008):
Task: "Test backward compatibility with existing annotations"
Task: "Test cmd/gen_route.go integration"
# Launch refactoring tasks together (T009-T012):
Task: "Refactor route.go parsing logic for better readability"
Task: "Refactor builder.go for clearer separation of concerns"
Task: "Improve error handling and diagnostics"
Task: "Optimize render.go coordination logic"
```
## Notes
- [P] tasks = different components/files, no dependencies
- Verify tests fail before implementing (TDD)
- Focus on minimal refactoring for better readability
- Keep business files flat - no complex directory structures
- Ensure backward compatibility with existing @Router and @Bind annotations
- Ensure cmd/gen_route.go interface remains unchanged
- Follow KISS principle - minimal changes for maximum clarity
## Task Generation Rules Compliance
### SOLID Compliance
- ✅ Single Responsibility: Each task focuses on one specific component
- ✅ Open/Closed: Interface-based design allows extension without modification
- ✅ Interface Segregation: Focused interfaces for different components
- ✅ Dependency Inversion: Components depend on interfaces, not implementations
### KISS Compliance
- ✅ Simple, direct task descriptions
- ✅ Clear file organization and naming
- ✅ Minimal dependencies between tasks
### YAGNI Compliance
- ✅ Only essential tasks for refactoring goals
- ✅ No speculative functionality
- ✅ Focus on MVP refactoring first
### DRY Compliance
- ✅ Consolidated similar operations
- ✅ Reused patterns from provider module
- ✅ No duplicate task definitions
## Validation Checklist
- [x] All contracts have corresponding tests (T004-T005)
- [x] All entities have model tasks (T010-T012)
- [x] All tests come before implementation
- [x] Parallel tasks truly independent
- [x] Each task specifies exact file path
- [x] No task modifies same file as another [P] task
- [x] Backward compatibility maintained throughout
- [x] cmd/gen_route.go integration included
- [x] Performance considerations addressed (< 2s parsing)