Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions shorten/annotations.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ import (
// If a line already has one of these comments from a previous shortening round,
// then the comment contents are updated.
func (s *Shortener) annotateLongLines(lines []string) ([]string, int) {
var annotatedLines []string
var (
annotatedLines []string
nbLinesToShorten int
)

linesToShorten := 0
prevLen := -1

for _, line := range lines {
Expand All @@ -28,21 +30,23 @@ func (s *Shortener) annotateLongLines(lines []string) ([]string, int) {
} else if length < prevLen {
// Replace annotation with a new length
annotatedLines[len(annotatedLines)-1] = annotation.Create(length)
linesToShorten++

nbLinesToShorten++
}
} else if !comments.Is(line) && length > s.config.MaxLen {
annotatedLines = append(
annotatedLines,
annotation.Create(length),
)
linesToShorten++

nbLinesToShorten++
}

annotatedLines = append(annotatedLines, line)
prevLen = annotation.Parse(line)
}

return annotatedLines, linesToShorten
return annotatedLines, nbLinesToShorten
}

// removeAnnotations removes all comments added by the annotateLongLines function above.
Expand Down
66 changes: 34 additions & 32 deletions shorten/format.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ import (
"github.com/golangci/golines/shorten/internal/tags"
)

// formatFile formats the provided AST file starting at the top-level declarations.
func (s *Shortener) formatFile(file *dst.File) {
for _, decl := range file.Decls {
s.formatNode(decl)
}
}

// formatNode formats the provided AST node.
// The appropriate helper function is called based on
// whether the node is a declaration, expression, statement, or spec.
Expand Down Expand Up @@ -65,13 +72,6 @@ func (s *Shortener) formatDecl(decl dst.Decl) {
}
}

// formatFieldList formats a field list in a function declaration.
func (s *Shortener) formatFieldList(fieldList *dst.FieldList) {
for i, field := range fieldList.List {
formatList(field, i)
}
}

