java.vim 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. " Vim filetype plugin file
  2. " Language: Java
  3. " Maintainer: Aliaksei Budavei <0x000c70 AT gmail DOT com>
  4. " Former Maintainer: Dan Sharp
  5. " Repository: https://github.com/zzzyxwvut/java-vim.git
  6. " Last Change: 2024 Dec 25
  7. " 2024 Jan 14 by Vim Project (browsefilter)
  8. " 2024 May 23 by Riley Bruins <ribru17@gmail.com> ('commentstring')
  9. " Make sure the continuation lines below do not cause problems in
  10. " compatibility mode.
  11. let s:save_cpo = &cpo
  12. set cpo-=C
  13. if (exists("g:java_ignore_javadoc") || exists("g:java_ignore_markdown")) &&
  14. \ exists("*javaformat#RemoveCommonMarkdownWhitespace")
  15. delfunction javaformat#RemoveCommonMarkdownWhitespace
  16. unlet! g:loaded_javaformat
  17. endif
  18. if exists("b:did_ftplugin")
  19. let &cpo = s:save_cpo
  20. unlet s:save_cpo
  21. finish
  22. endif
  23. let b:did_ftplugin = 1
  24. " For filename completion, prefer the .java extension over the .class
  25. " extension.
  26. set suffixes+=.class
  27. " Enable gf on import statements. Convert . in the package
  28. " name to / and append .java to the name, then search the path.
  29. setlocal includeexpr=substitute(v:fname,'\\.','/','g')
  30. setlocal suffixesadd=.java
  31. " Clean up in case this file is sourced again.
  32. unlet! s:zip_func_upgradable
  33. """" STRIVE TO REMAIN COMPATIBLE FOR AT LEAST VIM 7.0.
  34. " Documented in ":help ft-java-plugin".
  35. if exists("g:ftplugin_java_source_path") &&
  36. \ type(g:ftplugin_java_source_path) == type("")
  37. if filereadable(g:ftplugin_java_source_path)
  38. if exists("#zip") &&
  39. \ g:ftplugin_java_source_path =~# '.\.\%(jar\|zip\)$'
  40. if !exists("s:zip_files")
  41. let s:zip_files = {}
  42. endif
  43. let s:zip_files[bufnr('%')] = g:ftplugin_java_source_path
  44. let s:zip_files[0] = g:ftplugin_java_source_path
  45. let s:zip_func_upgradable = 1
  46. function! JavaFileTypeZipFile() abort
  47. let @/ = substitute(v:fname, '\.', '\\/', 'g') . '.java'
  48. return get(s:zip_files, bufnr('%'), s:zip_files[0])
  49. endfunction
  50. " E120 for "inex=s:JavaFileTypeZipFile()" before v8.2.3900.
  51. setlocal includeexpr=JavaFileTypeZipFile()
  52. setlocal suffixesadd<
  53. endif
  54. else
  55. let &l:path = g:ftplugin_java_source_path . ',' . &l:path
  56. endif
  57. endif
  58. " Set 'formatoptions' to break comment lines but not other lines,
  59. " and insert the comment leader when hitting <CR> or using "o".
  60. setlocal formatoptions-=t formatoptions+=croql
  61. " Set 'comments' to format Markdown Javadoc comments and dashed lists
  62. " in other multi-line comments (it behaves just like C).
  63. setlocal comments& comments^=:///,sO:*\ -,mO:*\ \ ,exO:*/
  64. setlocal commentstring=//\ %s
  65. " Change the :browse e filter to primarily show Java-related files.
  66. if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
  67. let b:browsefilter="Java Files (*.java)\t*.java\n" .
  68. \ "Properties Files (*.prop*)\t*.prop*\n" .
  69. \ "Manifest Files (*.mf)\t*.mf\n"
  70. if has("win32")
  71. let b:browsefilter .= "All Files (*.*)\t*\n"
  72. else
  73. let b:browsefilter .= "All Files (*)\t*\n"
  74. endif
  75. endif
  76. """" Support pre- and post-compiler actions for SpotBugs.
  77. if (!empty(get(g:, 'spotbugs_properties', {})) ||
  78. \ !empty(get(b:, 'spotbugs_properties', {}))) &&
  79. \ filereadable($VIMRUNTIME . '/compiler/spotbugs.vim')
  80. function! s:SpotBugsGetProperty(name, default) abort
  81. return get(
  82. \ {s:spotbugs_properties_scope}spotbugs_properties,
  83. \ a:name,
  84. \ a:default)
  85. endfunction
  86. function! s:SpotBugsHasProperty(name) abort
  87. return has_key(
  88. \ {s:spotbugs_properties_scope}spotbugs_properties,
  89. \ a:name)
  90. endfunction
  91. function! s:SpotBugsGetProperties() abort
  92. return {s:spotbugs_properties_scope}spotbugs_properties
  93. endfunction
  94. " Work around ":bar"s and ":autocmd"s.
  95. function! JavaFileTypeExecuteActionOnce(cleanup_cmd, action_cmd) abort
  96. try
  97. execute a:cleanup_cmd
  98. finally
  99. execute a:action_cmd
  100. endtry
  101. endfunction
  102. if exists("b:spotbugs_properties")
  103. let s:spotbugs_properties_scope = 'b:'
  104. " Merge global entries, if any, in buffer-local entries, favouring
  105. " defined buffer-local ones.
  106. call extend(
  107. \ b:spotbugs_properties,
  108. \ get(g:, 'spotbugs_properties', {}),
  109. \ 'keep')
  110. elseif exists("g:spotbugs_properties")
  111. let s:spotbugs_properties_scope = 'g:'
  112. endif
  113. let s:commands = {}
  114. for s:name in ['DefaultPreCompilerCommand',
  115. \ 'DefaultPreCompilerTestCommand',
  116. \ 'DefaultPostCompilerCommand']
  117. if s:SpotBugsHasProperty(s:name)
  118. let s:commands[s:name] = remove(
  119. \ s:SpotBugsGetProperties(),
  120. \ s:name)
  121. endif
  122. endfor
  123. if s:SpotBugsHasProperty('compiler')
  124. " XXX: Postpone loading the script until all state, if any, has been
  125. " collected.
  126. if !empty(s:commands)
  127. let g:spotbugs#state = {
  128. \ 'compiler': remove(s:SpotBugsGetProperties(), 'compiler'),
  129. \ 'commands': copy(s:commands),
  130. \ }
  131. else
  132. let g:spotbugs#state = {
  133. \ 'compiler': remove(s:SpotBugsGetProperties(), 'compiler'),
  134. \ }
  135. endif
  136. " Merge default entries in global (or buffer-local) entries, favouring
  137. " defined global (or buffer-local) ones.
  138. call extend(
  139. \ {s:spotbugs_properties_scope}spotbugs_properties,
  140. \ spotbugs#DefaultProperties(),
  141. \ 'keep')
  142. elseif !empty(s:commands)
  143. " XXX: Postpone loading the script until all state, if any, has been
  144. " collected.
  145. let g:spotbugs#state = {'commands': copy(s:commands)}
  146. endif
  147. unlet s:commands s:name
  148. let s:request = 0
  149. if s:SpotBugsHasProperty('PostCompilerAction')
  150. let s:request += 4
  151. endif
  152. if s:SpotBugsHasProperty('PreCompilerTestAction')
  153. let s:dispatcher = printf('call call(%s, [])',
  154. \ string(s:SpotBugsGetProperties().PreCompilerTestAction))
  155. let s:request += 2
  156. endif
  157. if s:SpotBugsHasProperty('PreCompilerAction')
  158. let s:dispatcher = printf('call call(%s, [])',
  159. \ string(s:SpotBugsGetProperties().PreCompilerAction))
  160. let s:request += 1
  161. endif
  162. " Adapt the tests for "s:FindClassFiles()" from "compiler/spotbugs.vim".
  163. if (s:request == 3 || s:request == 7) &&
  164. \ (!empty(s:SpotBugsGetProperty('sourceDirPath', [])) &&
  165. \ !empty(s:SpotBugsGetProperty('classDirPath', [])) &&
  166. \ !empty(s:SpotBugsGetProperty('testSourceDirPath', [])) &&
  167. \ !empty(s:SpotBugsGetProperty('testClassDirPath', [])))
  168. function! s:DispatchAction(paths_action_pairs) abort
  169. let name = expand('%:p')
  170. for [paths, Action] in a:paths_action_pairs
  171. for path in paths
  172. if name =~# (path . '.\{-}\.java\=$')
  173. call Action()
  174. return
  175. endif
  176. endfor
  177. endfor
  178. endfunction
  179. let s:dir_cnt = min([
  180. \ len(s:SpotBugsGetProperties().sourceDirPath),
  181. \ len(s:SpotBugsGetProperties().classDirPath)])
  182. let s:test_dir_cnt = min([
  183. \ len(s:SpotBugsGetProperties().testSourceDirPath),
  184. \ len(s:SpotBugsGetProperties().testClassDirPath)])
  185. " Do not break up path pairs with filtering!
  186. let s:dispatcher = printf('call s:DispatchAction(%s)',
  187. \ string([[s:SpotBugsGetProperties().sourceDirPath[0 : s:dir_cnt - 1],
  188. \ s:SpotBugsGetProperties().PreCompilerAction],
  189. \ [s:SpotBugsGetProperties().testSourceDirPath[0 : s:test_dir_cnt - 1],
  190. \ s:SpotBugsGetProperties().PreCompilerTestAction]]))
  191. unlet s:test_dir_cnt s:dir_cnt
  192. endif
  193. if exists("s:dispatcher")
  194. function! s:ExecuteActions(pre_action, post_action) abort
  195. try
  196. execute a:pre_action
  197. catch /\<E42:/
  198. execute a:post_action
  199. endtry
  200. endfunction
  201. endif
  202. if s:request
  203. if exists("b:spotbugs_syntax_once") || empty(join(getline(1, 8), ''))
  204. let s:actions = [{'event': 'User'}]
  205. else
  206. " XXX: Handle multiple FileType events when vimrc contains more
  207. " than one filetype setting for the language, e.g.:
  208. " :filetype plugin indent on
  209. " :autocmd BufRead,BufNewFile *.java setlocal filetype=java ...
  210. " XXX: DO NOT ADD b:spotbugs_syntax_once TO b:undo_ftplugin !
  211. let b:spotbugs_syntax_once = 1
  212. let s:actions = [{
  213. \ 'event': 'Syntax',
  214. \ 'once': 1,
  215. \ }, {
  216. \ 'event': 'User',
  217. \ }]
  218. endif
  219. for s:idx in range(len(s:actions))
  220. if s:request == 7 || s:request == 6 || s:request == 5
  221. let s:actions[s:idx].cmd = printf('call s:ExecuteActions(%s, %s)',
  222. \ string(s:dispatcher),
  223. \ string(printf('compiler spotbugs | call call(%s, [])',
  224. \ string(s:SpotBugsGetProperties().PostCompilerAction))))
  225. elseif s:request == 4
  226. let s:actions[s:idx].cmd = printf(
  227. \ 'compiler spotbugs | call call(%s, [])',
  228. \ string(s:SpotBugsGetProperties().PostCompilerAction))
  229. elseif s:request == 3 || s:request == 2 || s:request == 1
  230. let s:actions[s:idx].cmd = printf('call s:ExecuteActions(%s, %s)',
  231. \ string(s:dispatcher),
  232. \ string('compiler spotbugs'))
  233. else
  234. let s:actions[s:idx].cmd = ''
  235. endif
  236. endfor
  237. if !exists("#java_spotbugs")
  238. augroup java_spotbugs
  239. augroup END
  240. endif
  241. " The events are defined in s:actions.
  242. silent! autocmd! java_spotbugs User <buffer>
  243. silent! autocmd! java_spotbugs Syntax <buffer>
  244. for s:action in s:actions
  245. if has_key(s:action, 'once')
  246. execute printf('autocmd java_spotbugs %s <buffer> ' .
  247. \ 'call JavaFileTypeExecuteActionOnce(%s, %s)',
  248. \ s:action.event,
  249. \ string(printf('autocmd! java_spotbugs %s <buffer>',
  250. \ s:action.event)),
  251. \ string(s:action.cmd))
  252. else
  253. execute printf('autocmd java_spotbugs %s <buffer> %s',
  254. \ s:action.event,
  255. \ s:action.cmd)
  256. endif
  257. endfor
  258. if s:SpotBugsHasProperty('PostCompilerActionExecutor') &&
  259. \ (s:request == 7 || s:request == 6 ||
  260. \ s:request == 5 || s:request == 4)
  261. let s:augroup = s:SpotBugsGetProperty(
  262. \ 'augroupForPostCompilerAction',
  263. \ 'java_spotbugs_post')
  264. let s:augroup = !empty(s:augroup) ? s:augroup : 'java_spotbugs_post'
  265. for s:candidate in ['java_spotbugs_post', s:augroup]
  266. if !exists("#" . s:candidate)
  267. execute printf('augroup %s | augroup END', s:candidate)
  268. endif
  269. endfor
  270. silent! autocmd! java_spotbugs_post User <buffer>
  271. " Define a User ":autocmd" to define a once-only ShellCmdPost
  272. " ":autocmd" that will invoke "PostCompilerActionExecutor" and let
  273. " it decide whether to proceed with ":compiler spotbugs" etc.; and
  274. " seek explicit synchronisation with ":doautocmd ShellCmdPost" by
  275. " omitting "nested" for "java_spotbugs_post" and "java_spotbugs".
  276. execute printf('autocmd java_spotbugs_post User <buffer> ' .
  277. \ 'call JavaFileTypeExecuteActionOnce(%s, %s)',
  278. \ string(printf('autocmd! %s ShellCmdPost <buffer>', s:augroup)),
  279. \ string(printf('autocmd %s ShellCmdPost <buffer> ' .
  280. \ 'call JavaFileTypeExecuteActionOnce(%s, %s)',
  281. \ s:augroup,
  282. \ string(printf('autocmd! %s ShellCmdPost <buffer>', s:augroup)),
  283. \ string(printf('call call(%s, [%s])',
  284. \ string(s:SpotBugsGetProperties().PostCompilerActionExecutor),
  285. \ string(printf('compiler spotbugs | call call(%s, [])',
  286. \ string(s:SpotBugsGetProperties().PostCompilerAction))))))))
  287. endif
  288. unlet! s:candidate s:augroup s:action s:actions s:idx s:dispatcher
  289. endif
  290. delfunction s:SpotBugsGetProperties
  291. delfunction s:SpotBugsHasProperty
  292. delfunction s:SpotBugsGetProperty
  293. unlet! s:request s:spotbugs_properties_scope
  294. endif
  295. function! JavaFileTypeCleanUp() abort
  296. setlocal suffixes< suffixesadd< formatoptions< comments< commentstring< path< includeexpr<
  297. unlet! b:browsefilter
  298. " The concatenated ":autocmd" removals may be misparsed as an ":autocmd".
  299. " A _once-only_ ShellCmdPost ":autocmd" is always a call-site definition.
  300. silent! autocmd! java_spotbugs User <buffer>
  301. silent! autocmd! java_spotbugs Syntax <buffer>
  302. silent! autocmd! java_spotbugs_post User <buffer>
  303. endfunction
  304. " Undo the stuff we changed.
  305. let b:undo_ftplugin = 'call JavaFileTypeCleanUp() | delfunction JavaFileTypeCleanUp'
  306. " See ":help vim9-mix".
  307. if !has("vim9script")
  308. let &cpo = s:save_cpo
  309. unlet s:save_cpo
  310. finish
  311. endif
  312. if exists("s:zip_func_upgradable")
  313. delfunction! JavaFileTypeZipFile
  314. def! s:JavaFileTypeZipFile(): string
  315. @/ = substitute(v:fname, '\.', '\\/', 'g') .. '.java'
  316. return get(zip_files, bufnr('%'), zip_files[0])
  317. enddef
  318. setlocal includeexpr=s:JavaFileTypeZipFile()
  319. setlocal suffixesadd<
  320. endif
  321. if exists("*s:DispatchAction")
  322. def! s:DispatchAction(paths_action_pairs: list<list<any>>)
  323. const name: string = expand('%:p')
  324. for [paths: list<string>, Action: func: any] in paths_action_pairs
  325. for path in paths
  326. if name =~# (path .. '.\{-}\.java\=$')
  327. Action()
  328. return
  329. endif
  330. endfor
  331. endfor
  332. enddef
  333. endif
  334. " Restore the saved compatibility options.
  335. let &cpo = s:save_cpo
  336. unlet s:save_cpo
  337. " vim: fdm=syntax sw=4 ts=8 noet sta