From 68a749947e9a2cc7e9073c8ad7bac4e0f454e5a8 Mon Sep 17 00:00:00 2001 From: ginokent <29125616+ginokent@users.noreply.github.com> Date: Sun, 12 Nov 2023 04:14:39 +0900 Subject: [PATCH 1/3] refactor: Add option to specify generated method name --- internal/arcgen/lang/go/generate.go | 14 ++--- internal/arcgen/lang/go/generate_test.go | 20 +++++-- internal/config/config.go | 60 ++++++++----------- internal/config/method_name_columns.go | 18 ++++++ ..._prefix_global.go => method_name_table.go} | 0 internal/config/timestamp.go | 18 ------ internal/contexts/now.go | 29 --------- pkg/arcgen/arcgen.go | 4 -- 8 files changed, 65 insertions(+), 98 deletions(-) create mode 100644 internal/config/method_name_columns.go rename internal/config/{method_prefix_global.go => method_name_table.go} (100%) delete mode 100644 internal/config/timestamp.go delete mode 100644 internal/contexts/now.go diff --git a/internal/arcgen/lang/go/generate.go b/internal/arcgen/lang/go/generate.go index 5475308..8767e26 100644 --- a/internal/arcgen/lang/go/generate.go +++ b/internal/arcgen/lang/go/generate.go @@ -89,7 +89,7 @@ func fprint(osFile io.Writer, buf buffer, arcSrcSet *ARCSourceSet) error { } } - appendAST(astFile, structName, tableName, config.MethodNameTable(), config.MethodPrefixColumn(), fieldNames, columnNames) + appendAST(astFile, structName, tableName, config.MethodNameTable(), config.MethodNameColumns(), config.MethodPrefixColumn(), fieldNames, columnNames) } if err := printer.Fprint(buf, token.NewFileSet(), astFile); err != nil { @@ -129,7 +129,7 @@ func extractTableNameFromCommentGroup(commentGroup *ast.CommentGroup) string { } //nolint:funlen -func appendAST(file *ast.File, structName string, tableName string, prefixGlobal string, prefixColumn string, fieldNames, columnNames []string) { +func appendAST(file *ast.File, structName string, tableName string, methodNameTable string, methodNameColumns string, methodPrefixColumn string, fieldNames, columnNames []string) { if tableName != "" { file.Decls = append(file.Decls, &ast.FuncDecl{ Recv: &ast.FieldList{ @@ -149,7 +149,7 @@ func appendAST(file *ast.File, structName string, tableName string, prefixGlobal }, }, Name: &ast.Ident{ - Name: prefixGlobal + "TableName", + Name: methodNameTable, }, Type: &ast.FuncType{ Params: &ast.FieldList{}, @@ -177,13 +177,13 @@ func appendAST(file *ast.File, structName string, tableName string, prefixGlobal }) } - file.Decls = append(file.Decls, generateASTColumnMethods(structName, prefixGlobal, prefixColumn, fieldNames, columnNames)...) + file.Decls = append(file.Decls, generateASTColumnMethods(structName, methodNameColumns, methodPrefixColumn, fieldNames, columnNames)...) return //nolint:gosimple } //nolint:funlen -func generateASTColumnMethods(structName string, prefixGlobal string, prefixColumn string, fieldNames, columnNames []string) []ast.Decl { +func generateASTColumnMethods(structName string, methodNameColumns string, prefixColumn string, fieldNames, columnNames []string) []ast.Decl { decls := make([]ast.Decl, 0) // all column names method @@ -212,7 +212,7 @@ func generateASTColumnMethods(structName string, prefixGlobal string, prefixColu }, }, Name: &ast.Ident{ - Name: prefixGlobal + "ColumnNames", + Name: methodNameColumns, }, Type: &ast.FuncType{ Params: &ast.FieldList{}, @@ -264,7 +264,7 @@ func generateASTColumnMethods(structName string, prefixGlobal string, prefixColu }, }, Name: &ast.Ident{ - Name: prefixGlobal + prefixColumn + fieldNames[i], + Name: prefixColumn + fieldNames[i], }, Type: &ast.FuncType{ Params: &ast.FieldList{}, diff --git a/internal/arcgen/lang/go/generate_test.go b/internal/arcgen/lang/go/generate_test.go index c38def9..bac47ad 100644 --- a/internal/arcgen/lang/go/generate_test.go +++ b/internal/arcgen/lang/go/generate_test.go @@ -23,7 +23,9 @@ func TestGenerate(t *testing.T) { ctx := contexts.WithArgs(context.Background(), []string{ "ddlgen", "--column-tag-go=dbtest", - "--method-name-table=Get", + "--method-name-table=GetTableName", + "--method-name-columns=GetColumnNames", + "--method-prefix-column=GetColumnName_", // "--src=tests/common.source", "--src=tests", }) @@ -58,7 +60,9 @@ func TestGenerate(t *testing.T) { ctx := contexts.WithArgs(context.Background(), []string{ "ddlgen", "--column-tag-go=dbtest", - "--method-name-table=Get", + "--method-name-table=GetTableName", + "--method-name-columns=GetColumnNames", + "--method-prefix-column=GetColumnName_", "--src=tests/no.errsource", }) @@ -76,7 +80,9 @@ func TestGenerate(t *testing.T) { ctx := contexts.WithArgs(context.Background(), []string{ "ddlgen", "--column-tag-go=dbtest", - "--method-name-table=Get", + "--method-name-table=GetTableName", + "--method-name-columns=GetColumnNames", + "--method-prefix-column=GetColumnName_", "--src=tests", }) @@ -94,7 +100,9 @@ func TestGenerate(t *testing.T) { ctx := contexts.WithArgs(context.Background(), []string{ "ddlgen", "--column-tag-go=dbtest", - "--method-name-table=Get", + "--method-name-table=GetTableName", + "--method-name-columns=GetColumnNames", + "--method-prefix-column=GetColumnName_", "--src=tests/no-such-file-or-directory", }) @@ -112,7 +120,9 @@ func TestGenerate(t *testing.T) { ctx := contexts.WithArgs(context.Background(), []string{ "ddlgen", "--column-tag-go=dbtest", - "--method-name-table=Get", + "--method-name-table=GetTableName", + "--method-name-columns=GetColumnNames", + "--method-prefix-column=GetColumnName_", "--src=tests/directory.dir", }) diff --git a/internal/config/config.go b/internal/config/config.go index 80626d0..2d10be5 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -4,7 +4,6 @@ import ( "context" "encoding/json" "sync" - "time" errorz "github.com/kunitsucom/util.go/errors" cliz "github.com/kunitsucom/util.go/exp/cli" @@ -17,16 +16,16 @@ import ( // //nolint:tagliatelle type config struct { - Version bool `json:"version"` - Trace bool `json:"trace"` - Debug bool `json:"debug"` - Timestamp string `json:"timestamp"` - Language string `json:"language"` - Source string `json:"source"` + Version bool `json:"version"` + Trace bool `json:"trace"` + Debug bool `json:"debug"` + Language string `json:"language"` + Source string `json:"source"` // Golang ColumnTagGo string `json:"column_tag_go"` - MethodPrefixColumn string `json:"column_method_prefix"` - MethodNameTable string `json:"method_table_name"` + MethodNameTable string `json:"method_name_table"` + MethodNameColumns string `json:"method_name_columns"` + MethodPrefixColumn string `json:"method_prefix_column"` } //nolint:gochecknoglobals @@ -74,18 +73,12 @@ const ( _OptionDebug = "debug" _EnvKeyDebug = "ARCGEN_DEBUG" - _OptionTimestamp = "timestamp" - _EnvKeyTimestamp = "ARCGEN_TIMESTAMP" - _OptionLanguage = "lang" _EnvKeyLanguage = "ARCGEN_LANGUAGE" _OptionSource = "src" _EnvKeySource = "ARCGEN_SOURCE" - _OptionDestination = "dst" - _EnvKeyDestination = "ARCGEN_DESTINATION" - // Golang _OptionColumnTagGo = "column-tag-go" @@ -94,6 +87,9 @@ const ( _OptionMethodNameTable = "method-name-table" _EnvKeyMethodNameTable = "ARCGEN_METHOD_NAME_TABLE" + _OptionMethodNameColumns = "method-name-columns" + _EnvKeyMethodNameColumns = "ARCGEN_METHOD_NAME_COLUMNS" + _OptionMethodPrefixColumn = "method-prefix-column" _EnvKeyMethodPrefixColumn = "ARCGEN_METHOD_PREFIX_COLUMN" ) @@ -103,8 +99,8 @@ const ( //nolint:funlen func load(ctx context.Context) (cfg *config, err error) { //nolint:unparam cmd := &cliz.Command{ - Name: "ARCgen", - Description: "Generate DDL from annotated source code.", + Name: "arcgen", + Description: "Generate methods that return information such as DB table names and column names from Go struct tags.", Options: []cliz.Option{ &cliz.BoolOption{ Name: _OptionVersion, @@ -123,12 +119,6 @@ func load(ctx context.Context) (cfg *config, err error) { //nolint:unparam Description: "debug mode", Default: cliz.Default(false), }, - &cliz.StringOption{ - Name: _OptionTimestamp, - Environment: _EnvKeyTimestamp, - Description: "code generation timestamp", - Default: cliz.Default(time.Now().Format(time.RFC3339)), - }, &cliz.StringOption{ Name: _OptionLanguage, Environment: _EnvKeyLanguage, @@ -141,12 +131,6 @@ func load(ctx context.Context) (cfg *config, err error) { //nolint:unparam Description: "source file or directory", Default: cliz.Default("/dev/stdin"), }, - &cliz.StringOption{ - Name: _OptionDestination, - Environment: _EnvKeyDestination, - Description: "destination file or directory", - Default: cliz.Default("/dev/stdout"), - }, // Golang &cliz.StringOption{ Name: _OptionColumnTagGo, @@ -160,6 +144,12 @@ func load(ctx context.Context) (cfg *config, err error) { //nolint:unparam Description: "method name for table", Default: cliz.Default("TableName"), }, + &cliz.StringOption{ + Name: _OptionMethodNameColumns, + Environment: _EnvKeyMethodNameColumns, + Description: "method name for columns", + Default: cliz.Default("ColumnNames"), + }, &cliz.StringOption{ Name: _OptionMethodPrefixColumn, Environment: _EnvKeyMethodPrefixColumn, @@ -174,15 +164,15 @@ func load(ctx context.Context) (cfg *config, err error) { //nolint:unparam } c := &config{ - Version: loadVersion(ctx, cmd), - Trace: loadTrace(ctx, cmd), - Debug: loadDebug(ctx, cmd), - Timestamp: loadTimestamp(ctx, cmd), - Language: loadLanguage(ctx, cmd), - Source: loadSource(ctx, cmd), + Version: loadVersion(ctx, cmd), + Trace: loadTrace(ctx, cmd), + Debug: loadDebug(ctx, cmd), + Language: loadLanguage(ctx, cmd), + Source: loadSource(ctx, cmd), // Golang ColumnTagGo: loadColumnTagGo(ctx, cmd), MethodNameTable: loadMethodNameTable(ctx, cmd), + MethodNameColumns: loadMethodNameColumns(ctx, cmd), MethodPrefixColumn: loadMethodPrefixColumn(ctx, cmd), } diff --git a/internal/config/method_name_columns.go b/internal/config/method_name_columns.go new file mode 100644 index 0000000..7134d15 --- /dev/null +++ b/internal/config/method_name_columns.go @@ -0,0 +1,18 @@ +package config + +import ( + "context" + + cliz "github.com/kunitsucom/util.go/exp/cli" +) + +func loadMethodNameColumns(_ context.Context, cmd *cliz.Command) string { + v, _ := cmd.GetOptionString(_OptionMethodNameColumns) + return v +} + +func MethodNameColumns() string { + globalConfigMu.RLock() + defer globalConfigMu.RUnlock() + return globalConfig.MethodNameColumns +} diff --git a/internal/config/method_prefix_global.go b/internal/config/method_name_table.go similarity index 100% rename from internal/config/method_prefix_global.go rename to internal/config/method_name_table.go diff --git a/internal/config/timestamp.go b/internal/config/timestamp.go deleted file mode 100644 index d07a6d1..0000000 --- a/internal/config/timestamp.go +++ /dev/null @@ -1,18 +0,0 @@ -package config - -import ( - "context" - - cliz "github.com/kunitsucom/util.go/exp/cli" -) - -func loadTimestamp(_ context.Context, cmd *cliz.Command) string { - v, _ := cmd.GetOptionString(_OptionTimestamp) - return v -} - -func Timestamp() string { - globalConfigMu.RLock() - defer globalConfigMu.RUnlock() - return globalConfig.Timestamp -} diff --git a/internal/contexts/now.go b/internal/contexts/now.go deleted file mode 100644 index 0788322..0000000 --- a/internal/contexts/now.go +++ /dev/null @@ -1,29 +0,0 @@ -package contexts - -import ( - "context" - "time" -) - -type contextKeyNow struct{} - -func Now(ctx context.Context) time.Time { - if now, ok := ctx.Value(contextKeyNow{}).(time.Time); ok { - return now - } - - return time.Now() -} - -func WithNow(ctx context.Context, now time.Time) context.Context { - return context.WithValue(ctx, contextKeyNow{}, now) -} - -func WithNowString(ctx context.Context, layout string, value string) context.Context { - v, err := time.Parse(layout, value) - if err != nil { - v = time.Now() - } - - return WithNow(ctx, v) -} diff --git a/pkg/arcgen/arcgen.go b/pkg/arcgen/arcgen.go index 7e5a443..283adaa 100644 --- a/pkg/arcgen/arcgen.go +++ b/pkg/arcgen/arcgen.go @@ -4,14 +4,12 @@ import ( "context" "errors" "fmt" - "time" errorz "github.com/kunitsucom/util.go/errors" cliz "github.com/kunitsucom/util.go/exp/cli" arcgengo "github.com/kunitsucom/arcgen/internal/arcgen/lang/go" "github.com/kunitsucom/arcgen/internal/config" - "github.com/kunitsucom/arcgen/internal/contexts" "github.com/kunitsucom/arcgen/internal/logs" ) @@ -31,8 +29,6 @@ func ARCGen(ctx context.Context) error { return nil } - ctx = contexts.WithNowString(ctx, time.RFC3339, config.Timestamp()) - src := config.Source() logs.Info.Printf("source: %s", src) From e07826786ba573e849646ef5b107d8d467cbeeb0 Mon Sep 17 00:00:00 2001 From: ginokent <29125616+ginokent@users.noreply.github.com> Date: Sun, 12 Nov 2023 04:15:11 +0900 Subject: [PATCH 2/3] docs: Create README.md --- README.md | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..39729b9 --- /dev/null +++ b/README.md @@ -0,0 +1,146 @@ +# [arcgen](https://github.com/kunitsucom/arcgen) + +[![license](https://img.shields.io/github/license/kunitsucom/arcgen)](LICENSE) +[![pkg](https://pkg.go.dev/badge/github.com/kunitsucom/arcgen)](https://pkg.go.dev/github.com/kunitsucom/arcgen) +[![goreportcard](https://goreportcard.com/badge/github.com/kunitsucom/arcgen)](https://goreportcard.com/report/github.com/kunitsucom/arcgen) +[![workflow](https://github.com/kunitsucom/arcgen/workflows/go-lint/badge.svg)](https://github.com/kunitsucom/arcgen/tree/main) +[![workflow](https://github.com/kunitsucom/arcgen/workflows/go-test/badge.svg)](https://github.com/kunitsucom/arcgen/tree/main) +[![workflow](https://github.com/kunitsucom/arcgen/workflows/go-vuln/badge.svg)](https://github.com/kunitsucom/arcgen/tree/main) +[![codecov](https://codecov.io/gh/kunitsucom/arcgen/graph/badge.svg?token=Y19kZ7UtVZ)](https://codecov.io/gh/kunitsucom/arcgen) +[![sourcegraph](https://sourcegraph.com/github.com/kunitsucom/arcgen/-/badge.svg)](https://sourcegraph.com/github.com/kunitsucom/arcgen) + +## Overview + +`arcgen` is a tool that generates methods that return information such as DB table names and column names from Go struct tags. + +## Example + +```console +$ # == 1. Prepare your annotated model source code ================================ +$ cat <<"EOF" > /tmp/sample.go +package sample + +// User is a user model struct. +// +// db: table: Users +type User struct { + ID int64 `db:"Id" spanddl:"STRING(36) NOT NULL"` + Name string `db:"Name" spanddl:"STRING(255) NOT NULL"` + Age int64 `db:"Age" spanddl:"INT64 NOT NULL"` +} + +// Group is a group model struct. +// +type Group struct { + ID int64 `db:"Id" spanddl:"STRING(36) NOT NULL"` + Name string `db:"Name" spanddl:"STRING(255) NOT NULL"` + Description string `db:"Description" spanddl:"STRING(2048) NOT NULL"` +} +EOF + +$ # == 2. generate file ================================ +$ arcgen --src /tmp/sample.go +INFO: 2023/11/12 03:56:59 arcgen.go:33: source: /tmp/sample.go + +$ # == 3. Check generated file ================================ +$ cat /tmp/sample.db.gen.go +// Code generated by arcgen. DO NOT EDIT. +// +// source: tmp/sample.go + +package sample + +func (s *User) TableName() string { + return "Users" +} + +func (s *User) ColumnNames() []string { + return []string{"Id", "Name", "Age"} +} + +func (s *User) ColumnName_ID() string { + return "Id" +} + +func (s *User) ColumnName_Name() string { + return "Name" +} + +func (s *User) ColumnName_Age() string { + return "Age" +} + +func (s *Group) ColumnNames() []string { + return []string{"Id", "Name", "Description"} +} + +func (s *Group) ColumnName_ID() string { + return "Id" +} + +func (s *Group) ColumnName_Name() string { + return "Name" +} + +func (s *Group) ColumnName_Description() string { + return "Description" +} +``` + +## Installation + +### pre-built binary + +```bash +VERSION=v0.0.3 + +# download +curl -fLROSs https://github.com/kunitsucom/arcgen/releases/download/${VERSION}/arcgen_${VERSION}_darwin_arm64.zip + +# unzip +unzip -j arcgen_${VERSION}_darwin_arm64.zip '*/arcgen' +``` + +### go install + +```bash +go install github.com/kunitsucom/arcgen/cmd/arcgen@latest +``` + +## Usage + +```console +$ arcgen --help +Usage: + arcgen [options] + +Description: + Generate methods that return information such as DB table names and column names from Go struct tags. + +options: + --version (default: false) + show version information and exit + --trace (env: ARCGEN_TRACE, default: false) + trace mode enabled + --debug (env: ARCGEN_DEBUG, default: false) + debug mode + --lang (env: ARCGEN_LANGUAGE, default: go) + programming language to generate DDL + --src (env: ARCGEN_SOURCE, default: /dev/stdin) + source file or directory + --column-tag-go (env: ARCGEN_COLUMN_TAG_GO, default: db) + column annotation key for Go struct tag + --method-name-table (env: ARCGEN_METHOD_NAME_TABLE, default: TableName) + method name for table + --method-name-columns (env: ARCGEN_METHOD_NAME_COLUMNS, default: ColumnNames) + method name for columns + --method-prefix-column (env: ARCGEN_METHOD_PREFIX_COLUMN, default: ColumnName_) + method prefix for column name + --help (default: false) + show usage +``` + +## TODO + +- lang + - [x] Support `go` From 9f0a17f398326a26b6d5199702099dda55555d65 Mon Sep 17 00:00:00 2001 From: ginokent <29125616+ginokent@users.noreply.github.com> Date: Sun, 12 Nov 2023 04:17:38 +0900 Subject: [PATCH 3/3] test: fix misc --- internal/arcgen/lang/go/generate_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/internal/arcgen/lang/go/generate_test.go b/internal/arcgen/lang/go/generate_test.go index bac47ad..b43610c 100644 --- a/internal/arcgen/lang/go/generate_test.go +++ b/internal/arcgen/lang/go/generate_test.go @@ -21,7 +21,7 @@ import ( func TestGenerate(t *testing.T) { t.Run("success,tests", func(t *testing.T) { ctx := contexts.WithArgs(context.Background(), []string{ - "ddlgen", + "arcgen", "--column-tag-go=dbtest", "--method-name-table=GetTableName", "--method-name-columns=GetColumnNames", @@ -58,7 +58,7 @@ func TestGenerate(t *testing.T) { t.Run("failure,no.errsource", func(t *testing.T) { ctx := contexts.WithArgs(context.Background(), []string{ - "ddlgen", + "arcgen", "--column-tag-go=dbtest", "--method-name-table=GetTableName", "--method-name-columns=GetColumnNames", @@ -78,7 +78,7 @@ func TestGenerate(t *testing.T) { t.Run("failure,no.errsource", func(t *testing.T) { ctx := contexts.WithArgs(context.Background(), []string{ - "ddlgen", + "arcgen", "--column-tag-go=dbtest", "--method-name-table=GetTableName", "--method-name-columns=GetColumnNames", @@ -98,7 +98,7 @@ func TestGenerate(t *testing.T) { t.Run("failure,no-such-file-or-directory", func(t *testing.T) { ctx := contexts.WithArgs(context.Background(), []string{ - "ddlgen", + "arcgen", "--column-tag-go=dbtest", "--method-name-table=GetTableName", "--method-name-columns=GetColumnNames", @@ -118,7 +118,7 @@ func TestGenerate(t *testing.T) { t.Run("failure,directory.dir", func(t *testing.T) { ctx := contexts.WithArgs(context.Background(), []string{ - "ddlgen", + "arcgen", "--column-tag-go=dbtest", "--method-name-table=GetTableName", "--method-name-columns=GetColumnNames",