Skip to content

Commit

Permalink
Merge pull request #19 from metal3d/develop
Browse files Browse the repository at this point in the history
Error and output handlers
  • Loading branch information
metal3d authored Jun 27, 2023
2 parents 4101065 + 83cfd48 commit 0494211
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 124 deletions.
29 changes: 27 additions & 2 deletions cmd/goreorder/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"errors"
"fmt"
"io"
"os"
"os/exec"
"path/filepath"
Expand All @@ -14,7 +15,20 @@ import (
"github.com/spf13/viper"
)

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
)

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",
}
noDocumentation := false
bashv1Completion := false
completionCmd := &cobra.Command{
Expand Down Expand Up @@ -56,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]",
Expand All @@ -71,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,
Expand Down Expand Up @@ -136,8 +162,7 @@ func buildReorderCommand(config *ReorderConfig) *cobra.Command {
return fmt.Errorf("The executable '" + config.FormatToolName + "' does not exist")
}
logger.SetVerbose(config.Verbose)
run(config, args...)
return nil
return reorder(config, args...)
},
}

Expand Down
5 changes: 5 additions & 0 deletions cmd/goreorder/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{
Expand Down
119 changes: 48 additions & 71 deletions cmd/goreorder/main.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"bytes"
"fmt"
"io"
"io/ioutil"
Expand All @@ -12,37 +13,18 @@ import (
"github.com/metal3d/goreorder/ordering"
)

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
log = logger.GetLogger()
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{
"$ %[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
log = logger.GetLogger()
)

func main() {
if err := buildMainCommand().Execute(); err != nil {
fmt.Println(fmt.Errorf("%v", err))
io.WriteString(defaultErrOutpout, fmt.Sprintf("%s\n", err))
os.Exit(1)
}
}

// ReorderConfig is the configuration for the reorder command
type ReorderConfig struct {
FormatToolName string `yaml:"format"`
Write bool `yaml:"write"`
Expand All @@ -52,10 +34,40 @@ type ReorderConfig struct {
DefOrder []string `yaml:"order"`
}

func processFile(fileOrDirectoryName string, input []byte, config *ReorderConfig) {
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") {
log.Println("Skipping test file: " + fileOrDirectoryName)
return
return fmt.Errorf("Skipping test file: " + fileOrDirectoryName)
}

if input != nil && len(input) != 0 {
Expand All @@ -68,36 +80,32 @@ func processFile(fileOrDirectoryName string, input []byte, config *ReorderConfig
Src: input,
})
if err != nil {
log.Fatal(err)
return fmt.Errorf("Error while reordering source: %w", err)
}
fmt.Print(string(content))
return
return nil
}

stat, err := os.Stat(fileOrDirectoryName)
if err != nil {
log.Fatal(err)
return
return fmt.Errorf("Error while getting file stat: %w", err)
}
if stat.IsDir() {
// skip vendor directory
if strings.HasSuffix(fileOrDirectoryName, "vendor") {
log.Println("Skipping vendor directory: " + fileOrDirectoryName)
return
return fmt.Errorf("Skipping vendor directory: " + fileOrDirectoryName)
}
// get all files in directory and process them
log.Println("Processing directory: " + fileOrDirectoryName)
filepath.Walk(fileOrDirectoryName, func(path string, info os.FileInfo, err error) error {
return filepath.Walk(fileOrDirectoryName, func(path string, info os.FileInfo, err error) error {
if err != nil {
log.Fatal(err)
return err
return fmt.Errorf("Error while walking directory: %w", err)
}
if strings.HasSuffix(path, ".go") {
processFile(path, nil, config)
}
return nil
})
return
}

log.Println("Processing file: " + fileOrDirectoryName)
Expand All @@ -110,47 +118,16 @@ func processFile(fileOrDirectoryName string, input []byte, config *ReorderConfig
Src: input,
})
if err != nil {
log.Println("ERR: Ordering error:", err)
return
return fmt.Errorf("Error while reordering file: %w", err)
}
if config.Write {
err = ioutil.WriteFile(fileOrDirectoryName, []byte(output), 0644)
if err != nil {
log.Fatal("ERR: Write to file failed:", err)
}
} else {
fmt.Println(output)
}
}

func run(config *ReorderConfig, args ...string) {

// 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 {
log.Fatal(err)
return fmt.Errorf("Error while writing to file: %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 == "" {
log.Println("filename is empty")
os.Exit(1)
}
_, err := os.Stat(filename)
if err != nil {
log.Fatal(err)
}
//fmt.Println(output)
io.Copy(defaultOutpout, bytes.NewBufferString(output))
}

processFile(filename, input, config)
return nil
}
8 changes: 5 additions & 3 deletions cmd/goreorder/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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})
Expand Down
23 changes: 0 additions & 23 deletions ordering/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
25 changes: 0 additions & 25 deletions ordering/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
Loading

0 comments on commit 0494211

Please sign in to comment.