patch 9.1.0894: No test for what the spotbug compiler parses

Problem:  No test for what the spotbug compiler parses
          (after commit: 65311c6f472de67b368)
Solution: Test &makeprg for the SpotBugs compiler plugin
          (Aliaksei Budavei)

closes: #16096

Signed-off-by: Aliaksei Budavei <0x000c70@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
diff --git a/src/testdir/test_compiler.vim b/src/testdir/test_compiler.vim
index b7315e1..d650808 100644
--- a/src/testdir/test_compiler.vim
+++ b/src/testdir/test_compiler.vim
@@ -85,4 +85,196 @@
   unlet! g:current_compiler
 endfunc
 
+func s:SpotBugsParseFilterMakePrg(dirname, makeprg)
+  let result = {}
+  let result.sourcepath = ''
+  let result.classfiles = []
+
+  " Get the argument after the rightmost occurrence of "-sourcepath".
+  let offset = strridx(a:makeprg, '-sourcepath')
+  if offset < 0
+    return result
+  endif
+  let offset += 1 + strlen('-sourcepath')
+  let result.sourcepath = matchstr(strpart(a:makeprg, offset), '.\{-}\ze[ \t]')
+
+  " Get the class file arguments, dropping the pathname prefix.
+  let offset = stridx(a:makeprg, a:dirname, offset)
+  if offset < 0
+    return result
+  endif
+
+  while offset > -1
+    let candidate = matchstr(a:makeprg, '[^ \t]\{-}\.class\>', offset)
+    if empty(candidate)
+      break
+    endif
+    call add(result.classfiles, candidate)
+    let offset = stridx(a:makeprg, a:dirname, (1 + strlen(candidate) + offset))
+  endwhile
+
+  call sort(result.classfiles)
+  return result
+endfunc
+
+func Test_compiler_spotbugs_makeprg()
+  let save_shellslash = &shellslash
+  set shellslash
+
+  call assert_true(mkdir('Xspotbugs/src/tests/α/β/γ/δ', 'pR'))
+  call assert_true(mkdir('Xspotbugs/tests/α/β/γ/δ', 'pR'))
+
+  let lines =<< trim END
+      // EOL comment. /*
+      abstract class
+      𐌂1 /* Multiline comment. */ {
+          /* Multiline comment. */ // EOL comment. /*
+          static final String COMMENT_A_LIKE = "/*";
+          { new Object() {/* Try globbing. */}; }
+          static { interface 𐌉𐌉1 {} }
+          static class 𐌂11 { interface 𐌉𐌉2 {} }
+      }
+      /* Multiline comment. */ // EOL comment. /*
+      final class 𐌂2 {
+          public static void main(String... aa) {
+              record 𐌓() {}
+              enum 𐌄 {}
+          }
+      } // class
+  END
+
+  " THE EXPECTED RESULTS.
+  let results = {}
+  let results['Xspotbugs/src/tests/𐌂1.java'] = {
+      \ 'sourcepath': '%:p:h:S',
+      \ 'classfiles': sort([
+          \ 'Xspotbugs/tests/𐌂1$1.class',
+          \ 'Xspotbugs/tests/𐌂1$1𐌉𐌉1.class',
+          \ 'Xspotbugs/tests/𐌂1$𐌂11$𐌉𐌉2.class',
+          \ 'Xspotbugs/tests/𐌂1$𐌂11.class',
+          \ 'Xspotbugs/tests/𐌂1.class',
+          \ 'Xspotbugs/tests/𐌂2$1𐌄.class',
+          \ 'Xspotbugs/tests/𐌂2$1𐌓.class',
+          \ 'Xspotbugs/tests/𐌂2.class']),
+      \ }
+  " No class file for an empty source file even with "-Xpkginfo:always".
+  let results['Xspotbugs/src/tests/package-info.java'] = {
+      \ 'sourcepath': '',
+      \ 'classfiles': [],
+      \ }
+  let results['Xspotbugs/src/tests/α/𐌂1.java'] = {
+      \ 'sourcepath': '%:p:h:h:S',
+      \ 'classfiles': sort([
+          \ 'Xspotbugs/tests/α/𐌂1$1.class',
+          \ 'Xspotbugs/tests/α/𐌂1$1𐌉𐌉1.class',
+          \ 'Xspotbugs/tests/α/𐌂1$𐌂11$𐌉𐌉2.class',
+          \ 'Xspotbugs/tests/α/𐌂1$𐌂11.class',
+          \ 'Xspotbugs/tests/α/𐌂1.class',
+          \ 'Xspotbugs/tests/α/𐌂2$1𐌄.class',
+          \ 'Xspotbugs/tests/α/𐌂2$1𐌓.class',
+          \ 'Xspotbugs/tests/α/𐌂2.class']),
+      \ }
+  let results['Xspotbugs/src/tests/α/package-info.java'] = {
+      \ 'sourcepath': '%:p:h:S',
+      \ 'classfiles': ['Xspotbugs/tests/α/package-info.class'],
+      \ }
+  let results['Xspotbugs/src/tests/α/β/𐌂1.java'] = {
+      \ 'sourcepath': '%:p:h:h:h:S',
+      \ 'classfiles': sort([
+          \ 'Xspotbugs/tests/α/β/𐌂1$1.class',
+          \ 'Xspotbugs/tests/α/β/𐌂1$1𐌉𐌉1.class',
+          \ 'Xspotbugs/tests/α/β/𐌂1$𐌂11$𐌉𐌉2.class',
+          \ 'Xspotbugs/tests/α/β/𐌂1$𐌂11.class',
+          \ 'Xspotbugs/tests/α/β/𐌂1.class',
+          \ 'Xspotbugs/tests/α/β/𐌂2$1𐌄.class',
+          \ 'Xspotbugs/tests/α/β/𐌂2$1𐌓.class',
+          \ 'Xspotbugs/tests/α/β/𐌂2.class']),
+      \ }
+  let results['Xspotbugs/src/tests/α/β/package-info.java'] = {
+      \ 'sourcepath': '%:p:h:S',
+      \ 'classfiles': ['Xspotbugs/tests/α/β/package-info.class'],
+      \ }
+  let results['Xspotbugs/src/tests/α/β/γ/𐌂1.java'] = {
+      \ 'sourcepath': '%:p:h:h:h:h:S',
+      \ 'classfiles': sort([
+          \ 'Xspotbugs/tests/α/β/γ/𐌂1$1.class',
+          \ 'Xspotbugs/tests/α/β/γ/𐌂1$1𐌉𐌉1.class',
+          \ 'Xspotbugs/tests/α/β/γ/𐌂1$𐌂11$𐌉𐌉2.class',
+          \ 'Xspotbugs/tests/α/β/γ/𐌂1$𐌂11.class',
+          \ 'Xspotbugs/tests/α/β/γ/𐌂1.class',
+          \ 'Xspotbugs/tests/α/β/γ/𐌂2$1𐌄.class',
+          \ 'Xspotbugs/tests/α/β/γ/𐌂2$1𐌓.class',
+          \ 'Xspotbugs/tests/α/β/γ/𐌂2.class']),
+      \ }
+  let results['Xspotbugs/src/tests/α/β/γ/package-info.java'] = {
+      \ 'sourcepath': '%:p:h:S',
+      \ 'classfiles': ['Xspotbugs/tests/α/β/γ/package-info.class'],
+      \ }
+  let results['Xspotbugs/src/tests/α/β/γ/δ/𐌂1.java'] = {
+      \ 'sourcepath': '%:p:h:h:h:h:h:S',
+      \ 'classfiles': sort([
+          \ 'Xspotbugs/tests/α/β/γ/δ/𐌂1$1.class',
+          \ 'Xspotbugs/tests/α/β/γ/δ/𐌂1$1𐌉𐌉1.class',
+          \ 'Xspotbugs/tests/α/β/γ/δ/𐌂1$𐌂11$𐌉𐌉2.class',
+          \ 'Xspotbugs/tests/α/β/γ/δ/𐌂1$𐌂11.class',
+          \ 'Xspotbugs/tests/α/β/γ/δ/𐌂1.class',
+          \ 'Xspotbugs/tests/α/β/γ/δ/𐌂2$1𐌄.class',
+          \ 'Xspotbugs/tests/α/β/γ/δ/𐌂2$1𐌓.class',
+          \ 'Xspotbugs/tests/α/β/γ/δ/𐌂2.class']),
+      \ }
+  let results['Xspotbugs/src/tests/α/β/γ/δ/package-info.java'] = {
+      \ 'sourcepath': '%:p:h:S',
+      \ 'classfiles': ['Xspotbugs/tests/α/β/γ/δ/package-info.class'],
+      \ }
+
+  " MAKE CLASS FILES DISCOVERABLE!
+  let g:spotbugs_properties = {
+    \ 'sourceDirPath': 'src/tests',
+    \ 'classDirPath': 'tests',
+  \ }
+
+  call assert_true(has_key(s:SpotBugsParseFilterMakePrg('Xspotbugs', ''), 'sourcepath'))
+  call assert_true(has_key(s:SpotBugsParseFilterMakePrg('Xspotbugs', ''), 'classfiles'))
+
+  " Write 45 mock-up class files for 10 source files.
+  for [class_dir, src_dir, package] in [
+        \ ['Xspotbugs/tests/', 'Xspotbugs/src/tests/', ''],
+        \ ['Xspotbugs/tests/α/', 'Xspotbugs/src/tests/α/', 'package α;'],
+        \ ['Xspotbugs/tests/α/β/', 'Xspotbugs/src/tests/α/β/', 'package α.β;'],
+        \ ['Xspotbugs/tests/α/β/γ/', 'Xspotbugs/src/tests/α/β/γ/', 'package α.β.γ;'],
+        \ ['Xspotbugs/tests/α/β/γ/δ/', 'Xspotbugs/src/tests/α/β/γ/δ/', 'package α.β.γ.δ;']]
+    for class_file in ['𐌂1$1.class', '𐌂1$1𐌉𐌉1.class', '𐌂1$𐌂11$𐌉𐌉2.class',
+          \ '𐌂1$𐌂11.class', '𐌂1.class', '𐌂2$1𐌄.class', '𐌂2$1𐌓.class', '𐌂2.class']
+      call writefile(0zcafe.babe.0000.0041, class_dir .. class_file)
+    endfor
+    call writefile(0zcafe.babe.0000.0041, class_dir .. 'package-info.class')
+
+    " Write Java source files.
+    let type_file = src_dir .. '𐌂1.java'
+    call writefile(insert(copy(lines), package), type_file)
+    let package_file = src_dir .. 'package-info.java'
+    call writefile([package], src_dir .. 'package-info.java')
+
+    for s in ['on', 'off']
+      execute 'syntax ' .. s
+
+      execute 'edit ' .. type_file
+      compiler spotbugs
+      let result = s:SpotBugsParseFilterMakePrg('Xspotbugs', &l:makeprg)
+      call assert_equal(results[type_file].sourcepath, result.sourcepath)
+      call assert_equal(results[type_file].classfiles, result.classfiles)
+      bwipeout
+
+      execute 'edit ' .. package_file
+      compiler spotbugs
+      let result = s:SpotBugsParseFilterMakePrg('Xspotbugs', &l:makeprg)
+      call assert_equal(results[package_file].sourcepath, result.sourcepath)
+      call assert_equal(results[package_file].classfiles, result.classfiles)
+      bwipeout
+    endfor
+  endfor
+
+  let &shellslash = save_shellslash
+endfunc
+
 " vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/version.c b/src/version.c
index 8c4afd0..46f313b 100644
--- a/src/version.c
+++ b/src/version.c
@@ -705,6 +705,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    894,
+/**/
     893,
 /**/
     892,