Skip to content
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

Add golangci-lint #1890

Merged
merged 4 commits into from
Sep 6, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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) |
Expand Down
56 changes: 56 additions & 0 deletions ale_linters/go/golangci_lint.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
" Author: Sascha Grunert <mail@saschagrunert.de>
" 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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is EscapePCRE correct here? l:filename doesn't seem to be a regular expression, but just a regular filename. The documentation isn't clear, but this tool also doesn't seem to accept regular expressions here:

[~tw/utils](master)% golangci-lint run '.*'
ERRO Running error: context loading failed: can't eval symlinks for path .*: lstat .*: no such file or directory
 3 [~tw/utils](master)% golangci-lint run ./...
[~tw/utils](master)%

I think it should be ale#util#EscapeVim or ale#Escape()?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change it to ale#Escape if that works instead.

\ . ' ' . 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,
\})
33 changes: 33 additions & 0 deletions doc/ale-go.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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:
3 changes: 2 additions & 1 deletion doc/ale.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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|
Expand Down Expand Up @@ -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`
Expand Down
38 changes: 38 additions & 0 deletions test/command_callback/test_golangci_lint_command_callback.vader
Original file line number Diff line number Diff line change
@@ -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'
55 changes: 55 additions & 0 deletions test/handler/test_golangci_lint_handler.vader
Original file line number Diff line number Diff line change
@@ -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)',
\ ])