From 83cfd48a02a891e22983846460bbf18fe144448d Mon Sep 17 00:00:00 2001 From: Patrice Ferlet Date: Tue, 27 Jun 2023 12:19:05 +0200 Subject: [PATCH] Handle output and move types --- cmd/goreorder/commands.go | 34 ++++++++-------- cmd/goreorder/config_test.go | 5 +++ cmd/goreorder/main.go | 79 +++++++++++++++++++----------------- cmd/goreorder/main_test.go | 8 ++-- ordering/main.go | 23 ----------- ordering/parser.go | 25 ------------ ordering/types.go | 52 ++++++++++++++++++++++++ 7 files changed, 121 insertions(+), 105 deletions(-) create mode 100644 ordering/types.go diff --git a/cmd/goreorder/commands.go b/cmd/goreorder/commands.go index 3f2614a..73a95a1 100644 --- a/cmd/goreorder/commands.go +++ b/cmd/goreorder/commands.go @@ -15,30 +15,20 @@ import ( "github.com/spf13/viper" ) -const ( - usage = `%[1]s reorders the types, methods... in a Go -source file. By default, it will print the result to stdout. To allow %[1]s -to write to the file, use the -write flag.` +var ( + version = "master" // changed at compilation time + defaultOutpout io.Writer = os.Stdout // default output is stdout + defaultErrOutpout io.Writer = os.Stderr // default error output is stderr ) -var ( - version = "master" // changed at compilation time - examples = []string{ - "$ %[1]s reorder --write --reorder-types --format gofmt file.go", - "$ %[1]s reorder --diff ./mypackage", - "$ cat file.go | %[1]s reorder", - } - completionExamples = []string{ +func buildCompletionCommand() *cobra.Command { + var completionExamples = []string{ "$ %[1]s completion bash", "$ %[1]s completion bash -no-documentation", "$ %[1]s completion zsh", "$ %[1]s completion fish", "$ %[1]s completion powershell", } - defaultOutpout io.Writer = os.Stdout -) - -func buildCompletionCommand() *cobra.Command { noDocumentation := false bashv1Completion := false completionCmd := &cobra.Command{ @@ -80,6 +70,14 @@ func buildCompletionCommand() *cobra.Command { } func buildMainCommand() *cobra.Command { + const usage = `%[1]s reorders the types, methods... in a Go +source file. By default, it will print the result to stdout. To allow %[1]s +to write to the file, use the -write flag.` + var examples = []string{ + "$ %[1]s reorder --write --reorder-types --format gofmt file.go", + "$ %[1]s reorder --diff ./mypackage", + "$ cat file.go | %[1]s reorder", + } cmd := cobra.Command{ Use: "goreorder [flags] [file.go|directory|stdin]", @@ -95,6 +93,10 @@ func buildMainCommand() *cobra.Command { }, } + // my god this is so cool... + cmd.SetOut(defaultOutpout) + cmd.SetErr(defaultErrOutpout) + config := &ReorderConfig{ FormatToolName: "gofmt", Write: false, diff --git a/cmd/goreorder/config_test.go b/cmd/goreorder/config_test.go index 05a8a01..c6eb837 100644 --- a/cmd/goreorder/config_test.go +++ b/cmd/goreorder/config_test.go @@ -10,6 +10,11 @@ import ( "gopkg.in/yaml.v3" ) +func init() { + defaultOutpout = bytes.NewBuffer([]byte{}) + defaultErrOutpout = bytes.NewBuffer([]byte{}) +} + func TestNoConfigFile(t *testing.T) { defaultOutpout = bytes.NewBuffer([]byte{}) printConfigFile(&ReorderConfig{ diff --git a/cmd/goreorder/main.go b/cmd/goreorder/main.go index 39d2ba7..109b72c 100644 --- a/cmd/goreorder/main.go +++ b/cmd/goreorder/main.go @@ -1,7 +1,9 @@ package main import ( + "bytes" "fmt" + "io" "io/ioutil" "os" "path/filepath" @@ -17,7 +19,7 @@ var ( func main() { if err := buildMainCommand().Execute(); err != nil { - fmt.Println(fmt.Errorf("%w", err)) + io.WriteString(defaultErrOutpout, fmt.Sprintf("%s\n", err)) os.Exit(1) } } @@ -32,6 +34,37 @@ type ReorderConfig struct { DefOrder []string `yaml:"order"` } +func reorder(config *ReorderConfig, args ...string) error { + + // is there something in stdin? + filename := "" + var input []byte + var err error + stat, _ := os.Stdin.Stat() + if (stat.Mode() & os.ModeCharDevice) == 0 { + // read from stdin + input, err = ioutil.ReadAll(os.Stdin) + if err != nil { + return fmt.Errorf("Error while reading stdin: %w", err) + } + filename = "stdin.go" + config.Write = false + log.Println("Processing stdin, write is set to false") + } else { + // read from file or directory + filename = args[0] + if filename == "" { + return fmt.Errorf("Filename is empty") + } + _, err := os.Stat(filename) + if err != nil { + return fmt.Errorf("Error while getting file stat: %w", err) + } + } + + return processFile(filename, input, config) +} + func processFile(fileOrDirectoryName string, input []byte, config *ReorderConfig) error { if strings.HasSuffix(fileOrDirectoryName, "_test.go") { return fmt.Errorf("Skipping test file: " + fileOrDirectoryName) @@ -47,7 +80,7 @@ func processFile(fileOrDirectoryName string, input []byte, config *ReorderConfig Src: input, }) if err != nil { - return fmt.Errorf("Error while reordering source: %v", err) + return fmt.Errorf("Error while reordering source: %w", err) } fmt.Print(string(content)) return nil @@ -55,7 +88,7 @@ func processFile(fileOrDirectoryName string, input []byte, config *ReorderConfig stat, err := os.Stat(fileOrDirectoryName) if err != nil { - return fmt.Errorf("Error while getting file stat: %v", err) + return fmt.Errorf("Error while getting file stat: %w", err) } if stat.IsDir() { // skip vendor directory @@ -66,7 +99,7 @@ func processFile(fileOrDirectoryName string, input []byte, config *ReorderConfig log.Println("Processing directory: " + fileOrDirectoryName) return filepath.Walk(fileOrDirectoryName, func(path string, info os.FileInfo, err error) error { if err != nil { - return fmt.Errorf("Error while walking directory: %v", err) + return fmt.Errorf("Error while walking directory: %w", err) } if strings.HasSuffix(path, ".go") { processFile(path, nil, config) @@ -85,46 +118,16 @@ func processFile(fileOrDirectoryName string, input []byte, config *ReorderConfig Src: input, }) if err != nil { - return fmt.Errorf("Error while reordering file: %v", err) + return fmt.Errorf("Error while reordering file: %w", err) } if config.Write { err = ioutil.WriteFile(fileOrDirectoryName, []byte(output), 0644) if err != nil { - return fmt.Errorf("Error while writing to file: %v", err) + return fmt.Errorf("Error while writing to file: %w", err) } } else { - fmt.Println(output) + //fmt.Println(output) + io.Copy(defaultOutpout, bytes.NewBufferString(output)) } return nil } - -func reorder(config *ReorderConfig, args ...string) error { - - // is there something in stdin? - filename := "" - var input []byte - var err error - stat, _ := os.Stdin.Stat() - if (stat.Mode() & os.ModeCharDevice) == 0 { - // read from stdin - input, err = ioutil.ReadAll(os.Stdin) - if err != nil { - return fmt.Errorf("Error while reading stdin: %v", err) - } - filename = "stdin.go" - config.Write = false - log.Println("Processing stdin, write is set to false") - } else { - // read from file or directory - filename = args[0] - if filename == "" { - return fmt.Errorf("Filename is empty") - } - _, err := os.Stat(filename) - if err != nil { - return fmt.Errorf("Error while getting file stat: %v", err) - } - } - - return processFile(filename, input, config) -} diff --git a/cmd/goreorder/main_test.go b/cmd/goreorder/main_test.go index f647e75..b1e01d0 100644 --- a/cmd/goreorder/main_test.go +++ b/cmd/goreorder/main_test.go @@ -8,6 +8,11 @@ import ( "testing" ) +func init() { + defaultOutpout = bytes.NewBuffer([]byte{}) + defaultErrOutpout = bytes.NewBuffer([]byte{}) +} + func TestBuildCommand(t *testing.T) { cmd := buildMainCommand() if cmd == nil { @@ -138,9 +143,6 @@ func TestNoArgs(t *testing.T) { } func TestCompletionCommands(t *testing.T) { - - defaultOutpout = &bytes.Buffer{} - for _, shell := range []string{"bash", "zsh", "fish", "powershell"} { cmd := buildMainCommand() cmd.SetArgs([]string{"completion", shell}) diff --git a/ordering/main.go b/ordering/main.go index be7b2d5..8996637 100644 --- a/ordering/main.go +++ b/ordering/main.go @@ -12,35 +12,12 @@ import ( "strings" ) -const ( - Const Order = "const" - Init Order = "init" - Main Order = "main" - Var Order = "var" - Interface Order = "interface" - Type Order = "type" - Func Order = "func" -) - // DefaultOrder is the default order of elements. // // Note, Init and Main are not in the list. If they are present, the init and main functions // will be moved. var DefaultOrder = []Order{Const, Var, Interface, Type, Func} -// Order is the type of order, it's an alias of string. -type Order = string - -// ReorderConfig is the configuration for the reorder function. -type ReorderConfig struct { - Filename string - FormatCommand string - ReorderStructs bool - Diff bool - Src interface{} - DefOrder []Order -} - func formatWithCommand(content []byte, output string, opt ReorderConfig) (newcontent []byte, err error) { // we use the format command given by the user // on a temporary file we need to create and remove diff --git a/ordering/parser.go b/ordering/parser.go index 489a61d..640c762 100644 --- a/ordering/parser.go +++ b/ordering/parser.go @@ -9,31 +9,6 @@ import ( "strings" ) -// GoType represents a struct, method or constructor. The "SourceCode" field contains the doc comment and source in Go, formated and ready to be injected in the source file. -type GoType struct { - // Name of the struct, method or constructor - Name string - // SourceCode contains the doc comment and source in Go, formated and ready to be injected in the source file. - SourceCode string - // OpeningLine is the line number where the struct, method or constructor starts in the source file. - OpeningLine int - // ClosingLine is the line number where the struct, method or constructor ends in the source file. - ClosingLine int -} - -// ParsedInfo contains information we need to sort in the source file. -type ParsedInfo struct { - Functions map[string]*GoType - Methods map[string][]*GoType - Constructors map[string][]*GoType - Types map[string]*GoType - Interfaces map[string]*GoType - Constants map[string]*GoType - Variables map[string]*GoType - TypeNames *StingList - InterfaceNames *StingList -} - // Parse the given file and return the methods, constructors and structs. func Parse(filename string, src interface{}) (*ParsedInfo, error) { fset := token.NewFileSet() diff --git a/ordering/types.go b/ordering/types.go new file mode 100644 index 0000000..bef9874 --- /dev/null +++ b/ordering/types.go @@ -0,0 +1,52 @@ +package ordering + +const ( + Const Order = "const" + Init Order = "init" + Main Order = "main" + Var Order = "var" + Interface Order = "interface" + Type Order = "type" + Func Order = "func" +) + +// GoType represents a struct, method or constructor. The "SourceCode" field contains the doc comment and source in Go, formated and ready to be injected in the source file. +type GoType struct { + // Name of the struct, method or constructor + Name string + + // SourceCode contains the doc comment and source in Go, formated and ready to be injected in the source file. + SourceCode string + + // OpeningLine is the line number where the struct, method or constructor starts in the source file. + OpeningLine int + + // ClosingLine is the line number where the struct, method or constructor ends in the source file. + ClosingLine int +} + +// Order is the type of order, it's an alias of string. +type Order = string + +// ParsedInfo contains information we need to sort in the source file. +type ParsedInfo struct { + Functions map[string]*GoType + Methods map[string][]*GoType + Constructors map[string][]*GoType + Types map[string]*GoType + Interfaces map[string]*GoType + Constants map[string]*GoType + Variables map[string]*GoType + TypeNames *StingList + InterfaceNames *StingList +} + +// ReorderConfig is the configuration for the reorder function. +type ReorderConfig struct { + Filename string + FormatCommand string + ReorderStructs bool + Diff bool + Src interface{} + DefOrder []Order +}