// formatStmt formats an AST statement node.
// Among other examples, these include assignments, case clauses,
// for statements, if statements, and select statements.
Expand All @@ -87,14 +87,10 @@ func (s *Shortener) formatStmt(stmt dst.Stmt, force bool) {

switch st := stmt.(type) {
case *dst.AssignStmt:
for _, expr := range st.Rhs {
s.formatExpr(expr, shouldShorten, false)
}
s.formatExprs(st.Rhs, shouldShorten, false)

case *dst.BlockStmt:
for _, stmt := range st.List {
s.formatStmt(stmt, false)
}
s.formatStmts(st.List, false)

case *dst.CaseClause:
if shouldShorten {
Expand All @@ -105,14 +101,10 @@ func (s *Shortener) formatStmt(stmt dst.Stmt, force bool) {
}
}

for _, stmt := range st.Body {
s.formatStmt(stmt, false)
}
s.formatStmts(st.Body, false)

case *dst.CommClause:
for _, stmt := range st.Body {
s.formatStmt(stmt, false)
}
s.formatStmts(st.Body, false)

case *dst.DeclStmt:
s.formatDecl(st.Decl)
Expand Down Expand Up @@ -145,9 +137,7 @@ func (s *Shortener) formatStmt(stmt dst.Stmt, force bool) {
s.formatStmt(st.Body, false)

case *dst.ReturnStmt:
for _, expr := range st.Results {
s.formatExpr(expr, shouldShorten, false)
}
s.formatExprs(st.Results, shouldShorten, false)

case *dst.SelectStmt:
s.formatStmt(st.Body, false)
Expand Down Expand Up @@ -193,10 +183,7 @@ func (s *Shortener) formatExpr(expr dst.Expr, force, isChain bool) {
s.config.ChainSplitDots && (isChain || chainLength(e) > 1) {
e.Decorations().After = dst.NewLine

for _, arg := range e.Args {
s.formatExpr(arg, false, true)
}

s.formatExprs(e.Args, false, true)
s.formatExpr(e.Fun, shouldShorten, true)
} else {
for i, arg := range e.Args {
Expand All @@ -221,9 +208,7 @@ func (s *Shortener) formatExpr(expr dst.Expr, force, isChain bool) {
}
}

for _, element := range e.Elts {
s.formatExpr(element, false, isChain)
}
s.formatExprs(e.Elts, false, isChain)

case *dst.FuncLit:
s.formatStmt(e.Body, false)
Expand Down Expand Up @@ -271,9 +256,7 @@ func (s *Shortener) formatSpec(spec dst.Spec, force bool) {

switch sp := spec.(type) {
case *dst.ValueSpec:
for _, expr := range sp.Values {
s.formatExpr(expr, shouldShorten, false)
}
s.formatExprs(sp.Values, shouldShorten, false)

case *dst.TypeSpec:
s.formatExpr(sp.Type, false, false)
Expand All @@ -288,6 +271,25 @@ func (s *Shortener) formatSpec(spec dst.Spec, force bool) {
}
}

func (s *Shortener) formatStmts(stmts []dst.Stmt, force bool) {
for _, stmt := range stmts {
s.formatStmt(stmt, force)
}
}

func (s *Shortener) formatExprs(exprs []dst.Expr, force, isChain bool) {
for _, expr := range exprs {
s.formatExpr(expr, force, isChain)
}
}

// formatFieldList formats a field list in a function declaration.
func (s *Shortener) formatFieldList(fieldList *dst.FieldList) {
for i, field := range fieldList.List {
formatList(field, i)
}
}

func formatList(node dst.Node, index int) {
decorations := node.Decorations()

Expand Down
4 changes: 2 additions & 2 deletions shorten/internal/tags/tags.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ import (

var structTagRegexp = regexp.MustCompile("`([ ]*[a-zA-Z0-9_-]+:\".*\"[ ]*){2,}`")

// HasMultipleTags returns whether the given lines have a multikey struct line.
// HasMultipleEntries returns whether the given lines have a multi-entries struct line.
// It's used as an optimization step to avoid unnecessary shortening rounds.
func HasMultipleTags(lines []string) bool {
func HasMultipleEntries(lines []string) bool {
return slices.ContainsFunc(lines, structTagRegexp.MatchString)
}

Expand Down
4 changes: 2 additions & 2 deletions shorten/internal/tags/tags_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"github.com/stretchr/testify/assert"
)

func TestHasMultipleTags(t *testing.T) {
func TestHasMultipleEntries(t *testing.T) {
testCases := []struct {
desc string
lines []string
Expand Down Expand Up @@ -55,7 +55,7 @@ func TestHasMultipleTags(t *testing.T) {
t.Run(test.desc, func(t *testing.T) {
t.Parallel()

test.assert(t, HasMultipleTags(test.lines))
test.assert(t, HasMultipleEntries(test.lines))
})
}
}
Expand Down
32 changes: 14 additions & 18 deletions shorten/shortener.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,21 +120,9 @@ func (s *Shortener) Process(content []byte) ([]byte, error) {

// Annotate all long lines
lines := strings.Split(string(content), "\n")
annotatedLines, linesToShorten := s.annotateLongLines(lines)
annotatedLines, nbLinesToShorten := s.annotateLongLines(lines)

var stop bool

if linesToShorten == 0 {
if round == 0 {
if !s.config.ReformatTags || !tags.HasMultipleTags(lines) {
stop = true
}
} else {
stop = true
}
}

if stop {
if !s.shouldContinue(nbLinesToShorten, round, lines) {
s.logger.Debug("nothing more to shorten or reformat, stopping")

break
Expand All @@ -155,10 +143,8 @@ func (s *Shortener) Process(content []byte) ([]byte, error) {
}
}

// Process the file starting at the top-level declarations
for _, decl := range result.Decls {
s.formatNode(decl)
}
// Process the file.
s.formatFile(result)

// Materialize output
output := bytes.NewBuffer([]byte{})
Expand Down Expand Up @@ -196,6 +182,16 @@ func (s *Shortener) Process(content []byte) ([]byte, error) {
return content, nil
}

// shouldContinue returns true:
// if there are lines to shorten,
// or if this is the first round (0),
// and the option to reformat struct tags is enabled,
// and there are struct tags with multiple entries.
func (s *Shortener) shouldContinue(nbLinesToShorten, round int, lines []string) bool {
return nbLinesToShorten > 0 ||
round == 0 && s.config.ReformatTags && tags.HasMultipleEntries(lines)
}

func (s *Shortener) createDot(result dst.Node) error {
dotFile, err := os.Create(s.config.DotFile)
if err != nil {
Expand Down
Loading