syntastic/syntax_checkers/java/javac.vim

421 lines
15 KiB
VimL
Raw Normal View History

"============================================================================
"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.
"============================================================================
2014-04-19 03:03:53 -04:00
if exists('g:loaded_syntastic_java_javac_checker')
finish
endif
let g:loaded_syntastic_java_javac_checker = 1
2014-04-19 03:03:53 -04:00
let g:syntastic_java_javac_maven_pom_tags = ['build', 'properties']
let g:syntastic_java_javac_maven_pom_properties = {}
let s:has_maven = 0
2015-01-04 05:46:54 -05:00
let s:save_cpo = &cpo
set cpo&vim
" Checker options {{{1
2014-04-19 03:03:53 -04:00
if !exists('g:syntastic_java_javac_executable')
let g:syntastic_java_javac_executable = 'javac'
endif
2014-04-19 03:03:53 -04:00
if !exists('g:syntastic_java_maven_executable')
2013-03-13 12:00:17 -04:00
let g:syntastic_java_maven_executable = 'mvn'
endif
2014-04-19 03:03:53 -04:00
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
2014-04-19 03:03:53 -04:00
if !exists('g:syntastic_java_javac_classpath')
let g:syntastic_java_javac_classpath = ''
endif
2014-04-19 03:03:53 -04:00
if !exists('g:syntastic_java_javac_delete_output')
let g:syntastic_java_javac_delete_output = 1
endif
2014-04-19 03:03:53 -04:00
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
2014-04-19 03:03:53 -04:00
if !exists('g:syntastic_java_javac_maven_pom_ftime')
let g:syntastic_java_javac_maven_pom_ftime = {}
endif
2014-04-19 03:03:53 -04:00
if !exists('g:syntastic_java_javac_maven_pom_classpath')
let g:syntastic_java_javac_maven_pom_classpath = {}
endif
2015-01-04 05:46:54 -05:00
" }}}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()
2015-01-04 05:46:54 -05:00
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 != ''
let lines = system(g:syntastic_java_javac_custom_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)
2015-01-04 05:46:54 -05:00
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 =
2015-02-13 04:56:09 -05:00
\ '%E%f:%l: error: %m,'.
\ '%W%f:%l: warning: %m,'.
\ '%A%f:%l: %m,'.
2015-01-04 05:46:54 -05:00
\ '%+Z%p^,'.
\ '%+C%.%#,'.
\ '%-G%.%#'
if output_dir != ''
2015-01-04 05:46:54 -05:00
silent! call mkdir(output_dir, 'p')
endif
let errors = SyntasticMake({
\ 'makeprg': makeprg,
\ 'errorformat': errorformat,
\ 'postprocess': ['cygwinRemoveCR'] })
if output_dir != ''
2015-01-04 05:46:54 -05:00
call syntastic#util#rmrf(output_dir)
endif
return errors
endfunction " }}}1
" Utilities {{{1
function! s:RemoveCarriageReturn(line) " {{{2
2014-04-19 03:03:53 -04:00
return substitute(a:line, "\r", '', 'g')
2015-01-04 05:46:54 -05:00
endfunction " }}}2
2015-01-04 05:46:54 -05:00
function! s:ClassSep() " {{{2
2014-04-19 03:03:53 -04:00
return (syntastic#util#isRunningWindows() || has('win32unix')) ? ';' : ':'
2015-01-04 05:46:54 -05:00
endfunction " }}}2
2014-04-19 03:03:53 -04:00
2015-01-04 05:46:54 -05:00
function! s:AddToClasspath(classpath, path) " {{{2
if a:path == ''
return a:classpath
endif
2014-04-19 03:03:53 -04:00
return (a:classpath != '') ? a:classpath . s:ClassSep() . a:path : a:path
2015-01-04 05:46:54 -05:00
endfunction " }}}2
2015-01-04 05:46:54 -05:00
function! s:SplitClasspath(classpath) " {{{2
2014-04-19 03:03:53 -04:00
return split(a:classpath, s:ClassSep())
2015-01-04 05:46:54 -05:00
endfunction " }}}2
2015-01-04 05:46:54 -05:00
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
2015-01-04 05:46:54 -05:00
endfunction " }}}2
2015-01-04 05:46:54 -05:00
function! s:SaveClasspath() " {{{2
" build classpath from lines
let path = ''
2013-05-13 09:37:16 -04:00
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)
2014-04-19 03:03:53 -04:00
else
let i += 1
endif
endwhile
else
let lines = []
endif
" add new g:syntastic_java_javac_classpath option to config
2014-04-19 03:03:53 -04:00
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
2015-01-04 05:46:54 -05:00
endfunction " }}}2
2015-01-04 05:46:54 -05:00
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
2014-04-19 03:03:53 -04:00
call extend(path, s:SplitClasspath(p))
endfor
execute (len(path) + 5) . 'sp ' . fnameescape(command)
2013-05-13 09:37:16 -04:00
augroup syntastic
autocmd BufWriteCmd <buffer> call s:SaveClasspath() | bwipeout
augroup END
setlocal buftype=acwrite bufhidden=wipe nobuflisted noswapfile nowrap number
for p in path
2013-05-13 09:37:16 -04:00
call append(line('$') - 1, p)
endfor
let &modified = 0
else
execute winnr . 'wincmd w'
endif
2015-01-04 05:46:54 -05:00
endfunction " }}}2
2015-01-04 05:46:54 -05:00
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
2015-01-04 05:46:54 -05:00
endfunction " }}}2
2015-01-04 05:46:54 -05:00
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
2015-01-04 05:46:54 -05:00
endfunction " }}}2
2015-01-04 05:46:54 -05:00
function! s:GetMavenProperties() " {{{2
let mvn_properties = {}
2014-04-19 03:03:53 -04:00
let pom = findfile('pom.xml', '.;')
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(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
2014-04-19 03:03:53 -04:00
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
2015-01-04 05:46:54 -05:00
endfunction " }}}2
2015-01-04 05:46:54 -05:00
function! s:GetMavenClasspath() " {{{2
2014-04-19 03:03:53 -04:00
let pom = findfile('pom.xml', '.;')
if s:has_maven && filereadable(pom)
2013-07-01 12:57:21 -04:00
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(system(mvn_cmd . ' dependency:build-classpath'), "\n")
2013-09-19 18:27:28 -04:00
let mvn_classpath = ''
let class_path_next = 0
2013-05-13 09:37:16 -04:00
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
2013-05-13 09:37:16 -04:00
let mvn_properties = s:GetMavenProperties()
2015-02-20 09:15:44 -05:00
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)
2015-02-20 09:15:44 -05:00
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)
2013-05-13 09:37:16 -04:00
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 ''
2015-01-04 05:46:54 -05:00
endfunction " }}}2
2015-01-04 05:46:54 -05:00
function! s:MavenOutputDirectory() " {{{2
2014-04-19 03:03:53 -04:00
let pom = findfile('pom.xml', '.;')
if s:has_maven && filereadable(pom)
let mvn_properties = s:GetMavenProperties()
2013-05-13 09:37:16 -04:00
let output_dir = getcwd()
if has_key(mvn_properties, 'project.properties.build.dir')
let output_dir = mvn_properties['project.properties.build.dir']
endif
2015-02-20 02:47:43 -05:00
let sep = syntastic#util#Slash()
if stridx(expand('%:p:h', 1), join(['src', 'main', 'java'], sep)) >= 0
2015-02-20 09:15:44 -05:00
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
2013-05-13 09:37:16 -04:00
endif
2015-02-20 02:47:43 -05:00
if stridx(expand('%:p:h', 1), join(['src', 'test', 'java'], sep)) >= 0
2015-02-20 09:15:44 -05:00
let output_dir = join([output_dir, 'target', 'test-classes'], sep)
if has_key(mvn_properties, 'project.build.testOutputDirectory')
2013-07-01 12:50:48 -04:00
let output_dir = mvn_properties['project.build.testOutputDirectory']
endif
2013-05-13 09:37:16 -04:00
endif
if has('win32unix')
let output_dir = syntastic#util#CygwinPath(output_dir)
2013-05-13 09:37:16 -04:00
endif
return output_dir
endif
return '.'
2015-01-04 05:46:54 -05:00
endfunction " }}}2
2015-01-04 05:46:54 -05:00
" }}}1
call g:SyntasticRegistry.CreateAndRegisterChecker({
\ 'filetype': 'java',
\ 'name': 'javac'})
let &cpo = s:save_cpo
unlet s:save_cpo
2015-01-04 05:46:54 -05:00
" vim: set sw=4 sts=4 et fdm=marker: