github.com/JarrahG/buffalocli@v0.0.0-20230801092127-b85bfd5d395a/internal/genny/fix/imports.go (about)

     1  package fix
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"go/ast"
     7  	"go/parser"
     8  	"go/printer"
     9  	"go/token"
    10  	"os"
    11  	"path/filepath"
    12  	"strconv"
    13  
    14  	"github.com/gobuffalo/genny/v2"
    15  	"golang.org/x/tools/go/ast/astutil"
    16  )
    17  
    18  var replace = map[string]string{
    19  	"github.com/gobuffalo/buffalo-plugins":          "github.com/JarrahG/buffalocli/internal/plugins",
    20  	"github.com/gobuffalo/buffalo-pop/":             "github.com/gobuffalo/buffalo-pop/v3",
    21  	"github.com/gobuffalo/buffalo-pop/v2/":          "github.com/gobuffalo/buffalo-pop/v3",
    22  	"github.com/gobuffalo/buffalo-pop/pop/popmw":    "github.com/gobuffalo/buffalo-pop/v3/pop/popmw",
    23  	"github.com/gobuffalo/buffalo-pop/v2/pop/popmw": "github.com/gobuffalo/buffalo-pop/v3/pop/popmw",
    24  	"github.com/gobuffalo/genny":                    "github.com/gobuffalo/genny/v2",
    25  	"github.com/gobuffalo/mw-contenttype":           "github.com/gobuffalo/middleware/contenttype",
    26  	"github.com/gobuffalo/mw-csrf":                  "github.com/gobuffalo/middleware/csrf",
    27  	"github.com/gobuffalo/mw-forcessl":              "github.com/gobuffalo/middleware/forcessl",
    28  	"github.com/gobuffalo/mw-i18n":                  "github.com/gobuffalo/middleware/i18n",
    29  	"github.com/gobuffalo/mw-i18n/v2":               "github.com/gobuffalo/middleware/i18n",
    30  	"github.com/gobuffalo/mw-paramlogger":           "github.com/gobuffalo/middleware/paramlogger",
    31  	"github.com/gobuffalo/packr/v2":                 "",
    32  	"github.com/gobuffalo/plush":                    "github.com/gobuffalo/plush/v4",
    33  	"github.com/gobuffalo/pop":                      "github.com/gobuffalo/pop/v6",
    34  	"github.com/gobuffalo/pop/v5":                   "github.com/gobuffalo/pop/v6",
    35  	"github.com/gobuffalo/pop/nulls":                "github.com/gobuffalo/nulls",
    36  	"github.com/gobuffalo/suite":                    "github.com/gobuffalo/suite/v4",
    37  	"github.com/gobuffalo/uuid":                     "github.com/gofrs/uuid",
    38  	"github.com/gobuffalo/validate":                 "github.com/gobuffalo/validate/v3",
    39  	"github.com/gobuffalo/validate/validators":      "github.com/gobuffalo/validate/v3/validators",
    40  	"github.com/markbates/grift":                    "github.com/gobuffalo/grift",
    41  	"github.com/markbates/grift/grift":              "github.com/gobuffalo/grift/grift",
    42  	"github.com/markbates/pop":                      "github.com/gobuffalo/pop/v6",
    43  	"github.com/markbates/refresh":                  "github.com/gobuffalo/refresh",
    44  	"github.com/markbates/validate":                 "github.com/gobuffalo/validate/v3",
    45  	"github.com/markbates/willie":                   "github.com/gobuffalo/httptest",
    46  	"github.com/satori/go.uuid":                     "github.com/gofrs/uuid",
    47  	"github.com/shurcooL/github_flavored_markdown":  "github.com/gobuffalo/github_flavored_markdown",
    48  }
    49  
    50  // RewriteImports walks all the .go files in an application
    51  // It will then attempt to convert any old import paths to any new import paths
    52  // used by this version Buffalo.
    53  func RewriteImports(opts *Options) genny.RunFn {
    54  	return func(r *genny.Runner) error {
    55  		fmt.Println("~~~ Rewriting Imports ~~~")
    56  		return walkDisk(r.Disk, ".", func(path string, info os.FileInfo, err error) error {
    57  			if err != nil {
    58  				return err
    59  			}
    60  
    61  			if info.IsDir() {
    62  				return nil
    63  			}
    64  
    65  			if filepath.Ext(path) != ".go" {
    66  				return nil
    67  			}
    68  
    69  			f, err := r.FindFile(path)
    70  			if err != nil {
    71  				return err
    72  			}
    73  			if err := rewriteImports(f); err != nil {
    74  				return err
    75  			}
    76  			return r.File(f)
    77  		})
    78  	}
    79  }
    80  
    81  func rewriteImports(file genny.File) error {
    82  	fset := token.NewFileSet()
    83  	f, err := parser.ParseFile(fset, file.Name(), file.String(), parser.ParseComments)
    84  	if err != nil {
    85  		return err
    86  	}
    87  
    88  	names := make(map[string]string)
    89  	for _, imports := range astutil.Imports(fset, f) {
    90  		for _, imp := range imports {
    91  			i, err := strconv.Unquote(imp.Path.Value)
    92  			if err != nil {
    93  				return err
    94  			}
    95  			if imp.Name != nil {
    96  				names[i] = imp.Name.Name
    97  			} else {
    98  				names[i] = ""
    99  			}
   100  		}
   101  	}
   102  
   103  	changed := false
   104  	for key, value := range replace {
   105  		name, ok := names[key]
   106  		if !ok {
   107  			continue
   108  		}
   109  
   110  		astutil.DeleteNamedImport(fset, f, name, key)
   111  		if value != "" {
   112  			astutil.AddNamedImport(fset, f, names[key], value)
   113  		}
   114  
   115  		changed = true
   116  	}
   117  
   118  	// if no change occurred, then we don't need to write to disk, just return.
   119  	if !changed {
   120  		return nil
   121  	}
   122  
   123  	// since the imports changed, resort them.
   124  	ast.SortImports(fset, f)
   125  
   126  	bb := &bytes.Buffer{}
   127  	if err := printer.Fprint(bb, fset, f); err != nil {
   128  		return err
   129  	}
   130  
   131  	_, err = file.Write(bb.Bytes())
   132  	return err
   133  }