feat: simple format file (without actually format)
check go file -> parse ast -> ignore generatedmain
parent
6b8625be56
commit
27a82681f1
|
@ -46,8 +46,9 @@ func (a *action) Run(c *cli.Context) error {
|
||||||
imports.FormatterWithDiff(a.flags.diff),
|
imports.FormatterWithDiff(a.flags.diff),
|
||||||
)
|
)
|
||||||
|
|
||||||
if err := f.Format(c.Args().Slice()...); err != nil {
|
args := c.Args().Slice()
|
||||||
return fmt.Errorf("imports formatter: failed to format %v: %w", c.Args().Slice(), err)
|
if err := f.Format(args...); err != nil {
|
||||||
|
return fmt.Errorf("imports formatter: failed to format %v: %w", args, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
package imports
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/ast"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var reGoGenerated = regexp.MustCompile(`^// Code generated .* DO NOT EDIT\.$`)
|
||||||
|
|
||||||
|
// Copy from https://github.com/mvdan/gofumpt
|
||||||
|
func isGoFile(name string) bool {
|
||||||
|
// Hidden files are ignored
|
||||||
|
if strings.HasPrefix(name, ".") {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.HasSuffix(name, ".go")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy from https://github.com/mvdan/gofumpt
|
||||||
|
func isGoGenerated(file *ast.File) bool {
|
||||||
|
for _, cg := range file.Comments {
|
||||||
|
// Ignore if package ... is on top
|
||||||
|
if cg.Pos() > file.Package {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, line := range cg.List {
|
||||||
|
if reGoGenerated.MatchString(line.Text) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
|
@ -1,5 +1,16 @@
|
||||||
package imports
|
package imports
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"go/parser"
|
||||||
|
"go/token"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ErrEmptyPaths = errors.New("empty paths")
|
||||||
|
|
||||||
type Formatter struct {
|
type Formatter struct {
|
||||||
isList bool
|
isList bool
|
||||||
isWrite bool
|
isWrite bool
|
||||||
|
@ -7,16 +18,70 @@ type Formatter struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFormmater(opts ...FormatterOptionFn) *Formatter {
|
func NewFormmater(opts ...FormatterOptionFn) *Formatter {
|
||||||
f := &Formatter{}
|
ft := &Formatter{}
|
||||||
|
|
||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
opt(f)
|
opt(ft)
|
||||||
}
|
}
|
||||||
|
|
||||||
return f
|
return ft
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accept a list of files or directories
|
||||||
|
func (ft *Formatter) Format(paths ...string) error {
|
||||||
|
if len(paths) == 0 {
|
||||||
|
return ErrEmptyPaths
|
||||||
|
}
|
||||||
|
|
||||||
|
// Logic switch case copy from goimports, gofumpt
|
||||||
|
for _, path := range paths {
|
||||||
|
switch dir, err := os.Stat(path); {
|
||||||
|
case err != nil:
|
||||||
|
return fmt.Errorf("os: failed to stat: [%s] %w", path, err)
|
||||||
|
case dir.IsDir():
|
||||||
|
if err := ft.formatDir(path); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
if err := ft.formatFile(path); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ft *Formatter) formatDir(path string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ft *Formatter) formatFile(path string) error {
|
||||||
|
// Check go file
|
||||||
|
if !isGoFile(filepath.Base(path)) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
pathBytes, err := os.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("os: failed to read file: [%s] %w", path, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse ast
|
||||||
|
fset := token.NewFileSet()
|
||||||
|
|
||||||
|
parserMode := parser.Mode(0)
|
||||||
|
parserMode |= parser.ParseComments
|
||||||
|
|
||||||
|
pathASTFile, err := parser.ParseFile(fset, path, pathBytes, parserMode)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("parser: failed to parse file [%s]: %w", path, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore generated file
|
||||||
|
if isGoGenerated(pathASTFile) {
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accept a list of files or directories aka fsNames
|
|
||||||
func (f *Formatter) Format(fsNames ...string) error {
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue