@@ -27,12 +27,14 @@ import (
2727 "strconv"
2828 "strings"
2929
30+ "github.com/cloudwego/abcoder/src/lang/utils"
3031 "github.com/cloudwego/abcoder/src/uniast"
3132)
3233
3334var _ uniast.Writer = (* Writer )(nil )
3435
3536type Options struct {
37+ RepoDir string
3638 OutDir string
3739 GoVersion string
3840}
@@ -44,7 +46,7 @@ type Writer struct {
4446
4547type fileNode struct {
4648 chunks []chunk
47- impts []string
49+ impts []uniast. Import
4850}
4951
5052type chunk struct {
@@ -101,19 +103,13 @@ func (w *Writer) WriteModule(repo *uniast.Repository, modPath string) error {
101103 }
102104 sb .WriteString ("\n \n " )
103105
104- var fimpts []string
106+ var fimpts []uniast. Import
105107 if fi , ok := mod .Files [filepath .Join (mod .Dir , rel , fpath )]; ok && fi .Imports != nil {
106108 fimpts = fi .Imports
107109 }
108- impts := w . mergeImports (fimpts , f .impts )
110+ impts := mergeImports (fimpts , f .impts )
109111 if len (impts ) > 0 {
110- sb .WriteString ("import (\n " )
111- for _ , v := range impts {
112- sb .WriteString ("\t " )
113- sb .WriteString (v )
114- sb .WriteString ("\n " )
115- }
116- sb .WriteString (")\n \n " )
112+ writeImport (& sb , impts )
117113 }
118114
119115 sort .SliceStable (f .chunks , func (i , j int ) bool {
@@ -208,15 +204,15 @@ func (w *Writer) appendNode(node *uniast.Node, pkg string, isMain bool, file str
208204 if fs == nil {
209205 fs = & fileNode {
210206 chunks : make ([]chunk , 0 , len (node .Dependencies )),
211- impts : make ([]string , 0 , len (node .Dependencies )),
207+ impts : make ([]uniast. Import , 0 , len (node .Dependencies )),
212208 }
213209 p [fpath ] = fs
214210 }
215211 for _ , v := range node .Dependencies {
216212 if v .Target .PkgPath == "" || v .Target .PkgPath == pkg {
217213 continue
218214 }
219- fs .impts = append (fs .impts , strconv .Quote (v .Target .PkgPath ))
215+ fs .impts = append (fs .impts , uniast. Import { Path : strconv .Quote (v .Target .PkgPath )} )
220216 }
221217
222218 // 检查是否有imports
@@ -235,19 +231,19 @@ func (w *Writer) appendNode(node *uniast.Node, pkg string, isMain bool, file str
235231}
236232
237233// receive a piece of golang code, parse it and splits the imports and codes
238- func (w Writer ) SplitImportsAndCodes (src string ) (codes string , imports []string , err error ) {
234+ func (w Writer ) SplitImportsAndCodes (src string ) (codes string , imports []uniast. Import , err error ) {
239235 fset := token .NewFileSet ()
240236 f , err := parser .ParseFile (fset , "" , src , parser .SkipObjectResolution )
241237 if err != nil {
242238 // NOTICE: if parse failed, just return the src
243239 return src , nil , nil
244240 }
245241 for _ , imp := range f .Imports {
246- var impt = imp . Path . Value
242+ var alias string
247243 if imp .Name != nil {
248- impt = fmt . Sprintf ( "%s %s" , imp .Name .Name , impt )
244+ alias = imp .Name .Name
249245 }
250- imports = append (imports , impt )
246+ imports = append (imports , uniast. Import { Path : imp . Path . Value , Alias : & alias } )
251247 }
252248 start := 0
253249 for _ , s := range f .Decls {
@@ -260,42 +256,58 @@ func (w Writer) SplitImportsAndCodes(src string) (codes string, imports []string
260256 return src [start :], imports , nil
261257}
262258
263- func (w * Writer ) IdToImport (id uniast.Identity ) (string , error ) {
264- return strconv .Quote (id .PkgPath ), nil
259+ func (w * Writer ) IdToImport (id uniast.Identity ) (uniast. Import , error ) {
260+ return uniast. Import { Path : strconv .Quote (id .PkgPath )} , nil
265261}
266262
267- // merge the imports of file and nodes, and return the merged imports
268- // file is in priority (because it contains alias)
269- func (w * Writer ) mergeImports (priors []string , subs []string ) (ret []string ) {
270- visited := make (map [string ]bool , len (priors )+ len (subs ))
271- ret = make ([]string , 0 , len (priors )+ len (subs ))
272- for _ , v := range priors {
273- sp := strings .Split (v , " " )
274- var impt = sp [0 ]
275- if len (sp ) >= 2 {
276- impt = sp [1 ]
263+ func (p * Writer ) PatchImports (file * uniast.File ) ([]byte , error ) {
264+ bs , err := os .ReadFile (filepath .Join (p .Options .RepoDir , file .Path ))
265+ if err != nil {
266+ return nil , utils .WrapError (err , "fail read file %s" , file .Path )
267+ }
268+
269+ fs := token .NewFileSet ()
270+ f , err := parser .ParseFile (fs , file .Path , bs , parser .ImportsOnly )
271+ if err != nil {
272+ return nil , utils .WrapError (err , "fail parse file %s" , file .Path )
273+ }
274+
275+ old := make ([]uniast.Import , 0 , len (f .Imports ))
276+ for _ , imp := range f .Imports {
277+ i := uniast.Import {
278+ Path : imp .Path .Value ,
277279 }
278- key , _ := strconv .Unquote (impt )
279- if visited [key ] {
280- continue
281- } else {
282- visited [key ] = true
283- ret = append (ret , v )
280+ if imp .Name != nil {
281+ tmp := imp .Name .Name
282+ i .Alias = & tmp
284283 }
284+ old = append (old , i )
285+ }
286+
287+ impts := mergeImports (old , file .Imports )
288+ if len (impts ) == len (old ) {
289+ return bs , nil
285290 }
286- for _ , v := range subs {
287- sp := strings .Split (v , " " )
288- var impt = sp [0 ]
289- if len (sp ) >= 2 {
290- impt = sp [1 ]
291+
292+ var sb strings.Builder
293+ writeImport (& sb , impts )
294+ final := sb .String ()
295+
296+ imptStart := fs .Position (f .Name .End ()).Offset + 1
297+ if len (f .Imports ) > 0 {
298+ for imptStart < len (bs ) && bs [imptStart ] != 'i' {
299+ imptStart ++
291300 }
292- key , _ := strconv . Unquote ( impt )
293- if visited [ key ] {
294- continue
295- } else {
296- visited [ key ] = true
297- ret = append ( ret , v )
301+ }
302+ imptEnd := imptStart
303+ if len ( f . Imports ) > 1 {
304+ imptEnd = fs . Position ( f . Imports [ len ( f . Imports ) - 1 ]. End ()). Offset
305+ for len ( old ) > 1 && imptEnd < len ( bs ) && ( bs [ imptEnd ] != ')' ) {
306+ imptEnd ++
298307 }
308+ imptEnd += 2 // for `)`
299309 }
300- return
310+ r1 := append (bs [:imptStart :imptStart ], final ... )
311+ ret := append (r1 , bs [imptEnd :]... )
312+ return ret , nil
301313}
0 commit comments