summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--ale_linters/ruby/reek.vim53
-rw-r--r--doc/ale-ruby.txt21
-rw-r--r--doc/ale.txt3
-rw-r--r--test/handler/test_reek_handler.vader69
5 files changed, 146 insertions, 2 deletions
diff --git a/README.md b/README.md
index 325e7816..b34c385c 100644
--- a/README.md
+++ b/README.md
@@ -96,7 +96,7 @@ name. That seems to be the fairest way to arrange this table.
| Python | [flake8](http://flake8.pycqa.org/en/latest/), [mypy](http://mypy-lang.org/), [pylint](https://www.pylint.org/) |
| reStructuredText | [proselint](http://proselint.com/)|
| RPM spec | [rpmlint](https://github.com/rpm-software-management/rpmlint) |
-| Ruby | [rubocop](https://github.com/bbatsov/rubocop), [ruby](https://www.ruby-lang.org) |
+| Ruby | [reek](https://github.com/troessner/reek), [rubocop](https://github.com/bbatsov/rubocop), [ruby](https://www.ruby-lang.org) |
| Rust | [rustc](https://www.rust-lang.org/), cargo (see `:help ale-integration-rust` for configuration instructions) |
| SASS | [sass-lint](https://www.npmjs.com/package/sass-lint), [stylelint](https://github.com/stylelint/stylelint) |
| SCSS | [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/reek.vim b/ale_linters/ruby/reek.vim
new file mode 100644
index 00000000..5f476fb1
--- /dev/null
+++ b/ale_linters/ruby/reek.vim
@@ -0,0 +1,53 @@
+" Author: Eddie Lebow https://github.com/elebow
+" Description: Reek, a code smell detector for Ruby files
+
+let g:ale_ruby_reek_show_context =
+\ get(g:, 'ale_ruby_reek_show_context', 0)
+
+let g:ale_ruby_reek_show_wiki_link =
+\ get(g:, 'ale_ruby_reek_show_wiki_link', 0)
+
+function! ale_linters#ruby#reek#Handle(buffer, lines) abort
+ if len(a:lines) == 0
+ return []
+ endif
+
+ let l:errors = json_decode(a:lines[0])
+
+ let l:output = []
+
+ for l:error in l:errors
+ for l:location in l:error.lines
+ call add(l:output, {
+ \ 'lnum': l:location,
+ \ 'type': 'W',
+ \ 'text': s:BuildText(a:buffer, l:error),
+ \})
+ endfor
+ endfor
+
+ return l:output
+endfunction
+
+function! s:BuildText(buffer, error) abort
+ let l:text = a:error.smell_type . ':'
+
+ if ale#Var(a:buffer, 'ruby_reek_show_context')
+ let l:text .= ' ' . a:error.context
+ endif
+
+ let l:text .= ' ' . a:error.message
+
+ if ale#Var(a:buffer, 'ruby_reek_show_wiki_link')
+ let l:text .= ' [' . a:error.wiki_link . ']'
+ endif
+
+ return l:text
+endfunction
+
+call ale#linter#Define('ruby', {
+\ 'name': 'reek',
+\ 'executable': 'reek',
+\ 'command': 'reek -f json --no-progress --no-color',
+\ 'callback': 'ale_linters#ruby#reek#Handle',
+\})
diff --git a/doc/ale-ruby.txt b/doc/ale-ruby.txt
index 77ea7342..033da360 100644
--- a/doc/ale-ruby.txt
+++ b/doc/ale-ruby.txt
@@ -3,6 +3,27 @@ ALE Ruby Integration *ale-ruby-options*
-------------------------------------------------------------------------------
+reek *ale-ruby-reek*
+
+g:ale_ruby_reek_show_context *g:ale_ruby_reek_show_context*
+
+ Type: |Number|
+ Default: 0
+
+ Controls whether context is included in the linter message. Defaults to off
+ because context is usually obvious while viewing a file.
+
+
+g:ale_ruby_reek_show_wiki_link *g:ale_ruby_reek_show_wiki_link*
+
+ Type: |Number|
+ Default: 0
+
+ Controls whether linter messages contain a link to an explanatory wiki page
+ for the type of code smell. Defaults to off to improve readability.
+
+
+-------------------------------------------------------------------------------
rubocop *ale-ruby-rubocop*
g:ale_ruby_rubocop_options *g:ale_ruby_rubocop_options*
diff --git a/doc/ale.txt b/doc/ale.txt
index 8979b1b8..8011a215 100644
--- a/doc/ale.txt
+++ b/doc/ale.txt
@@ -60,6 +60,7 @@ CONTENTS *ale-contents*
mypy................................|ale-python-mypy|
pylint..............................|ale-python-pylint|
ruby..................................|ale-ruby-options|
+ reek................................|ale-ruby-reek|
rubocop.............................|ale-ruby-rubocop|
rust..................................|ale-rust-options|
cargo...............................|ale-rust-cargo|
@@ -155,7 +156,7 @@ The following languages and tools are supported.
* reStructuredText: 'proselint'
* RPM spec: 'spec'
* Rust: 'rustc' (see |ale-integration-rust|)
-* Ruby: 'rubocop'
+* Ruby: 'reek', 'rubocop'
* SASS: 'sasslint', 'stylelint'
* SCSS: 'sasslint', 'scsslint', 'stylelint'
* Scala: 'scalac'
diff --git a/test/handler/test_reek_handler.vader b/test/handler/test_reek_handler.vader
new file mode 100644
index 00000000..67ba6f60
--- /dev/null
+++ b/test/handler/test_reek_handler.vader
@@ -0,0 +1,69 @@
+Before:
+ runtime ale_linters/ruby/reek.vim
+
+After:
+ call ale#linter#Reset()
+
+Execute(The reek handler should parse JSON correctly, with only context enabled):
+ let g:ale_ruby_reek_show_context = 1
+ let g:ale_ruby_reek_show_wiki_link = 0
+
+ AssertEqual
+ \ [
+ \ {
+ \ 'lnum': 12,
+ \ 'text': 'Rule1: Context#method violates rule number one',
+ \ 'type': 'W',
+ \ },
+ \ {
+ \ 'lnum': 34,
+ \ 'text': 'Rule2: Context#method violates rule number two',
+ \ 'type': 'W',
+ \ },
+ \ {
+ \ 'lnum': 56,
+ \ 'text': 'Rule2: Context#method violates rule number two',
+ \ 'type': 'W',
+ \ },
+ \ ],
+ \ ale_linters#ruby#reek#Handle(347, [
+ \ '[{"context":"Context#method","lines":[12],"message":"violates rule number one","smell_type":"Rule1","source":"/home/user/file.rb","parameter":"bad parameter","wiki_link":"https://example.com/Rule1.md"},{"context":"Context#method","lines":[34, 56],"message":"violates rule number two","smell_type":"Rule2","source":"/home/user/file.rb","name":"bad code","count":2,"wiki_link":"https://example.com/Rule1.md"}]'
+ \ ])
+
+Execute(The reek handler should parse JSON correctly, with no context or wiki links):
+ let g:ale_ruby_reek_show_context = 0
+ let g:ale_ruby_reek_show_wiki_link = 0
+
+ AssertEqual
+ \ [
+ \ {
+ \ 'lnum': 12,
+ \ 'text': 'Rule1: violates rule number one',
+ \ 'type': 'W',
+ \ },
+ \ ],
+ \ ale_linters#ruby#reek#Handle(347, [
+ \ '[{"context":"Context#method","lines":[12],"message":"violates rule number one","smell_type":"Rule1","source":"/home/user/file.rb","parameter":"bad parameter","wiki_link":"https://example.com/Rule1.md"}]'
+ \ ])
+
+Execute(The reek handler should parse JSON correctly, with both context and wiki links):
+ let g:ale_ruby_reek_show_context = 1
+ let g:ale_ruby_reek_show_wiki_link = 1
+
+ AssertEqual
+ \ [
+ \ {
+ \ 'lnum': 12,
+ \ 'text': 'Rule1: Context#method violates rule number one [https://example.com/Rule1.md]',
+ \ 'type': 'W',
+ \ },
+ \ ],
+ \ ale_linters#ruby#reek#Handle(347, [
+ \ '[{"context":"Context#method","lines":[12],"message":"violates rule number one","smell_type":"Rule1","source":"/home/user/file.rb","parameter":"bad parameter","wiki_link":"https://example.com/Rule1.md"}]'
+ \ ])
+
+Execute(The reek handler should parse JSON correctly when there is no output from reek):
+ AssertEqual
+ \ [],
+ \ ale_linters#ruby#reek#Handle(347, [
+ \ ])