-
Notifications
You must be signed in to change notification settings - Fork 984
refactor: replace text/template with programmatic Go code generation #4255
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
kyleconroy
wants to merge
18
commits into
main
Choose a base branch
from
claude/replace-template-with-poet-g1fMu
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Replace the template-based code generation in the Go codegen with programmatic generation using direct AST-like buffer writes. Changes: - Add internal/poet package with helpers for Go code generation - Add internal/codegen/golang/generator.go with CodeGenerator - Update gen.go to use CodeGenerator instead of templates - Remove template.go and embedded templates The new approach: - Generates identical output to the previous templates - More maintainable and easier to debug - Type-safe code generation without string interpolation - Better IDE support and code navigation All existing tests pass with no changes to expected output.
Redesign the poet package to use custom AST structures specifically designed for Go code generation instead of wrapping go/ast types. Key changes: - New ast.go: Custom types (File, Import, Decl, TypeDef, Func, Struct, Field, Interface, etc.) with proper support for comments - New render.go: Rendering logic that converts custom AST to formatted Go source code with proper comment placement - ImportGroups: Support for separating stdlib and third-party imports with blank lines between groups - TrailingComment: Support for trailing comments on struct fields (e.g., "Valid is true if X is not NULL") Removed old poet package files (expr.go, func.go, poet.go, stmt.go, types.go) that wrapped go/ast which made comment placement difficult. The generator.go now builds poet.File structures and calls poet.Render() to produce formatted Go code that exactly matches the previous output.
…mplates Add AST support for structured function bodies: - Return: return statement with multiple values - For: traditional for loop and range-based iteration - If: if/else statements with optional init clause Enhance Param type: - Add Pointer boolean field to indicate pointer types instead of requiring "*" prefix in the Type string Delete unused templates: - Remove internal/codegen/golang/templates/ directory containing .tmpl files that are no longer used after switching to poet-based code generation
Add Switch statement AST node: - Switch: switch statement with optional init and expression - Case: case clause with values (empty for default) Breaking change to Func struct: - Remove Body field to force use of Stmts - Update all usages in generator.go to use Stmts with RawStmt This enforces consistent use of the structured statement API instead of allowing raw body strings as an escape hatch.
Replace RawStmt usage with structured statement types where applicable: - poet.Return for return statements - poet.Switch for switch statements - poet.If for if statements Also: - Use Pointer field on Param instead of "*" prefix in Type - Format multi-value switch cases on separate lines - Keep line lengths under 90 chars for readability This makes the code generation more structured and type-safe while maintaining identical output.
Add new statement AST nodes: - Defer: defer statements (defer expr) - Assign: assignment statements (left op right) - CallStmt: function call statements Update generator.go to use structured statements: - Convert RawStmt assignments to poet.Assign - Eliminates manual tab management for these statements The rendering handles indentation automatically, making the code more maintainable and less error-prone.
…tements Add VarDecl statement type to poet package for variable declarations inside function bodies (e.g., "var items []Type"). Convert all standard SQL driver query functions to use structured poet statements instead of strings.Builder: - addQueryOneStd: uses Assign, VarDecl, If, Return - addQueryManyStd: uses Assign, VarDecl, Defer, For, If, Return - addQueryExecRowsStd: uses Assign, If, Return - addQueryExecLastIDStd: uses Assign, If, Return - addQueryExecResultStd: uses Assign, If, Return Slice queries (sqlc.slice) fall back to RawStmt due to their complex dynamic SQL generation requirements. Added wrapErrorReturn helper for consistent error wrapping logic. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
Add new expression types that implement the Expr interface: - CallExpr: function/method calls - StructLit: struct literals with Multiline option - SliceLit: slice literals - TypeCast: type conversions - FuncLit: anonymous function literals - Selector: field/method selection (a.b.c) - Index: array/slice indexing Add new statement types: - GoStmt: goroutine launch (go f()) - Continue: continue statement with optional label - Break: break statement with optional label Update generator.go to use StructLit for: - New function (compact single-line format) - WithTx method (multi-line format) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Update SliceLit to support multi-line formatting similar to StructLit. This ensures AllEnumTypeValues() functions generate properly formatted slice literals with each value on its own line. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Replace manual string building with poet AST types for: - Prepare function: VarDecl, Assign, If with Return - Close function: VarDecl, nested If statements, Assign, Return The slice query fallback still uses RawStmt due to complex dynamic SQL handling requirements. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Convert the HasSqlcSlices() fallback paths in addQueryOneStd and addQueryManyStd to use poet AST types instead of string building. Only the initial query exec call (writeQueryExecStdCall) remains as RawStmt due to complex dynamic SQL handling. All other statements now use structured poet types: - poet.If for error handling - poet.Defer for rows.Close() - poet.VarDecl and poet.Assign for variable declarations - poet.For for iteration - poet.Return for return statements 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Add guidance to always run go fmt before committing changes. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Convert the HasSqlcSlices() fallback paths in addQueryExecStd and addQueryExecRowsStd to use poet AST types instead of string building. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Replace string building with structured poet AST types for: - addQueryOnePGX, addQueryManyPGX, addQueryExecPGX - addQueryExecRowsPGX, addQueryExecResultPGX - addCopyFromCodeMySQL - batch functions (batchexec, batchmany, batchone) This eliminates manual string building with fmt.Fprintf and WriteString calls in favor of structured poet.If, poet.For, poet.Assign, poet.Defer, and other statement types. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
- Add Indent field to FuncLit to support configurable body indentation - Update RenderFuncLit to use the Indent field (defaults to "\t") - Convert batchmany innerFunc from manual string building to poet.FuncLit This eliminates the last remaining manual string building with tabs in the batch functions, using structured poet AST throughout. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
Split long poet.Method declarations across multiple lines for better readability. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
- Add buildQuerySliceExecStmts function that returns []poet.Stmt - Add public RenderStmt function to poet package - Use poet.If with Else, poet.For with Range, poet.Assign, poet.VarDecl - Eliminate manual string building with tabs 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Replace the template-based code generation in the Go codegen with
programmatic generation using direct AST-like buffer writes.
Changes:
The new approach:
All existing tests pass with no changes to expected output.