spotbugs.vim 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. " Default pre- and post-compiler actions for SpotBugs
  2. " Maintainers: @konfekt and @zzzyxwvut
  3. " Last Change: 2024 Nov 27
  4. let s:save_cpo = &cpo
  5. set cpo&vim
  6. if v:version > 900
  7. function! spotbugs#DeleteClassFiles() abort
  8. if !exists('b:spotbugs_class_files')
  9. return
  10. endif
  11. for pathname in b:spotbugs_class_files
  12. let classname = pathname =~# "^'.\\+\\.class'$"
  13. \ ? eval(pathname)
  14. \ : pathname
  15. if classname =~# '\.class$' && filereadable(classname)
  16. " Since v9.0.0795.
  17. let octad = readblob(classname, 0, 8)
  18. " Test the magic number and the major version number (45 for v1.0).
  19. " Since v9.0.2027.
  20. if len(octad) == 8 && octad[0 : 3] == 0zcafe.babe &&
  21. \ or((octad[6] << 8), octad[7]) >= 45
  22. echomsg printf('Deleting %s: %d', classname, delete(classname))
  23. endif
  24. endif
  25. endfor
  26. let b:spotbugs_class_files = []
  27. endfunction
  28. else
  29. function! s:DeleteClassFilesWithNewLineCodes(classname) abort
  30. " The distribution of "0a"s in class file versions 2560 and 2570:
  31. "
  32. " 0zca.fe.ba.be.00.00.0a.00 0zca.fe.ba.be.00.00.0a.0a
  33. " 0zca.fe.ba.be.00.0a.0a.00 0zca.fe.ba.be.00.0a.0a.0a
  34. " 0zca.fe.ba.be.0a.00.0a.00 0zca.fe.ba.be.0a.00.0a.0a
  35. " 0zca.fe.ba.be.0a.0a.0a.00 0zca.fe.ba.be.0a.0a.0a.0a
  36. let numbers = [0, 0, 0, 0, 0, 0, 0, 0]
  37. let offset = 0
  38. let lines = readfile(a:classname, 'b', 4)
  39. " Track NL byte counts to handle files of less than 8 bytes.
  40. let nl_cnt = len(lines)
  41. " Track non-NL byte counts for "0zca.fe.ba.be.0a.0a.0a.0a".
  42. let non_nl_cnt = 0
  43. for line in lines
  44. for idx in range(strlen(line))
  45. " Remap NLs to Nuls.
  46. let numbers[offset] = (line[idx] == "\n") ? 0 : char2nr(line[idx]) % 256
  47. let non_nl_cnt += 1
  48. let offset += 1
  49. if offset > 7
  50. break
  51. endif
  52. endfor
  53. let nl_cnt -= 1
  54. if offset > 7 || (nl_cnt < 1 && non_nl_cnt > 4)
  55. break
  56. endif
  57. " Reclaim NLs.
  58. let numbers[offset] = 10
  59. let offset += 1
  60. if offset > 7
  61. break
  62. endif
  63. endfor
  64. " Test the magic number and the major version number (45 for v1.0).
  65. if offset > 7 && numbers[0] == 0xca && numbers[1] == 0xfe &&
  66. \ numbers[2] == 0xba && numbers[3] == 0xbe &&
  67. \ (numbers[6] * 256 + numbers[7]) >= 45
  68. echomsg printf('Deleting %s: %d', a:classname, delete(a:classname))
  69. endif
  70. endfunction
  71. function! spotbugs#DeleteClassFiles() abort
  72. if !exists('b:spotbugs_class_files')
  73. return
  74. endif
  75. let encoding = &encoding
  76. try
  77. set encoding=latin1
  78. for pathname in b:spotbugs_class_files
  79. let classname = pathname =~# "^'.\\+\\.class'$"
  80. \ ? eval(pathname)
  81. \ : pathname
  82. if classname =~# '\.class$' && filereadable(classname)
  83. let line = get(readfile(classname, 'b', 1), 0, '')
  84. let length = strlen(line)
  85. " Test the magic number and the major version number (45 for v1.0).
  86. if length > 3 && line[0 : 3] == "\xca\xfe\xba\xbe"
  87. if length > 7 && ((line[6] == "\n" ? 0 : char2nr(line[6]) % 256) * 256 +
  88. \ (line[7] == "\n" ? 0 : char2nr(line[7]) % 256)) >= 45
  89. echomsg printf('Deleting %s: %d', classname, delete(classname))
  90. else
  91. call s:DeleteClassFilesWithNewLineCodes(classname)
  92. endif
  93. endif
  94. endif
  95. endfor
  96. finally
  97. let &encoding = encoding
  98. endtry
  99. let b:spotbugs_class_files = []
  100. endfunction
  101. endif
  102. function! spotbugs#DefaultPostCompilerAction() abort
  103. " Since v7.4.191.
  104. make %:S
  105. endfunction
  106. " Look for "spotbugs#compiler" in "ftplugin/java.vim".
  107. let s:compiler = exists('spotbugs#compiler') ? spotbugs#compiler : ''
  108. let s:readable = filereadable($VIMRUNTIME . '/compiler/' . s:compiler . '.vim')
  109. if s:readable && s:compiler ==# 'maven' && executable('mvn')
  110. function! spotbugs#DefaultPreCompilerAction() abort
  111. call spotbugs#DeleteClassFiles()
  112. compiler maven
  113. make compile
  114. endfunction
  115. function! spotbugs#DefaultPreCompilerTestAction() abort
  116. call spotbugs#DeleteClassFiles()
  117. compiler maven
  118. make test-compile
  119. endfunction
  120. function! spotbugs#DefaultProperties() abort
  121. return {
  122. \ 'PreCompilerAction':
  123. \ function('spotbugs#DefaultPreCompilerAction'),
  124. \ 'PreCompilerTestAction':
  125. \ function('spotbugs#DefaultPreCompilerTestAction'),
  126. \ 'PostCompilerAction':
  127. \ function('spotbugs#DefaultPostCompilerAction'),
  128. \ 'sourceDirPath': 'src/main/java',
  129. \ 'classDirPath': 'target/classes',
  130. \ 'testSourceDirPath': 'src/test/java',
  131. \ 'testClassDirPath': 'target/test-classes',
  132. \ }
  133. endfunction
  134. unlet s:readable s:compiler
  135. elseif s:readable && s:compiler ==# 'ant' && executable('ant')
  136. function! spotbugs#DefaultPreCompilerAction() abort
  137. call spotbugs#DeleteClassFiles()
  138. compiler ant
  139. make compile
  140. endfunction
  141. function! spotbugs#DefaultPreCompilerTestAction() abort
  142. call spotbugs#DeleteClassFiles()
  143. compiler ant
  144. make compile-test
  145. endfunction
  146. function! spotbugs#DefaultProperties() abort
  147. return {
  148. \ 'PreCompilerAction':
  149. \ function('spotbugs#DefaultPreCompilerAction'),
  150. \ 'PreCompilerTestAction':
  151. \ function('spotbugs#DefaultPreCompilerTestAction'),
  152. \ 'PostCompilerAction':
  153. \ function('spotbugs#DefaultPostCompilerAction'),
  154. \ 'sourceDirPath': 'src',
  155. \ 'classDirPath': 'build/classes',
  156. \ 'testSourceDirPath': 'test',
  157. \ 'testClassDirPath': 'build/test/classes',
  158. \ }
  159. endfunction
  160. unlet s:readable s:compiler
  161. elseif s:readable && s:compiler ==# 'javac' && executable('javac')
  162. function! spotbugs#DefaultPreCompilerAction() abort
  163. call spotbugs#DeleteClassFiles()
  164. compiler javac
  165. if get(b:, 'javac_makeprg_params', get(g:, 'javac_makeprg_params', '')) =~ '\s@\S'
  166. " Read options and filenames from @options [@sources ...].
  167. make
  168. else
  169. " Let Javac figure out what files to compile.
  170. execute 'make ' . join(map(filter(copy(v:argv),
  171. \ "v:val =~# '\\.java\\=$'"),
  172. \ 'shellescape(v:val)'), ' ')
  173. endif
  174. endfunction
  175. function! spotbugs#DefaultPreCompilerTestAction() abort
  176. call spotbugs#DefaultPreCompilerAction()
  177. endfunction
  178. function! spotbugs#DefaultProperties() abort
  179. return {
  180. \ 'PreCompilerAction':
  181. \ function('spotbugs#DefaultPreCompilerAction'),
  182. \ 'PreCompilerTestAction':
  183. \ function('spotbugs#DefaultPreCompilerTestAction'),
  184. \ 'PostCompilerAction':
  185. \ function('spotbugs#DefaultPostCompilerAction'),
  186. \ }
  187. endfunction
  188. unlet s:readable s:compiler
  189. else
  190. function! spotbugs#DefaultPreCompilerAction() abort
  191. echomsg printf('Not supported: "%s"', s:compiler)
  192. endfunction
  193. function! spotbugs#DefaultPreCompilerTestAction() abort
  194. call spotbugs#DefaultPreCompilerAction()
  195. endfunction
  196. function! spotbugs#DefaultProperties() abort
  197. return {}
  198. endfunction
  199. unlet s:readable
  200. endif
  201. let &cpo = s:save_cpo
  202. unlet s:save_cpo
  203. " vim: set foldmethod=syntax shiftwidth=2 expandtab: