github.com/Johnny2210/revive@v1.0.8-0.20210625134200-febf37ccd0f5/rule/line-length-limit.go (about) 1 package rule 2 3 import ( 4 "bufio" 5 "bytes" 6 "fmt" 7 "go/token" 8 "strings" 9 "unicode/utf8" 10 11 "github.com/mgechev/revive/lint" 12 ) 13 14 // LineLengthLimitRule lints given else constructs. 15 type LineLengthLimitRule struct{} 16 17 // Apply applies the rule to given file. 18 func (r *LineLengthLimitRule) Apply(file *lint.File, arguments lint.Arguments) []lint.Failure { 19 if len(arguments) != 1 { 20 panic(`invalid configuration for "line-length-limit"`) 21 } 22 23 max, ok := arguments[0].(int64) // Alt. non panicking version 24 if !ok || max < 0 { 25 panic(`invalid value passed as argument number to the "line-length-limit" rule`) 26 } 27 28 var failures []lint.Failure 29 checker := lintLineLengthNum{ 30 max: int(max), 31 file: file, 32 onFailure: func(failure lint.Failure) { 33 failures = append(failures, failure) 34 }, 35 } 36 37 checker.check() 38 39 return failures 40 } 41 42 // Name returns the rule name. 43 func (r *LineLengthLimitRule) Name() string { 44 return "line-length-limit" 45 } 46 47 type lintLineLengthNum struct { 48 max int 49 file *lint.File 50 onFailure func(lint.Failure) 51 } 52 53 func (r lintLineLengthNum) check() { 54 f := bytes.NewReader(r.file.Content()) 55 spaces := strings.Repeat(" ", 4) // tab width = 4 56 l := 1 57 s := bufio.NewScanner(f) 58 for s.Scan() { 59 t := s.Text() 60 t = strings.Replace(t, "\t", spaces, -1) 61 c := utf8.RuneCountInString(t) 62 if c > r.max { 63 r.onFailure(lint.Failure{ 64 Category: "code-style", 65 Position: lint.FailurePosition{ 66 // Offset not set; it is non-trivial, and doesn't appear to be needed. 67 Start: token.Position{ 68 Filename: r.file.Name, 69 Line: l, 70 Column: 0, 71 }, 72 End: token.Position{ 73 Filename: r.file.Name, 74 Line: l, 75 Column: c, 76 }, 77 }, 78 Confidence: 1, 79 Failure: fmt.Sprintf("line is %d characters, out of limit %d", c, r.max), 80 }) 81 } 82 l++ 83 } 84 }