@@ -2,30 +2,157 @@ package main
22
33import (
44 "flag"
5+ "fmt"
6+ "io/fs"
57 "log/slog"
68 "os"
79 "path/filepath"
10+ "strings"
811
12+ "github.com/origadmin/adptool/internal/compiler"
913 "github.com/origadmin/adptool/internal/config"
10- "github.com/origadmin/adptool/internal/engine "
14+ "github.com/origadmin/adptool/internal/generator "
1115 "github.com/origadmin/adptool/internal/loader"
16+ "github.com/origadmin/adptool/internal/parser"
1217)
1318
19+ // processFile processes a single Go file and generates its adapter
20+ func processFile (filePath string , cfg * config.Config ) error {
21+ // First check if the file has the adapter directive
22+ hasAdapter , err := hasAdapterDirective (filePath )
23+ if err != nil {
24+ return fmt .Errorf ("failed to check adapter directive in %s: %w" , filePath , err )
25+ }
26+
27+ if ! hasAdapter {
28+ slog .Debug ("Skipping file without //go:adapter directive" , "file" , filePath )
29+ return nil
30+ }
31+
32+ // Parse the Go file to get the AST
33+ file , fset , err := loader .LoadGoFile (filePath )
34+ if err != nil {
35+ return fmt .Errorf ("failed to load Go file %s: %w" , filePath , err )
36+ }
37+
38+ // Parse file directives using the loaded config
39+ pkgConfig , err := parser .ParseFileDirectives (cfg , file , fset )
40+ if err != nil {
41+ return fmt .Errorf ("failed to parse file directives in %s: %w" , filePath , err )
42+ }
43+
44+ // Compile the configuration
45+ compiledCfg , err := compiler .Compile (pkgConfig )
46+ if err != nil {
47+ return fmt .Errorf ("error compiling config for %s: %w" , filePath , err )
48+ }
49+
50+ replacer := compiler .NewReplacer (compiledCfg )
51+
52+ // Set output file path (same directory as input file with .adapter.go suffix)
53+ dir := filepath .Dir (filePath )
54+ baseName := filepath .Base (filePath )
55+ ext := filepath .Ext (baseName )
56+ outputBase := baseName [:len (baseName )- len (ext )] + ".adapter.go"
57+ outputFile := filepath .Join (dir , outputBase )
58+
59+ // Convert PackageConfig to PackageInfo
60+ var packageInfos []* generator.PackageInfo
61+ for _ , pkg := range pkgConfig .Packages {
62+ packageInfos = append (packageInfos , & generator.PackageInfo {
63+ ImportPath : pkg .Import ,
64+ ImportAlias : pkg .Alias ,
65+ })
66+ }
67+
68+ // Determine the package name
69+ packageName := pkgConfig .PackageName
70+ if packageName == "" {
71+ packageName = filepath .Base (dir )
72+ }
73+
74+ // Generate the adapter file
75+ gen := generator .NewGenerator (packageName , outputFile , replacer ).
76+ WithNoEditHeader (true )
77+
78+ if err := gen .Generate (packageInfos ); err != nil {
79+ return fmt .Errorf ("error generating adapter file %s: %w" , outputFile , err )
80+ }
81+
82+ slog .Info ("Generated adapter file" , "path" , outputFile )
83+ return nil
84+ }
85+
86+ // hasAdapterDirective checks if the file contains //go:adapter directive
87+ func hasAdapterDirective (filePath string ) (bool , error ) {
88+ content , err := os .ReadFile (filePath )
89+ if err != nil {
90+ return false , fmt .Errorf ("failed to read file %s: %w" , filePath , err )
91+ }
92+ return strings .Contains (string (content ), parser .DirectivePrefix ), nil
93+ }
94+
95+ // findGoFiles finds all .go files in the given directory that contain //go:adapter directive
96+ func findGoFiles (dir string ) ([]string , error ) {
97+ // Handle current directory (.) case
98+ if dir == "." {
99+ var err error
100+ dir , err = os .Getwd ()
101+ if err != nil {
102+ return nil , fmt .Errorf ("failed to get current directory: %w" , err )
103+ }
104+ }
105+
106+ var files []string
107+ err := filepath .WalkDir (dir , func (path string , d fs.DirEntry , err error ) error {
108+ if err != nil {
109+ return err
110+ }
111+
112+ // Skip directories, test files, and non-Go files
113+ if d .IsDir () ||
114+ strings .HasSuffix (d .Name (), "_test.go" ) ||
115+ ! strings .HasSuffix (d .Name (), ".go" ) ||
116+ strings .HasPrefix (d .Name (), "." ) {
117+ return nil
118+ }
119+
120+ // Check if file contains //go:adapter directive
121+ hasAdapter , err := hasAdapterDirective (path )
122+ if err != nil {
123+ slog .Warn ("Failed to check adapter directive" , "file" , path , "error" , err )
124+ return nil
125+ }
126+
127+ if hasAdapter {
128+ files = append (files , path )
129+ }
130+
131+ return nil
132+ })
133+
134+ if err != nil {
135+ return nil , fmt .Errorf ("error walking directory %s: %w" , dir , err )
136+ }
137+
138+ return files , nil
139+ }
140+
14141func main () {
15- configFile := flag .String ("f " , "" , "Configuration file (YAML/JSON). If specified, it completely replaces adptool.yaml." )
142+ configFile := flag .String ("c " , "" , "Configuration file (YAML/JSON). If specified, it completely replaces adptool.yaml." )
16143 flag .Parse ()
17144
18- // Get the input Go file from command line arguments
145+ // Get the input path from command line arguments
19146 args := flag .Args ()
20147 if len (args ) == 0 {
21- slog .Error ("No input Go file specified" )
148+ slog .Error ("No input path specified" )
22149 os .Exit (1 )
23150 }
24151
25- inputFile := args [0 ]
152+ inputPath := args [0 ]
26153
27- // Get absolute path to the input file
28- abspath , err := filepath .Abs (inputFile )
154+ // Get absolute path to the input path
155+ abspath , err := filepath .Abs (inputPath )
29156 if err != nil {
30157 slog .Error ("Failed to get absolute path" , "error" , err )
31158 os .Exit (1 )
@@ -41,16 +168,53 @@ func main() {
41168 slog .Error ("Failed to load config file" , "file" , * configFile , "error" , err )
42169 os .Exit (1 )
43170 }
44- // Merge the loaded config with defaults
171+ // Use the loaded config
45172 cfg = fileCfg
46173 }
47174
48- // Create and use the new engine
49- e := engine . New ( )
50- if err := e . ExecuteFile ( abspath , cfg ); err != nil {
51- slog .Error ("Failed to execute engine" , "error" , err )
175+ // Check if the input is a directory or a file
176+ fileInfo , err := os . Stat ( abspath )
177+ if err != nil {
178+ slog .Error ("Failed to get file info" , "path" , abspath , "error" , err )
52179 os .Exit (1 )
53180 }
54181
55- slog .Info ("Successfully generated adapter file" , "path" , abspath )
182+ var filesToProcess []string
183+
184+ if fileInfo .IsDir () {
185+ // If it's a directory, find all .go files
186+ files , err := findGoFiles (abspath )
187+ if err != nil {
188+ slog .Error ("Failed to find Go files in directory" , "directory" , abspath , "error" , err )
189+ os .Exit (1 )
190+ }
191+
192+ if len (files ) == 0 {
193+ slog .Info ("No Go files found in directory" , "directory" , abspath )
194+ return
195+ }
196+
197+ filesToProcess = files
198+ } else {
199+ // If it's a single file, just process that file
200+ if ! strings .HasSuffix (abspath , ".go" ) {
201+ slog .Error ("Input file is not a Go file" , "file" , abspath )
202+ os .Exit (1 )
203+ }
204+ filesToProcess = []string {abspath }
205+ }
206+
207+ // Process each file
208+ var hasErrors bool
209+ for _ , file := range filesToProcess {
210+ if err := processFile (file , cfg ); err != nil {
211+ slog .Error ("Error processing file" , "file" , file , "error" , err )
212+ hasErrors = true
213+ }
214+ }
215+
216+ if hasErrors {
217+ slog .Error ("Failed to process some files" )
218+ os .Exit (1 )
219+ }
56220}
0 commit comments