8269ba278d
Allows '%FILE_PATH%', '%FILE_NAME%' and '%FILE_DIR%' to be used in the Java custom classpath command to refer to the full file path, the file basename, and the file directory, respectively.
428 lines
15 KiB
VimL
428 lines
15 KiB
VimL
"============================================================================
|
|
"File: javac.vim
|
|
"Description: Syntax checking plugin for syntastic.vim
|
|
"Maintainer: Jochen Keil <jochen.keil at gmail dot com>
|
|
" Dmitry Geurkov <d.geurkov at gmail dot com>
|
|
"License: This program is free software. It comes without any warranty,
|
|
" to the extent permitted by applicable law. You can redistribute
|
|
" it and/or modify it under the terms of the Do What The Fuck You
|
|
" Want To Public License, Version 2, as published by Sam Hocevar.
|
|
" See http://sam.zoy.org/wtfpl/COPYING for more details.
|
|
"============================================================================
|
|
|
|
if exists('g:loaded_syntastic_java_javac_checker')
|
|
finish
|
|
endif
|
|
let g:loaded_syntastic_java_javac_checker = 1
|
|
let g:syntastic_java_javac_maven_pom_tags = ['build', 'properties']
|
|
let g:syntastic_java_javac_maven_pom_properties = {}
|
|
let s:has_maven = 0
|
|
|
|
let s:save_cpo = &cpo
|
|
set cpo&vim
|
|
|
|
" Checker options {{{1
|
|
|
|
if !exists('g:syntastic_java_javac_executable')
|
|
let g:syntastic_java_javac_executable = 'javac'
|
|
endif
|
|
|
|
if !exists('g:syntastic_java_maven_executable')
|
|
let g:syntastic_java_maven_executable = 'mvn'
|
|
endif
|
|
|
|
if !exists('g:syntastic_java_javac_options')
|
|
let g:syntastic_java_javac_options = '-Xlint'
|
|
endif
|
|
|
|
if !exists('g:syntastic_java_maven_options')
|
|
let g:syntastic_java_maven_options = ''
|
|
endif
|
|
|
|
if !exists('g:syntastic_java_javac_classpath')
|
|
let g:syntastic_java_javac_classpath = ''
|
|
endif
|
|
|
|
if !exists('g:syntastic_java_javac_delete_output')
|
|
let g:syntastic_java_javac_delete_output = 1
|
|
endif
|
|
|
|
if !exists('g:syntastic_java_javac_autoload_maven_classpath')
|
|
let g:syntastic_java_javac_autoload_maven_classpath = 1
|
|
endif
|
|
|
|
if !exists('g:syntastic_java_javac_config_file_enabled')
|
|
let g:syntastic_java_javac_config_file_enabled = 0
|
|
endif
|
|
|
|
if !exists('g:syntastic_java_javac_config_file')
|
|
let g:syntastic_java_javac_config_file = '.syntastic_javac_config'
|
|
endif
|
|
|
|
if !exists('g:syntastic_java_javac_custom_classpath_command')
|
|
let g:syntastic_java_javac_custom_classpath_command = ''
|
|
endif
|
|
|
|
if !exists('g:syntastic_java_javac_maven_pom_ftime')
|
|
let g:syntastic_java_javac_maven_pom_ftime = {}
|
|
endif
|
|
|
|
if !exists('g:syntastic_java_javac_maven_pom_classpath')
|
|
let g:syntastic_java_javac_maven_pom_classpath = {}
|
|
endif
|
|
|
|
" }}}1
|
|
|
|
command! SyntasticJavacEditClasspath call s:EditClasspath()
|
|
|
|
if g:syntastic_java_javac_config_file_enabled
|
|
command! SyntasticJavacEditConfig call s:EditConfig()
|
|
endif
|
|
|
|
function! SyntaxCheckers_java_javac_IsAvailable() dict " {{{1
|
|
let s:has_maven = executable(expand(g:syntastic_java_maven_executable, 1))
|
|
return executable(expand(g:syntastic_java_javac_executable, 1))
|
|
endfunction " }}}1
|
|
|
|
function! SyntaxCheckers_java_javac_GetLocList() dict " {{{1
|
|
let javac_opts = g:syntastic_java_javac_options
|
|
|
|
let output_dir = ''
|
|
if g:syntastic_java_javac_delete_output
|
|
let output_dir = syntastic#util#tmpdir()
|
|
let javac_opts .= ' -d ' . syntastic#util#shescape(output_dir)
|
|
endif
|
|
|
|
" load classpath from config file
|
|
if g:syntastic_java_javac_config_file_enabled
|
|
call s:LoadConfigFile()
|
|
endif
|
|
|
|
|
|
" add classpathes to javac_classpath {{{2
|
|
let javac_classpath = ''
|
|
|
|
for path in split(g:syntastic_java_javac_classpath, s:ClassSep())
|
|
if path !=# ''
|
|
try
|
|
let ps = glob(path, 1, 1)
|
|
catch
|
|
let ps = split(glob(path, 1), "\n")
|
|
endtry
|
|
if type(ps) == type([])
|
|
for p in ps
|
|
let javac_classpath = s:AddToClasspath(javac_classpath, p)
|
|
endfor
|
|
else
|
|
let javac_classpath = s:AddToClasspath(javac_classpath, ps)
|
|
endif
|
|
endif
|
|
endfor
|
|
|
|
if s:has_maven && g:syntastic_java_javac_autoload_maven_classpath
|
|
if !g:syntastic_java_javac_delete_output
|
|
let javac_opts .= ' -d ' . syntastic#util#shescape(s:MavenOutputDirectory())
|
|
endif
|
|
let javac_classpath = s:AddToClasspath(javac_classpath, s:GetMavenClasspath())
|
|
endif
|
|
" }}}2
|
|
|
|
" load custom classpath {{{2
|
|
if g:syntastic_java_javac_custom_classpath_command !=# ''
|
|
" Pre-process the classpath command string a little.
|
|
let classpath_command = g:syntastic_java_javac_custom_classpath_command
|
|
for sub in [['%FILE_PATH%', expand('%:p')],
|
|
\ ['%FILE_NAME%', expand('%:t')],
|
|
\ ['%FILE_DIR%', expand('%:p:h')]]
|
|
let classpath_command = substitute(classpath_command, sub[0], sub[1], 'g')
|
|
endfor
|
|
let lines = system(classpath_command)
|
|
if syntastic#util#isRunningWindows() || has('win32unix')
|
|
let lines = substitute(lines, "\r\n", "\n", 'g')
|
|
endif
|
|
for l in split(lines, "\n")
|
|
let javac_classpath = s:AddToClasspath(javac_classpath, l)
|
|
endfor
|
|
endif
|
|
|
|
if javac_classpath !=# ''
|
|
let javac_opts .= ' -cp ' . syntastic#util#shexpand(javac_classpath)
|
|
endif
|
|
" }}}2
|
|
|
|
let fname = expand('%:p:h', 1) . syntastic#util#Slash() . expand ('%:t', 1)
|
|
|
|
if has('win32unix')
|
|
let fname = syntastic#util#CygwinPath(fname)
|
|
endif
|
|
|
|
let makeprg = self.makeprgBuild({
|
|
\ 'args': javac_opts,
|
|
\ 'fname': syntastic#util#shescape(fname) })
|
|
|
|
" unashamedly stolen from *errorformat-javac* (quickfix.txt) and modified to include error types
|
|
let errorformat =
|
|
\ '%E%f:%l: error: %m,'.
|
|
\ '%W%f:%l: warning: %m,'.
|
|
\ '%A%f:%l: %m,'.
|
|
\ '%+Z%p^,'.
|
|
\ '%+C%.%#,'.
|
|
\ '%-G%.%#'
|
|
|
|
if output_dir !=# ''
|
|
silent! call mkdir(output_dir, 'p')
|
|
endif
|
|
let errors = SyntasticMake({
|
|
\ 'makeprg': makeprg,
|
|
\ 'errorformat': errorformat,
|
|
\ 'postprocess': ['cygwinRemoveCR'] })
|
|
|
|
if output_dir !=# ''
|
|
call syntastic#util#rmrf(output_dir)
|
|
endif
|
|
return errors
|
|
|
|
endfunction " }}}1
|
|
|
|
" Utilities {{{1
|
|
|
|
function! s:RemoveCarriageReturn(line) " {{{2
|
|
return substitute(a:line, "\r", '', 'g')
|
|
endfunction " }}}2
|
|
|
|
function! s:ClassSep() " {{{2
|
|
return (syntastic#util#isRunningWindows() || has('win32unix')) ? ';' : ':'
|
|
endfunction " }}}2
|
|
|
|
function! s:AddToClasspath(classpath, path) " {{{2
|
|
if a:path ==# ''
|
|
return a:classpath
|
|
endif
|
|
return (a:classpath !=# '') ? a:classpath . s:ClassSep() . a:path : a:path
|
|
endfunction " }}}2
|
|
|
|
function! s:SplitClasspath(classpath) " {{{2
|
|
return split(a:classpath, s:ClassSep())
|
|
endfunction " }}}2
|
|
|
|
function! s:LoadConfigFile() " {{{2
|
|
if filereadable(expand(g:syntastic_java_javac_config_file, 1))
|
|
execute 'source ' . fnameescape(expand(g:syntastic_java_javac_config_file, 1))
|
|
endif
|
|
endfunction " }}}2
|
|
|
|
function! s:SaveClasspath() " {{{2
|
|
" build classpath from lines
|
|
let path = ''
|
|
let lines = getline(1, line('$'))
|
|
for l in lines
|
|
let path = s:AddToClasspath(path, l)
|
|
endfor
|
|
" save classpath to config file
|
|
if g:syntastic_java_javac_config_file_enabled
|
|
if filereadable(expand(g:syntastic_java_javac_config_file, 1))
|
|
" load lines from config file
|
|
let lines = readfile(expand(g:syntastic_java_javac_config_file, 1))
|
|
" strip g:syntastic_java_javac_classpath options from config file lines
|
|
let i = 0
|
|
while i < len(lines)
|
|
if match(lines[i], 'g:syntastic_java_javac_classpath') != -1
|
|
call remove(lines, i)
|
|
else
|
|
let i += 1
|
|
endif
|
|
endwhile
|
|
else
|
|
let lines = []
|
|
endif
|
|
" add new g:syntastic_java_javac_classpath option to config
|
|
call add(lines, 'let g:syntastic_java_javac_classpath = ' . string(path))
|
|
" save config file lines
|
|
call writefile(lines, expand(g:syntastic_java_javac_config_file, 1))
|
|
endif
|
|
" set new classpath
|
|
let g:syntastic_java_javac_classpath = path
|
|
let &modified = 0
|
|
endfunction " }}}2
|
|
|
|
function! s:EditClasspath() " {{{2
|
|
let command = 'syntastic javac classpath'
|
|
let winnr = bufwinnr('^' . command . '$')
|
|
if winnr < 0
|
|
let path = []
|
|
let pathlines = split(g:syntastic_java_javac_classpath, "\n")
|
|
for p in pathlines
|
|
call extend(path, s:SplitClasspath(p))
|
|
endfor
|
|
execute (len(path) + 5) . 'sp ' . fnameescape(command)
|
|
|
|
augroup syntastic
|
|
autocmd BufWriteCmd <buffer> call s:SaveClasspath() | bwipeout
|
|
augroup END
|
|
|
|
setlocal buftype=acwrite bufhidden=wipe nobuflisted noswapfile nowrap number
|
|
for p in path
|
|
call append(line('$') - 1, p)
|
|
endfor
|
|
let &modified = 0
|
|
else
|
|
execute winnr . 'wincmd w'
|
|
endif
|
|
endfunction " }}}2
|
|
|
|
function! s:SaveConfig() " {{{2
|
|
" get lines
|
|
let lines = getline(1, line('$'))
|
|
if g:syntastic_java_javac_config_file_enabled
|
|
" save config file lines
|
|
call writefile(lines, expand(g:syntastic_java_javac_config_file, 1))
|
|
endif
|
|
let &modified = 0
|
|
endfunction " }}}2
|
|
|
|
function! s:EditConfig() " {{{2
|
|
let command = 'syntastic javac config'
|
|
let winnr = bufwinnr('^' . command . '$')
|
|
if winnr < 0
|
|
let lines = []
|
|
if filereadable(expand(g:syntastic_java_javac_config_file, 1))
|
|
let lines = readfile(expand(g:syntastic_java_javac_config_file, 1))
|
|
endif
|
|
execute (len(lines) + 5) . 'sp ' . fnameescape(command)
|
|
|
|
augroup syntastic
|
|
autocmd BufWriteCmd <buffer> call s:SaveConfig() | bwipeout
|
|
augroup END
|
|
|
|
setlocal ft=vim buftype=acwrite bufhidden=wipe nobuflisted noswapfile nowrap number
|
|
for l in lines
|
|
call append(line('$') - 1, l)
|
|
endfor
|
|
let &modified = 0
|
|
else
|
|
execute winnr . 'wincmd w'
|
|
endif
|
|
endfunction " }}}2
|
|
|
|
function! s:GetMavenProperties() " {{{2
|
|
let mvn_properties = {}
|
|
let pom = findfile('pom.xml', escape(expand('%:p:h', 1), ' ') . ';')
|
|
if s:has_maven && filereadable(pom)
|
|
if !has_key(g:syntastic_java_javac_maven_pom_properties, pom)
|
|
let mvn_cmd = syntastic#util#shexpand(g:syntastic_java_maven_executable) .
|
|
\ ' -f ' . syntastic#util#shescape(pom) .
|
|
\ ' ' . g:syntastic_java_maven_options
|
|
let mvn_is_managed_tag = 1
|
|
let mvn_settings_output = split(syntastic#util#system(mvn_cmd . ' help:effective-pom'), "\n")
|
|
let current_path = 'project'
|
|
for line in mvn_settings_output
|
|
let matches = matchlist(line, '\m^\s*<\([a-zA-Z0-9\-\.]\+\)>\s*$')
|
|
if mvn_is_managed_tag && !empty(matches)
|
|
let mvn_is_managed_tag = index(g:syntastic_java_javac_maven_pom_tags, matches[1]) >= 0
|
|
let current_path .= '.' . matches[1]
|
|
else
|
|
let matches = matchlist(line, '\m^\s*</\([a-zA-Z0-9\-\.]\+\)>\s*$')
|
|
if !empty(matches)
|
|
let mvn_is_managed_tag = index(g:syntastic_java_javac_maven_pom_tags, matches[1]) < 0
|
|
let current_path = substitute(current_path, '\m\.' . matches[1] . '$', '', '')
|
|
else
|
|
let matches = matchlist(line, '\m^\s*<\([a-zA-Z0-9\-\.]\+\)>\(.\+\)</[a-zA-Z0-9\-\.]\+>\s*$')
|
|
if mvn_is_managed_tag && !empty(matches)
|
|
let mvn_properties[current_path . '.' . matches[1]] = matches[2]
|
|
endif
|
|
endif
|
|
endif
|
|
endfor
|
|
let g:syntastic_java_javac_maven_pom_properties[pom] = mvn_properties
|
|
endif
|
|
return g:syntastic_java_javac_maven_pom_properties[pom]
|
|
endif
|
|
return mvn_properties
|
|
endfunction " }}}2
|
|
|
|
function! s:GetMavenClasspath() " {{{2
|
|
let pom = findfile('pom.xml', escape(expand('%:p:h', 1), ' ') . ';')
|
|
if s:has_maven && filereadable(pom)
|
|
if !has_key(g:syntastic_java_javac_maven_pom_ftime, pom) || g:syntastic_java_javac_maven_pom_ftime[pom] != getftime(pom)
|
|
let mvn_cmd = syntastic#util#shexpand(g:syntastic_java_maven_executable) .
|
|
\ ' -f ' . syntastic#util#shescape(pom) .
|
|
\ ' ' . g:syntastic_java_maven_options
|
|
let mvn_classpath_output = split(syntastic#util#system(mvn_cmd . ' dependency:build-classpath'), "\n")
|
|
let mvn_classpath = ''
|
|
let class_path_next = 0
|
|
|
|
for line in mvn_classpath_output
|
|
if class_path_next == 1
|
|
let mvn_classpath = s:RemoveCarriageReturn(line)
|
|
break
|
|
endif
|
|
if stridx(line, 'Dependencies classpath:') >= 0
|
|
let class_path_next = 1
|
|
endif
|
|
endfor
|
|
|
|
let mvn_properties = s:GetMavenProperties()
|
|
|
|
let sep = syntastic#util#Slash()
|
|
let output_dir = join(['target', 'classes'], sep)
|
|
if has_key(mvn_properties, 'project.build.outputDirectory')
|
|
let output_dir = mvn_properties['project.build.outputDirectory']
|
|
endif
|
|
let mvn_classpath = s:AddToClasspath(mvn_classpath, output_dir)
|
|
|
|
let test_output_dir = join(['target', 'test-classes'], sep)
|
|
if has_key(mvn_properties, 'project.build.testOutputDirectory')
|
|
let test_output_dir = mvn_properties['project.build.testOutputDirectory']
|
|
endif
|
|
let mvn_classpath = s:AddToClasspath(mvn_classpath, test_output_dir)
|
|
|
|
let g:syntastic_java_javac_maven_pom_ftime[pom] = getftime(pom)
|
|
let g:syntastic_java_javac_maven_pom_classpath[pom] = mvn_classpath
|
|
endif
|
|
return g:syntastic_java_javac_maven_pom_classpath[pom]
|
|
endif
|
|
return ''
|
|
endfunction " }}}2
|
|
|
|
function! s:MavenOutputDirectory() " {{{2
|
|
let pom = findfile('pom.xml', escape(expand('%:p:h', 1), ' ') . ';')
|
|
if s:has_maven && filereadable(pom)
|
|
let mvn_properties = s:GetMavenProperties()
|
|
let output_dir = getcwd()
|
|
if has_key(mvn_properties, 'project.properties.build.dir')
|
|
let output_dir = mvn_properties['project.properties.build.dir']
|
|
endif
|
|
|
|
let sep = syntastic#util#Slash()
|
|
if stridx(expand('%:p:h', 1), join(['src', 'main', 'java'], sep)) >= 0
|
|
let output_dir = join ([output_dir, 'target', 'classes'], sep)
|
|
if has_key(mvn_properties, 'project.build.outputDirectory')
|
|
let output_dir = mvn_properties['project.build.outputDirectory']
|
|
endif
|
|
endif
|
|
if stridx(expand('%:p:h', 1), join(['src', 'test', 'java'], sep)) >= 0
|
|
let output_dir = join([output_dir, 'target', 'test-classes'], sep)
|
|
if has_key(mvn_properties, 'project.build.testOutputDirectory')
|
|
let output_dir = mvn_properties['project.build.testOutputDirectory']
|
|
endif
|
|
endif
|
|
|
|
if has('win32unix')
|
|
let output_dir = syntastic#util#CygwinPath(output_dir)
|
|
endif
|
|
return output_dir
|
|
endif
|
|
return '.'
|
|
endfunction " }}}2
|
|
|
|
" }}}1
|
|
|
|
call g:SyntasticRegistry.CreateAndRegisterChecker({
|
|
\ 'filetype': 'java',
|
|
\ 'name': 'javac'})
|
|
|
|
let &cpo = s:save_cpo
|
|
unlet s:save_cpo
|
|
|
|
" vim: set sw=4 sts=4 et fdm=marker:
|