codekingpro/portable-devtools
115k
1" Vim filetype plugin file2" Language: Java3" Maintainer: Aliaksei Budavei <0x000c70 AT gmail DOT com>4" Former Maintainer: Dan Sharp5" Repository: https://github.com/zzzyxwvut/java-vim.git6" Last Change: 2025 May 087 8" Make sure the continuation lines below do not cause problems in9" compatibility mode.10let s:save_cpo = &cpo11set cpo-=C12 13if (exists("g:java_ignore_javadoc") || exists("g:java_ignore_markdown")) &&14 \ exists("*javaformat#RemoveCommonMarkdownWhitespace")15 delfunction javaformat#RemoveCommonMarkdownWhitespace16 unlet! g:loaded_javaformat17endif18 19if exists("b:did_ftplugin")20 let &cpo = s:save_cpo21 unlet s:save_cpo22 finish23endif24 25let b:did_ftplugin = 126 27" For filename completion, prefer the .java extension over the .class28" extension.29set suffixes+=.class30 31" Set up "&define" and "&include".32let s:peek = ''33 34try35 " Since v7.3.1037.36 if 'ab' !~ 'a\@1<!b'37 let s:peek = string(strlen('instanceof') + 8)38 endif39catch /\<E59:/40endtry41 42" Treat "s:common" as a non-backtracking unit to avoid matching constructor43" declarations whose package-private headers are indistinguishable from method44" invocation. Note that "[@-]" must not and "$" may not be in "&l:iskeyword".45let s:common = '\%(\%(\%(@\%(interface\)\@!\%(\K\k*\.\)*\K\k*\)\s\+\)*' .46 \ '\%(p\%(rivate\|rotected\|ublic\)\s\+\)\=\)\@>'47let s:types = '\%(\%(abstract\|final\|non-sealed\|s\%(ealed\|tatic\|trictfp\)\)\s\+\)*' .48 \ '\%(class\|enum\|@\=interface\|record\)\s\+\ze\K\k*\>'49let 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*('53let &l:define = printf('\C\m^\s*%s\%%(%s\|%s\)', s:common, s:types, s:methods)54let &l:include = '\C\m^\s*import\s\+\ze\%(\K\k*\.\)\+\K\k*;'55unlet s:methods s:types s:common s:peek56 57" Enable gf on import statements. Convert . in the package58" name to / and append .java to the name, then search the path.59setlocal includeexpr=substitute(v:fname,'\\.','/','g')60setlocal suffixesadd=.java61 62" Clean up in case this file is sourced again.63unlet! s:zip_func_upgradable64 65"""" STRIVE TO REMAIN COMPATIBLE FOR AT LEAST VIM 7.0.66 67" Documented in ":help ft-java-plugin".68if 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 endif76 77 let s:zip_files[bufnr('%')] = g:ftplugin_java_source_path78 let s:zip_files[0] = g:ftplugin_java_source_path79 let s:zip_func_upgradable = 180 81 function! JavaFileTypeZipFile() abort82 let @/ = substitute(v:fname, '\.', '\\/', 'g') . '.java'83 return get(s:zip_files, bufnr('%'), s:zip_files[0])84 endfunction85 86 " E120 for "inex=s:JavaFileTypeZipFile()" before v8.2.3900.87 setlocal includeexpr=JavaFileTypeZipFile()88 setlocal suffixesadd<89 endif90 else91 let &l:path = g:ftplugin_java_source_path . ',' . &l:path92 endif93endif94 95" Set 'formatoptions' to break comment lines but not other lines,96" and insert the comment leader when hitting <CR> or using "o".97setlocal formatoptions-=t formatoptions+=croql98 99" Set 'comments' to format Markdown Javadoc comments and dashed lists100" in other multi-line comments (it behaves just like C).101setlocal comments& comments^=:///,sO:*\ -,mO:*\ \ ,exO:*/102 103setlocal commentstring=//\ %s104 105" Change the :browse e filter to primarily show Java-related files.106if (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 else113 let b:browsefilter .= "All Files (*)\t*\n"114 endif115endif116 117"""" Support pre- and post-compiler actions for SpotBugs.118if (!empty(get(g:, 'spotbugs_properties', {})) ||119 \ !empty(get(b:, 'spotbugs_properties', {}))) &&120 \ filereadable($VIMRUNTIME . '/compiler/spotbugs.vim')121 122 function! s:SpotBugsGetProperty(name, default) abort123 return get(124 \ {s:spotbugs_properties_scope}spotbugs_properties,125 \ a:name,126 \ a:default)127 endfunction128 129 function! s:SpotBugsHasProperty(name) abort130 return has_key(131 \ {s:spotbugs_properties_scope}spotbugs_properties,132 \ a:name)133 endfunction134 135 function! s:SpotBugsGetProperties() abort136 return {s:spotbugs_properties_scope}spotbugs_properties137 endfunction138 139 " Work around ":bar"s and ":autocmd"s.140 function! JavaFileTypeExecuteActionOnce(cleanup_cmd, action_cmd) abort141 try142 execute a:cleanup_cmd143 finally144 execute a:action_cmd145 endtry146 endfunction147 148 if exists("b:spotbugs_properties")149 let s:spotbugs_properties_scope = 'b:'150 151 " Merge global entries, if any, in buffer-local entries, favouring152 " 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 endif160 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 endif171 endfor172 173 if s:SpotBugsHasProperty('compiler')174 " XXX: Postpone loading the script until all state, if any, has been175 " collected.176 if !empty(s:commands)177 let g:spotbugs#state = {178 \ 'compiler': remove(s:SpotBugsGetProperties(), 'compiler'),179 \ 'commands': copy(s:commands),180 \ }181 else182 let g:spotbugs#state = {183 \ 'compiler': remove(s:SpotBugsGetProperties(), 'compiler'),184 \ }185 endif186 187 " Merge default entries in global (or buffer-local) entries, favouring188 " 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 been195 " collected.196 let g:spotbugs#state = {'commands': copy(s:commands)}197 endif198 199 unlet s:commands s:name200 let s:request = 0201 202 if s:SpotBugsHasProperty('PostCompilerAction')203 let s:request += 4204 endif205 206 if s:SpotBugsHasProperty('PreCompilerTestAction')207 let s:dispatcher = printf('call call(%s, [])',208 \ string(s:SpotBugsGetProperties().PreCompilerTestAction))209 let s:request += 2210 endif211 212 if s:SpotBugsHasProperty('PreCompilerAction')213 let s:dispatcher = printf('call call(%s, [])',214 \ string(s:SpotBugsGetProperties().PreCompilerAction))215 let s:request += 1216 endif217 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) abort225 let name = expand('%:p')226 227 for [paths, Action] in a:paths_action_pairs228 for path in paths229 if name =~# (path . '.\{-}\.java\=$')230 call Action()231 return232 endif233 endfor234 endfor235 endfunction236 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_cnt251 endif252 253 if exists("s:dispatcher")254 function! s:ExecuteActions(pre_action, post_action) abort255 try256 execute a:pre_action257 catch /\<E42:/258 execute a:post_action259 endtry260 endfunction261 endif262 263 if s:request264 if exists("b:spotbugs_syntax_once") || empty(join(getline(1, 8), ''))265 let s:actions = [{'event': 'User'}]266 else267 " XXX: Handle multiple FileType events when vimrc contains more268 " than one filetype setting for the language, e.g.:269 " :filetype plugin indent on270 " :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 = 1273 let s:actions = [{274 \ 'event': 'Syntax',275 \ 'once': 1,276 \ }, {277 \ 'event': 'User',278 \ }]279 endif280 281 for s:idx in range(len(s:actions))282 if s:request == 7 || s:request == 6 || s:request == 5283 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 == 4288 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 == 1292 let s:actions[s:idx].cmd = printf('call s:ExecuteActions(%s, %s)',293 \ string(s:dispatcher),294 \ string('compiler spotbugs'))295 else296 let s:actions[s:idx].cmd = ''297 endif298 endfor299 300 if !exists("#java_spotbugs")301 augroup java_spotbugs302 augroup END303 endif304 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:actions310 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 else318 execute printf('autocmd java_spotbugs %s <buffer> %s',319 \ s:action.event,320 \ s:action.cmd)321 endif322 endfor323 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 endif336 endfor337 338 silent! autocmd! java_spotbugs_post User <buffer>339 340 " Define a User ":autocmd" to define a once-only ShellCmdPost341 " ":autocmd" that will invoke "PostCompilerActionExecutor" and let342 " it decide whether to proceed with ":compiler spotbugs" etc.; and343 " seek explicit synchronisation with ":doautocmd ShellCmdPost" by344 " 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 endif357 358 unlet! s:candidate s:augroup s:action s:actions s:idx s:dispatcher359 endif360 361 delfunction s:SpotBugsGetProperties362 delfunction s:SpotBugsHasProperty363 delfunction s:SpotBugsGetProperty364 unlet! s:request s:spotbugs_properties_scope365endif366 367function! JavaFileTypeCleanUp() abort368 setlocal suffixes< suffixesadd< formatoptions< comments< commentstring< path< includeexpr< include< define<369 unlet! b:browsefilter370 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>376endfunction377 378" Undo the stuff we changed.379let b:undo_ftplugin = 'call JavaFileTypeCleanUp() | delfunction JavaFileTypeCleanUp'380 381" See ":help vim9-mix".382if !has("vim9script")383 let &cpo = s:save_cpo384 unlet s:save_cpo385 finish386endif387 388if exists("s:zip_func_upgradable")389 delfunction! JavaFileTypeZipFile390 391 def! s:JavaFileTypeZipFile(): string392 @/ = substitute(v:fname, '\.', '\\/', 'g') .. '.java'393 return get(zip_files, bufnr('%'), zip_files[0])394 enddef395 396 setlocal includeexpr=s:JavaFileTypeZipFile()397 setlocal suffixesadd<398endif399 400if 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_pairs405 for path in paths406 if name =~# (path .. '.\{-}\.java\=$')407 Action()408 return409 endif410 endfor411 endfor412 enddef413endif414 415" Restore the saved compatibility options.416let &cpo = s:save_cpo417unlet s:save_cpo418" vim: fdm=syntax sw=4 ts=8 noet sta419 