From c91f455bf9630b10e1dee9643fc4e44d877da7bd Mon Sep 17 00:00:00 2001 From: Patrice Ferlet Date: Fri, 10 May 2024 15:18:17 +0200 Subject: [PATCH 1/2] Refacto + simplifications --- ordering/main.go | 143 +++++++++++++++++++++++++++------------------ ordering/parser.go | 74 ++++++++++++----------- 2 files changed, 127 insertions(+), 90 deletions(-) diff --git a/ordering/main.go b/ordering/main.go index dc51b1f..df477c4 100644 --- a/ordering/main.go +++ b/ordering/main.go @@ -17,7 +17,9 @@ import ( // will be moved. var DefaultOrder = []Order{Const, Var, Interface, Type, Func} -func formatWithCommand(content []byte, output string, opt ReorderConfig) (newcontent []byte, err error) { +const reorderSignature = "// -- " + +func formatWithCommand(content []byte, output []byte, 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 tmpfile, err := os.CreateTemp("", "") @@ -27,7 +29,7 @@ func formatWithCommand(content []byte, output string, opt ReorderConfig) (newcon defer os.Remove(tmpfile.Name()) // write the temporary file - if _, err := tmpfile.Write([]byte(output)); err != nil { + if _, err := tmpfile.Write(output); err != nil { return content, errors.New("Failed to write temp file: " + err.Error()) } tmpfile.Close() @@ -58,7 +60,7 @@ func processConst( *lineNumberWhereInject = info.Constants[name].OpeningLine } for ln := sourceCode.OpeningLine - 1; ln < sourceCode.ClosingLine; ln++ { - originalContent[ln] = "// -- " + sign + originalContent[ln] = reorderSignature + sign } source = append(source, sourceCode.SourceCode) *removedLines += len(info.Constants) @@ -84,7 +86,7 @@ func processExtractedFunction( *lineNumberWhereInject = info.Functions[name].OpeningLine } for ln := sourceCode.OpeningLine - 1; ln < sourceCode.ClosingLine; ln++ { - originalContent[ln] = "// -- " + sign + originalContent[ln] = reorderSignature + sign } source = append(source, "\n"+sourceCode.SourceCode) *removedLines += len(info.Functions) @@ -113,7 +115,7 @@ func processFunctions( *lineNumberWhereInject = info.Functions[name].OpeningLine } for ln := sourceCode.OpeningLine - 1; ln < sourceCode.ClosingLine; ln++ { - originalContent[ln] = "// -- " + sign + originalContent[ln] = reorderSignature + sign } source = append(source, "\n"+sourceCode.SourceCode) *removedLines += len(info.Functions) @@ -134,7 +136,7 @@ func processInterfaces( *lineNumberWhereInject = info.Interfaces[name].OpeningLine } for ln := sourceCode.OpeningLine - 1; ln < sourceCode.ClosingLine; ln++ { - originalContent[ln] = "// -- " + sign + originalContent[ln] = reorderSignature + sign } source = append(source, sourceCode.SourceCode) *removedLines += len(info.Interfaces) @@ -155,7 +157,7 @@ func processTypes( } // replace the definitions by "// -- line to remove for ln := info.Types[typename].OpeningLine - 1; ln < info.Types[typename].ClosingLine; ln++ { - originalContent[ln] = "// -- " + sign + originalContent[ln] = reorderSignature + sign } *removedLines += info.Types[typename].ClosingLine - info.Types[typename].OpeningLine // add the struct definition to "source" @@ -164,7 +166,7 @@ func processTypes( // same for constructors for _, constructor := range info.Constructors[typename] { for ln := constructor.OpeningLine - 1; ln < constructor.ClosingLine; ln++ { - originalContent[ln] = "// -- " + sign + originalContent[ln] = reorderSignature + sign } // add the constructor to "source" source = append(source, "\n"+constructor.SourceCode) @@ -174,7 +176,7 @@ func processTypes( // same for methods for _, method := range info.Methods[typename] { for ln := method.OpeningLine - 1; ln < method.ClosingLine; ln++ { - originalContent[ln] = "// -- " + sign + originalContent[ln] = reorderSignature + sign } // add the method to "source" source = append(source, "\n"+method.SourceCode) @@ -196,7 +198,7 @@ func processVars( *lineNumberWhereInject = info.Variables[name].OpeningLine } for ln := sourceCode.OpeningLine - 1; ln < sourceCode.ClosingLine; ln++ { - originalContent[ln] = "// -- " + sign + originalContent[ln] = reorderSignature + sign } source = append(source, sourceCode.SourceCode) *removedLines += len(info.Variables) @@ -218,22 +220,7 @@ func ReorderSource(opt ReorderConfig) (string, error) { if opt.DefOrder == nil { opt.DefOrder = DefaultOrder } - if len(opt.DefOrder) != len(DefaultOrder) { - // wich one is missing? - for _, order := range DefaultOrder { - found := false - for _, defOrder := range opt.DefOrder { - if order == defOrder { - found = true - break - } - } - if !found { - // add it to the end - opt.DefOrder = append(opt.DefOrder, order) - } - } - } + findMissingOrderElement(&opt) var content []byte var err error @@ -258,33 +245,18 @@ func ReorderSource(opt ReorderConfig) (string, error) { // sort methods by name for _, method := range info.Methods { - sort.Slice(method, func(i, j int) bool { - return method[i].Name < method[j].Name - }) + sortGoTypes(method) } for _, constructor := range info.Constructors { - sort.Slice(constructor, func(i, j int) bool { - return constructor[i].Name < constructor[j].Name - }) + sortGoTypes(constructor) } - functionNames := make([]string, 0, len(info.Functions)) - for functionName := range info.Functions { - functionNames = append(functionNames, functionName) - } + functionNames := getKeys(info.Functions) + varNames := getKeys(info.Variables) + constNames := getKeys(info.Constants) sort.Strings(functionNames) - - varNames := make([]string, 0, len(info.Variables)) - for varName := range info.Variables { - varNames = append(varNames, varName) - } sort.Strings(varNames) - - constNames := make([]string, 0, len(info.Constants)) - for constName := range info.Constants { - constNames = append(constNames, constName) - } sort.Strings(constNames) if opt.ReorderStructs { @@ -375,34 +347,91 @@ func ReorderSource(opt ReorderConfig) (string, error) { originalContent = append(originalContent[:lineNumberWhereInject], append(source, originalContent[lineNumberWhereInject:]...)...) // remove the lines that were marked as "// -- line to remove" - temp := []string{} - for _, line := range originalContent { - if line != "// -- "+sign { - temp = append(temp, line) + originalContent = removeSignedLine(originalContent, sign) + output := []byte(strings.Join(originalContent, "\n")) + + // write in a temporary file and use "gofmt" to format it + //newcontent := []byte(output) + newcontent, err := formatSource(content, output, opt) + if err != nil { + return string(content), err + } + + if opt.Diff { + return doDiff(content, newcontent, opt.Filename) + } + return string(newcontent), nil +} + +// findMissingOrderElement finds the missing order element. +// If the default order is not complete, it will add the missing elements. +func findMissingOrderElement(opt *ReorderConfig) { + + if len(opt.DefOrder) != len(DefaultOrder) { + // wich one is missing? + for _, order := range DefaultOrder { + found := false + for _, defOrder := range opt.DefOrder { + if order == defOrder { + found = true + break + } + } + if !found { + // add it to the end + opt.DefOrder = append(opt.DefOrder, order) + } } } - originalContent = temp - output := strings.Join(originalContent, "\n") +} + +func sortGoTypes(v []*GoType) { + sort.Slice(v, func(i, j int) bool { + return v[i].Name < v[j].Name + }) +} + +func getKeys(m map[string]*GoType) []string { + keys := make([]string, len(m)) + i := 0 + for k := range m { + keys[i] = k + i++ + } + return keys +} + +func formatSource(content, output []byte, opt ReorderConfig) ([]byte, error) { // write in a temporary file and use "gofmt" to format it //newcontent := []byte(output) var newcontent []byte + var err error switch opt.FormatCommand { case "gofmt": // format the temporary file newcontent, err = format.Source([]byte(output)) if err != nil { - return string(content), errors.New("Failed to format source: " + err.Error()) + return content, errors.New("Failed to format source: " + err.Error()) } default: newcontent, err = formatWithCommand(content, output, opt) if err != nil { - return string(content), errors.New("Failed to format source: " + err.Error()) + return content, errors.New("Failed to format source: " + err.Error()) } } - if opt.Diff { - return doDiff(content, newcontent, opt.Filename) + return newcontent, nil +} + +func removeSignedLine(originalContent []string, sign string) []string { + // remove the lines that were marked as "// -- line to remove" + temp := []string{} + for _, line := range originalContent { + if line != reorderSignature+sign { + temp = append(temp, line) + } } - return string(newcontent), nil + + return temp } diff --git a/ordering/parser.go b/ordering/parser.go index 722a6c8..8a69541 100644 --- a/ordering/parser.go +++ b/ordering/parser.go @@ -60,7 +60,7 @@ func Parse(filename string, src interface{}) (*ParsedInfo, error) { for _, decl := range f.Decls { switch d := decl.(type) { case *ast.FuncDecl: - findConstructors(d, fset, sourceLines, methods, constructors) + findConstructors(d, fset, sourceLines, constructors) } } // and now functions @@ -108,7 +108,7 @@ func GetTypeComments(d *ast.GenDecl) (comments []string) { return } -func findConstructors(d *ast.FuncDecl, fset *token.FileSet, sourceLines []string, methods, constructors map[string][]*GoType) { +func findConstructors(d *ast.FuncDecl, fset *token.FileSet, sourceLines []string, constructors map[string][]*GoType) { if d.Type == nil || d.Type.Results == nil || len(d.Type.Results.List) == 0 { // no return type return @@ -186,41 +186,49 @@ func findGlobalVarsAndConsts(d *ast.GenDecl, fset *token.FileSet, sourceLines [] return } for _, spec := range d.Specs { - if s, ok := spec.(*ast.ValueSpec); ok { - for _, name := range s.Names { - // log the source code for the variable or constant - varDef := &GoType{ - Name: name.Name, - OpeningLine: fset.Position(d.Pos()).Line, - ClosingLine: fset.Position(d.End()).Line, - } - comments := GetTypeComments(d) - if len(comments) > 0 { - varDef.SourceCode = strings.Join(comments, "\n") + "\n" - } - varDef.SourceCode += strings.Join(sourceLines[varDef.OpeningLine-1:varDef.ClosingLine], "\n") - varDef.OpeningLine -= len(comments) - - // this time, if const or vars are defined in a parenthesis, the source code is the same for all - // found var or const. So, what we do is to check if the source code is already in the map, and if - // so, we skip it. - // we will use the source code signature as the key for the map - signature := fmt.Sprintf("%d-%d", varDef.OpeningLine, varDef.ClosingLine) - if _, ok := varTypes[signature]; ok { - continue - } - - switch d.Tok { - case token.CONST: - constTypes[signature] = varDef - case token.VAR: - varTypes[signature] = varDef - } - } + s, ok := spec.(*ast.ValueSpec) + if !ok { + continue + } + for _, name := range s.Names { + parseConstantAndVars(name, d, fset, sourceLines, varTypes, constTypes) } } } +func parseConstantAndVars(name *ast.Ident, d *ast.GenDecl, fset *token.FileSet, sourceLines []string, varTypes, constTypes map[string]*GoType) { + + // log the source code for the variable or constant + varDef := &GoType{ + Name: name.Name, + OpeningLine: fset.Position(d.Pos()).Line, + ClosingLine: fset.Position(d.End()).Line, + } + comments := GetTypeComments(d) + if len(comments) > 0 { + varDef.SourceCode = strings.Join(comments, "\n") + "\n" + } + varDef.SourceCode += strings.Join(sourceLines[varDef.OpeningLine-1:varDef.ClosingLine], "\n") + varDef.OpeningLine -= len(comments) + + // this time, if const or vars are defined in a parenthesis, the source code is the same for all + // found var or const. So, what we do is to check if the source code is already in the map, and if + // so, we skip it. + // we will use the source code signature as the key for the map + signature := fmt.Sprintf("%d-%d", varDef.OpeningLine, varDef.ClosingLine) + if _, ok := varTypes[signature]; ok { + return + } + + switch d.Tok { + case token.CONST: + constTypes[signature] = varDef + case token.VAR: + varTypes[signature] = varDef + } + +} + func findInterfaces(d *ast.GenDecl, fset *token.FileSet, sourceLines []string, interfaceNames *StingList, interfaceTypes map[string]*GoType) { // finc interfaces if d.Tok != token.TYPE { From b56e35038a5a3a299c901cad34369acfd290efa3 Mon Sep 17 00:00:00 2001 From: Patrice Ferlet Date: Fri, 10 May 2024 15:24:00 +0200 Subject: [PATCH 2/2] Reordering --- ordering/main.go | 148 ++++++++++++++++++++++----------------------- ordering/parser.go | 66 ++++++++++---------- 2 files changed, 107 insertions(+), 107 deletions(-) diff --git a/ordering/main.go b/ordering/main.go index df477c4..d1b36f1 100644 --- a/ordering/main.go +++ b/ordering/main.go @@ -11,13 +11,58 @@ import ( "strings" ) +const reorderSignature = "// -- " + // 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} -const reorderSignature = "// -- " +// findMissingOrderElement finds the missing order element. +// If the default order is not complete, it will add the missing elements. +func findMissingOrderElement(opt *ReorderConfig) { + + if len(opt.DefOrder) != len(DefaultOrder) { + // wich one is missing? + for _, order := range DefaultOrder { + found := false + for _, defOrder := range opt.DefOrder { + if order == defOrder { + found = true + break + } + } + if !found { + // add it to the end + opt.DefOrder = append(opt.DefOrder, order) + } + } + } +} + +func formatSource(content, output []byte, opt ReorderConfig) ([]byte, error) { + + // write in a temporary file and use "gofmt" to format it + //newcontent := []byte(output) + var newcontent []byte + var err error + switch opt.FormatCommand { + case "gofmt": + // format the temporary file + newcontent, err = format.Source([]byte(output)) + if err != nil { + return content, errors.New("Failed to format source: " + err.Error()) + } + default: + newcontent, err = formatWithCommand(content, output, opt) + if err != nil { + return content, errors.New("Failed to format source: " + err.Error()) + } + } + + return newcontent, nil +} func formatWithCommand(content []byte, output []byte, opt ReorderConfig) (newcontent []byte, err error) { // we use the format command given by the user @@ -47,6 +92,16 @@ func formatWithCommand(content []byte, output []byte, opt ReorderConfig) (newcon return newcontent, nil } +func getKeys(m map[string]*GoType) []string { + keys := make([]string, len(m)) + i := 0 + for k := range m { + keys[i] = k + i++ + } + return keys +} + // const and vars func processConst( info *ParsedInfo, @@ -206,6 +261,24 @@ func processVars( return source } +func removeSignedLine(originalContent []string, sign string) []string { + // remove the lines that were marked as "// -- line to remove" + temp := []string{} + for _, line := range originalContent { + if line != reorderSignature+sign { + temp = append(temp, line) + } + } + + return temp +} + +func sortGoTypes(v []*GoType) { + sort.Slice(v, func(i, j int) bool { + return v[i].Name < v[j].Name + }) +} + // ReorderSource reorders the source code in the given filename. // It will be helped by the formatCommand (gofmt or goimports). // If gofmt is used, the source code will be formatted with the go/fmt package in memory. @@ -362,76 +435,3 @@ func ReorderSource(opt ReorderConfig) (string, error) { } return string(newcontent), nil } - -// findMissingOrderElement finds the missing order element. -// If the default order is not complete, it will add the missing elements. -func findMissingOrderElement(opt *ReorderConfig) { - - if len(opt.DefOrder) != len(DefaultOrder) { - // wich one is missing? - for _, order := range DefaultOrder { - found := false - for _, defOrder := range opt.DefOrder { - if order == defOrder { - found = true - break - } - } - if !found { - // add it to the end - opt.DefOrder = append(opt.DefOrder, order) - } - } - } -} - -func sortGoTypes(v []*GoType) { - sort.Slice(v, func(i, j int) bool { - return v[i].Name < v[j].Name - }) -} - -func getKeys(m map[string]*GoType) []string { - keys := make([]string, len(m)) - i := 0 - for k := range m { - keys[i] = k - i++ - } - return keys -} - -func formatSource(content, output []byte, opt ReorderConfig) ([]byte, error) { - - // write in a temporary file and use "gofmt" to format it - //newcontent := []byte(output) - var newcontent []byte - var err error - switch opt.FormatCommand { - case "gofmt": - // format the temporary file - newcontent, err = format.Source([]byte(output)) - if err != nil { - return content, errors.New("Failed to format source: " + err.Error()) - } - default: - newcontent, err = formatWithCommand(content, output, opt) - if err != nil { - return content, errors.New("Failed to format source: " + err.Error()) - } - } - - return newcontent, nil -} - -func removeSignedLine(originalContent []string, sign string) []string { - // remove the lines that were marked as "// -- line to remove" - temp := []string{} - for _, line := range originalContent { - if line != reorderSignature+sign { - temp = append(temp, line) - } - } - - return temp -} diff --git a/ordering/parser.go b/ordering/parser.go index 8a69541..3e03574 100644 --- a/ordering/parser.go +++ b/ordering/parser.go @@ -196,39 +196,6 @@ func findGlobalVarsAndConsts(d *ast.GenDecl, fset *token.FileSet, sourceLines [] } } -func parseConstantAndVars(name *ast.Ident, d *ast.GenDecl, fset *token.FileSet, sourceLines []string, varTypes, constTypes map[string]*GoType) { - - // log the source code for the variable or constant - varDef := &GoType{ - Name: name.Name, - OpeningLine: fset.Position(d.Pos()).Line, - ClosingLine: fset.Position(d.End()).Line, - } - comments := GetTypeComments(d) - if len(comments) > 0 { - varDef.SourceCode = strings.Join(comments, "\n") + "\n" - } - varDef.SourceCode += strings.Join(sourceLines[varDef.OpeningLine-1:varDef.ClosingLine], "\n") - varDef.OpeningLine -= len(comments) - - // this time, if const or vars are defined in a parenthesis, the source code is the same for all - // found var or const. So, what we do is to check if the source code is already in the map, and if - // so, we skip it. - // we will use the source code signature as the key for the map - signature := fmt.Sprintf("%d-%d", varDef.OpeningLine, varDef.ClosingLine) - if _, ok := varTypes[signature]; ok { - return - } - - switch d.Tok { - case token.CONST: - constTypes[signature] = varDef - case token.VAR: - varTypes[signature] = varDef - } - -} - func findInterfaces(d *ast.GenDecl, fset *token.FileSet, sourceLines []string, interfaceNames *StingList, interfaceTypes map[string]*GoType) { // finc interfaces if d.Tok != token.TYPE { @@ -320,6 +287,39 @@ func findTypes(d *ast.GenDecl, fset *token.FileSet, sourceLines []string, typeNa } } +func parseConstantAndVars(name *ast.Ident, d *ast.GenDecl, fset *token.FileSet, sourceLines []string, varTypes, constTypes map[string]*GoType) { + + // log the source code for the variable or constant + varDef := &GoType{ + Name: name.Name, + OpeningLine: fset.Position(d.Pos()).Line, + ClosingLine: fset.Position(d.End()).Line, + } + comments := GetTypeComments(d) + if len(comments) > 0 { + varDef.SourceCode = strings.Join(comments, "\n") + "\n" + } + varDef.SourceCode += strings.Join(sourceLines[varDef.OpeningLine-1:varDef.ClosingLine], "\n") + varDef.OpeningLine -= len(comments) + + // this time, if const or vars are defined in a parenthesis, the source code is the same for all + // found var or const. So, what we do is to check if the source code is already in the map, and if + // so, we skip it. + // we will use the source code signature as the key for the map + signature := fmt.Sprintf("%d-%d", varDef.OpeningLine, varDef.ClosingLine) + if _, ok := varTypes[signature]; ok { + return + } + + switch d.Tok { + case token.CONST: + constTypes[signature] = varDef + case token.VAR: + varTypes[signature] = varDef + } + +} + func inConstructors(constructorMap map[string][]*GoType, funcname string) bool { for _, constructors := range constructorMap { for _, constructor := range constructors {