summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--ale_linters/ruby/rubocop.vim32
-rw-r--r--ale_linters/ruby/standardrb.vim23
-rw-r--r--autoload/ale/fix/registry.vim5
-rw-r--r--autoload/ale/fixers/standardrb.vim23
-rw-r--r--autoload/ale/ruby.vim32
-rw-r--r--doc/ale-ruby.txt22
-rw-r--r--doc/ale.txt3
-rw-r--r--test/command_callback/ruby_paths/with_config/.standard.yml0
-rw-r--r--test/command_callback/test_standardrb_command_callback.vader29
-rw-r--r--test/fixers/test_standardrb_fixer_callback.vader54
-rw-r--r--test/handler/test_rubocop_handler.vader12
12 files changed, 198 insertions, 39 deletions
diff --git a/README.md b/README.md
index 5fcca8c7..39d8f501 100644
--- a/README.md
+++ b/README.md
@@ -182,7 +182,7 @@ formatting.
| reStructuredText | [alex](https://github.com/wooorm/alex) !!, [proselint](http://proselint.com/), [redpen](http://redpen.cc/), [rstcheck](https://github.com/myint/rstcheck), [vale](https://github.com/ValeLint/vale), [write-good](https://github.com/btford/write-good) |
| Re:VIEW | [redpen](http://redpen.cc/) |
| RPM spec | [rpmlint](https://github.com/rpm-software-management/rpmlint) (disabled by default; see `:help ale-integration-spec`) |
-| Ruby | [brakeman](http://brakemanscanner.org/) !!, [rails_best_practices](https://github.com/flyerhzm/rails_best_practices) !!, [reek](https://github.com/troessner/reek), [rubocop](https://github.com/bbatsov/rubocop), [ruby](https://www.ruby-lang.org), [rufo](https://github.com/ruby-formatter/rufo), [solargraph](https://solargraph.org) |
+| Ruby | [brakeman](http://brakemanscanner.org/) !!, [rails_best_practices](https://github.com/flyerhzm/rails_best_practices) !!, [reek](https://github.com/troessner/reek), [rubocop](https://github.com/bbatsov/rubocop), [ruby](https://www.ruby-lang.org), [rufo](https://github.com/ruby-formatter/rufo), [solargraph](https://solargraph.org), [standardrb](https://github.com/testdouble/standard) |
| Rust | [cargo](https://github.com/rust-lang/cargo) !! (see `:help ale-integration-rust` for configuration instructions), [rls](https://github.com/rust-lang-nursery/rls), [rustc](https://www.rust-lang.org/), [rustfmt](https://github.com/rust-lang-nursery/rustfmt) |
| SASS | [sass-lint](https://www.npmjs.com/package/sass-lint), [stylelint](https://github.com/stylelint/stylelint) |
| SCSS | [prettier](https://github.com/prettier/prettier), [sass-lint](https://www.npmjs.com/package/sass-lint), [scss-lint](https://github.com/brigade/scss-lint), [stylelint](https://github.com/stylelint/stylelint) |
diff --git a/ale_linters/ruby/rubocop.vim b/ale_linters/ruby/rubocop.vim
index 45218394..790ca82c 100644
--- a/ale_linters/ruby/rubocop.vim
+++ b/ale_linters/ruby/rubocop.vim
@@ -13,36 +13,6 @@ function! ale_linters#ruby#rubocop#GetCommand(buffer) abort
\ . ' --stdin ' . ale#Escape(expand('#' . a:buffer . ':p'))
endfunction
-function! ale_linters#ruby#rubocop#Handle(buffer, lines) abort
- try
- let l:errors = json_decode(a:lines[0])
- catch
- return []
- endtry
-
- if !has_key(l:errors, 'summary')
- \|| l:errors['summary']['offense_count'] == 0
- \|| empty(l:errors['files'])
- return []
- endif
-
- let l:output = []
-
- for l:error in l:errors['files'][0]['offenses']
- let l:start_col = l:error['location']['column'] + 0
- call add(l:output, {
- \ 'lnum': l:error['location']['line'] + 0,
- \ 'col': l:start_col,
- \ 'end_col': l:start_col + l:error['location']['length'] - 1,
- \ 'code': l:error['cop_name'],
- \ 'text': l:error['message'],
- \ 'type': ale_linters#ruby#rubocop#GetType(l:error['severity']),
- \})
- endfor
-
- return l:output
-endfunction
-
function! ale_linters#ruby#rubocop#GetType(severity) abort
if a:severity is? 'convention'
\|| a:severity is? 'warning'
@@ -57,5 +27,5 @@ call ale#linter#Define('ruby', {
\ 'name': 'rubocop',
\ 'executable_callback': ale#VarFunc('ruby_rubocop_executable'),
\ 'command_callback': 'ale_linters#ruby#rubocop#GetCommand',
-\ 'callback': 'ale_linters#ruby#rubocop#Handle',
+\ 'callback': 'ale#ruby#HandleRubocopOutput',
\})
diff --git a/ale_linters/ruby/standardrb.vim b/ale_linters/ruby/standardrb.vim
new file mode 100644
index 00000000..95e10934
--- /dev/null
+++ b/ale_linters/ruby/standardrb.vim
@@ -0,0 +1,23 @@
+" Author: Justin Searls https://github.com/searls, ynonp - https://github.com/ynonp, Eddie Lebow https://github.com/elebow
+" based on the ale rubocop linter
+" Description: StandardRB - Ruby Style Guide, with linter & automatic code fixer
+
+call ale#Set('ruby_standardrb_executable', 'standardrb')
+call ale#Set('ruby_standardrb_options', '')
+
+function! ale_linters#ruby#standardrb#GetCommand(buffer) abort
+ let l:executable = ale#Var(a:buffer, 'ruby_standardrb_executable')
+
+ return ale#handlers#ruby#EscapeExecutable(l:executable, 'standardrb')
+ \ . ' --format json --force-exclusion '
+ \ . ale#Var(a:buffer, 'ruby_standardrb_options')
+ \ . ' --stdin ' . ale#Escape(expand('#' . a:buffer . ':p'))
+endfunction
+
+" standardrb is based on RuboCop so the callback is the same
+call ale#linter#Define('ruby', {
+\ 'name': 'standardrb',
+\ 'executable_callback': ale#VarFunc('ruby_standardrb_executable'),
+\ 'command_callback': 'ale_linters#ruby#standardrb#GetCommand',
+\ 'callback': 'ale#ruby#HandleRubocopOutput',
+\})
diff --git a/autoload/ale/fix/registry.vim b/autoload/ale/fix/registry.vim
index 75fd1508..6a8fd382 100644
--- a/autoload/ale/fix/registry.vim
+++ b/autoload/ale/fix/registry.vim
@@ -115,6 +115,11 @@ let s:default_registry = {
\ 'suggested_filetypes': ['javascript'],
\ 'description': 'Fix JavaScript files using standard --fix',
\ },
+\ 'standardrb': {
+\ 'function': 'ale#fixers#standardrb#Fix',
+\ 'suggested_filetypes': ['ruby'],
+\ 'description': 'Fix ruby files with standardrb --fix',
+\ },
\ 'stylelint': {
\ 'function': 'ale#fixers#stylelint#Fix',
\ 'suggested_filetypes': ['css', 'sass', 'scss', 'stylus'],
diff --git a/autoload/ale/fixers/standardrb.vim b/autoload/ale/fixers/standardrb.vim
new file mode 100644
index 00000000..fab1e2bc
--- /dev/null
+++ b/autoload/ale/fixers/standardrb.vim
@@ -0,0 +1,23 @@
+" Author: Justin Searls - https://github.com/searls
+" Description: Fix Ruby files with StandardRB.
+
+call ale#Set('ruby_standardrb_options', '')
+call ale#Set('ruby_standardrb_executable', 'standardrb')
+
+function! ale#fixers#standardrb#GetCommand(buffer) abort
+ let l:executable = ale#Var(a:buffer, 'ruby_standardrb_executable')
+ let l:config = ale#path#FindNearestFile(a:buffer, '.standard.yml')
+ let l:options = ale#Var(a:buffer, 'ruby_standardrb_options')
+
+ return ale#handlers#ruby#EscapeExecutable(l:executable, 'standardrb')
+ \ . (!empty(l:config) ? ' --config ' . ale#Escape(l:config) : '')
+ \ . (!empty(l:options) ? ' ' . l:options : '')
+ \ . ' --fix --force-exclusion %t'
+endfunction
+
+function! ale#fixers#standardrb#Fix(buffer) abort
+ return {
+ \ 'command': ale#fixers#standardrb#GetCommand(a:buffer),
+ \ 'read_temporary_file': 1,
+ \}
+endfunction
diff --git a/autoload/ale/ruby.vim b/autoload/ale/ruby.vim
index 5f0aa50d..3d9c5a51 100644
--- a/autoload/ale/ruby.vim
+++ b/autoload/ale/ruby.vim
@@ -42,3 +42,35 @@ function! ale#ruby#FindProjectRoot(buffer) abort
return ''
endfunction
+
+" Handle output from rubocop and linters that depend on it (e.b. standardrb)
+function! ale#ruby#HandleRubocopOutput(buffer, lines) abort
+ try
+ let l:errors = json_decode(a:lines[0])
+ catch
+ return []
+ endtry
+
+ if !has_key(l:errors, 'summary')
+ \|| l:errors['summary']['offense_count'] == 0
+ \|| empty(l:errors['files'])
+ return []
+ endif
+
+ let l:output = []
+
+ for l:error in l:errors['files'][0]['offenses']
+ let l:start_col = l:error['location']['column'] + 0
+ call add(l:output, {
+ \ 'lnum': l:error['location']['line'] + 0,
+ \ 'col': l:start_col,
+ \ 'end_col': l:start_col + l:error['location']['length'] - 1,
+ \ 'code': l:error['cop_name'],
+ \ 'text': l:error['message'],
+ \ 'type': ale_linters#ruby#rubocop#GetType(l:error['severity']),
+ \})
+ endfor
+
+ return l:output
+endfunction
+
diff --git a/doc/ale-ruby.txt b/doc/ale-ruby.txt
index f8a41999..bf971e7c 100644
--- a/doc/ale-ruby.txt
+++ b/doc/ale-ruby.txt
@@ -130,4 +130,26 @@ g:ale_ruby_solargraph_executable *g:ale_ruby_solargraph_executable*
===============================================================================
+standardrb *ale-ruby-standardrb*
+
+g:ale_ruby_standardrb_executable *g:ale_ruby_standardrb_executable*
+ *b:ale_ruby_standardrb_executable*
+ Type: String
+ Default: `'standardrb'`
+
+ Override the invoked standardrb binary. Set this to `'bundle'` to invoke
+ `'bundle` `exec` standardrb'.
+
+
+g:ale_ruby_standardrb_options *g:ale_ruby_standardrb_options*
+ *b:ale_ruby_standardrb_options*
+ Type: |String|
+ Default: `''`
+
+ This variable can be change to modify flags given to standardrb.
+
+
+===============================================================================
+
+===============================================================================
vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl:
diff --git a/doc/ale.txt b/doc/ale.txt
index 87d4e017..0b127725 100644
--- a/doc/ale.txt
+++ b/doc/ale.txt
@@ -285,6 +285,7 @@ CONTENTS *ale-contents*
ruby................................|ale-ruby-ruby|
rufo................................|ale-ruby-rufo|
solargraph..........................|ale-ruby-solargraph|
+ standardrb..........................|ale-ruby-standardrb|
rust..................................|ale-rust-options|
cargo...............................|ale-rust-cargo|
rls.................................|ale-rust-rls|
@@ -486,7 +487,7 @@ Notes:
* reStructuredText: `alex`!!, `proselint`, `redpen`, `rstcheck`, `vale`, `write-good`
* Re:VIEW: `redpen`
* RPM spec: `rpmlint`
-* Ruby: `brakeman`, `rails_best_practices`!!, `reek`, `rubocop`, `ruby`, `rufo`, `solargraph`
+* Ruby: `brakeman`, `rails_best_practices`!!, `reek`, `rubocop`, `ruby`, `rufo`, `solargraph`, `standardrb`
* Rust: `cargo`!!, `rls`, `rustc` (see |ale-integration-rust|), `rustfmt`
* SASS: `sass-lint`, `stylelint`
* SCSS: `prettier`, `sass-lint`, `scss-lint`, `stylelint`
diff --git a/test/command_callback/ruby_paths/with_config/.standard.yml b/test/command_callback/ruby_paths/with_config/.standard.yml
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/test/command_callback/ruby_paths/with_config/.standard.yml
diff --git a/test/command_callback/test_standardrb_command_callback.vader b/test/command_callback/test_standardrb_command_callback.vader
new file mode 100644
index 00000000..7bc1c976
--- /dev/null
+++ b/test/command_callback/test_standardrb_command_callback.vader
@@ -0,0 +1,29 @@
+Before:
+ call ale#assert#SetUpLinterTest('ruby', 'standardrb')
+ call ale#test#SetFilename('dummy.rb')
+
+ let g:ale_ruby_standardrb_executable = 'standardrb'
+ let g:ale_ruby_standardrb_options = ''
+
+After:
+ call ale#assert#TearDownLinterTest()
+
+Execute(Executable should default to standardrb):
+ AssertLinter 'standardrb', ale#Escape('standardrb')
+ \ . ' --format json --force-exclusion --stdin '
+ \ . ale#Escape(ale#path#Simplify(g:dir . '/dummy.rb'))
+
+Execute(Should be able to set a custom executable):
+ let g:ale_ruby_standardrb_executable = 'bin/standardrb'
+
+ AssertLinter 'bin/standardrb' , ale#Escape('bin/standardrb')
+ \ . ' --format json --force-exclusion --stdin '
+ \ . ale#Escape(ale#path#Simplify(g:dir . '/dummy.rb'))
+
+Execute(Setting bundle appends 'exec standardrb'):
+ let g:ale_ruby_standardrb_executable = 'path to/bundle'
+
+ AssertLinter 'path to/bundle', ale#Escape('path to/bundle')
+ \ . ' exec standardrb'
+ \ . ' --format json --force-exclusion --stdin '
+ \ . ale#Escape(ale#path#Simplify(g:dir . '/dummy.rb'))
diff --git a/test/fixers/test_standardrb_fixer_callback.vader b/test/fixers/test_standardrb_fixer_callback.vader
new file mode 100644
index 00000000..99234b79
--- /dev/null
+++ b/test/fixers/test_standardrb_fixer_callback.vader
@@ -0,0 +1,54 @@
+Before:
+ Save g:ale_ruby_standardrb_executable
+ Save g:ale_ruby_standardrb_options
+
+ " Use an invalid global executable, so we don't match it.
+ let g:ale_ruby_standardrb_executable = 'xxxinvalid'
+ let g:ale_ruby_standardrb_options = ''
+
+ call ale#test#SetDirectory('/testplugin/test/fixers')
+ silent cd ..
+ silent cd command_callback
+ let g:dir = getcwd()
+
+After:
+ Restore
+
+ call ale#test#RestoreDirectory()
+
+Execute(The standardrb callback should return the correct default values):
+ call ale#test#SetFilename('ruby_paths/dummy.rb')
+
+ AssertEqual
+ \ {
+ \ 'read_temporary_file': 1,
+ \ 'command': ale#Escape(g:ale_ruby_standardrb_executable)
+ \ . ' --fix --force-exclusion %t',
+ \ },
+ \ ale#fixers#standardrb#Fix(bufnr(''))
+
+Execute(The standardrb callback should include configuration files):
+ call ale#test#SetFilename('ruby_paths/with_config/dummy.rb')
+
+ AssertEqual
+ \ {
+ \ 'read_temporary_file': 1,
+ \ 'command': ale#Escape(g:ale_ruby_standardrb_executable)
+ \ . ' --config ' . ale#Escape(ale#path#Simplify(g:dir . '/ruby_paths/with_config/.standard.yml'))
+ \ . ' --fix --force-exclusion %t',
+ \ },
+ \ ale#fixers#standardrb#Fix(bufnr(''))
+
+Execute(The standardrb callback should include custom rubocop options):
+ let g:ale_ruby_standardrb_options = '--except Lint/Debugger'
+ call ale#test#SetFilename('ruby_paths/with_config/dummy.rb')
+
+ AssertEqual
+ \ {
+ \ 'read_temporary_file': 1,
+ \ 'command': ale#Escape(g:ale_ruby_standardrb_executable)
+ \ . ' --config ' . ale#Escape(ale#path#Simplify(g:dir . '/ruby_paths/with_config/.standard.yml'))
+ \ . ' --except Lint/Debugger'
+ \ . ' --fix --force-exclusion %t',
+ \ },
+ \ ale#fixers#standardrb#Fix(bufnr(''))
diff --git a/test/handler/test_rubocop_handler.vader b/test/handler/test_rubocop_handler.vader
index ef0137d6..d7868f26 100644
--- a/test/handler/test_rubocop_handler.vader
+++ b/test/handler/test_rubocop_handler.vader
@@ -41,21 +41,21 @@ Execute(The rubocop handler should parse lines correctly):
\ 'type': 'E',
\ },
\ ],
- \ ale_linters#ruby#rubocop#Handle(347, [
+ \ ale#ruby#HandleRubocopOutput(347, [
\ '{"metadata":{"rubocop_version":"0.47.1","ruby_engine":"ruby","ruby_version":"2.1.5","ruby_patchlevel":"273","ruby_platform":"x86_64-linux-gnu"},"files":[{"path":"my_great_file.rb","offenses":[{"severity":"convention","message":"Prefer single-quoted strings...","cop_name":"Style/SomeCop","corrected":false,"location":{"line":83,"column":29,"length":7}},{"severity":"fatal","message":"Some error","cop_name":"Style/SomeOtherCop","corrected":false,"location":{"line":12,"column":2,"length":1}},{"severity":"warning","message":"Regular warning","cop_name":"Style/WarningCop","corrected":false,"location":{"line":10,"column":5,"length":8}},{"severity":"error","message":"Another error","cop_name":"Style/SpaceBeforeBlockBraces","corrected":false,"location":{"line":11,"column":1,"length":1}}]}],"summary":{"offense_count":4,"target_file_count":1,"inspected_file_count":1}}'
\ ])
Execute(The rubocop handler should handle when files are checked and no offenses are found):
AssertEqual
\ [],
- \ ale_linters#ruby#rubocop#Handle(347, [
+ \ ale#ruby#HandleRubocopOutput(347, [
\ '{"metadata":{"rubocop_version":"0.47.1","ruby_engine":"ruby","ruby_version":"2.1.5","ruby_patchlevel":"273","ruby_platform":"x86_64-linux-gnu"},"files":[{"path":"my_great_file.rb","offenses":[]}],"summary":{"offense_count":0,"target_file_count":1,"inspected_file_count":1}}'
\ ])
Execute(The rubocop handler should handle when no files are checked):
AssertEqual
\ [],
- \ ale_linters#ruby#rubocop#Handle(347, [
+ \ ale#ruby#HandleRubocopOutput(347, [
\ '{"metadata":{"rubocop_version":"0.47.1","ruby_engine":"ruby","ruby_version":"2.1.5","ruby_patchlevel":"273","ruby_platform":"x86_64-linux-gnu"},"files":[],"summary":{"offense_count":0,"target_file_count":0,"inspected_file_count":0}}'
\ ])
@@ -66,11 +66,11 @@ Execute(The rubocop handler should handle output without any errors):
AssertEqual
\ [],
- \ ale_linters#ruby#rubocop#Handle(347, g:lines)
+ \ ale#ruby#HandleRubocopOutput(347, g:lines)
\
AssertEqual
\ [],
- \ ale_linters#ruby#rubocop#Handle(347, ['{}'])
+ \ ale#ruby#HandleRubocopOutput(347, ['{}'])
AssertEqual
\ [],
- \ ale_linters#ruby#rubocop#Handle(347, [])
+ \ ale#ruby#HandleRubocopOutput(347, [])