Skip to content

Commit e184f97

Browse files
authored
chore: extract comment shortener into dedicated package
1 parent cb15abe commit e184f97

File tree

8 files changed

+164
-31
lines changed

8 files changed

+164
-31
lines changed

shorten/.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
/testdata/** text eol=lf
22
/internal/graph/testdata/** text eol=lf
3+
/internal/comments/testdata/** text eol=lf

shorten/annotations.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ package shorten
33
import (
44
"strings"
55

6+
"github.com/golangci/golines/shorten/internal"
67
"github.com/golangci/golines/shorten/internal/annotation"
8+
"github.com/golangci/golines/shorten/internal/comments"
79
)
810

911
// annotateLongLines adds specially formatted comments to all eligible lines that
@@ -17,7 +19,7 @@ func (s *Shortener) annotateLongLines(lines []string) ([]string, int) {
1719
prevLen := -1
1820

1921
for _, line := range lines {
20-
length := s.lineLen(line)
22+
length := internal.LineLength(line, s.config.TabLen)
2123

2224
if prevLen > -1 {
2325
if length <= s.config.MaxLen {
@@ -28,7 +30,7 @@ func (s *Shortener) annotateLongLines(lines []string) ([]string, int) {
2830
annotatedLines[len(annotatedLines)-1] = annotation.Create(length)
2931
linesToShorten++
3032
}
31-
} else if !isComment(line) && length > s.config.MaxLen {
33+
} else if !comments.Is(line) && length > s.config.MaxLen {
3234
annotatedLines = append(
3335
annotatedLines,
3436
annotation.Create(length),

shorten/comments.go renamed to shorten/internal/comments/comments.go

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,48 @@
1-
package shorten
1+
package comments
22

33
import (
44
"fmt"
55
"regexp"
66
"strings"
77

8+
"github.com/golangci/golines/shorten/internal"
89
"github.com/golangci/golines/shorten/internal/annotation"
910
)
1011

12+
// Shortener is a struct that can be used to shorten long comments.
13+
//
14+
// As noted in the repo README,
15+
// this functionality has some quirks and is disabled by default.
16+
type Shortener struct {
17+
MaxLen int
18+
TabLen int
19+
}
20+
1121
// Go directive (should be ignored).
1222
// https://go.dev/doc/comment#syntax
1323
var directivePattern = regexp.MustCompile(`\s*//(line |extern |export |[a-z0-9]+:[a-z0-9])`)
1424

15-
// shortenCommentsFunc attempts to shorten long comments in the provided source.
25+
// Process attempts to shorten long comments in the provided source.
1626
//
1727
// As noted in the repo README,
1828
// this functionality has some quirks and is disabled by default.
19-
func (s *Shortener) shortenCommentsFunc(content []byte) []byte {
29+
func (s *Shortener) Process(content []byte) []byte {
30+
if len(content) == 0 {
31+
return content
32+
}
33+
2034
var cleanedLines []string
2135

22-
var words []string // all words in a contiguous sequence of long comments
36+
// all words in a contiguous sequence of long comments
37+
var words []string
2338

2439
prefix := ""
2540

2641
lines := strings.SplitSeq(string(content), "\n")
2742
for line := range lines {
28-
if isComment(line) && !annotation.Is(line) &&
43+
if Is(line) && !annotation.Is(line) &&
2944
!isDirective(line) &&
30-
s.lineLen(line) > s.config.MaxLen {
45+
internal.LineLength(line, s.TabLen) > s.MaxLen {
3146
start := strings.Index(line, "//")
3247
prefix = line[0:(start + 2)]
3348
trimmedLine := strings.Trim(line[(start+2):], " ")
@@ -39,7 +54,7 @@ func (s *Shortener) shortenCommentsFunc(content []byte) []byte {
3954

4055
var currLineWords []string
4156

42-
maxCommentLen := s.config.MaxLen - s.lineLen(prefix)
57+
maxCommentLen := s.MaxLen - internal.LineLength(prefix, s.TabLen)
4358
for _, word := range words {
4459
if currLineLen > 0 && currLineLen+1+len(word) > maxCommentLen {
4560
cleanedLines = append(
@@ -78,12 +93,12 @@ func (s *Shortener) shortenCommentsFunc(content []byte) []byte {
7893
return []byte(strings.Join(cleanedLines, "\n"))
7994
}
8095

96+
// Is determines whether the provided line is a non-block comment.
97+
func Is(line string) bool {
98+
return strings.HasPrefix(strings.Trim(line, " \t"), "//")
99+
}
100+
81101
// isDirective determines whether the provided line is a directive, e.g., for `go:generate`.
82102
func isDirective(line string) bool {
83103
return directivePattern.MatchString(line)
84104
}
85-
86-
// isComment determines whether the provided line is a non-block comment.
87-
func isComment(line string) bool {
88-
return strings.HasPrefix(strings.Trim(line, " \t"), "//")
89-
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package comments
2+
3+
import (
4+
"os"
5+
"testing"
6+
7+
"github.com/stretchr/testify/assert"
8+
"github.com/stretchr/testify/require"
9+
)
10+
11+
func TestShortener_Process(t *testing.T) {
12+
cs := &Shortener{MaxLen: 100, TabLen: 4}
13+
14+
src, err := os.ReadFile("testdata/comments.go")
15+
require.NoError(t, err)
16+
17+
result := cs.Process(src)
18+
19+
expectedContent, err := os.ReadFile("testdata/comments.go.golden")
20+
require.NoError(t, err)
21+
22+
assert.Equal(t, string(expectedContent), string(result))
23+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package testdata
2+
3+
import "fmt"
4+
5+
// Short prefix
6+
// This is a really, really long comment on a single line. We should try to break it up if possible because it's longer than 100 chars. In fact, it's so long that it should probably be on three lines instead of two. Wow, so long!!
7+
// Short suffix
8+
//
9+
10+
// This comment contains multiple contiguous lines which are greater than the target maximum line length.
11+
// The expected result is a sequence of shortened (reflown) lines without preserving the position of line breaks.
12+
13+
// Another comment
14+
15+
/*
16+
A block comment. Really long lines in here aren't currently processed because they're a bit harder to handle.
17+
18+
func(aReallyLongArgument string, anotherReallyLongArgument string, aThirdReallyLongArgument string) (string, error) {
19+
return "", nil
20+
}
21+
*/
22+
//go:generate this is a really long go generate line. We don't want to shorten this because that could cause problems running go generate.
23+
func _() {
24+
for i := 0; i < 10; i++ {
25+
if i > 5 {
26+
// This is a another really, really long comment on a single line. We should try to break it up if possible because it's longer than 100 chars.
27+
fmt.Print("hello")
28+
29+
// These are comments like the ones in https://github.com/segmentio/golines/issues/9
30+
//
31+
// Documentation: https://swagger.io/docs/specification/authentication/bearer-authentication/more/more/more/more/more
32+
//
33+
// More documentation:
34+
// https://swagger.io/docs/specification/authentication/bearer-authentication/more/more/more/more/more
35+
fmt.Println("Hello again")
36+
}
37+
}
38+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package testdata
2+
3+
import "fmt"
4+
5+
// Short prefix
6+
// This is a really, really long comment on a single line. We should try to break it up if possible
7+
// because it's longer than 100 chars. In fact, it's so long that it should probably be on three
8+
// lines instead of two. Wow, so long!!
9+
// Short suffix
10+
//
11+
12+
// This comment contains multiple contiguous lines which are greater than the target maximum line
13+
// length. The expected result is a sequence of shortened (reflown) lines without preserving the
14+
// position of line breaks.
15+
16+
// Another comment
17+
18+
/*
19+
A block comment. Really long lines in here aren't currently processed because they're a bit harder to handle.
20+
21+
func(aReallyLongArgument string, anotherReallyLongArgument string, aThirdReallyLongArgument string) (string, error) {
22+
return "", nil
23+
}
24+
*/
25+
//go:generate this is a really long go generate line. We don't want to shorten this because that could cause problems running go generate.
26+
func _() {
27+
for i := 0; i < 10; i++ {
28+
if i > 5 {
29+
// This is a another really, really long comment on a single line. We should try to
30+
// break it up if possible because it's longer than 100 chars.
31+
fmt.Print("hello")
32+
33+
// These are comments like the ones in https://github.com/segmentio/golines/issues/9
34+
//
35+
// Documentation:
36+
// https://swagger.io/docs/specification/authentication/bearer-authentication/more/more/more/more/more
37+
//
38+
// More documentation:
39+
// https://swagger.io/docs/specification/authentication/bearer-authentication/more/more/more/more/more
40+
fmt.Println("Hello again")
41+
}
42+
}
43+
}

shorten/internal/line.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package internal
2+
3+
// LineLength gets the width of the provided line after tab expansion.
4+
func LineLength(line string, tabLen int) int {
5+
length := 0
6+
7+
for _, char := range line {
8+
if char == '\t' {
9+
length += tabLen
10+
} else {
11+
length++
12+
}
13+
}
14+
15+
return length
16+
}

shorten/shortener.go

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010

1111
"github.com/dave/dst"
1212
"github.com/dave/dst/decorator"
13+
"github.com/golangci/golines/shorten/internal/comments"
1314
"github.com/golangci/golines/shorten/internal/graph"
1415
"github.com/golangci/golines/shorten/internal/tags"
1516
)
@@ -72,6 +73,8 @@ func WithLogger(logger Logger) Options {
7273
type Shortener struct {
7374
config *Config
7475

76+
cs *comments.Shortener
77+
7578
logger Logger
7679
}
7780

@@ -86,6 +89,13 @@ func NewShortener(config *Config, opts ...Options) *Shortener {
8689
logger: &noopLogger{},
8790
}
8891

92+
if config.ShortenComments {
93+
s.cs = &comments.Shortener{
94+
MaxLen: config.MaxLen,
95+
TabLen: config.TabLen,
96+
}
97+
}
98+
8999
for _, opt := range opts {
90100
opt(s)
91101
}
@@ -173,8 +183,8 @@ func (s *Shortener) Process(content []byte) ([]byte, error) {
173183
content = removeAnnotations(content)
174184
}
175185

176-
if s.config.ShortenComments {
177-
content = s.shortenCommentsFunc(content)
186+
if s.cs != nil {
187+
content = s.cs.Process(content)
178188
}
179189

180190
// Do the final round of non-line-length-aware formatting after we've fixed up the comments
@@ -186,21 +196,6 @@ func (s *Shortener) Process(content []byte) ([]byte, error) {
186196
return content, nil
187197
}
188198

189-
// lineLen gets the width of the provided line after tab expansion.
190-
func (s *Shortener) lineLen(line string) int {
191-
length := 0
192-
193-
for _, char := range line {
194-
if char == '\t' {
195-
length += s.config.TabLen
196-
} else {
197-
length++
198-
}
199-
}
200-
201-
return length
202-
}
203-
204199
func (s *Shortener) createDot(result dst.Node) error {
205200
dotFile, err := os.Create(s.config.DotFile)
206201
if err != nil {

0 commit comments

Comments
 (0)