patch 9.1.0935: SpotBugs compiler can be improved

Problem:  SpotBugs compiler can be improved
Solution: runtime(compiler): Improve defaults and error handling for
          SpotBugs; update test_compiler.vim (Aliaksei Budavei)

runtime(compiler): Improve defaults and error handling for SpotBugs

* Keep "spotbugs#DefaultPreCompilerTestAction()" defined but
  do not assign its Funcref to the "PreCompilerTestAction"
  key of "g:spotbugs_properties": there are no default and
  there can only be introduced arbitrary "*sourceDirPath"
  entries; therefore, this assignment is confusing at best,
  given that the function's implementation delegates to
  whatever "PreCompilerAction" is.

* Allow for the possibility of relative source pathnames
  passed as arguments to Vim for the Javac default actions,
  and the necessity to have them properly reconciled when
  the current working directory is changed.

* Do not expect users to remember or know that new source
  files ‘must be’ ":argadd"'d to be then known to the Javac
  default actions; so collect the names of Java-file buffers
  and Java-file Vim arguments; and let users providing the
  "@sources" file-lists in the "g:javac_makeprg_params"
  variable update these file-lists themselves.

* Strive to not leave behind a fire-once Syntax ":autocmd"
  for a Java buffer whenever an arbitrary pre-compile action
  errors out.

* Only attempt to run a post-compiler action in the absence
  of failures for a pre-compiler action.  Note that warnings
  and failures are treated alike (?!) by the Javac compiler,
  so when previews are tried out with "--enable-preview",
  remember about passing "-Xlint:-preview" too to also let
  SpotBugs have a go.

* Properly group conditional operators when testing for key
  entries in a user-defined variable.

* Also test whether "javaExternal" is defined when choosing
  an implementation for source-file parsing.

* Two commands are provided to toggle actions for buffer-local
  autocommands:
  - SpotBugsRemoveBufferAutocmd;
  - SpotBugsDefineBufferAutocmd.

For example, try this from "~/.vim/after/ftplugin/java.vim":
------------------------------------------------------------
if exists(':SpotBugsDefineBufferAutocmd') == 2
	SpotBugsDefineBufferAutocmd BufWritePost SigUSR1
endif
------------------------------------------------------------

And ":doautocmd java_spotbugs User" can be manually used at will.

closes: #16140

Signed-off-by: Aliaksei Budavei <0x000c70@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
diff --git a/runtime/doc/quickfix.txt b/runtime/doc/quickfix.txt
index 6d46458..1cd075f 100644
--- a/runtime/doc/quickfix.txt
+++ b/runtime/doc/quickfix.txt
@@ -1,4 +1,4 @@
-*quickfix.txt*  For Vim version 9.1.  Last change: 2024 Nov 28
+*quickfix.txt*  For Vim version 9.1.  Last change: 2024 Dec 16
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -1349,7 +1349,7 @@
 (Therefore, `:compiler! spotbugs` is not supported.)
 
 Commonly used compiler options can be added to 'makeprg' by setting the
-"b:" or "g:spotbugs_makeprg_params" variable.  For example: >
+"b:" or "g:spotbugs_makeprg_params" variable.  For example: >vim
 
 	let b:spotbugs_makeprg_params = "-longBugCodes -effort:max -low"
 
@@ -1359,22 +1359,25 @@
 files are placed.  However, typical Java projects use distinct directories
 for source files and class files.  To make both known to SpotBugs, assign
 their paths (distinct and relative to their common root directory) to the
-following properties (using the example of a common Maven project): >
+following properties (using the example of a common Maven project): >vim
 
 	let g:spotbugs_properties = {
-		\ 'sourceDirPath':	'src/main/java',
-		\ 'classDirPath':	'target/classes',
-		\ 'testSourceDirPath':	'src/test/java',
-		\ 'testClassDirPath':	'target/test-classes',
+		\ 'sourceDirPath':	['src/main/java'],
+		\ 'classDirPath':	['target/classes'],
+		\ 'testSourceDirPath':	['src/test/java'],
+		\ 'testClassDirPath':	['target/test-classes'],
 	\ }
 
+Note that source and class path entries are expected to come in pairs: define
+both "sourceDirPath" and "classDirPath" when you are considering at least one,
+and apply the same logic to "testSourceDirPath" and "testClassDirPath".
 Note that values for the path keys describe only for SpotBugs where to look
 for files; refer to the documentation for particular compiler plugins for more
 information.
 
 The default pre- and post-compiler actions are provided for Ant, Maven, and
 Javac compiler plugins and can be selected by assigning the name of a compiler
