diff options
Diffstat (limited to 'vim/bundle/syntastic/syntax_checkers/java/javac.vim')
-rw-r--r-- | vim/bundle/syntastic/syntax_checkers/java/javac.vim | 427 |
1 files changed, 427 insertions, 0 deletions
diff --git a/vim/bundle/syntastic/syntax_checkers/java/javac.vim b/vim/bundle/syntastic/syntax_checkers/java/javac.vim new file mode 100644 index 0000000..948c244 --- /dev/null +++ b/vim/bundle/syntastic/syntax_checkers/java/javac.vim @@ -0,0 +1,427 @@ +"============================================================================ +"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 + +" Constants {{{1 + +let s:_FILE_SHORTCUTS = { + \ '%FILE_PATH%': '%:p', + \ '%FILE_NAME%': '%:t', + \ '%FILE_DIR%': '%:p:h', + \ } +lockvar! s:_FILE_SHORTCUTS + +" }}}1 + +" Commands {{{1 + +command! SyntasticJavacEditClasspath call s:EditClasspath() +command! SyntasticJavacEditConfig call s:EditConfig() + +" }}}1 + +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 [key, val] in items(s:_FILE_SHORTCUTS) + let classpath_command = substitute(classpath_command, '\V' . key, syntastic#util#shexpand(val), 'g') + endfor + let lines = syntastic#util#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,'. + \ '%E%f:%l: %m,'. + \ '%Z%p^,'. + \ '%-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 + if !g:syntastic_java_javac_config_file_enabled + return + endif + + 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 = syntastic#util#findFileInParent('pom.xml', 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 = syntastic#util#findFileInParent('pom.xml', 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 -DincludeScope=test'), "\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 = get(mvn_properties, 'project.build.outputDirectory', join(['target', 'classes'], sep)) + let mvn_classpath = s:AddToClasspath(mvn_classpath, output_dir) + + let test_output_dir = get(mvn_properties, 'project.build.testOutputDirectory', join(['target', 'test-classes'], sep)) + 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 = syntastic#util#findFileInParent('pom.xml', expand('%:p:h', 1)) + if s:has_maven && filereadable(pom) + let mvn_properties = s:GetMavenProperties() + let output_dir = get(mvn_properties, 'project.properties.build.dir', getcwd()) + + let sep = syntastic#util#Slash() + let src_main_dir = get(mvn_properties, 'project.build.sourceDirectory', join(['src', 'main', 'java'], sep)) + let src_test_dir = get(mvn_properties, 'project.build.testsourceDirectory', join(['src', 'test', 'java'], sep)) + if stridx(expand('%:p:h', 1), src_main_dir) >= 0 + let output_dir = get(mvn_properties, 'project.build.outputDirectory', join ([output_dir, 'target', 'classes'], sep)) + endif + if stridx(expand('%:p:h', 1), src_test_dir) >= 0 + let output_dir = get(mvn_properties, 'project.build.testOutputDirectory', join([output_dir, 'target', 'test-classes'], sep)) + 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: |