Skip to content

Commit

Permalink
lint: max_line_length supports utf-8
Browse files Browse the repository at this point in the history
Signed-off-by: Yoan Blanc <[email protected]>
  • Loading branch information
greut committed Nov 22, 2019
1 parent b70c99e commit 311cf02
Show file tree
Hide file tree
Showing 8 changed files with 108 additions and 36 deletions.
2 changes: 2 additions & 0 deletions doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Package eclint is a set of linters to for the EditorConfig rules
package eclint
12 changes: 6 additions & 6 deletions files.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import (
// When args are given, it recursively walks into them.
func ListFiles(log logr.Logger, args ...string) ([]string, error) {
if len(args) == 0 {
fs, err := gitLsFiles(log, ".")
fs, err := GitLsFiles(log, ".")
if err == nil {
return fs, nil
}
Expand All @@ -28,11 +28,11 @@ func ListFiles(log logr.Logger, args ...string) ([]string, error) {
args = append(args, ".")
}

return walk(log, args...)
return Walk(log, args...)
}

// walk iterates on each path item recursively.
func walk(log logr.Logger, paths ...string) ([]string, error) {
// Walk iterates on each path item recursively.
func Walk(log logr.Logger, paths ...string) ([]string, error) {
files := make([]string, 0)
for _, path := range paths {
err := filepath.Walk(path, func(p string, i os.FileInfo, e error) error {
Expand All @@ -53,11 +53,11 @@ func walk(log logr.Logger, paths ...string) ([]string, error) {
return files, nil
}

// gitLsFiles returns the list of file based on what is in the git index.
// GitLsFiles returns the list of file based on what is in the git index.
//
// -z is mandatory as some repositories non-ASCII file names which creates
// quoted and escaped file names.
func gitLsFiles(log logr.Logger, path string) ([]string, error) {
func GitLsFiles(log logr.Logger, path string) ([]string, error) {
output, err := exec.Command("git", "ls-files", "-z", path).Output()
if err != nil {
return nil, err
Expand Down
15 changes: 8 additions & 7 deletions files_test.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package eclint
package eclint_test

import (
"fmt"
"os"
"testing"

tlogr "github.com/go-logr/logr/testing"
"gitlab.com/greut/eclint"
)

const (
Expand All @@ -17,7 +18,7 @@ const (
func TestListFiles(t *testing.T) {
l := tlogr.TestLogger{}
d := testdataSimple
fs, err := ListFiles(l, d)
fs, err := eclint.ListFiles(l, d)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -45,7 +46,7 @@ func TestListFilesNoArgs(t *testing.T) {
t.Fatal(err)
}

fs, err := ListFiles(l)
fs, err := eclint.ListFiles(l)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -78,7 +79,7 @@ func TestListFilesNoGit(t *testing.T) {
t.Fatal(err)
}

fs, err := ListFiles(l)
fs, err := eclint.ListFiles(l)
if err != nil {
t.Fatal(err)
}
Expand All @@ -90,7 +91,7 @@ func TestListFilesNoGit(t *testing.T) {
func TestWalk(t *testing.T) {
l := tlogr.TestLogger{}
d := testdataSimple
fs, err := walk(l, d)
fs, err := eclint.Walk(l, d)
if err != nil {
t.Fatal(err)
}
Expand All @@ -103,7 +104,7 @@ func TestGitLsFiles(t *testing.T) {
l := tlogr.TestLogger{}
d := testdataSimple

fs, err := gitLsFiles(l, d)
fs, err := eclint.GitLsFiles(l, d)
if err != nil {
t.Fatal(err)
}
Expand All @@ -121,7 +122,7 @@ func TestGitLsFilesFailure(t *testing.T) {
t.Fatal(err)
}

_, err = gitLsFiles(l, d)
_, err = eclint.GitLsFiles(l, d)
if err == nil {
t.Error("an error was expected")
}
Expand Down
8 changes: 4 additions & 4 deletions lint.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,18 +64,18 @@ func validate(r io.Reader, log logr.Logger, def *editorconfig.Definition) []erro
}
}

errs := readLines(r, func(index int, data []byte) error {
errs := ReadLines(r, func(index int, data []byte) error {
var err error

// The first line may contain the BOM for detecting some encodings
if index == 1 {
if index == 0 {
if def.Charset != "utf-8" && def.Charset != "latin1" {
charset = detectCharsetUsingBOM(data)

if def.Charset != "" && charset != def.Charset {
return validationError{
error: fmt.Sprintf("no %s prefix were found (got %q)", def.Charset, charset),
position: 1,
position: 0,
index: index,
line: data,
}
Expand Down Expand Up @@ -136,7 +136,7 @@ func validate(r io.Reader, log logr.Logger, def *editorconfig.Definition) []erro
if err == nil && maxLength > 0 && tabWidth > 0 {
// Remove any BOM from the first line.
d := data
if index == 1 && charset != "" {
if index == 0 && charset != "" {
for _, bom := range [][]byte{utf8Bom} {
if bytes.HasPrefix(data, bom) {
d = data[len(utf8Bom):]
Expand Down
6 changes: 3 additions & 3 deletions print.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ func PrintErrors(opt Option, filename string, errors []error) error {
if ve, ok := err.(validationError); ok {
log.V(4).Info("lint error", "error", ve)
if !opt.Summary {
vi := au.Green(strconv.Itoa(ve.index))
vp := au.Green(strconv.Itoa(ve.position))
vi := au.Green(strconv.Itoa(ve.index + 1))
vp := au.Green(strconv.Itoa(ve.position + 1))
fmt.Fprintf(stdout, "%s:%s: %s\n", vi, vp, ve.error)
l, err := errorAt(au, ve.line, ve.position-1)
l, err := errorAt(au, ve.line, ve.position)
if err != nil {
log.Error(err, "line formating failure", "error", ve)
return err
Expand Down
18 changes: 9 additions & 9 deletions scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import (
"io"
)

// lineFunc is the callback for a line.
// LineFunc is the callback for a line.
//
// It returns the line number starting from zero.
type lineFunc func(int, []byte) error
type LineFunc func(int, []byte) error

// splitLines works like bufio.ScanLines while keeping the line endings.
func splitLines(data []byte, atEOF bool) (int, []byte, error) {
// SplitLines works like bufio.ScanLines while keeping the line endings.
func SplitLines(data []byte, atEOF bool) (int, []byte, error) {
i := 0
for i < len(data) {
if data[i] == cr {
Expand All @@ -38,17 +38,17 @@ func splitLines(data []byte, atEOF bool) (int, []byte, error) {
return 0, nil, io.EOF
}

// readLines consumes the reader and emit each line via the lineFunc
// ReadLines consumes the reader and emit each line via the LineFunc
//
// Line numbering starts at 1. Scanner is pretty smart an will reuse
// Line numbering starts at 0. Scanner is pretty smart an will reuse
// its memory structure. This is somehing we explicitly avoid by copying
// the content to a new slice.
func readLines(r io.Reader, fn lineFunc) []error {
func ReadLines(r io.Reader, fn LineFunc) []error {
errs := make([]error, 0)
sc := bufio.NewScanner(r)
sc.Split(splitLines)
sc.Split(SplitLines)

i := 1
i := 0
for sc.Scan() {
l := sc.Bytes()
line := make([]byte, len(l))
Expand Down
70 changes: 70 additions & 0 deletions scanner_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package eclint_test

import (
"bytes"
"fmt"
"testing"

"gitlab.com/greut/eclint"
)

func TestReadLines(t *testing.T) {
tests := []struct {
Name string
File []byte
LineFunc eclint.LineFunc
}{
{
Name: "Empty file",
File: []byte(""),
LineFunc: func(i int, line []byte) error {
if i != 0 || len(line) > 0 {
return fmt.Errorf("more than one line found (%d), or non epmty line %q", i, line)
}
return nil
},
}, {
Name: "crlf",
File: []byte("\r\n\r\n"),
LineFunc: func(i int, line []byte) error {
if i > 1 || len(line) > 2 {
return fmt.Errorf("more than two lines found (%d), or non empty line %q", i, line)
}
return nil
},
}, {
Name: "cr",
File: []byte("\r\r"),
LineFunc: func(i int, line []byte) error {
if i > 1 || len(line) > 2 {
return fmt.Errorf("more than two lines found (%d), or non empty line %q", i, line)
}
return nil
},
}, {
Name: "lf",
File: []byte("\n\n"),
LineFunc: func(i int, line []byte) error {
if i > 1 || len(line) > 2 {
return fmt.Errorf("more than two lines found (%d), or non empty line %q", i, line)
}
return nil
},
},
}

for _, tc := range tests {
tc := tc

t.Run(tc.Name, func(t *testing.T) {
t.Parallel()

r := bytes.NewReader(tc.File)
errs := eclint.ReadLines(r, tc.LineFunc)
if len(errs) > 0 {
t.Errorf("no errors were expected, got some. %s", errs[0])
return
}
})
}
}
13 changes: 6 additions & 7 deletions validators.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,7 @@ func detectCharset(charset string, data []byte) error {

if len(results) > 0 {
return validationError{
error: fmt.Sprintf("detected charset %q does not match expected %q", results[0].Charset, charset),
position: 1,
error: fmt.Sprintf("detected charset %q does not match expected %q", results[0].Charset, charset),
}
}

Expand Down Expand Up @@ -146,15 +145,15 @@ func indentStyle(style string, size int, data []byte) error {
if data[i] == x {
return validationError{
error: fmt.Sprintf("indentation style mismatch expected %q (%s) got %q", c, style, x),
position: i + 1,
position: i,
}
}
if data[i] == cr || data[i] == lf || (size > 0 && i%size == 0) {
break
}
return validationError{
error: fmt.Sprintf("indentation size doesn't match expected %d, got %d", size, i),
position: i + 1,
position: i,
}
}

Expand All @@ -170,7 +169,7 @@ func trimTrailingWhitespace(data []byte) error {
if data[i] == space || data[i] == tab {
return validationError{
error: "line has some trailing whitespaces",
position: i + 1,
position: i,
}
}
break
Expand Down Expand Up @@ -198,7 +197,7 @@ func checkBlockComment(i int, prefix []byte, data []byte) error {
if !bytes.HasPrefix(data[i:], prefix) {
return validationError{
error: fmt.Sprintf("block_comment prefix %q was expected inside a block comment", string(prefix)),
position: i + 1,
position: i,
}
}
break
Expand Down Expand Up @@ -245,7 +244,7 @@ func MaxLineLength(maxLength int, tabWidth int, data []byte) error {
if length > maxLength {
return validationError{
error: fmt.Sprintf("line is too long (%d > %d)", length, maxLength),
position: breakingPosition + 1,
position: breakingPosition,
}
}

Expand Down

0 comments on commit 311cf02

Please sign in to comment.