Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a new import group called "named" which groups aliased imports (internal and external) #117

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading