Skip to content

Commit

Permalink
Add a new import group called "named" which groups aliased imports (i…
Browse files Browse the repository at this point in the history
…nternal and external)
  • Loading branch information
ustun-ed committed Aug 8, 2023
1 parent 390547f commit dfe24b3
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 38 deletions.
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@
![GitHub release (latest by date)](https://img.shields.io/github/v/release/incu6us/goimports-reviser?color=green)
[![goimports-reviser](https://snapcraft.io//goimports-reviser/badge.svg)](https://snapcraft.io/goimports-reviser)
![license](https://img.shields.io/github/license/incu6us/goimports-reviser)
[![Mentioned in Awesome Go](https://awesome.re/mentioned-badge.svg)](https://github.com/avelino/awesome-go)
[![Mentioned in Awesome Go](https://awesome.re/mentioned-badge.svg)](https://github.com/avelino/awesome-go)

<a href="https://www.buymeacoffee.com/slavka" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 60px !important;width: 217px !important;"></a>

!['logo'](./images/reviser-muscot_200.png)


Tool for Golang to sort goimports by 3-4 groups(with own [linter](linter/README.md)): std, general, company(which is optional) and project dependencies.
Also, formatting for your code will be prepared(so, you don't need to use `gofmt` or `goimports` separately).
Also, formatting for your code will be prepared(so, you don't need to use `gofmt` or `goimports` separately).
Use additional options `-rm-unused` to remove unused imports and `-set-alias` to rewrite import aliases for versioned packages or for packages with additional prefix/suffix(example: `opentracing "github.com/opentracing/opentracing-go"`).
`-company-prefixes` - will create group for company imports(libs inside your organization). Values should be comma-separated.

Expand Down Expand Up @@ -60,12 +60,12 @@ Usage of goimports-reviser:
-format
Option will perform additional formatting. Optional parameter.
-imports-order string
Your imports groups can be sorted in your way.
std - std import group;
general - libs for general purpose;
company - inter-org or your company libs(if you set '-company-prefixes'-option, then 4th group will be split separately. In other case, it will be the part of general purpose libs);
project - your local project dependencies.
Optional parameter. (default "std,general,company,project")
Your imports groups can be sorted in your way.
std - std import group;
general - libs for general purpose;
company - inter-org or your company libs(if you set '-company-prefixes'-option, then 4th group will be split separately. In other case, it will be the part of general purpose libs);
project - your local project dependencies.
Optional parameter. (default "std,general,company,named,project")
-list-diff
Option will list files whose formatting differs from goimports-reviser. Optional parameter.
-output string
Expand Down Expand Up @@ -115,7 +115,7 @@ import (

"golang.org/x/exp/slices"
)
```
```

After usage:
```go
Expand All @@ -138,7 +138,7 @@ package testdata
import (
"fmt" // comments to the package here
)
```
```

### Example with `-company-prefixes`-option

Expand Down
13 changes: 7 additions & 6 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,12 +100,13 @@ func init() {
flag.StringVar(
&importsOrder,
importsOrderArg,
"std,general,company,project",
`Your imports groups can be sorted in your way.
std - std import group;
general - libs for general purpose;
company - inter-org or your company libs(if you set '-company-prefixes'-option, then 4th group will be split separately. In other case, it will be the part of general purpose libs);
project - your local project dependencies.
"std,general,company,project,named",
`Your imports groups can be sorted in your way.
std - std import group;
general - libs for general purpose;
named - named imports (aliased libs);
company - inter-org or your company libs(if you set '-company-prefixes'-option, then 4th group will be split separately. In other case, it will be the part of general purpose libs);
project - your local project dependencies.
Optional parameter.`,
)

Expand Down
48 changes: 39 additions & 9 deletions reviser/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ func (f *SourceFile) Fix(options ...SourceFileOption) ([]byte, bool, error) {
return nil, false, err
}

stdImports, generalImports, projectLocalPkgs, projectImports := groupImports(
stdImports, generalImports, namedImports, projectLocalPkgs, projectImports := groupImports(
f.projectName,
f.companyPackagePrefixes,
importsWithMetadata,
Expand All @@ -96,7 +96,7 @@ func (f *SourceFile) Fix(options ...SourceFileOption) ([]byte, bool, error) {
pf.Decls = decls
}

f.fixImports(pf, stdImports, generalImports, projectLocalPkgs, projectImports, importsWithMetadata)
f.fixImports(pf, stdImports, generalImports, namedImports, projectLocalPkgs, projectImports, importsWithMetadata)

f.formatDecls(pf)

Expand Down Expand Up @@ -161,15 +161,22 @@ func groupImports(
projectName string,
localPkgPrefixes []string,
importsWithMetadata map[string]*commentsMetadata,
) ([]string, []string, []string, []string) {
) ([]string, []string, []string, []string, []string) {
var (
stdImports []string
projectImports []string
projectLocalPkgs []string
namedImports []string
generalImports []string
)

for imprt := range importsWithMetadata {
values := strings.Split(imprt, " ")
if len(values) > 1 {
namedImports = append(namedImports, imprt)
continue
}

pkgWithoutAlias := skipPackageAlias(imprt)

if _, ok := std.StdPackages[pkgWithoutAlias]; ok {
Expand All @@ -179,7 +186,9 @@ func groupImports(

var isLocalPackageFound bool
for _, localPackagePrefix := range localPkgPrefixes {
if strings.HasPrefix(pkgWithoutAlias, localPackagePrefix) && !strings.HasPrefix(pkgWithoutAlias, projectName) {
fmt.Printf("pkgWithoutAlias: %s localPackagePrefix: %s\n", pkgWithoutAlias, localPackagePrefix)
if strings.HasPrefix(pkgWithoutAlias, localPackagePrefix) { // && !strings.HasPrefix(pkgWithoutAlias, projectName) {
fmt.Printf("local package found: %s\n", imprt)
projectLocalPkgs = append(projectLocalPkgs, imprt)
isLocalPackageFound = true
break
Expand All @@ -200,10 +209,11 @@ func groupImports(

sort.Strings(stdImports)
sort.Strings(generalImports)
sort.Strings(namedImports)
sort.Strings(projectLocalPkgs)
sort.Strings(projectImports)

return stdImports, generalImports, projectLocalPkgs, projectImports
return stdImports, generalImports, namedImports, projectLocalPkgs, projectImports
}

func skipPackageAlias(pkg string) string {
Expand Down Expand Up @@ -237,7 +247,7 @@ func isSingleCgoImport(dd *ast.GenDecl) bool {

func (f *SourceFile) fixImports(
file *ast.File,
stdImports, generalImports, projectLocalPkgs, projectImports []string,
stdImports, generalImports, namedImports, projectLocalPkgs, projectImports []string,
commentsMetadata map[string]*commentsMetadata,
) {
var importsPositions []*importPosition
Expand All @@ -258,8 +268,9 @@ func (f *SourceFile) fixImports(
},
)

one, two, three, four := f.importsOrders.sortImportsByOrder(stdImports, generalImports, projectLocalPkgs, projectImports)
dd.Specs = rebuildImports(dd.Tok, commentsMetadata, one, two, three, four)
fmt.Printf("named: %v\n", namedImports)
one, two, three, four, five := f.importsOrders.sortImportsByOrder(stdImports, generalImports, namedImports, projectLocalPkgs, projectImports)
dd.Specs = rebuildImports(dd.Tok, commentsMetadata, one, two, three, four, five)
}

clearImportDocs(file, importsPositions)
Expand All @@ -275,8 +286,10 @@ func (f *SourceFile) fixImports(
// to
// -----
// import (
// "fmt"
//
// "fmt"
// "io"
//
// )
func hasMultipleImportDecls(f *ast.File) ([]ast.Decl, bool) {
importSpecs := make([]ast.Spec, 0, len(f.Imports))
Expand Down Expand Up @@ -356,6 +369,7 @@ func rebuildImports(
secondImportsGroup []string,
thirdImportsGroup []string,
fourthImportGroup []string,
fifthImportGroup []string,
) []ast.Spec {
var specs []ast.Spec

Expand Down Expand Up @@ -407,11 +421,27 @@ func rebuildImports(
}
}

linesCounter = len(fourthImportGroup)
for _, imprt := range fourthImportGroup {
spec := &ast.ImportSpec{
Path: &ast.BasicLit{Value: importWithComment(imprt, commentsMetadata), Kind: tok},
}
specs = append(specs, spec)

linesCounter--

if linesCounter == 0 && len(fourthImportGroup) > 0 {
spec = &ast.ImportSpec{Path: &ast.BasicLit{Value: "", Kind: token.STRING}}

specs = append(specs, spec)
}
}

for _, imprt := range fifthImportGroup {
spec := &ast.ImportSpec{
Path: &ast.BasicLit{Value: importWithComment(imprt, commentsMetadata), Kind: tok},
}
specs = append(specs, spec)
}

return specs
Expand Down
2 changes: 1 addition & 1 deletion reviser/file_option.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func WithCompanyPackagePrefixes(s string) SourceFileOption {
}
}

// WithImportsOrder will sort by needed order. Default order is "std,general,company,project"
// WithImportsOrder will sort by needed order. Default order is "std,general,company,project,named"
func WithImportsOrder(orders []ImportsOrder) SourceFileOption {
return func(f *SourceFile) error {
f.importsOrders = orders
Expand Down
8 changes: 4 additions & 4 deletions reviser/file_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ import (
projectName: "github.com/incu6us/goimports-reviser",
filePath: "./testdata/example.go",
fileContent: `package testdata
import (
"log"
Expand Down Expand Up @@ -367,7 +367,7 @@ import (
import (
"github.com/incu6us/goimports-reviser/testdata/innderpkg" // test1
"fmt" //test2
// this should be skipped
)
Expand Down Expand Up @@ -640,11 +640,11 @@ import (
wantErr: false,
},
{
name: "success std,general,company,project",
name: "success std,general,company,project,named",
args: args{
projectName: "github.com/incu6us/goimports-reviser",
filePath: "./testdata/example.go",
importsOrder: "std,general,company,project",
importsOrder: "std,general,company,named,project",
fileContent: `package testdata
import (
Expand Down
23 changes: 15 additions & 8 deletions reviser/import_order.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,16 @@ const (
StdImportsOrder ImportsOrder = "std"
// CompanyImportsOrder is packages that belong to the same organization
CompanyImportsOrder ImportsOrder = "company"
// NamedImportsOrder is packages that are inside the current project
NamedImportsOrder ImportsOrder = "named"
// ProjectImportsOrder is packages that are inside the current project
ProjectImportsOrder ImportsOrder = "project"
// GeneralImportsOrder is packages that are outside. In other words it is general purpose libraries
GeneralImportsOrder ImportsOrder = "general"
)

const (
defaultImportsOrder = "std,general,company,project"
defaultImportsOrder = "std,general,company,named,project"
)

// ImportsOrders alias to []ImportsOrder
Expand All @@ -29,11 +31,12 @@ type ImportsOrders []ImportsOrder
func (o ImportsOrders) sortImportsByOrder(
std []string,
general []string,
named []string,
company []string,
project []string,
) ([]string, []string, []string, []string) {
) ([]string, []string, []string, []string, []string) {
if len(o) == 0 {
return std, general, company, project
return std, general, named, company, project
}

var result [][]string
Expand All @@ -46,33 +49,37 @@ func (o ImportsOrders) sortImportsByOrder(
imports = general
case CompanyImportsOrder:
imports = company
case NamedImportsOrder:
imports = named
case ProjectImportsOrder:
imports = project
}

fmt.Printf("%v %v\n", group, imports)

result = append(result, imports)
}

return result[0], result[1], result[2], result[3]
return result[0], result[1], result[2], result[3], result[4]
}

// StringToImportsOrders will convert string, like "std,general,company,project" to ImportsOrder array type.
// Default value for empty string is "std,general,company,project"
// StringToImportsOrders will convert string, like "std,general,company,named,project" to ImportsOrder array type.
// Default value for empty string is "std,general,company,named,project"
func StringToImportsOrders(s string) (ImportsOrders, error) {
if len(strings.TrimSpace(s)) == 0 {
s = defaultImportsOrder
}

groups := unique(strings.Split(s, ","))
if len(groups) != 4 {
if len(groups) != 5 {
return nil, fmt.Errorf(`use this parameters to sort all groups of your imports: "%s"`, defaultImportsOrder)
}

var groupOrder []ImportsOrder
for _, g := range groups {
group := ImportsOrder(strings.TrimSpace(g))
switch group {
case StdImportsOrder, CompanyImportsOrder, ProjectImportsOrder, GeneralImportsOrder:
case StdImportsOrder, CompanyImportsOrder, NamedImportsOrder, ProjectImportsOrder, GeneralImportsOrder:
default:
return nil, fmt.Errorf(`unknown order group type: "%s"`, group)
}
Expand Down

0 comments on commit dfe24b3

Please sign in to comment.