-plugin to the "compiler" key: >
+plugin (`ant`, `maven`, or `javac`) to the "compiler" key: >vim
 
 	let g:spotbugs_properties = {
 		\ 'compiler':		'maven',
@@ -1384,7 +1387,7 @@
 the exception made for the "PreCompilerAction" and "PreCompilerTestAction"
 values: their listed |Funcref|s will obtain no-op implementations whereas the
 implicit Funcrefs of the "compiler" key will obtain the requested defaults if
-available. >
+available. >vim
 
 	let g:spotbugs_properties = {
 		\ 'PreCompilerAction':
@@ -1393,10 +1396,10 @@
 			\ function('spotbugs#DefaultPreCompilerTestAction'),
 		\ 'PostCompilerAction':
 			\ function('spotbugs#DefaultPostCompilerAction'),
-		\ 'sourceDirPath':	'src/main/java',
-		\ 'classDirPath':	'target/classes',
-		\ 'testSourceDirPath':	'src/test/java',
-		\ 'testClassDirPath':	'target/test-classes',
+		\ 'sourceDirPath':	['src/main/java'],
+		\ 'classDirPath':	['target/classes'],
+		\ 'testSourceDirPath':	['src/test/java'],
+		\ 'testClassDirPath':	['target/test-classes'],
 	\ }
 
 With default actions, the compiler of choice will attempt to rebuild the class
@@ -1404,23 +1407,42 @@
 syntax file is loaded; then, `spotbugs` will attempt to analyze the quality of
 the compilation unit of the buffer.
 
-When default actions are not suited to a desired workflow, consider writing
-arbitrary functions yourself and matching their |Funcref|s to the supported
+Vim commands proficient in 'makeprg' [0] can be composed with default actions.
+Begin by considering which of the supported keys, "DefaultPreCompilerCommand",
+"DefaultPreCompilerTestCommand", or "DefaultPostCompilerCommand", you need to
+write an implementation for, observing that each of these keys corresponds to
+a particular "*Action" key.  Follow it by defining a new function that always
+declares an only parameter of type string and puts to use a command equivalent
+of |:make|, and assigning its |Funcref| to the selected key.  For example:
+>vim
+	function! GenericPostCompilerCommand(arguments) abort
+		execute 'make ' . a:arguments
+	endfunction
+
+	let g:spotbugs_properties = {
+		\ 'DefaultPostCompilerCommand':
+			\ function('GenericPostCompilerCommand'),
+	\ }
+
+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".
 
 The next example re-implements the default pre-compiler actions for a Maven
-project and requests other default Maven settings with the "compiler" entry: >
-
+project and requests other default Maven settings with the "compiler" entry:
+>vim
 	function! MavenPreCompilerAction() abort
 		call spotbugs#DeleteClassFiles()
 		compiler maven
 		make compile
+		cc
 	endfunction
 
 	function! MavenPreCompilerTestAction() abort
 		call spotbugs#DeleteClassFiles()
 		compiler maven
 		make test-compile
+		cc
 	endfunction
 
 	let g:spotbugs_properties = {
@@ -1433,14 +1455,46 @@
 
 Note that all entered custom settings will take precedence over the matching
 default settings in "g:spotbugs_properties".
+Note that it is necessary to notify the plugin of the result of a pre-compiler
+action before further work can be undertaken.  Using |:cc| after |:make| (or
+|:ll| after |:lmake|) as the last command of an action is the supported means
+of such communication.
+
+Two commands, "SpotBugsRemoveBufferAutocmd" and "SpotBugsDefineBufferAutocmd",
+are provided to toggle actions for buffer-local autocommands.  For example, to
+also run actions on any |BufWritePost| and |SigUSR1| event, add these lines to
+`~/.vim/after/ftplugin/java.vim`: >vim
+
+	if exists(':SpotBugsDefineBufferAutocmd') == 2
+		SpotBugsDefineBufferAutocmd BufWritePost SigUSR1
+	endif
+
+Otherwise, you can turn to `:doautocmd java_spotbugs User` at any time.
 
 The "g:spotbugs_properties" variable is consulted by the Java filetype plugin
 (|ft-java-plugin|) to arrange for the described automation, and, therefore, it
 must be defined before |FileType| events can take place for the buffers loaded
 with Java source files.  It could, for example, be set in a project-local
-|vimrc| loaded by [0].
+|vimrc| loaded by [1].
 
-[0] https://github.com/MarcWeber/vim-addon-local-vimrc/
+Both "g:spotbugs_properties" and "b:spotbugs_properties" are recognized and
+must be modifiable (|:unlockvar|).  The "*Command" entries are always treated
+as global functions to be shared among all Java buffers.
+
+The SpotBugs Java library and, by extension, its distributed shell scripts do
+not support in the `-textui` mode listed pathnames with directory filenames
+that contain blank characters [2].  To work around this limitation, consider
+making a symbolic link to such a directory from a directory that does not have
+blank characters in its name and passing this information to SpotBugs: >vim
+
+	let g:spotbugs_alternative_path = {
+		\ 'fromPath':	'path/to/dir_without_blanks',
+		\ 'toPath':	'path/to/dir with blanks',
+	\ }
+
+[0] https://github.com/Konfekt/vim-compilers
+[1] https://github.com/MarcWeber/vim-addon-local-vimrc
+[2] https://github.com/spotbugs/spotbugs/issues/909
 
 GNU MAKE						*compiler-make*