Fix lint errors on files with //line directive (#1065)

If the target files contains `//line` directive and it indicates
a non-go file, the linter is going to handle it as a go file,
which results in failure.
The cause of this issue is that the linters (`Analyzer`s) are using
`pass.Fset.Position()`. This func returns the adjusted position using
`//line` directive.
The example project reported in #998 has `//line` directive that
indicates other non-go file.
According to the description of "Compiler Directives”
(https://golang.org/cmd/compile/#hdr-Compiler_Directives),
line directives is mainly used for reporting original positions to
the generators or something.
On linters of golangci-lint, `pass.Fset.Position()` is used just to
aggregate file names; we don't have to adjust positions.
This changes `Analyzer`s that use `pass.Fset.Position()` to aggregate
file names to use `pass.Fset.PositionFor()` with `adjusted == false`.

Relates: #998
This commit is contained in:
Soichiro Kashima 2020-05-06 00:49:34 +09:00 committed by GitHub
parent 279b6d62d3
commit 7f48cc88b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 78 additions and 8 deletions

View File

@ -34,7 +34,7 @@ func NewDupl() *goanalysis.Linter {
analyzer.Run = func(pass *analysis.Pass) (interface{}, error) {
var fileNames []string
for _, f := range pass.Files {
pos := pass.Fset.Position(f.Pos())
pos := pass.Fset.PositionFor(f.Pos(), false)
fileNames = append(fileNames, pos.Filename)
}

View File

@ -31,7 +31,7 @@ func NewGofmt() *goanalysis.Linter {
analyzer.Run = func(pass *analysis.Pass) (interface{}, error) {
var fileNames []string
for _, f := range pass.Files {
pos := pass.Fset.Position(f.Pos())
pos := pass.Fset.PositionFor(f.Pos(), false)
fileNames = append(fileNames, pos.Filename)
}

View File

@ -32,7 +32,7 @@ func NewGoimports() *goanalysis.Linter {
analyzer.Run = func(pass *analysis.Pass) (interface{}, error) {
var fileNames []string
for _, f := range pass.Files {
pos := pass.Fset.Position(f.Pos())
pos := pass.Fset.PositionFor(f.Pos(), false)
fileNames = append(fileNames, pos.Filename)
}

View File

@ -54,7 +54,7 @@ func NewGomodguard() *goanalysis.Linter {
}
for _, file := range pass.Files {
files = append(files, pass.Fset.Position(file.Pos()).Filename)
files = append(files, pass.Fset.PositionFor(file.Pos(), false).Filename)
}
processor, err := gomodguard.NewProcessor(processorCfg, log.New(os.Stderr, "", 0))

View File

@ -31,7 +31,7 @@ func NewIneffassign() *goanalysis.Linter {
analyzer.Run = func(pass *analysis.Pass) (interface{}, error) {
var fileNames []string
for _, f := range pass.Files {
pos := pass.Fset.Position(f.Pos())
pos := pass.Fset.PositionFor(f.Pos(), false)
fileNames = append(fileNames, pos.Filename)
}

View File

@ -92,7 +92,7 @@ func NewLLL() *goanalysis.Linter {
analyzer.Run = func(pass *analysis.Pass) (interface{}, error) {
var fileNames []string
for _, f := range pass.Files {
pos := pass.Fset.Position(f.Pos())
pos := pass.Fset.PositionFor(f.Pos(), false)
fileNames = append(fileNames, pos.Filename)
}

View File

@ -102,7 +102,7 @@ func NewMisspell() *goanalysis.Linter {
var fileNames []string
for _, f := range pass.Files {
pos := pass.Fset.Position(f.Pos())
pos := pass.Fset.PositionFor(f.Pos(), false)
fileNames = append(fileNames, pos.Filename)
}

View File

@ -52,7 +52,7 @@ func NewWSL() *goanalysis.Linter {
)
for _, file := range pass.Files {
files = append(files, pass.Fset.Position(file.Pos()).Filename)
files = append(files, pass.Fset.PositionFor(file.Pos(), false).Filename)
}
wslErrors, _ := wsl.NewProcessorWithConfig(processorCfg).

View File

@ -137,6 +137,27 @@ func TestLineDirectiveProcessedFilesFullLoading(t *testing.T) {
r.ExpectExitCode(exitcodes.IssuesFound).ExpectOutputEq(output + "\n")
}
func TestLintFilesWithLineDirective(t *testing.T) {
testshared.NewLintRunner(t).Run("-Edupl", "--disable-all", "--config=testdata/linedirective/dupl.yml", getTestDataDir("linedirective")).
ExpectHasIssue("21-23 lines are duplicate of `testdata/linedirective/hello.go:25-27` (dupl)")
testshared.NewLintRunner(t).Run("-Egofmt", "--disable-all", "--no-config", getTestDataDir("linedirective")).
ExpectHasIssue("File is not `gofmt`-ed with `-s` (gofmt)")
testshared.NewLintRunner(t).Run("-Egoimports", "--disable-all", "--no-config", getTestDataDir("linedirective")).
ExpectHasIssue("File is not `goimports`-ed (goimports)")
testshared.NewLintRunner(t).
Run("-Egomodguard", "--disable-all", "--config=testdata/linedirective/gomodguard.yml", getTestDataDir("linedirective")).
ExpectHasIssue("import of package `github.com/ryancurrah/gomodguard` is blocked because the module is not " +
"in the allowed modules list. (gomodguard)")
testshared.NewLintRunner(t).Run("-Eineffassign", "--disable-all", "--no-config", getTestDataDir("linedirective")).
ExpectHasIssue("ineffectual assignment to `x` (ineffassign)")
testshared.NewLintRunner(t).Run("-Elll", "--disable-all", "--config=testdata/linedirective/lll.yml", getTestDataDir("linedirective")).
ExpectHasIssue("line is 57 characters (lll)")
testshared.NewLintRunner(t).Run("-Emisspell", "--disable-all", "--no-config", getTestDataDir("linedirective")).
ExpectHasIssue("is a misspelling of `language` (misspell)")
testshared.NewLintRunner(t).Run("-Ewsl", "--disable-all", "--no-config", getTestDataDir("linedirective")).
ExpectHasIssue("block should not start with a whitespace (wsl)")
}
func TestSkippedDirsNoMatchArg(t *testing.T) {
dir := getTestDataDir("skipdirs", "skip_me", "nested")
r := testshared.NewLintRunner(t).Run("--print-issued-lines=false", "--no-config", "--skip-dirs", dir, "-Egolint", dir)

3
test/testdata/linedirective/dupl.yml vendored Normal file
View File

@ -0,0 +1,3 @@
linters-settings:
dupl:
threshold: 10

View File

@ -0,0 +1,5 @@
linters-settings:
gomodguard:
allowed:
domains:
- golang.org

37
test/testdata/linedirective/hello.go vendored Normal file
View File

@ -0,0 +1,37 @@
// Refers a existent, but non-go file with line directive
//line hello.tmpl:1
package main
import (
"github.com/ryancurrah/gomodguard"
)
func _() {
var x int
_ = x
x = 0 //x
}
func main() {
a()
b()
wsl()
}
func a() {
fmt.Println("foo")
}
func b() {
fmt.Println("foo")
}
func wsl() bool {
return true
}
func notFormatted() {
}
// langauge

View File

@ -0,0 +1 @@
# This is a template file for some code generator, and is not a valid go source file.

3
test/testdata/linedirective/lll.yml vendored Normal file
View File

@ -0,0 +1,3 @@
linters-settings:
lll:
line-length: 50