mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
vim-patch:9.1.0967: SpotBugs compiler setup can be further improved
Problem: SpotBugs compiler can be further improved
Solution: Introduce event-driven primitives for SpotBugs
(Aliaksei Budavei)
closes: vim/vim#16258
2e252474c4
Co-authored-by: Aliaksei Budavei <0x000c70@gmail.com>
This commit is contained in:
parent
d7426bc9e9
commit
89c2945148
@ -1,7 +1,7 @@
|
||||
" Vim compiler file
|
||||
" Compiler: Spotbugs (Java static checker; needs javac compiled classes)
|
||||
" Maintainer: @konfekt and @zzzyxwvut
|
||||
" Last Change: 2024 Dec 14
|
||||
" Maintainers: @konfekt and @zzzyxwvut
|
||||
" Last Change: 2024 Dec 20
|
||||
|
||||
if exists('g:current_compiler') || bufname() !~# '\.java\=$' || wordcount().chars < 9
|
||||
finish
|
||||
|
@ -1410,6 +1410,70 @@ of |:make|, and assigning its |Funcref| to the selected key. For example:
|
||||
\ function('GenericPostCompilerCommand'),
|
||||
\ }
|
||||
|
||||
When "PostCompilerAction" is available, "PostCompilerActionExecutor" is also
|
||||
supported. Its value must be a Funcref pointing to a function that always
|
||||
declares a single parameter of type string and decides whether |:execute| can
|
||||
be dispatched on its argument, containing a pending post-compiler action,
|
||||
after ascertaining the current status of |:cc| (or |:ll|): >vim
|
||||
|
||||
function! GenericPostCompilerActionExecutor(action) abort
|
||||
try
|
||||
cc
|
||||
catch /\<E42:/
|
||||
execute a:action
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
Complementary, some or all of the available "Pre*Action"s (or "*Pre*Command"s)
|
||||
may run `:doautocmd java_spotbugs_post User` in their implementations before
|
||||
|:make| (or its equivalent) to define a once-only |ShellCmdPost| `:autocmd`
|
||||
that will arrange for "PostCompilerActionExecutor" to be invoked; and then run
|
||||
`:doautocmd java_spotbugs_post ShellCmdPost` to consume this event: >vim
|
||||
|
||||
function! GenericPreCompilerCommand(arguments) abort
|
||||
if !exists('g:spotbugs_compilation_done')
|
||||
doautocmd java_spotbugs_post User
|
||||
execute 'make ' . a:arguments
|
||||
" only run doautocmd when :make was synchronous
|
||||
" see note below
|
||||
doautocmd java_spotbugs_post ShellCmdPost " XXX: (a)
|
||||
let g:spotbugs_compilation_done = 1
|
||||
else
|
||||
cc
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! GenericPreCompilerTestCommand(arguments) abort
|
||||
if !exists('g:spotbugs_test_compilation_done')
|
||||
doautocmd java_spotbugs_post User
|
||||
execute 'make ' . a:arguments
|
||||
" only run doautocmd when :make was synchronous
|
||||
" see note below
|
||||
doautocmd java_spotbugs_post ShellCmdPost " XXX: (b)
|
||||
let g:spotbugs_test_compilation_done = 1
|
||||
else
|
||||
cc
|
||||
endif
|
||||
endfunction
|
||||
|
||||
let g:spotbugs_properties = {
|
||||
\ 'compiler': 'maven',
|
||||
\ 'DefaultPreCompilerCommand':
|
||||
\ function('GenericPreCompilerCommand'),
|
||||
\ 'DefaultPreCompilerTestCommand':
|
||||
\ function('GenericPreCompilerTestCommand'),
|
||||
\ 'PostCompilerActionExecutor':
|
||||
\ function('GenericPostCompilerActionExecutor'),
|
||||
\ }
|
||||
|
||||
If a command equivalent of `:make` is capable of asynchronous execution and
|
||||
consuming `ShellCmdPost` events, `:doautocmd java_spotbugs_post ShellCmdPost`
|
||||
must be removed from such "*Action" (or "*Command") implementations (i.e. the
|
||||
lines `(a)` and `(b)` in the listed examples) to retain a sequential order for
|
||||
non-blocking execution, and any notification (see below) must be suppressed.
|
||||
A `ShellCmdPost` `:autocmd` can be associated with any |:augroup| by assigning
|
||||
its name to the "augroupForPostCompilerAction" key.
|
||||
|
||||
When default actions are not suited to a desired workflow, proceed by writing
|
||||
arbitrary functions yourself and matching their Funcrefs to the supported
|
||||
keys: "PreCompilerAction", "PreCompilerTestAction", and "PostCompilerAction".
|
||||
|
@ -3,7 +3,7 @@
|
||||
" Maintainer: Aliaksei Budavei <0x000c70 AT gmail DOT com>
|
||||
" Former Maintainer: Dan Sharp
|
||||
" Repository: https://github.com/zzzyxwvut/java-vim.git
|
||||
" Last Change: 2024 Dec 16
|
||||
" Last Change: 2024 Dec 25
|
||||
" 2024 Jan 14 by Vim Project (browsefilter)
|
||||
" 2024 May 23 by Riley Bruins <ribru17@gmail.com> ('commentstring')
|
||||
|
||||
@ -113,7 +113,7 @@ if (!empty(get(g:, 'spotbugs_properties', {})) ||
|
||||
endfunction
|
||||
|
||||
" Work around ":bar"s and ":autocmd"s.
|
||||
function! s:ExecuteActionOnce(cleanup_cmd, action_cmd) abort
|
||||
function! JavaFileTypeExecuteActionOnce(cleanup_cmd, action_cmd) abort
|
||||
try
|
||||
execute a:cleanup_cmd
|
||||
finally
|
||||
@ -285,7 +285,7 @@ if (!empty(get(g:, 'spotbugs_properties', {})) ||
|
||||
for s:action in s:actions
|
||||
if has_key(s:action, 'once')
|
||||
execute printf('autocmd java_spotbugs %s <buffer> ' .
|
||||
\ 'call s:ExecuteActionOnce(%s, %s)',
|
||||
\ 'call JavaFileTypeExecuteActionOnce(%s, %s)',
|
||||
\ s:action.event,
|
||||
\ string(printf('autocmd! java_spotbugs %s <buffer>',
|
||||
\ s:action.event)),
|
||||
@ -297,7 +297,41 @@ if (!empty(get(g:, 'spotbugs_properties', {})) ||
|
||||
endif
|
||||
endfor
|
||||
|
||||
unlet! s:action s:actions s:idx s:dispatcher
|
||||
if s:SpotBugsHasProperty('PostCompilerActionExecutor') &&
|
||||
\ (s:request == 7 || s:request == 6 ||
|
||||
\ s:request == 5 || s:request == 4)
|
||||
let s:augroup = s:SpotBugsGetProperty(
|
||||
\ 'augroupForPostCompilerAction',
|
||||
\ 'java_spotbugs_post')
|
||||
let s:augroup = !empty(s:augroup) ? s:augroup : 'java_spotbugs_post'
|
||||
|
||||
for s:candidate in ['java_spotbugs_post', s:augroup]
|
||||
if !exists("#" . s:candidate)
|
||||
execute printf('augroup %s | augroup END', s:candidate)
|
||||
endif
|
||||
endfor
|
||||
|
||||
silent! autocmd! java_spotbugs_post User <buffer>
|
||||
|
||||
" Define a User ":autocmd" to define a once-only ShellCmdPost
|
||||
" ":autocmd" that will invoke "PostCompilerActionExecutor" and let
|
||||
" it decide whether to proceed with ":compiler spotbugs" etc.; and
|
||||
" seek explicit synchronisation with ":doautocmd ShellCmdPost" by
|
||||
" omitting "nested" for "java_spotbugs_post" and "java_spotbugs".
|
||||
execute printf('autocmd java_spotbugs_post User <buffer> ' .
|
||||
\ 'call JavaFileTypeExecuteActionOnce(%s, %s)',
|
||||
\ string(printf('autocmd! %s ShellCmdPost <buffer>', s:augroup)),
|
||||
\ string(printf('autocmd %s ShellCmdPost <buffer> ' .
|
||||
\ 'call JavaFileTypeExecuteActionOnce(%s, %s)',
|
||||
\ s:augroup,
|
||||
\ string(printf('autocmd! %s ShellCmdPost <buffer>', s:augroup)),
|
||||
\ string(printf('call call(%s, [%s])',
|
||||
\ string(s:SpotBugsGetProperties().PostCompilerActionExecutor),
|
||||
\ string(printf('compiler spotbugs | call call(%s, [])',
|
||||
\ string(s:SpotBugsGetProperties().PostCompilerAction))))))))
|
||||
endif
|
||||
|
||||
unlet! s:candidate s:augroup s:action s:actions s:idx s:dispatcher
|
||||
endif
|
||||
|
||||
delfunction s:SpotBugsGetProperties
|
||||
@ -310,9 +344,11 @@ function! JavaFileTypeCleanUp() abort
|
||||
setlocal suffixes< suffixesadd< formatoptions< comments< commentstring< path< includeexpr<
|
||||
unlet! b:browsefilter
|
||||
|
||||
" The concatenated removals may be misparsed as a User autocmd.
|
||||
" The concatenated ":autocmd" removals may be misparsed as an ":autocmd".
|
||||
" A _once-only_ ShellCmdPost ":autocmd" is always a call-site definition.
|
||||
silent! autocmd! java_spotbugs User <buffer>
|
||||
silent! autocmd! java_spotbugs Syntax <buffer>
|
||||
silent! autocmd! java_spotbugs_post User <buffer>
|
||||
endfunction
|
||||
|
||||
" Undo the stuff we changed.
|
||||
|
@ -399,12 +399,22 @@ func Test_compiler_spotbugs_properties()
|
||||
endfunc
|
||||
defer execute('delfunction g:SpotBugsPostCommand')
|
||||
|
||||
func! g:SpotBugsPostCompilerActionExecutor(action) abort
|
||||
try
|
||||
" XXX: Notify the spotbugs compiler about success or failure.
|
||||
cc
|
||||
catch /\<E42:/
|
||||
execute a:action
|
||||
endtry
|
||||
endfunc
|
||||
defer execute('delfunction g:SpotBugsPostCompilerActionExecutor')
|
||||
|
||||
" TEST INTEGRATION WITH A SUPPORTED COMPILER PLUGIN.
|
||||
if filereadable($VIMRUNTIME .. '/compiler/maven.vim')
|
||||
if !executable('mvn')
|
||||
if has('win32')
|
||||
" This is what ":help executable()" suggests.
|
||||
call writefile([], 'Xspotbugs/mvn.exe')
|
||||
call writefile([], 'Xspotbugs/mvn.cmd')
|
||||
else
|
||||
let $PATH = 'Xspotbugs:' .. $PATH
|
||||
call writefile([], 'Xspotbugs/mvn')
|
||||
@ -590,6 +600,8 @@ func Test_compiler_spotbugs_properties()
|
||||
\ 'DefaultPreCompilerTestCommand': function('g:SpotBugsPreTestCommand'),
|
||||
\ 'DefaultPreCompilerCommand': function('g:SpotBugsPreCommand'),
|
||||
\ 'DefaultPostCompilerCommand': function('g:SpotBugsPostCommand'),
|
||||
\ 'PostCompilerActionExecutor': function('g:SpotBugsPostCompilerActionExecutor'),
|
||||
\ 'augroupForPostCompilerAction': 'java_spotbugs_test',
|
||||
\ 'sourceDirPath': ['Xspotbugs/src'],
|
||||
\ 'classDirPath': ['Xspotbugs/src'],
|
||||
\ 'testSourceDirPath': ['tests'],
|
||||
@ -636,6 +648,56 @@ func Test_compiler_spotbugs_properties()
|
||||
call assert_match('^spotbugs\s', &l:makeprg)
|
||||
endif
|
||||
|
||||
setlocal makeprg=
|
||||
let s:spotbugs_results.preActionDone = 0
|
||||
let s:spotbugs_results.preTestActionOtherDone = 0
|
||||
let s:spotbugs_results.preTestLocalActionDone = 0
|
||||
let s:spotbugs_results.postActionDone = 0
|
||||
let s:spotbugs_results.preCommandArguments = ''
|
||||
let s:spotbugs_results.preTestCommandArguments = ''
|
||||
let s:spotbugs_results.postCommandArguments = ''
|
||||
|
||||
" When "PostCompilerActionExecutor", "Pre*Action" and/or "Pre*TestAction",
|
||||
" and "Post*Action" are available, "#java_spotbugs_post" must be defined.
|
||||
call assert_true(exists('#java_spotbugs_post'))
|
||||
call assert_true(exists('#java_spotbugs_post#User'))
|
||||
call assert_false(exists('#java_spotbugs_post#ShellCmdPost'))
|
||||
call assert_false(exists('#java_spotbugs_test#ShellCmdPost'))
|
||||
|
||||
" Re-link a Funcref on the fly.
|
||||
func! g:SpotBugsPreTestCommand(arguments) abort
|
||||
let s:spotbugs_results.preTestActionOtherDone = 1
|
||||
let s:spotbugs_results.preTestCommandArguments = a:arguments
|
||||
" Define a once-only ":autocmd" for "#java_spotbugs_test#ShellCmdPost".
|
||||
doautocmd java_spotbugs_post User
|
||||
" XXX: Do NOT use ":cc" to notify the spotbugs compiler about success or
|
||||
" failure, and assume the transfer of control to a ShellCmdPost command.
|
||||
endfunc
|
||||
|
||||
doautocmd java_spotbugs User
|
||||
" No match: "test_file !~# 'Xspotbugs/src'".
|
||||
call assert_false(s:spotbugs_results.preActionDone)
|
||||
call assert_true(empty(s:spotbugs_results.preCommandArguments))
|
||||
" A match: "test_file =~# 'tests'".
|
||||
call assert_true(s:spotbugs_results.preTestActionOtherDone)
|
||||
call assert_equal('test-compile', s:spotbugs_results.preTestCommandArguments)
|
||||
" For a pre-match, no post-action (without ":cc") UNLESS a ShellCmdPost
|
||||
" event is consumed whose command will invoke "PostCompilerActionExecutor"
|
||||
" and the latter will accept a post-compiler action argument.
|
||||
call assert_false(s:spotbugs_results.postActionDone)
|
||||
call assert_true(exists('#java_spotbugs_test#ShellCmdPost'))
|
||||
doautocmd ShellCmdPost
|
||||
call assert_false(exists('#java_spotbugs_test#ShellCmdPost'))
|
||||
call assert_true(s:spotbugs_results.postActionDone)
|
||||
call assert_equal('%:S', s:spotbugs_results.postCommandArguments)
|
||||
|
||||
" With a match, confirm that ":compiler spotbugs" has run.
|
||||
if has('win32')
|
||||
call assert_match('^spotbugs\.bat\s', &l:makeprg)
|
||||
else
|
||||
call assert_match('^spotbugs\s', &l:makeprg)
|
||||
endif
|
||||
|
||||
bwipeout
|
||||
setlocal makeprg=
|
||||
endif
|
||||
|
Loading…
Reference in New Issue
Block a user