diff --git a/README.md b/README.md index 63f8fa3..0e603a6 100644 --- a/README.md +++ b/README.md @@ -277,6 +277,7 @@ List of all available rules. The rules ported from `golint` are left unchanged a | `waitgroup-by-value` | n/a | Warns on functions taking sync.WaitGroup as a by-value parameter | no | no | | `atomic` | n/a | Check for common mistaken usages of the `sync/atomic` package | no | no | | `empty-lines` | n/a | Warns when there are heading or trailing newlines in a block | no | no | +| `line-lenght-limit` | int | Specifies the maximum number of characters in a line | no | no | ## Configurable rules @@ -410,4 +411,3 @@ Currently, type checking is enabled by default. If you want to run the linter wi ## License MIT - diff --git a/config.go b/config.go index be7569b..d6b1a6b 100644 --- a/config.go +++ b/config.go @@ -71,6 +71,7 @@ var allRules = append([]lint.Rule{ &rule.WaitGroupByValueRule{}, &rule.AtomicRule{}, &rule.EmptyLinesRule{}, + &rule.LineLengthLimitRule{}, }, defaultRules...) var allFormatters = []lint.Formatter{ diff --git a/fixtures/line-length-limit.go b/fixtures/line-length-limit.go new file mode 100644 index 0000000..abc1200 --- /dev/null +++ b/fixtures/line-length-limit.go @@ -0,0 +1,7 @@ +package fixtures + +import "fmt" + +func foo(a, b int) { + fmt.Printf("single line characters out of limit") // MATCH /line is 105 characters, out of limit 100/ +} diff --git a/rule/line-length-limit.go b/rule/line-length-limit.go new file mode 100644 index 0000000..06a7050 --- /dev/null +++ b/rule/line-length-limit.go @@ -0,0 +1,85 @@ +package rule + +import ( + "bufio" + "bytes" + "fmt" + "go/token" + "strings" + "unicode/utf8" + + "github.com/mgechev/revive/lint" +) + +// LineLengthLimitRule lints given else constructs. +type LineLengthLimitRule struct{} + +// Apply applies the rule to given file. +func (r *LineLengthLimitRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { + if len(arguments) != 1 { + panic(`invalid configuration for "line-length-limit"`) + } + + max, ok := arguments[0].(int64) // Alt. non panicking version + if !ok || max < 0 { + panic(`invalid value passed as argument number to the "line-length-limit" rule`) + } + + var failures []lint.Failure + checker := lintLineLengthNum{ + max: int(max), + file: file, + onFailure: func(failure lint.Failure) { + failures = append(failures, failure) + }, + } + + checker.check() + + return failures +} + +// Name returns the rule name. +func (r *LineLengthLimitRule) Name() string { + return "line-length-limit" +} + +type lintLineLengthNum struct { + max int + file *lint.File + onFailure func(lint.Failure) +} + +func (r lintLineLengthNum) check() { + f := bytes.NewReader(r.file.Content()) + spaces := strings.Repeat(" ", 4) // tab width = 4 + l := 1 + s := bufio.NewScanner(f) + for s.Scan() { + t := s.Text() + t = strings.Replace(t, "\t", spaces, -1) + c := utf8.RuneCountInString(t) + if c > r.max { + r.onFailure(lint.Failure{ + Category: "code-style", + Position: lint.FailurePosition{ + // Offset not set; it is non-trivial, and doesn't appear to be needed. + Start: token.Position{ + Filename: r.file.Name, + Line: l, + Column: 0, + }, + End: token.Position{ + Filename: r.file.Name, + Line: l, + Column: c, + }, + }, + Confidence: 1, + Failure: fmt.Sprintf("line is %d characters, out of limit %d", c, r.max), + URL: "", + }) + } + l++ + } +} diff --git a/test/line-length-limit_test.go b/test/line-length-limit_test.go new file mode 100644 index 0000000..24807db --- /dev/null +++ b/test/line-length-limit_test.go @@ -0,0 +1,14 @@ +package test + +import ( + "testing" + + "github.com/mgechev/revive/lint" + "github.com/mgechev/revive/rule" +) + +func TestLineLengthLimit(t *testing.T) { + testRule(t, "line-length-limit", &rule.LineLengthLimitRule{}, &lint.RuleConfig{ + Arguments: []interface{}{int64(100)}, + }) +} diff --git a/untyped.toml b/untyped.toml index b7ee1d2..c824dd0 100644 --- a/untyped.toml +++ b/untyped.toml @@ -16,3 +16,6 @@ [rule.range-val-in-closure] [rule.waitgroup-by-value] [rule.atomic] +[rule.empty-lines] +[rule.line-length-limit] + arguments = [200]