neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

java.vim (13669B)


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