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),
|
||||
)
|
||||
|
||||
if err := f.Format(c.Args().Slice()...); err != nil {
|
||||
return fmt.Errorf("imports formatter: failed to format %v: %w", c.Args().Slice(), err)
|
||||
args := c.Args().Slice()
|
||||
if err := f.Format(args...); err != nil {
|
||||
return fmt.Errorf("imports formatter: failed to format %v: %w", args, err)
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
var ErrEmptyPaths = errors.New("empty paths")
|
||||
|
||||
type Formatter struct {
|
||||
isList bool
|
||||
isWrite bool
|
||||
|
@ -7,16 +18,70 @@ type Formatter struct {
|
|||
}
|
||||
|
||||
func NewFormmater(opts ...FormatterOptionFn) *Formatter {
|
||||
f := &Formatter{}
|
||||
ft := &Formatter{}
|
||||
|
||||
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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue