diff options
author | zeertzjq <zeertzjq@outlook.com> | 2024-12-28 07:32:08 +0800 |
---|---|---|
committer | zeertzjq <zeertzjq@outlook.com> | 2025-02-04 06:45:25 +0800 |
commit | 89c294514853ee4849855f880d6d7ff349494c4d (patch) | |
tree | c9e47794be4f9f2c0afc1f43b0d6dbfb5832f8df | |
parent | d7426bc9e99a44e5c79a3645aa74fc2a300e3ae6 (diff) | |
download | rneovim-89c294514853ee4849855f880d6d7ff349494c4d.tar.gz rneovim-89c294514853ee4849855f880d6d7ff349494c4d.tar.bz2 rneovim-89c294514853ee4849855f880d6d7ff349494c4d.zip |
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
https://github.com/vim/vim/commit/2e252474c4df5018b9819d86ebb70bf3b1b1a1af
Co-authored-by: Aliaksei Budavei <0x000c70@gmail.com>
-rw-r--r-- | runtime/compiler/spotbugs.vim | 4 | ||||
-rw-r--r-- | runtime/doc/quickfix.txt | 64 | ||||
-rw-r--r-- | runtime/ftplugin/java.vim | 46 | ||||
-rw-r--r-- | test/old/testdir/test_compiler.vim | 64 |
4 files changed, 170 insertions, 8 deletions
diff --git a/runtime/compiler/spotbugs.vim b/runtime/compiler/spotbugs.vim index 10d164b6af..8ed45f8ee0 100644 --- a/runtime/compiler/spotbugs.vim +++ b/runtime/compiler/spotbugs.vim @@ -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 diff --git a/runtime/doc/quickfix.txt b/runtime/doc/quickfix.txt index e56de9c1b4..7aeb494437 100644 --- a/runtime/doc/quickfix.txt +++ b/runtime/doc/quickfix.txt @@ -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". diff --git a/runtime/ftplugin/java.vim b/runtime/ftplugin/java.vim index 0fa773335d..cfd25bce6c 100644 --- a/runtime/ftplugin/java.vim +++ b/runtime/ftplugin/java.vim @@ -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. diff --git a/test/old/testdir/test_compiler.vim b/test/old/testdir/test_compiler.vim index e6d5e57824..f9e7bf042d 100644 --- a/test/old/testdir/test_compiler.vim +++ b/test/old/testdir/test_compiler.vim @@ -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 |