summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Tibbitts <tibbs@math.uh.edu>2017-04-19 17:40:58 -0500
committerw0rp <w0rp@users.noreply.github.com>2017-04-19 23:40:58 +0100
commit4eeb4783d33eafeeda88186c058b8517a21e82bc (patch)
treefdcc5433c021be2923785427055d2486832bbb15
parentd8dcc56af58d1545cf3a7a9f6160d8ba6ad39923 (diff)
downloadale-4eeb4783d33eafeeda88186c058b8517a21e82bc.zip
Add rpm spec file linter (rpmlint) (#486)
* Initial attempt at an rpmlint linter. * Add some basic documentation. * Play with indentation in the test file. * Another attempt to fix the rpmlint test. * Hopefully this does it.
-rw-r--r--README.md1
-rw-r--r--ale_linters/spec/rpmlint.vim85
-rw-r--r--doc/ale-spec.txt28
-rw-r--r--doc/ale.txt3
-rw-r--r--test/handler/test_rpmlint_handler.vader29
5 files changed, 146 insertions, 0 deletions
diff --git a/README.md b/README.md
index bdc38249..325e7816 100644
--- a/README.md
+++ b/README.md
@@ -95,6 +95,7 @@ name. That seems to be the fairest way to arrange this table.
| Puppet | [puppet](https://puppet.com), [puppet-lint](https://puppet-lint.com) |
| 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) |
| 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) |
diff --git a/ale_linters/spec/rpmlint.vim b/ale_linters/spec/rpmlint.vim
new file mode 100644
index 00000000..f5308af6
--- /dev/null
+++ b/ale_linters/spec/rpmlint.vim
@@ -0,0 +1,85 @@
+" Author: Jason Tibbitts <tibbs@math.uh.edu>
+" Description: Adds support for checking RPM spec files with rpmlint
+
+" rpmlint will produce varions types of output:
+"
+" Lines like the following are output when the file is simply not able to be
+" parsed by rpmspec -P:
+" apcupsd.spec: E: specfile-error warning: bogus date in %changelog: Mon Oct 1 2005 - Foo
+" apcupsd.spec: E: specfile-error error: %changelog not in descending chronological order
+" They do not contain a line number, and there's not a whole lot that can be
+" done to locate them besides grep for them. rpmlint is just passing the
+" output from rpm along with the filename, an error indicator, and an error
+" type.
+"
+" Lines like the following:
+" cyrus-imapd.spec:23: W: macro-in-comment %version
+" cyrus-imapd.spec:18: E: hardcoded-library-path in %_prefix/lib/%name
+" indicate warnings and errors, respectively. No column numbers are provided
+"
+" Lines like:
+" apcupsd.spec: I: checking
+" apcupsd.spec: I: checking-url https://downloads.sourceforge.net/apcupsd/apcupsd-3.14.14.tar.gz (timeout 10 seconds)
+" are merely informational and are only output when -v is passed. But they
+" may be useful in a log to know why things are taking so long.
+"
+" And this is always output at the end and should just be ignored:
+" 0 packages and 1 specfiles checked; 4 errors, 0 warnings.
+
+let g:ale_spec_rpmlint_executable =
+\ get(g:, 'ale_spec_rpmlint_executable', 'rpmlint')
+
+let g:ale_spec_rpmlint_options =
+\ get(g:, 'ale_spec_rpmlint_options', '')
+
+function! ale_linters#spec#rpmlint#GetExecutable(buffer) abort
+ return ale#Var(a:buffer, 'spec_rpmlint_executable')
+endfunction
+
+function! ale_linters#spec#rpmlint#GetCommand(buffer) abort
+ return ale_linters#spec#rpmlint#GetExecutable(a:buffer)
+ \ . ' ' . ale#Var(a:buffer, 'spec_rpmlint_options')
+ \ . ' -o "NetworkEnabled False"'
+ \ . ' -v'
+ \ . ' %t'
+endfunction
+
+function! ale_linters#spec#rpmlint#Handle(buffer, lines) abort
+ " let l:pat_inform = '^.\+: I: \(.+\)'
+ let l:pat_errwarn = '^.\+:\(\d\+\): \([EW]\): \(.\+\)'
+ let l:pat_baderr = '^.\+: E: \(.\+\)'
+ let l:output = []
+
+ for l:line in a:lines
+ let l:match_errwarn = matchlist(l:line, l:pat_errwarn)
+ let l:match_baderr = matchlist(l:line, l:pat_baderr)
+
+ if len(l:match_errwarn) > 0
+ let l:text = l:match_errwarn[3]
+ let l:type = l:match_errwarn[2]
+ let l:lnum = l:match_errwarn[1] + 0
+ elseif len(l:match_baderr) > 0
+ let l:text = l:match_baderr[1]
+ let l:type = 'E'
+ let l:lnum = 1
+ else
+ continue
+ endif
+
+ call add(l:output, {
+ \ 'bufnr': a:buffer,
+ \ 'lnum': l:lnum,
+ \ 'text': l:text,
+ \ 'type': l:type,
+ \})
+ endfor
+
+ return l:output
+endfunction
+
+call ale#linter#Define('spec', {
+\ 'name': 'rpmlint',
+\ 'executable_callback': 'ale_linters#spec#rpmlint#GetExecutable',
+\ 'command_callback': 'ale_linters#spec#rpmlint#GetCommand',
+\ 'callback': 'ale_linters#spec#rpmlint#Handle',
+\})
diff --git a/doc/ale-spec.txt b/doc/ale-spec.txt
new file mode 100644
index 00000000..fc6be562
--- /dev/null
+++ b/doc/ale-spec.txt
@@ -0,0 +1,28 @@
+===============================================================================
+ALE RPM Spec Integration *ale-spec-options*
+
+
+-------------------------------------------------------------------------------
+rpmlint *ale-spec-rpmlint*
+
+g:ale_spec_rpmlint_executable *g:ale_spec_rpmlint_executable*
+
+ Type: |String|
+ Default: `'rpmlint'`
+
+ This variable sets executable used for rpmlint.
+
+
+g:ale_spec_rpmlint_options *g:ale_spec_rpmlint_options*
+
+ Type: |String|
+ Default: `''`
+
+ Set this to pass extra arguments to rpmlint.
+
+ For example, to instruct rpmlint to use a specific configuration file:
+
+ let g:ale_spec_rpmlint_options = '-f custom.cf'
+
+-------------------------------------------------------------------------------
+ vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl:
diff --git a/doc/ale.txt b/doc/ale.txt
index 1e332993..d3044d7e 100644
--- a/doc/ale.txt
+++ b/doc/ale.txt
@@ -71,6 +71,8 @@ CONTENTS *ale-contents*
sh....................................|ale-sh-options|
shell...............................|ale-sh-shell|
shellcheck..........................|ale-sh-shellcheck|
+ spec..................................|ale-spec-options|
+ rpmlint.............................|ale-spec-rpmlint|
tex...................................|ale-tex-options|
chktex..............................|ale-tex-chktex|
lacheck.............................|ale-tex-lacheck|
@@ -151,6 +153,7 @@ The following languages and tools are supported.
* Puppet: 'puppet', 'puppet-lint'
* Python: 'flake8', 'mypy', 'pylint'
* reStructuredText: 'proselint'
+* RPM spec: 'spec'
* Rust: 'rustc' (see |ale-integration-rust|)
* Ruby: 'rubocop'
* SASS: 'sasslint', 'stylelint'
diff --git a/test/handler/test_rpmlint_handler.vader b/test/handler/test_rpmlint_handler.vader
new file mode 100644
index 00000000..45f50719
--- /dev/null
+++ b/test/handler/test_rpmlint_handler.vader
@@ -0,0 +1,29 @@
+Execute(The rpmlint handler should parse error messages correctly):
+ runtime ale_linters/spec/rpmlint.vim
+
+ AssertEqual
+ \ [
+ \ {
+ \ 'bufnr': 42,
+ \ 'lnum': 23,
+ \ 'text': 'macro-in-comment %version',
+ \ 'type': 'W',
+ \ },
+ \ {
+ \ 'bufnr': 42,
+ \ 'lnum': 17,
+ \ 'text': 'hardcoded-library-path in %_prefix/lib/%name',
+ \ 'type': 'E',
+ \ },
+ \ {
+ \ 'bufnr': 42,
+ \ 'lnum': 1,
+ \ 'text': 'specfile-error warning: bogus date in %changelog: Mon Oct 1 2005 - Foo',
+ \ 'type': 'E',
+ \ },
+ \ ],
+ \ ale_linters#spec#rpmlint#Handle(42, [
+ \ 'cyrus-imapd.spec:23: W: macro-in-comment %version',
+ \ 'cyrus-imapd.spec:17: E: hardcoded-library-path in %_prefix/lib/%name',
+ \ 'apcupsd.spec: E: specfile-error warning: bogus date in %changelog: Mon Oct 1 2005 - Foo',
+ \ ])