All patches and comments are welcome. Please squash your changes to logical
commits before using git-format-patch and git-send-email to
patches@git.madduck.net.
If you'd read over the Git project's submission guidelines and adhered to them,
I'd be especially grateful.
1 " Author: Francis Agyapong <francisgyapong2@gmail.com>
2 " Description: A linter for the Kotlin programming language that uses kotlinc
4 let g:ale_kotlin_kotlinc_options = get(g:, 'ale_kotlin_kotlinc_options', '')
5 let g:ale_kotlin_kotlinc_enable_config = get(g:, 'ale_kotlin_kotlinc_enable_config', 0)
6 let g:ale_kotlin_kotlinc_config_file = get(g:, 'ale_kotlin_kotlinc_config_file', '.ale_kotlinc_config')
7 let g:ale_kotlin_kotlinc_classpath = get(g:, 'ale_kotlin_kotlinc_classpath', '')
8 let g:ale_kotlin_kotlinc_sourcepath = get(g:, 'ale_kotlin_kotlinc_sourcepath', '')
9 let g:ale_kotlin_kotlinc_use_module_file = get(g:, 'ale_kotlin_kotlinc_use_module_file', 0)
10 let g:ale_kotlin_kotlinc_module_filename = get(g:, 'ale_kotlin_kotlinc_module_filename', 'module.xml')
12 let s:classpath_sep = has('unix') ? ':' : ';'
14 function! ale_linters#kotlin#kotlinc#RunWithImportPaths(buffer) abort
17 " exec maven/gradle only if classpath is not set
18 if !empty(ale#Var(a:buffer, 'kotlin_kotlinc_classpath'))
19 return ale_linters#kotlin#kotlinc#GetCommand(a:buffer, [], {})
22 let [l:cwd, l:command] = ale#maven#BuildClasspathCommand(a:buffer)
24 " Try to use Gradle if Maven isn't available.
26 let [l:cwd, l:command] = ale#gradle#BuildClasspathCommand(a:buffer)
30 return ale_linters#kotlin#kotlinc#GetCommand(a:buffer, [], {})
33 return ale#command#Run(
36 \ function('ale_linters#kotlin#kotlinc#GetCommand'),
41 function! s:BuildClassPathOption(buffer, import_paths) abort
42 " Filter out lines like [INFO], etc.
43 let l:class_paths = filter(a:import_paths[:], 'v:val !~# ''[''')
46 \ split(ale#Var(a:buffer, 'kotlin_kotlinc_classpath'), s:classpath_sep),
49 return !empty(l:class_paths)
50 \ ? ' -cp ' . ale#Escape(join(l:class_paths, s:classpath_sep))
54 function! ale_linters#kotlin#kotlinc#GetCommand(buffer, import_paths, meta) abort
55 let l:kotlinc_opts = ale#Var(a:buffer, 'kotlin_kotlinc_options')
56 let l:command = 'kotlinc '
58 " If the config file is enabled and readable, source it
59 if ale#Var(a:buffer, 'kotlin_kotlinc_enable_config')
60 let l:conf = expand(ale#Var(a:buffer, 'kotlin_kotlinc_config_file'), 1)
62 if filereadable(l:conf)
63 execute 'source ' . fnameescape(l:conf)
67 " If use module and module file is readable use that and return
68 if ale#Var(a:buffer, 'kotlin_kotlinc_use_module_file')
69 let l:module_filename = ale#Escape(expand(ale#Var(a:buffer, 'kotlin_kotlinc_module_filename'), 1))
71 if filereadable(l:module_filename)
72 let l:kotlinc_opts .= ' -module ' . l:module_filename
73 let l:command .= 'kotlinc ' . l:kotlinc_opts
79 " We only get here if not using module or the module file not readable
80 if ale#Var(a:buffer, 'kotlin_kotlinc_classpath') isnot# ''
81 let l:kotlinc_opts .= ' -cp ' . ale#Var(a:buffer, 'kotlin_kotlinc_classpath')
83 " get classpath from maven/gradle
84 let l:kotlinc_opts .= s:BuildClassPathOption(a:buffer, a:import_paths)
89 if ale#Var(a:buffer, 'kotlin_kotlinc_sourcepath') isnot# ''
90 let l:fname .= expand(ale#Var(a:buffer, 'kotlin_kotlinc_sourcepath'), 1) . ' '
92 " Find the src directory for files in this project.
93 let l:project_root = ale#gradle#FindProjectRoot(a:buffer)
95 if !empty(l:project_root)
96 let l:src_dir = l:project_root
98 let l:src_dir = ale#path#FindNearestDirectory(a:buffer, 'src/main/java')
99 \ . ' ' . ale#path#FindNearestDirectory(a:buffer, 'src/main/kotlin')
102 let l:fname .= expand(l:src_dir, 1) . ' '
105 let l:fname .= ale#Escape(expand('#' . a:buffer . ':p'))
106 let l:command .= l:kotlinc_opts . ' ' . l:fname
111 function! ale_linters#kotlin#kotlinc#Handle(buffer, lines) abort
112 let l:code_pattern = '^\(.*\):\([0-9]\+\):\([0-9]\+\):\s\+\(error\|warning\):\s\+\(.*\)'
113 let l:general_pattern = '^\(warning\|error\|info\):\s*\(.*\)'
116 for l:line in a:lines
117 let l:match = matchlist(l:line, l:code_pattern)
123 let l:file = l:match[1]
124 let l:line = l:match[2] + 0
125 let l:column = l:match[3] + 0
126 let l:type = l:match[4]
127 let l:text = l:match[5]
129 let l:buf_abspath = fnamemodify(l:file, ':p')
130 let l:curbuf_abspath = expand('#' . a:buffer . ':p')
132 " Skip if file is not loaded
133 if l:buf_abspath isnot# l:curbuf_abspath
137 let l:type_marker_str = l:type is# 'warning' ? 'W' : 'E'
143 \ 'type': l:type_marker_str,
147 " Non-code related messages
148 for l:line in a:lines
149 let l:match = matchlist(l:line, l:general_pattern)
155 let l:type = l:match[1]
156 let l:text = l:match[2]
158 let l:type_marker_str = l:type is# 'warning' || l:type is# 'info' ? 'W' : 'E'
163 \ 'type': l:type_marker_str,
170 call ale#linter#Define('kotlin', {
172 \ 'executable': 'kotlinc',
173 \ 'output_stream': 'stderr',
174 \ 'command': function('ale_linters#kotlin#kotlinc#RunWithImportPaths'),
175 \ 'callback': 'ale_linters#kotlin#kotlinc#Handle',