11package main
22
33import (
4+ "bytes"
45 "dissect/pkg/commands"
56 "dissect/pkg/gopls"
67 "dissect/pkg/goutils"
78 "fmt"
89 "go/ast"
10+ "go/printer"
911 "log/slog"
1012 "os"
1113 "path/filepath"
@@ -156,18 +158,12 @@ func moveIdentifier(sourceFile string, identifier string, targetFile string, mod
156158 // Remove the temp file when done
157159 defer os .Remove (tempFile )
158160
159- // Parse the temp file to extract the function declaration and imports using AST
160- _ , tempNode , err := goutils .ReadGoFile (tempFile )
161+ // Parse the temp file to extract the function (with comments preserved by gopls)
162+ tempFset , tempNode , err := goutils .ReadGoFile (tempFile )
161163 if err != nil {
162164 return fmt .Errorf ("error parsing temp file: %w" , err )
163165 }
164166
165- // Parse the target file
166- targetFset , targetNode , err := goutils .ReadGoFile (targetFile )
167- if err != nil {
168- return fmt .Errorf ("error parsing target file: %w" , err )
169- }
170-
171167 // Find the function in the temp file
172168 var funcToMove * ast.FuncDecl
173169 for _ , decl := range tempNode .Decls {
@@ -180,28 +176,55 @@ func moveIdentifier(sourceFile string, identifier string, targetFile string, mod
180176 if funcToMove == nil {
181177 return fmt .Errorf ("no function found in temp file" )
182178 }
179+
180+ // Extract imports from temp file for later merging
181+ var tempImports []* ast.ImportSpec
182+ for _ , imp := range tempNode .Imports {
183+ tempImports = append (tempImports , imp )
184+ }
183185
184- // Merge imports from temp file to target file
185- // Build a map of existing imports in target
186+ // Serialize just the function declaration (not a whole file) using printer
187+ // This gives us the function with its Doc comments as source text
188+ var funcBuf bytes.Buffer
189+ cfg := printer.Config {Mode : printer .UseSpaces | printer .TabIndent , Tabwidth : 8 }
190+ if err := cfg .Fprint (& funcBuf , tempFset , funcToMove ); err != nil {
191+ return fmt .Errorf ("error serializing function: %w" , err )
192+ }
193+
194+ // Read the current target file content
195+ targetContent , err := os .ReadFile (targetFile )
196+ if err != nil {
197+ return fmt .Errorf ("error reading target file: %w" , err )
198+ }
199+
200+ // Append the serialized function to the target file
201+ // printer.Fprint on a FuncDecl includes the Doc comments automatically
202+ newContent := string (targetContent ) + "\n " + funcBuf .String () + "\n "
203+ if err := os .WriteFile (targetFile , []byte (newContent ), 0644 ); err != nil {
204+ return fmt .Errorf ("error writing target file: %w" , err )
205+ }
206+
207+ // Now reparse the entire target file to get a proper AST
208+ targetFset , targetNode , err := goutils .ReadGoFile (targetFile )
209+ if err != nil {
210+ return fmt .Errorf ("error reparsing target file: %w" , err )
211+ }
212+
213+ // Merge imports from temp file using AST operations
186214 existingImports := make (map [string ]bool )
187215 for _ , imp := range targetNode .Imports {
188216 existingImports [imp .Path .Value ] = true
189217 }
190-
191- // Add new imports from temp file
192- for _ , imp := range tempNode .Imports {
218+
219+ for _ , imp := range tempImports {
193220 if ! existingImports [imp .Path .Value ] {
194221 targetNode .Imports = append (targetNode .Imports , imp )
195222 }
196223 }
197-
198- // Add the function declaration to the target file
199- targetNode .Decls = append (targetNode .Decls , funcToMove )
200-
201- // Write the modified target file back using AST
202- err = goutils .WriteGoFile (targetFile , targetFset , targetNode )
203- if err != nil {
204- return fmt .Errorf ("error writing target file: %w" , err )
224+
225+ // Write back the target file with merged imports
226+ if err := goutils .WriteGoFile (targetFile , targetFset , targetNode ); err != nil {
227+ return fmt .Errorf ("error writing target file with imports: %w" , err )
205228 }
206229
207230 // Run goimports to organize imports and format properly
0 commit comments