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  }