-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Adding gofumpt #1177
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding gofumpt #1177
Changes from 7 commits
0368987
b44db2b
d16d013
dffb7b4
d77761d
a5fcffd
2fa559f
badf526
108fb8c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
package golinters | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"go/token" | ||
"io" | ||
"io/ioutil" | ||
"os" | ||
"sync" | ||
|
||
"golang.org/x/tools/go/analysis" | ||
"mvdan.cc/gofumpt/format" | ||
|
||
"github.com/golangci/golangci-lint/pkg/golinters/goanalysis" | ||
"github.com/golangci/golangci-lint/pkg/lint/linter" | ||
"github.com/golangci/golangci-lint/pkg/result" | ||
) | ||
|
||
const gofumptName = "gofumpt" | ||
|
||
func NewGofumpt() *goanalysis.Linter { | ||
var mu sync.Mutex | ||
var resIssues []goanalysis.Issue | ||
|
||
analyzer := &analysis.Analyzer{ | ||
Name: gofumptName, | ||
Doc: goanalysis.TheOnlyanalyzerDoc, | ||
} | ||
return goanalysis.NewLinter( | ||
gofumptName, | ||
"Gofumpt checks whether code was gofumpt-ed.", | ||
[]*analysis.Analyzer{analyzer}, | ||
nil, | ||
).WithContextSetter(func(lintCtx *linter.Context) { | ||
analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { | ||
var fileNames []string | ||
for _, f := range pass.Files { | ||
pos := pass.Fset.PositionFor(f.Pos(), false) | ||
fileNames = append(fileNames, pos.Filename) | ||
} | ||
|
||
var issues []goanalysis.Issue | ||
|
||
for _, f := range fileNames { | ||
input, err := ioutil.ReadFile(f) | ||
if err != nil { | ||
return nil, fmt.Errorf("unable to open file %s: %w", f, err) | ||
} | ||
output, err := format.Source(input, "") | ||
if err != nil { | ||
return nil, fmt.Errorf("error while running gofumpt: %w", err) | ||
} | ||
if !bytes.Equal(input, output) { | ||
reader, err := os.Open(f) | ||
if err != nil { | ||
return nil, fmt.Errorf("unable to open file %s: %w", f, err) | ||
} | ||
numberOfLines, err := lineCounter(reader) | ||
if err != nil { | ||
return nil, fmt.Errorf("unable to count the number of lines: %w", err) | ||
} | ||
|
||
issues = append(issues, goanalysis.NewIssue(&result.Issue{ | ||
FromLinter: gofumptName, | ||
Text: "File is not `gofumpt`-ed", | ||
Pos: token.Position{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If I'm not mistaken, gofumpt provides only as a public function a way to get the gofumpt-ed version of the file (as a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @tetafro Am I correct? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yeah, sorry, I didn't think of it.
I'm not sure if it's a right thing to do. Someone more experienced with golangci-lint architecture should answer. Anyway, if there's no easy way to do this, just skip my first comment. |
||
Filename: f, | ||
Line: numberOfLines, | ||
}, | ||
}, pass)) | ||
} | ||
} | ||
|
||
if len(issues) == 0 { | ||
return nil, nil | ||
} | ||
|
||
mu.Lock() | ||
resIssues = append(resIssues, issues...) | ||
mu.Unlock() | ||
|
||
return nil, nil | ||
} | ||
}).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { | ||
return resIssues | ||
}).WithLoadMode(goanalysis.LoadModeSyntax) | ||
} | ||
|
||
const bufferSize = 32 * 1024 | ||
|
||
func lineCounter(r io.Reader) (int, error) { | ||
buf := make([]byte, bufferSize) | ||
count := 0 | ||
lineSep := []byte{'\n'} | ||
|
||
for { | ||
c, err := r.Read(buf) | ||
count += bytes.Count(buf[:c], lineSep) | ||
|
||
switch { | ||
case err == io.EOF: | ||
return count, nil | ||
|
||
case err != nil: | ||
return count, err | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
//args: -Egofumpt | ||
package testdata | ||
|
||
import "fmt" | ||
|
||
func GofumptNewLine() { | ||
|
||
fmt.Println("foo") | ||
} | ||
|
||
// ERROR "File is not `gofumpt`-ed" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it really necessary? You've already read the file into
input
. Just use strings.Count.