feat: support combine multi import decl (wip)

copy from goimports-reviser
main
sudo pacman -Syu 2022-11-26 17:00:15 +07:00
parent 8edb24314f
commit 1889ddb517
No known key found for this signature in database
GPG Key ID: D6CB5C6C567C47B0
1 changed files with 56 additions and 28 deletions

View File

@ -65,7 +65,7 @@ func NewFormmater(opts ...FormatterOptionFn) (*Formatter, error) {
for _, stdPackage := range stdPackages { for _, stdPackage := range stdPackages {
ft.stdPackages[stdPackage.PkgPath] = struct{}{} ft.stdPackages[stdPackage.PkgPath] = struct{}{}
} }
ft.log("stdPackages: %+v\n", ft.stdPackages) ft.log("NewFormmater: stdPackages: %+v\n", ft.stdPackages)
ft.moduleNames = make(map[string]string) ft.moduleNames = make(map[string]string)
ft.formattedPaths = make(map[string]struct{}) ft.formattedPaths = make(map[string]struct{})
@ -133,7 +133,7 @@ func (ft *Formatter) formatFile(path string) error {
} }
// Parse imports // Parse imports
importsAST, err := ft.parseImports(pathASTFile) importsAST, err := ft.parseImportsAndCombine(pathASTFile)
if err != nil { if err != nil {
return err return err
} }
@ -142,19 +142,19 @@ func (ft *Formatter) formatFile(path string) error {
if len(importsAST) == 0 { if len(importsAST) == 0 {
return nil return nil
} }
ft.log("importsAST: %+v\n", importsAST) ft.log("formatFile: importsAST: %+v\n", importsAST)
moduleName, err := ft.moduleName(path) moduleName, err := ft.moduleName(path)
if err != nil { if err != nil {
return err return err
} }
ft.log("moduleName: %+v\n", moduleName) ft.log("formatFile: moduleName: %+v\n", moduleName)
groupImports, err := ft.groupImports(importsAST, moduleName) groupImports, err := ft.groupImports(importsAST, moduleName)
if err != nil { if err != nil {
return err return err
} }
ft.log("groupImports: %+v\n", groupImports) ft.log("formatFile: groupImports: %+v\n", groupImports)
ft.muFormattedPaths.Lock() ft.muFormattedPaths.Lock()
ft.formattedPaths[path] = struct{}{} ft.formattedPaths[path] = struct{}{}
@ -183,38 +183,66 @@ func (ft *Formatter) wrapParseAST(path string, pathBytes []byte) (*ast.File, err
} }
// Copy from goimports-reviser // Copy from goimports-reviser
func (ft *Formatter) parseImports(pathASTFile *ast.File) (map[string]*ast.ImportSpec, error) { // If exist multi import, combine them into one
// This func will edit pathASTFile directly to combine
func (ft *Formatter) parseImportsAndCombine(pathASTFile *ast.File) (map[string]*ast.ImportSpec, error) {
result := make(map[string]*ast.ImportSpec) result := make(map[string]*ast.ImportSpec)
// Extract imports
importSpecs := make([]ast.Spec, 0, len(pathASTFile.Imports))
for _, importSpec := range pathASTFile.Imports {
ft.log("parseImportsAndCombine: importSpec: %+v %+v\n", importSpec.Name.String(), importSpec.Path.Value)
importSpecs = append(importSpecs, importSpec)
var importNameAndPath string
if importSpec.Name != nil {
// Handle alias import
// xyz "github.com/abc/xyz/123"
importNameAndPath = importSpec.Name.String() + " " + importSpec.Path.Value
} else {
// Handle normal import
// "github.com/abc/xyz"
importNameAndPath = importSpec.Path.Value
}
result[importNameAndPath] = importSpec
}
// Combine multi import decl
isMultiImportDecl := false
isExistFirstImportDecl := false
decls := make([]ast.Decl, 0, len(pathASTFile.Decls))
for _, decl := range pathASTFile.Decls { for _, decl := range pathASTFile.Decls {
genDecl, ok := decl.(*ast.GenDecl) genDecl, ok := decl.(*ast.GenDecl)
if !ok { if !ok {
decls = append(decls, decl)
continue continue
} }
if genDecl.Tok != token.IMPORT { if genDecl.Tok != token.IMPORT {
decls = append(decls, decl)
continue continue
} }
for _, spec := range genDecl.Specs { if isExistFirstImportDecl {
importSpec, ok := spec.(*ast.ImportSpec) isMultiImportDecl = true
if !ok { // TODO: explain this
continue storedGenDecl := decls[len(decls)-1].(*ast.GenDecl)
if storedGenDecl.Tok == token.IMPORT {
storedGenDecl.Rparen = genDecl.End()
} }
continue
var importNameAndPath string
if importSpec.Name != nil {
// Handle alias import
// xyz "github.com/abc/xyz/123"
importNameAndPath = importSpec.Name.String() + " " + importSpec.Path.Value
} else {
// Handle normal import
// "github.com/abc/xyz"
importNameAndPath = importSpec.Path.Value
}
result[importNameAndPath] = importSpec
} }
// First import decl take all
isExistFirstImportDecl = true
genDecl.Specs = importSpecs
decls = append(decls, genDecl)
}
ft.log("parseImportsAndCombine: decls: %+v\n", decls)
if isMultiImportDecl {
pathASTFile.Decls = decls
} }
return result, nil return result, nil
@ -257,12 +285,12 @@ func (ft *Formatter) groupImports(
result[thirdPartyImport] = append(result[thirdPartyImport], importNameAndPath) result[thirdPartyImport] = append(result[thirdPartyImport], importNameAndPath)
} }
ft.log("std %+v\n", result[stdImport]) ft.log("groupImports: std: %+v\n", result[stdImport])
ft.log("third-party %+v\n", result[thirdPartyImport]) ft.log("groupImports: third-party: %+v\n", result[thirdPartyImport])
if ft.companyPrefix != "" { if ft.companyPrefix != "" {
ft.log("company %+v\n", result[companyImport]) ft.log("groupImports: company: %+v\n", result[companyImport])
} }
ft.log("local %+v\n", result[localImport]) ft.log("groupImports: local: %+v\n", result[localImport])
// TODO: not sure if this match gofumpt output, but at lease it is sorted // TODO: not sure if this match gofumpt output, but at lease it is sorted
sort.Strings(result[stdImport]) sort.Strings(result[stdImport])
@ -308,7 +336,7 @@ func (ft *Formatter) moduleName(path string) (string, error) {
if goModPath == "" { if goModPath == "" {
return "", ErrGoModNotExist return "", ErrGoModNotExist
} }
ft.log("goModPath: %+v\n", goModPath) ft.log("moduleName: goModPath: %+v\n", goModPath)
goModPathBytes, err := os.ReadFile(goModPath) goModPathBytes, err := os.ReadFile(goModPath)
if err != nil { if err != nil {