diff --git a/.travis.yml b/.travis.yml index 2885bc5..e1a56a6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,17 @@ before_script: - git clone https://github.com/thinca/vim-themis --branch v1.4 --depth 1 /tmp/vim-themis - vim --version + - git clone https://github.com/vim/vim.git /tmp/vim + - git clone https://github.com/vim-jp/vital.vim.git /tmp/vital.vim + - git clone https://github.com/thinca/vim-quickrun.git /tmp/quickrun + - git clone https://github.com/Shougo/neocomplete.vim.git /tmp/neocom + - git clone https://github.com/easymotion/vim-easymotion.git /tmp/em + - git clone https://github.com/tpope/vim-fugitive /tmp/fug + - git clone https://github.com/scrooloose/syntastic /tmp/syntastic + - git clone https://github.com/itchyny/lightline.vim.git /tmp/ll + - git clone https://github.com/ctrlpvim/ctrlp.vim /tmp/cp + - git clone https://github.com/vim-airline/vim-airline.git /tmp/al + script: - rm -f /tmp/vimlint_test.log - vim -c 'set rtp+=.,/tmp/vimlparser' -c 'source test/vimlint-test.vim' -c 'call Vimlint_test("test", "/tmp/vimlint_test.log")' -c 'qall!' @@ -13,3 +24,16 @@ script: - sh ./bin/vimlint.sh -p /tmp/vimlparser -v autoload - sh ./test/err.sh -p /tmp/vimlparser test/test-ok.vim test/test-ng.vim - /tmp/vim-themis/bin/themis themis + + - sh ./bin/vimlint.sh -X -p /tmp/vimlparser -e EVL103=1 -e EVL102.l:_=1 /tmp/vim/runtime/autoload /tmp/vim/runtime/plugin + - sh ./bin/vimlint.sh -X -p /tmp/vimlparser -e EVL103=1 -e EVL102.l:_=1 -c func_abort=1 /tmp/vital.vim/autoload + - sh ./bin/vimlint.sh -X -p /tmp/vimlparser -e EVL103=1 -e EVL102.l:_=1 -c func_abort=1 /tmp/quickrun/autoload + - sh ./bin/vimlint.sh -X -p /tmp/vimlparser -e EVL103=1 -e EVL102.l:_=1 -c func_abort=1 /tmp/neocom/autoload + - sh ./bin/vimlint.sh -X -p /tmp/vimlparser -e EVL103=1 -e EVL102.l:_=1 -c func_abort=1 /tmp/em/autoload + - sh ./bin/vimlint.sh -X -p /tmp/vimlparser -e EVL103=1 -e EVL102.l:_=1 /tmp/fug/plugin + - sh ./bin/vimlint.sh -X -p /tmp/vimlparser -e EVL103=1 -e EVL102.l:_=1 /tmp/syntastic/autoload /tmp/syntastic/plugin + - sh ./bin/vimlint.sh -X -p /tmp/vimlparser -e EVL103=1 -e EVL102.l:_=1 -c func_abort=1 /tmp/ll/autoload + - sh ./bin/vimlint.sh -X -p /tmp/vimlparser -e EVL103=1 -e EVL102.l:_=1 /tmp/cp/autoload /tmp/cp/plugin + - sh ./bin/vimlint.sh -X -p /tmp/vimlparser -e EVL103=1 -e EVL102.l:_=1 /tmp/al/autoload /tmp/al/plugin + + diff --git a/autoload/vimlint.vim b/autoload/vimlint.vim index 4249422..0b37784 100644 --- a/autoload/vimlint.vim +++ b/autoload/vimlint.vim @@ -71,6 +71,8 @@ let s:default_errlevel.EVL204 = s:DEF_NON let s:default_errlevel.EVL205 = s:DEF_WRN let s:default_errlevel.EVL206 = s:DEF_NON let s:default_errlevel.EVL207 = s:DEF_NON +let s:default_errlevel.EVL301 = s:DEF_NON +let s:default_errlevel.EVL302 = s:DEF_NON let s:default_errlevel.EVL901 = s:DEF_WRN let s:default_errlevel.EVL902 = s:DEF_WRN let s:def_var_name = ':' @@ -130,7 +132,7 @@ function! s:extend_errlevel(param) abort " {{{ for key in keys(s:default_errlevel) " echo "param[" . key . "]" if !has_key(param, key) - call s:set_param(param, key, s:DEF_ERR, s:def_var_name) + call s:set_param(param, key, key[3] == '3' ? s:DEF_WRN : s:DEF_ERR, s:def_var_name) elseif type(param[key]) == type(0) call s:set_param(param, key, param[key], s:def_var_name) elseif type(param[key]) != type({}) @@ -657,7 +659,7 @@ function! s:reconstruct_varstack_rt(self, env, pos, brk_cont, nop) abort " {{{ if v.type ==# 'append' && v.v.ref == 0 && a:env.global.fins == 0 " 変数を追加したが参照していない " かつ, finally 句がない場合 - call a:self.error_mes(v.node, 'EVL102', 'unused variable2 `' . v.var. '`', v.var) + call a:self.error_mes(v.node, 'EVL102', 'unused variable2 `' . v.var . '`', v.var) endif let a:env.varstack[j] = nop endfor @@ -842,6 +844,40 @@ function! s:reconstruct_varstack_st(self, env, p) abort " {{{ endfunction " }}} " @vimlint(EVL103, 0, a:self) +function! s:VimlLint.abbrev_if(vl, node) abort " {{{ + for node in a:node.elseif + call a:vl.abbrev_common(node) + endfor + if a:node.else isnot s:vlp.NIL + call a:vl.abbrev_common(a:node.else) + endif + call a:vl.abbrev_common(a:node.endif) +endfunction " }}} +function! s:VimlLint.abbrev_for(vl, node) abort " {{{ + call a:vl.abbrev_common(a:node.endfor) +endfunction " }}} +function! s:VimlLint.abbrev_while(vl, node) abort " {{{ + call a:vl.abbrev_common(a:node.endwhile) +endfunction " }}} +function! s:VimlLint.abbrev_try(vl, node) abort " {{{ + for node in a:node.catch + call a:vl.abbrev_common(node) + endfor + if a:node.finally isnot s:vlp.NIL + call a:vl.abbrev_common(a:node.finally) + endif + call a:vl.abbrev_common(a:node.endtry) +endfunction " }}} +function! s:VimlLint.abbrev_func(vl, node) abort " {{{ + call a:vl.abbrev_common(a:node.endfunction) +endfunction " }}} +function! s:VimlLint.abbrev_common(node) abort " {{{ + let line = self.lines[a:node.pos.lnum - 1] + if match(line, '^' . a:node.ea.cmd.name . '\>', a:node.pos.col - 1) < 0 + call self.error_mes(a:node, 'EVL302', 'use the full command name `' . a:node.ea.cmd.name . '` instead of the abbreviation', a:node) + endif +endfunction " }}} + function s:VimlLint.compile(node, refchk) abort " {{{ if type(a:node) ==# type({}) && has_key(a:node, 'type') if a:node.type != 2 && g:vimlint#debug > 2 || g:vimlint#debug >= 5 @@ -859,6 +895,14 @@ function s:VimlLint.compile(node, refchk) abort " {{{ " echo a:node " throw "stop" " endtry + if has_key(a:node, 'ea') + if has_key(self.excmd_abbrev, a:node.type) + call self.excmd_abbrev[a:node.type](self, a:node) + elseif has_key(a:node.ea.cmd, 'name') + call self.abbrev_common(a:node) + endif + endif + return call(self.compile_funcs[a:node.type], [a:node, a:refchk], self) @@ -1670,7 +1714,15 @@ function s:VimlLint.compile_subtract(node, ...) abort endfunction function s:VimlLint.compile_concat(node, ...) abort - return self.compile_op2(a:node, '.') + let r = self.compile_op2(a:node, '.') + " google style guide. use spaces around operators + let line = self.lines[r.pos.lnum - 1] + if line[r.pos.col - 2] !~# '\s' || len(line) > r.pos.col && line[r.pos.col] !~# '\s' + if self.filename !=# '' + call self.error_mes(r, 'EVL301', 'use space around operator `.`', r) + endif + endif + return r endfunction function s:VimlLint.compile_multiply(node, ...) abort @@ -1736,6 +1788,7 @@ function s:VimlLint.parse_string(str, node, cmd, ref) abort "{{{ " @TODO 今は変数の中身は参照していないので適当に代入可能 endif let r = s:vlp.StringReader.new(lines) + let c.lines = lines call c.compile(p.parse(r), 1) catch call self.error_mes(a:node, 'EVL203', 'parse error in `' . a:cmd . '`', 1) @@ -1948,9 +2001,12 @@ function! s:vimlint_file(filename, param, progress) abort " {{{ if a:param.type ==# 'string' let r = s:vlp.StringReader.new(vimfile) let c.filename = '' + let c.lines = split(vimfile, "\n") else - let r = s:vlp.StringReader.new(readfile(vimfile)) + let l = readfile(vimfile) + let r = s:vlp.StringReader.new(l) let c.filename = vimfile + let c.lines = l endif @@ -2219,6 +2275,13 @@ let s:VimlLint.compile_funcs[s:vlp.NODE_CURLYNAME] = s:VimlLint.compile_curlynam let s:VimlLint.compile_funcs[s:vlp.NODE_ENV] = s:VimlLint.compile_env let s:VimlLint.compile_funcs[s:vlp.NODE_REG] = s:VimlLint.compile_reg +let s:VimlLint.excmd_abbrev = {} +let s:VimlLint.excmd_abbrev[s:vlp.NODE_IF] = s:VimlLint.abbrev_if +let s:VimlLint.excmd_abbrev[s:vlp.NODE_FOR] = s:VimlLint.abbrev_for +let s:VimlLint.excmd_abbrev[s:vlp.NODE_WHILE] = s:VimlLint.abbrev_while +let s:VimlLint.excmd_abbrev[s:vlp.NODE_TRY] = s:VimlLint.abbrev_try +let s:VimlLint.excmd_abbrev[s:vlp.NODE_FUNCTION] = s:VimlLint.abbrev_func + let &cpo = s:save_cpo unlet s:save_cpo diff --git a/bin/vimlint.sh b/bin/vimlint.sh index a9efc8c..c316dad 100755 --- a/bin/vimlint.sh +++ b/bin/vimlint.sh @@ -34,7 +34,7 @@ VOPT="-c 'set rtp+=`pwd`'" echo "call has_key(g:, \"vimlint#config\") | let g:vimlint#config = {}" > ${VF} echo "let g:vimlint#config.quiet = 1" >> ${VF} ERRGREP='Error|Warning' -while getopts 'hl:p:ue:vc:E' OPT; do +while getopts 'hl:p:ue:vc:EX' OPT; do case "$OPT" in p) if [ ! -f "${OPTARG}/autoload/vimlparser.vim" ]; then @@ -52,6 +52,8 @@ while getopts 'hl:p:ue:vc:E' OPT; do VOPT="$VOPT -u NONE -i NONE" ;; E) ERRGREP='Error' ;; + X) + ERRGREP='vimlint#vimlint' ;; # Exception e) if [ `echo ${OPTARG} | grep '^EVL[0-9]\+=[135]$' | wc -l` = 1 ]; then E=`echo ${OPTARG} | sed 's/=.*//'` diff --git a/doc/vimlint.txt b/doc/vimlint.txt index e23b758..98c8cec 100644 --- a/doc/vimlint.txt +++ b/doc/vimlint.txt @@ -344,6 +344,13 @@ EVL206: `v` can be used for `x` *EVL206* EVL207: statement with no effect *EVL207* + +style +EVL301: use space around operator `x` *EVL301* + *EVL302* +EVL302: use the full command name `x` instead of the abbreviation + + system error EVL901: unknown type `t` *EVL901* EVL902: assert error `t` *EVL902* diff --git a/test/concat1.vim b/test/concat1.vim new file mode 100644 index 0000000..62c8bf4 --- /dev/null +++ b/test/concat1.vim @@ -0,0 +1,5 @@ +" @ERR ["WVL301"] +function! Hoge() + return 'a'. bo() +endfunction + diff --git a/test/concat2.vim b/test/concat2.vim new file mode 100644 index 0000000..dd57ac6 --- /dev/null +++ b/test/concat2.vim @@ -0,0 +1,5 @@ +" @ERR ["WVL301"] +function! Hoge() + return 'qoo'. 'foo' +endfunction + diff --git a/test/concat3.vim b/test/concat3.vim new file mode 100644 index 0000000..efc68e7 --- /dev/null +++ b/test/concat3.vim @@ -0,0 +1,5 @@ +" @ERR [] +function! Hoge() + return 'a' . bo() +endfunction + diff --git a/test/concat4.vim b/test/concat4.vim new file mode 100644 index 0000000..e6283e2 --- /dev/null +++ b/test/concat4.vim @@ -0,0 +1,5 @@ +" @ERR ["WVL301"] +function! Hoge() + return 'qoo'. +\'foo' +endfunction