diff --git a/README.md b/README.md index f2f74411..873d2c81 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,7 @@ formatting. | FusionScript | [fusion-lint](https://github.com/RyanSquared/fusionscript) | | Git Commit Messages | [gitlint](https://github.com/jorisroovers/gitlint) | | GLSL | [glslang](https://github.com/KhronosGroup/glslang), [glslls](https://github.com/svenstaro/glsl-language-server) | -| Go | [gofmt](https://golang.org/cmd/gofmt/), [goimports](https://godoc.org/golang.org/x/tools/cmd/goimports), [go vet](https://golang.org/cmd/vet/) !!, [golint](https://godoc.org/github.com/golang/lint), [gotype](https://godoc.org/golang.org/x/tools/cmd/gotype) !!, [gometalinter](https://github.com/alecthomas/gometalinter) !!, [go build](https://golang.org/cmd/go/) !!, [gosimple](https://github.com/dominikh/go-tools/tree/master/cmd/gosimple) !!, [staticcheck](https://github.com/dominikh/go-tools/tree/master/cmd/staticcheck) !!, [golangserver](https://github.com/sourcegraph/go-langserver) | +| Go | [gofmt](https://golang.org/cmd/gofmt/), [goimports](https://godoc.org/golang.org/x/tools/cmd/goimports), [go vet](https://golang.org/cmd/vet/) !!, [golint](https://godoc.org/github.com/golang/lint), [gotype](https://godoc.org/golang.org/x/tools/cmd/gotype) !!, [gometalinter](https://github.com/alecthomas/gometalinter) !!, [go build](https://golang.org/cmd/go/) !!, [gosimple](https://github.com/dominikh/go-tools/tree/master/cmd/gosimple) !!, [staticcheck](https://github.com/dominikh/go-tools/tree/master/cmd/staticcheck) !!, [golangserver](https://github.com/sourcegraph/go-langserver), [golangci-lint](https://github.com/golangci/golangci-lint) !! | | GraphQL | [eslint](http://eslint.org/), [gqlint](https://github.com/happylinks/gqlint), [prettier](https://github.com/prettier/prettier) | | Hack | [hack](http://hacklang.org/), [hackfmt](https://github.com/facebook/hhvm/tree/master/hphp/hack/hackfmt), [hhast](https://github.com/hhvm/hhast) (disabled by default; see `:help ale-integration-hack`) | | Haml | [haml-lint](https://github.com/brigade/haml-lint) | diff --git a/ale_linters/go/golangci_lint.vim b/ale_linters/go/golangci_lint.vim new file mode 100644 index 00000000..b44a6239 --- /dev/null +++ b/ale_linters/go/golangci_lint.vim @@ -0,0 +1,56 @@ +" Author: Sascha Grunert +" Description: Adds support of golangci-lint + +call ale#Set('go_golangci_lint_options', '--enable-all') +call ale#Set('go_golangci_lint_executable', 'golangci-lint') +call ale#Set('go_golangci_lint_package', 0) + +function! ale_linters#go#golangci_lint#GetCommand(buffer) abort + let l:filename = expand('#' . a:buffer . ':t') + let l:options = ale#Var(a:buffer, 'go_golangci_lint_options') + let l:lint_package = ale#Var(a:buffer, 'go_golangci_lint_package') + + if l:lint_package + return ale#path#BufferCdString(a:buffer) + \ . '%e run ' + \ . l:options + endif + + return ale#path#BufferCdString(a:buffer) + \ . '%e run ' + \ . ale#util#EscapePCRE(l:filename) + \ . ' ' . l:options +endfunction + +function! ale_linters#go#golangci_lint#GetMatches(lines) abort + let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):?(\d+)?:?:?:?\s\*?(.+)$' + + return ale#util#GetMatches(a:lines, l:pattern) +endfunction + +function! ale_linters#go#golangci_lint#Handler(buffer, lines) abort + let l:dir = expand('#' . a:buffer . ':p:h') + let l:output = [] + + for l:match in ale_linters#go#golangci_lint#GetMatches(a:lines) + " l:match[1] will already be an absolute path, output from + " golangci_lint + call add(l:output, { + \ 'filename': ale#path#GetAbsPath(l:dir, l:match[1]), + \ 'lnum': l:match[2] + 0, + \ 'col': l:match[3] + 0, + \ 'type': 'E', + \ 'text': l:match[4], + \}) + endfor + + return l:output +endfunction + +call ale#linter#Define('go', { +\ 'name': 'golangci-lint', +\ 'executable_callback': ale#VarFunc('go_golangci_lint_executable'), +\ 'command_callback': 'ale_linters#go#golangci_lint#GetCommand', +\ 'callback': 'ale_linters#go#golangci_lint#Handler', +\ 'lint_file': 1, +\}) diff --git a/doc/ale-go.txt b/doc/ale-go.txt index c97f599e..1d55763e 100644 --- a/doc/ale-go.txt +++ b/doc/ale-go.txt @@ -134,5 +134,38 @@ g:ale_go_langserver_options *g:ale_go_langserver_options* by the |g:ale_completion_enabled| variable. +=============================================================================== +golangci-lint *ale-go-golangci-lint* + +`golangci-lint` is a `lint_file` linter, which only lints files that are +written to disk. This differs from the default behavior of linting the buffer. +See: |ale-lint-file| + +g:ale_go_golangci_lint_executable *g:ale_go_golangci_lint_executable* + *b:ale_go_golangci_lint_executable* + Type: |String| + Default: `'golangci-lint'` + + The executable that will be run for golangci-lint. + + +g:ale_go_golangci_lint_options *g:ale_go_golangci_lint_options* + *b:ale_go_golangci_lint_options* + Type: |String| + Default: `'--enable-all'` + + This variable can be changed to alter the command-line arguments to the + golangci-lint invocation. + + +g:ale_go_golangci_lint_package *g:ale_go_golangci_lint_package* + *b:ale_go_golangci_lint_package* + Type: |Number| + Default: `0` + + When set to `1`, the whole Go package will be checked instead of only the + current file. + + =============================================================================== vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl: diff --git a/doc/ale.txt b/doc/ale.txt index da7abcf1..e08946e5 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -96,6 +96,7 @@ CONTENTS *ale-contents* gometalinter........................|ale-go-gometalinter| staticcheck.........................|ale-go-staticcheck| golangserver........................|ale-go-golangserver| + golangci-lint.......................|ale-go-golangci-lint| graphql...............................|ale-graphql-options| eslint..............................|ale-graphql-eslint| gqlint..............................|ale-graphql-gqlint| @@ -385,7 +386,7 @@ Notes: * FusionScript: `fusion-lint` * Git Commit Messages: `gitlint` * GLSL: glslang, `glslls` -* Go: `gofmt`, `goimports`, `go vet`!!, `golint`, `gotype`!!, `gometalinter`!!, `go build`!!, `gosimple`!!, `staticcheck`!!, `golangserver` +* Go: `gofmt`, `goimports`, `go vet`!!, `golint`, `gotype`!!, `gometalinter`!!, `go build`!!, `gosimple`!!, `staticcheck`!!, `golangserver`, `golangci-lint`!! * GraphQL: `eslint`, `gqlint`, `prettier` * Hack: `hack`, `hackfmt`, `hhast` * Haml: `haml-lint` diff --git a/test/command_callback/test_golangci_lint_command_callback.vader b/test/command_callback/test_golangci_lint_command_callback.vader new file mode 100644 index 00000000..6cb73246 --- /dev/null +++ b/test/command_callback/test_golangci_lint_command_callback.vader @@ -0,0 +1,38 @@ +Before: + call ale#assert#SetUpLinterTest('go', 'golangci_lint') + call ale#test#SetFilename('test.go') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The golangci-lint defaults should be correct): + AssertLinter 'golangci-lint', + \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ . ale#Escape('golangci-lint') + \ . ' run ' . ale#util#EscapePCRE(expand('%' . ':t')) + \ . ' --enable-all' + +Execute(The golangci-lint callback should use a configured executable): + let b:ale_go_golangci_lint_executable = 'something else' + + AssertLinter 'something else', + \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ . ale#Escape('something else') + \ . ' run ' . ale#util#EscapePCRE(expand('%' . ':t')) + \ . ' --enable-all' + +Execute(The golangci-lint callback should use configured options): + let b:ale_go_golangci_lint_options = '--foobar' + + AssertLinter 'golangci-lint', + \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ . ale#Escape('golangci-lint') + \ . ' run ' . ale#util#EscapePCRE(expand('%' . ':t')) + \ . ' --foobar' + +Execute(The golangci-lint `lint_package` option should use the correct command): + let b:ale_go_golangci_lint_package = 1 + + AssertLinter 'golangci-lint', + \ 'cd ' . ale#Escape(expand('%:p:h')) . ' && ' + \ . ale#Escape('golangci-lint') . ' run --enable-all' diff --git a/test/handler/test_golangci_lint_handler.vader b/test/handler/test_golangci_lint_handler.vader new file mode 100644 index 00000000..fb6841f4 --- /dev/null +++ b/test/handler/test_golangci_lint_handler.vader @@ -0,0 +1,55 @@ +Before: + runtime ale_linters/go/golangci_lint.vim + +After: + call ale#linter#Reset() + +Execute (The golangci-lint handler should handle names with spaces): + " We can't test Windows paths with the path resovling on Linux, but we can + " test the regex. + AssertEqual + \ [ + \ [ + \ 'C:\something\file with spaces.go', + \ '12', + \ '3', + \ 'expected ''package'', found ''IDENT'' gibberish (staticcheck)', + \ ], + \ [ + \ 'C:\something\file with spaces.go', + \ '37', + \ '5', + \ 'expected ''package'', found ''IDENT'' gibberish (golint)', + \ ], + \ ], + \ map(ale_linters#go#golangci_lint#GetMatches([ + \ 'C:\something\file with spaces.go:12:3: expected ''package'', found ''IDENT'' gibberish (staticcheck)', + \ 'C:\something\file with spaces.go:37:5: expected ''package'', found ''IDENT'' gibberish (golint)', + \ ]), 'v:val[1:4]') + +Execute (The golangci-lint handler should handle paths correctly): + call ale#test#SetFilename('app/test.go') + + let file = ale#path#GetAbsPath(expand('%:p:h'), 'test.go') + + AssertEqual + \ [ + \ { + \ 'lnum': 12, + \ 'col': 3, + \ 'text': 'expected ''package'', found ''IDENT'' gibberish (staticcheck)', + \ 'type': 'E', + \ 'filename': ale#path#Simplify(expand('%:p:h') . '/test.go'), + \ }, + \ { + \ 'lnum': 37, + \ 'col': 5, + \ 'text': 'expected ''package'', found ''IDENT'' gibberish (golint)', + \ 'type': 'E', + \ 'filename': ale#path#Simplify(expand('%:p:h') . '/test.go'), + \ }, + \ ], + \ ale_linters#go#golangci_lint#Handler(bufnr(''), [ + \ file . ':12:3: expected ''package'', found ''IDENT'' gibberish (staticcheck)', + \ file . ':37:5: expected ''package'', found ''IDENT'' gibberish (golint)', + \ ])