From 2317c0632bf3399837bac2496d905a9a1e925ad7 Mon Sep 17 00:00:00 2001 From: Ilya Lesikov Date: Tue, 27 Jan 2026 06:17:59 +0300 Subject: [PATCH] feat: force function definition arguments and returns on a single line Signed-off-by: Ilya Lesikov --- README.md | 17 +++++++++ pkg/formatter/file.go | 1 + pkg/formatter/spacing.go | 55 ++++++++++++++++++++++++++++++ pkg/formatter/testdata/expected.go | 30 ++++++++++++++++ pkg/formatter/testdata/input.go | 45 ++++++++++++++++++++++++ 5 files changed, 148 insertions(+) diff --git a/README.md b/README.md index 03c0429..4794699 100644 --- a/README.md +++ b/README.md @@ -292,6 +292,23 @@ This conversion only applies to structs defined in the same file. External struc ### Functions +**Function signatures** are always collapsed to a single line: + +```go +// Before — multi-line signature +func Process( + ctx context.Context, + input Input, +) (Output, error) { + +// After — single line +func Process(ctx context.Context, input Input) (Output, error) { +``` + +This applies to function definitions, methods, function types, and interface methods. + +--- + **Standalone functions sorting:** 1. Exported first, then unexported 2. Within each group: by architectural layer (high-level first) diff --git a/pkg/formatter/file.go b/pkg/formatter/file.go index 99e992f..4baeff5 100644 --- a/pkg/formatter/file.go +++ b/pkg/formatter/file.go @@ -55,6 +55,7 @@ func FormatFile(filePath string, opts Options) error { return nil } + collapseFuncSignatures(f) originalFieldOrder := collectOriginalFieldOrder(f) convertPositionalToKeyed(f, originalFieldOrder) reorderStructFields(f) diff --git a/pkg/formatter/spacing.go b/pkg/formatter/spacing.go index 3537bae..dbd83c5 100644 --- a/pkg/formatter/spacing.go +++ b/pkg/formatter/spacing.go @@ -127,3 +127,58 @@ func normalizeSpacing(f *dst.File) { return true }) } + +func collapseFuncSignatures(f *dst.File) { + dst.Inspect(f, func(n dst.Node) bool { + switch node := n.(type) { + case *dst.FuncDecl: + if node.Type != nil { + collapseFuncType(node.Type) + } + case *dst.FuncLit: + if node.Type != nil { + collapseFuncType(node.Type) + } + case *dst.TypeSpec: + if ft, ok := node.Type.(*dst.FuncType); ok { + collapseFuncType(ft) + } + case *dst.InterfaceType: + if node.Methods != nil { + for _, method := range node.Methods.List { + if ft, ok := method.Type.(*dst.FuncType); ok { + collapseFuncType(ft) + } + } + } + } + + return true + }) +} + +func collapseFuncType(ft *dst.FuncType) { + if ft.Params != nil { + collapseFieldList(ft.Params) + } + if ft.Results != nil { + collapseFieldList(ft.Results) + } +} + +func collapseFieldList(fl *dst.FieldList) { + // Remove newlines from opening paren + fl.Decs.Opening = nil + + for i, field := range fl.List { + // First field: no newline before + if i == 0 { + field.Decs.Before = dst.None + } else { + // Subsequent fields: space only (comma handled automatically) + field.Decs.Before = dst.None + } + // No newline after any field + field.Decs.After = dst.None + } +} diff --git a/pkg/formatter/testdata/expected.go b/pkg/formatter/testdata/expected.go index 8810798..8b1b38a 100644 --- a/pkg/formatter/testdata/expected.go +++ b/pkg/formatter/testdata/expected.go @@ -1,7 +1,9 @@ package main import ( + "context" "fmt" + "net/http" "os" "strings" ) @@ -66,6 +68,9 @@ type StatusCode MyString type Priority int +// Test: function type should collapse +type MultiLineHandler func(w http.ResponseWriter, r *http.Request) + type Reader interface { Read(p []byte) (n int, err error) } @@ -78,6 +83,11 @@ type Closer interface { Close() error } +// Test: interface method should collapse +type MultiLineInterface interface { + Process(ctx context.Context, input Input) (Output, error) +} + type ReadWriter interface { Read(p []byte) (n int, err error) Write(p []byte) (n int, err error) @@ -118,6 +128,11 @@ func (s *Server) PublicMethod() {} func (s *Server) handleRequest() {} +// Test: multi-line method signature should collapse +func (s *Server) multiLineMethod(ctx context.Context, input string) (string, error) { + return input, nil +} + // Test: method declared before its type func (s *Server) privateMethod() { return @@ -227,6 +242,11 @@ type WithEmbedded struct { Extra string } +// Types for interface test +type Input struct{} + +type Output struct{} + func HelperUpper() {} func ProcessDataPublic(data string) string { @@ -360,6 +380,16 @@ func helperLower() { fmt.Println("helper") } +// Test: multi-line func signature should collapse to single line +func multiLineFunc(a int, b string, c bool) error { + return nil +} + +// Test: multi-line return values should collapse +func multiLineReturns() (result string, err error) { + return "", nil +} + func processData(data string) string { return strings.ToUpper(data) } diff --git a/pkg/formatter/testdata/input.go b/pkg/formatter/testdata/input.go index a019726..1934848 100644 --- a/pkg/formatter/testdata/input.go +++ b/pkg/formatter/testdata/input.go @@ -1,7 +1,9 @@ package main import ( + "context" "fmt" + "net/http" "os" "strings" ) @@ -338,3 +340,46 @@ func createKeyed() *PositionalTest { func createEmpty() *PositionalTest { return &PositionalTest{} } + +// Test: multi-line func signature should collapse to single line +func multiLineFunc( + a int, + b string, + c bool, +) error { + return nil +} + +// Test: multi-line method signature should collapse +func (s *Server) multiLineMethod( + ctx context.Context, + input string, +) (string, error) { + return input, nil +} + +// Test: multi-line return values should collapse +func multiLineReturns() ( + result string, + err error, +) { + return "", nil +} + +// Test: function type should collapse +type MultiLineHandler func( + w http.ResponseWriter, + r *http.Request, +) + +// Test: interface method should collapse +type MultiLineInterface interface { + Process( + ctx context.Context, + input Input, + ) (Output, error) +} + +// Types for interface test +type Input struct{} +type Output struct{}