blob: d62a4ee3fd3540ed02723ab2c0f978803e24653b [file] [log] [blame]
Bram Moolenaar10561fe2018-05-19 15:01:10 +02001" Test the :compiler command
2
Bram Moolenaar5a4c3082019-12-01 15:23:11 +01003source check.vim
Bram Moolenaar16531552020-02-08 16:00:46 +01004source shared.vim
Bram Moolenaar5a4c3082019-12-01 15:23:11 +01005
Bram Moolenaar10561fe2018-05-19 15:01:10 +02006func Test_compiler()
Bram Moolenaaraeb313f2020-11-27 19:13:28 +01007 CheckExecutable perl
Bram Moolenaar5a4c3082019-12-01 15:23:11 +01008 CheckFeature quickfix
Bram Moolenaar10561fe2018-05-19 15:01:10 +02009
Dominique Pelléca0ffc02023-09-24 22:57:41 +020010 let save_LC_ALL = $LC_ALL
11 let $LC_ALL= "C"
Bram Moolenaarf0447e82018-07-03 21:26:38 +020012
Bram Moolenaardff2adc2019-07-31 22:18:22 +020013 " %:S does not work properly with 'shellslash' set
14 let save_shellslash = &shellslash
15 set noshellslash
16
Bram Moolenaar10561fe2018-05-19 15:01:10 +020017 e Xfoo.pl
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +010018 " Play nice with other tests.
19 defer setqflist([])
Bram Moolenaar10561fe2018-05-19 15:01:10 +020020 compiler perl
21 call assert_equal('perl', b:current_compiler)
22 call assert_fails('let g:current_compiler', 'E121:')
23
Bram Moolenaar58ef8a32021-11-12 11:25:11 +000024 let verbose_efm = execute('verbose set efm')
Bram Moolenaar0a15c762021-11-12 16:09:54 +000025 call assert_match('Last set from .*[/\\]compiler[/\\]perl.vim ', verbose_efm)
Bram Moolenaar58ef8a32021-11-12 11:25:11 +000026
Bram Moolenaar10561fe2018-05-19 15:01:10 +020027 call setline(1, ['#!/usr/bin/perl -w', 'use strict;', 'my $foo=1'])
28 w!
29 call feedkeys(":make\<CR>\<CR>", 'tx')
30 call assert_fails('clist', 'E42:')
31
32 call setline(1, ['#!/usr/bin/perl -w', 'use strict;', '$foo=1'])
33 w!
34 call feedkeys(":make\<CR>\<CR>", 'tx')
35 let a=execute('clist')
Bram Moolenaarcebfcff2019-09-18 21:42:38 +020036 call assert_match('\n \d\+ Xfoo.pl:3: Global symbol "$foo" '
37 \ . 'requires explicit package name', a)
38
Bram Moolenaar10561fe2018-05-19 15:01:10 +020039
Bram Moolenaardff2adc2019-07-31 22:18:22 +020040 let &shellslash = save_shellslash
Bram Moolenaar10561fe2018-05-19 15:01:10 +020041 call delete('Xfoo.pl')
42 bw!
Dominique Pelléca0ffc02023-09-24 22:57:41 +020043 let $LC_ALL = save_LC_ALL
Bram Moolenaar10561fe2018-05-19 15:01:10 +020044endfunc
45
Bram Moolenaar60bc8e72020-11-23 21:24:58 +010046func GetCompilerNames()
47 return glob('$VIMRUNTIME/compiler/*.vim', 0, 1)
Bram Moolenaar142f2352020-11-23 21:39:14 +010048 \ ->map({i, v -> substitute(v, '.*[\\/]\([a-zA-Z0-9_\-]*\).vim', '\1', '')})
49 \ ->sort()
Bram Moolenaar60bc8e72020-11-23 21:24:58 +010050endfunc
51
Bram Moolenaar10561fe2018-05-19 15:01:10 +020052func Test_compiler_without_arg()
Bram Moolenaarc25e7022019-10-10 14:08:26 +020053 let runtime = substitute($VIMRUNTIME, '\\', '/', 'g')
54 let a = split(execute('compiler'))
Bram Moolenaar60bc8e72020-11-23 21:24:58 +010055 let exp = GetCompilerNames()
56 call assert_match(runtime .. '/compiler/' .. exp[0] .. '.vim$', a[0])
57 call assert_match(runtime .. '/compiler/' .. exp[1] .. '.vim$', a[1])
58 call assert_match(runtime .. '/compiler/' .. exp[-1] .. '.vim$', a[-1])
Bram Moolenaar10561fe2018-05-19 15:01:10 +020059endfunc
60
Bram Moolenaar16531552020-02-08 16:00:46 +010061" Test executing :compiler from the command line, not from a script
62func Test_compiler_commandline()
63 call system(GetVimCommandClean() .. ' --not-a-term -c "compiler gcc" -c "call writefile([b:current_compiler], ''XcompilerOut'')" -c "quit"')
64 call assert_equal(0, v:shell_error)
65 call assert_equal(["gcc"], readfile('XcompilerOut'))
66
67 call delete('XcompilerOut')
68endfunc
69
Bram Moolenaar10561fe2018-05-19 15:01:10 +020070func Test_compiler_completion()
Bram Moolenaar60bc8e72020-11-23 21:24:58 +010071 let clist = GetCompilerNames()->join(' ')
Bram Moolenaar10561fe2018-05-19 15:01:10 +020072 call feedkeys(":compiler \<C-A>\<C-B>\"\<CR>", 'tx')
Bram Moolenaar60bc8e72020-11-23 21:24:58 +010073 call assert_match('^"compiler ' .. clist .. '$', @:)
Bram Moolenaar10561fe2018-05-19 15:01:10 +020074
75 call feedkeys(":compiler p\<C-A>\<C-B>\"\<CR>", 'tx')
Konfekt3c2596a2024-11-30 11:32:49 +010076 call assert_match('"compiler pandoc pbx perl\( p[a-z_]\+\)\+ pyunit', @:)
Bram Moolenaar10561fe2018-05-19 15:01:10 +020077
78 call feedkeys(":compiler! p\<C-A>\<C-B>\"\<CR>", 'tx')
Konfekt3c2596a2024-11-30 11:32:49 +010079 call assert_match('"compiler! pandoc pbx perl\( p[a-z_]\+\)\+ pyunit', @:)
Bram Moolenaar10561fe2018-05-19 15:01:10 +020080endfunc
81
82func Test_compiler_error()
Bram Moolenaare20b9ec2020-02-03 21:40:04 +010083 let g:current_compiler = 'abc'
Bram Moolenaar10561fe2018-05-19 15:01:10 +020084 call assert_fails('compiler doesnotexist', 'E666:')
Bram Moolenaare20b9ec2020-02-03 21:40:04 +010085 call assert_equal('abc', g:current_compiler)
86 call assert_fails('compiler! doesnotexist', 'E666:')
87 unlet! g:current_compiler
Bram Moolenaar10561fe2018-05-19 15:01:10 +020088endfunc
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +020089
Aliaksei Budavei60ddb1a2024-11-28 22:05:37 +010090func s:SpotBugsParseFilterMakePrg(dirname, makeprg)
91 let result = {}
92 let result.sourcepath = ''
93 let result.classfiles = []
94
95 " Get the argument after the rightmost occurrence of "-sourcepath".
96 let offset = strridx(a:makeprg, '-sourcepath')
97 if offset < 0
98 return result
99 endif
100 let offset += 1 + strlen('-sourcepath')
101 let result.sourcepath = matchstr(strpart(a:makeprg, offset), '.\{-}\ze[ \t]')
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100102 let offset += 1 + strlen(result.sourcepath)
Aliaksei Budavei60ddb1a2024-11-28 22:05:37 +0100103
104 " Get the class file arguments, dropping the pathname prefix.
105 let offset = stridx(a:makeprg, a:dirname, offset)
106 if offset < 0
107 return result
108 endif
109
110 while offset > -1
111 let candidate = matchstr(a:makeprg, '[^ \t]\{-}\.class\>', offset)
112 if empty(candidate)
113 break
114 endif
115 call add(result.classfiles, candidate)
116 let offset = stridx(a:makeprg, a:dirname, (1 + strlen(candidate) + offset))
117 endwhile
118
119 call sort(result.classfiles)
120 return result
121endfunc
122
123func Test_compiler_spotbugs_makeprg()
124 let save_shellslash = &shellslash
125 set shellslash
126
127 call assert_true(mkdir('Xspotbugs/src/tests/α/β/γ/δ', 'pR'))
128 call assert_true(mkdir('Xspotbugs/tests/α/β/γ/δ', 'pR'))
129
130 let lines =<< trim END
131 // EOL comment. /*
132 abstract class
133 𐌂1 /* Multiline comment. */ {
134 /* Multiline comment. */ // EOL comment. /*
135 static final String COMMENT_A_LIKE = "/*";
136 { new Object() {/* Try globbing. */}; }
137 static { interface 𐌉𐌉1 {} }
138 static class 𐌂11 { interface 𐌉𐌉2 {} }
139 }
140 /* Multiline comment. */ // EOL comment. /*
141 final class 𐌂2 {
142 public static void main(String... aa) {
143 record 𐌓() {}
144 enum 𐌄 {}
145 }
146 } // class
147 END
148
149 " THE EXPECTED RESULTS.
150 let results = {}
151 let results['Xspotbugs/src/tests/𐌂1.java'] = {
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100152 \ 'Sourcepath': {-> fnamemodify('Xspotbugs/src/tests/𐌂1.java',
153 \ ':p:h:S')},
Aliaksei Budavei60ddb1a2024-11-28 22:05:37 +0100154 \ 'classfiles': sort([
155 \ 'Xspotbugs/tests/𐌂1$1.class',
156 \ 'Xspotbugs/tests/𐌂1$1𐌉𐌉1.class',
157 \ 'Xspotbugs/tests/𐌂1$𐌂11$𐌉𐌉2.class',
158 \ 'Xspotbugs/tests/𐌂1$𐌂11.class',
159 \ 'Xspotbugs/tests/𐌂1.class',
160 \ 'Xspotbugs/tests/𐌂2$1𐌄.class',
161 \ 'Xspotbugs/tests/𐌂2$1𐌓.class',
162 \ 'Xspotbugs/tests/𐌂2.class']),
163 \ }
164 " No class file for an empty source file even with "-Xpkginfo:always".
165 let results['Xspotbugs/src/tests/package-info.java'] = {
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100166 \ 'Sourcepath': {-> ''},
Aliaksei Budavei60ddb1a2024-11-28 22:05:37 +0100167 \ 'classfiles': [],
168 \ }
169 let results['Xspotbugs/src/tests/α/𐌂1.java'] = {
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100170 \ 'Sourcepath': {-> fnamemodify('Xspotbugs/src/tests/α/𐌂1.java',
171 \ ':p:h:h:S')},
Aliaksei Budavei60ddb1a2024-11-28 22:05:37 +0100172 \ 'classfiles': sort([
173 \ 'Xspotbugs/tests/α/𐌂1$1.class',
174 \ 'Xspotbugs/tests/α/𐌂1$1𐌉𐌉1.class',
175 \ 'Xspotbugs/tests/α/𐌂1$𐌂11$𐌉𐌉2.class',
176 \ 'Xspotbugs/tests/α/𐌂1$𐌂11.class',
177 \ 'Xspotbugs/tests/α/𐌂1.class',
178 \ 'Xspotbugs/tests/α/𐌂2$1𐌄.class',
179 \ 'Xspotbugs/tests/α/𐌂2$1𐌓.class',
180 \ 'Xspotbugs/tests/α/𐌂2.class']),
181 \ }
182 let results['Xspotbugs/src/tests/α/package-info.java'] = {
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100183 \ 'Sourcepath': {-> fnamemodify('Xspotbugs/src/tests/α/package-info.java',
184 \ ':p:h:S')},
Aliaksei Budavei60ddb1a2024-11-28 22:05:37 +0100185 \ 'classfiles': ['Xspotbugs/tests/α/package-info.class'],
186 \ }
187 let results['Xspotbugs/src/tests/α/β/𐌂1.java'] = {
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100188 \ 'Sourcepath': {-> fnamemodify('Xspotbugs/src/tests/α/β/𐌂1.java',
189 \ ':p:h:h:h:S')},
Aliaksei Budavei60ddb1a2024-11-28 22:05:37 +0100190 \ 'classfiles': sort([
191 \ 'Xspotbugs/tests/α/β/𐌂1$1.class',
192 \ 'Xspotbugs/tests/α/β/𐌂1$1𐌉𐌉1.class',
193 \ 'Xspotbugs/tests/α/β/𐌂1$𐌂11$𐌉𐌉2.class',
194 \ 'Xspotbugs/tests/α/β/𐌂1$𐌂11.class',
195 \ 'Xspotbugs/tests/α/β/𐌂1.class',
196 \ 'Xspotbugs/tests/α/β/𐌂2$1𐌄.class',
197 \ 'Xspotbugs/tests/α/β/𐌂2$1𐌓.class',
198 \ 'Xspotbugs/tests/α/β/𐌂2.class']),
199 \ }
200 let results['Xspotbugs/src/tests/α/β/package-info.java'] = {
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100201 \ 'Sourcepath': {-> fnamemodify('Xspotbugs/src/tests/α/β/package-info.java',
202 \ ':p:h:S')},
Aliaksei Budavei60ddb1a2024-11-28 22:05:37 +0100203 \ 'classfiles': ['Xspotbugs/tests/α/β/package-info.class'],
204 \ }
205 let results['Xspotbugs/src/tests/α/β/γ/𐌂1.java'] = {
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100206 \ 'Sourcepath': {-> fnamemodify('Xspotbugs/src/tests/α/β/γ/𐌂1.java',
207 \ ':p:h:h:h:h:S')},
Aliaksei Budavei60ddb1a2024-11-28 22:05:37 +0100208 \ 'classfiles': sort([
209 \ 'Xspotbugs/tests/α/β/γ/𐌂1$1.class',
210 \ 'Xspotbugs/tests/α/β/γ/𐌂1$1𐌉𐌉1.class',
211 \ 'Xspotbugs/tests/α/β/γ/𐌂1$𐌂11$𐌉𐌉2.class',
212 \ 'Xspotbugs/tests/α/β/γ/𐌂1$𐌂11.class',
213 \ 'Xspotbugs/tests/α/β/γ/𐌂1.class',
214 \ 'Xspotbugs/tests/α/β/γ/𐌂2$1𐌄.class',
215 \ 'Xspotbugs/tests/α/β/γ/𐌂2$1𐌓.class',
216 \ 'Xspotbugs/tests/α/β/γ/𐌂2.class']),
217 \ }
218 let results['Xspotbugs/src/tests/α/β/γ/package-info.java'] = {
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100219 \ 'Sourcepath': {-> fnamemodify('Xspotbugs/src/tests/α/β/γ/package-info.java',
220 \ ':p:h:S')},
Aliaksei Budavei60ddb1a2024-11-28 22:05:37 +0100221 \ 'classfiles': ['Xspotbugs/tests/α/β/γ/package-info.class'],
222 \ }
223 let results['Xspotbugs/src/tests/α/β/γ/δ/𐌂1.java'] = {
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100224 \ 'Sourcepath': {-> fnamemodify('Xspotbugs/src/tests/α/β/γ/δ/𐌂1.java',
225 \ ':p:h:h:h:h:h:S')},
Aliaksei Budavei60ddb1a2024-11-28 22:05:37 +0100226 \ 'classfiles': sort([
227 \ 'Xspotbugs/tests/α/β/γ/δ/𐌂1$1.class',
228 \ 'Xspotbugs/tests/α/β/γ/δ/𐌂1$1𐌉𐌉1.class',
229 \ 'Xspotbugs/tests/α/β/γ/δ/𐌂1$𐌂11$𐌉𐌉2.class',
230 \ 'Xspotbugs/tests/α/β/γ/δ/𐌂1$𐌂11.class',
231 \ 'Xspotbugs/tests/α/β/γ/δ/𐌂1.class',
232 \ 'Xspotbugs/tests/α/β/γ/δ/𐌂2$1𐌄.class',
233 \ 'Xspotbugs/tests/α/β/γ/δ/𐌂2$1𐌓.class',
234 \ 'Xspotbugs/tests/α/β/γ/δ/𐌂2.class']),
235 \ }
236 let results['Xspotbugs/src/tests/α/β/γ/δ/package-info.java'] = {
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100237 \ 'Sourcepath': {-> fnamemodify('Xspotbugs/src/tests/α/β/γ/δ/package-info.java',
238 \ ':p:h:S')},
Aliaksei Budavei60ddb1a2024-11-28 22:05:37 +0100239 \ 'classfiles': ['Xspotbugs/tests/α/β/γ/δ/package-info.class'],
240 \ }
241
242 " MAKE CLASS FILES DISCOVERABLE!
243 let g:spotbugs_properties = {
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100244 \ 'sourceDirPath': ['src/tests'],
245 \ 'classDirPath': ['tests'],
Aliaksei Budavei60ddb1a2024-11-28 22:05:37 +0100246 \ }
247
248 call assert_true(has_key(s:SpotBugsParseFilterMakePrg('Xspotbugs', ''), 'sourcepath'))
249 call assert_true(has_key(s:SpotBugsParseFilterMakePrg('Xspotbugs', ''), 'classfiles'))
250
251 " Write 45 mock-up class files for 10 source files.
252 for [class_dir, src_dir, package] in [
253 \ ['Xspotbugs/tests/', 'Xspotbugs/src/tests/', ''],
254 \ ['Xspotbugs/tests/α/', 'Xspotbugs/src/tests/α/', 'package α;'],
255 \ ['Xspotbugs/tests/α/β/', 'Xspotbugs/src/tests/α/β/', 'package α.β;'],
256 \ ['Xspotbugs/tests/α/β/γ/', 'Xspotbugs/src/tests/α/β/γ/', 'package α.β.γ;'],
257 \ ['Xspotbugs/tests/α/β/γ/δ/', 'Xspotbugs/src/tests/α/β/γ/δ/', 'package α.β.γ.δ;']]
258 for class_file in ['𐌂1$1.class', '𐌂1$1𐌉𐌉1.class', '𐌂1$𐌂11$𐌉𐌉2.class',
259 \ '𐌂1$𐌂11.class', '𐌂1.class', '𐌂2$1𐌄.class', '𐌂2$1𐌓.class', '𐌂2.class']
260 call writefile(0zcafe.babe.0000.0041, class_dir .. class_file)
261 endfor
262 call writefile(0zcafe.babe.0000.0041, class_dir .. 'package-info.class')
263
264 " Write Java source files.
265 let type_file = src_dir .. '𐌂1.java'
266 call writefile(insert(copy(lines), package), type_file)
267 let package_file = src_dir .. 'package-info.java'
268 call writefile([package], src_dir .. 'package-info.java')
269
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100270 " Note that using "off" for the first _outer_ iteration is preferable
271 " because only then "hlexists()" may be 0 (see "compiler/spotbugs.vim").
272 for s in ['off', 'on']
Aliaksei Budavei60ddb1a2024-11-28 22:05:37 +0100273 execute 'syntax ' .. s
274
275 execute 'edit ' .. type_file
276 compiler spotbugs
277 let result = s:SpotBugsParseFilterMakePrg('Xspotbugs', &l:makeprg)
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100278 call assert_equal(results[type_file].Sourcepath(), result.sourcepath)
Aliaksei Budavei60ddb1a2024-11-28 22:05:37 +0100279 call assert_equal(results[type_file].classfiles, result.classfiles)
280 bwipeout
281
282 execute 'edit ' .. package_file
283 compiler spotbugs
284 let result = s:SpotBugsParseFilterMakePrg('Xspotbugs', &l:makeprg)
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100285 call assert_equal(results[package_file].Sourcepath(), result.sourcepath)
Aliaksei Budavei60ddb1a2024-11-28 22:05:37 +0100286 call assert_equal(results[package_file].classfiles, result.classfiles)
287 bwipeout
288 endfor
289 endfor
290
291 let &shellslash = save_shellslash
292endfunc
293
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100294func s:SpotBugsBeforeFileTypeTryPluginAndClearCache(state)
295 " Ponder over "extend(spotbugs#DefaultProperties(), g:spotbugs_properties)"
296 " in "ftplugin/java.vim".
297 let g:spotbugs#state = a:state
298 runtime autoload/spotbugs.vim
299endfunc
300
301func Test_compiler_spotbugs_properties()
302 let save_shellslash = &shellslash
303 set shellslash
304 setlocal makeprg=
305 filetype plugin on
306
307 call assert_true(mkdir('Xspotbugs/src', 'pR'))
308 call assert_true(mkdir('Xspotbugs/tests', 'pR'))
309 let type_file = 'Xspotbugs/src/𐌄.java'
310 let test_file = 'Xspotbugs/tests/𐌄$.java'
311 call writefile(['enum 𐌄{}'], type_file)
312 call writefile(['class 𐌄${}'], test_file)
313
314 " TEST INTEGRATION WITH A BOGUS COMPILER PLUGIN.
315 if !filereadable($VIMRUNTIME .. '/compiler/foo.vim') && !executable('foo')
316 let g:spotbugs_properties = {'compiler': 'foo'}
317 " XXX: In case this "if" block is no longer first.
318 call s:SpotBugsBeforeFileTypeTryPluginAndClearCache({
319 \ 'compiler': g:spotbugs_properties.compiler,
320 \ })
321 execute 'edit ' .. type_file
322 call assert_equal('java', &l:filetype)
323 " This variable will indefinitely keep the compiler name.
324 call assert_equal('foo', g:spotbugs#state.compiler)
325 " The "compiler" entry should be gone after FileType and default entries
326 " should only appear for a supported compiler.
327 call assert_false(has_key(g:spotbugs_properties, 'compiler'))
328 call assert_true(empty(g:spotbugs_properties))
329 " Query default implementations.
330 call assert_true(exists('*spotbugs#DefaultProperties'))
331 call assert_true(exists('*spotbugs#DefaultPreCompilerAction'))
332 call assert_true(exists('*spotbugs#DefaultPreCompilerTestAction'))
333 call assert_true(empty(spotbugs#DefaultProperties()))
334 " Get a ":message".
335 redir => out
336 call spotbugs#DefaultPreCompilerAction()
337 redir END
338 call assert_equal('Not supported: "foo"', out[stridx(out, 'Not') :])
339 " Get a ":message".
340 redir => out
341 call spotbugs#DefaultPreCompilerTestAction()
342 redir END
343 call assert_equal('Not supported: "foo"', out[stridx(out, 'Not') :])
344 " No ":autocmd"s without one of "PreCompiler*Action", "PostCompilerAction".
345 call assert_false(exists('#java_spotbugs'))
346 bwipeout
347 endif
348
349 let s:spotbugs_results = {
350 \ 'preActionDone': 0,
351 \ 'preTestActionDone': 0,
352 \ 'preTestLocalActionDone': 0,
353 \ 'postActionDone': 0,
354 \ 'preCommandArguments': '',
355 \ 'preTestCommandArguments': '',
356 \ 'postCommandArguments': '',
357 \ }
358 defer execute('unlet s:spotbugs_results')
359
360 func! g:SpotBugsPreAction() abort
361 let s:spotbugs_results.preActionDone = 1
362 " XXX: Notify the spotbugs compiler about success or failure.
363 cc
364 endfunc
365 defer execute('delfunction g:SpotBugsPreAction')
366
367 func! g:SpotBugsPreTestAction() abort
368 let s:spotbugs_results.preTestActionDone = 1
369 " XXX: Let see compilation fail.
370 throw 'Oops'
371 endfunc
372 defer execute('delfunction g:SpotBugsPreTestAction')
373
374 func! g:SpotBugsPreTestLocalAction() abort
375 let s:spotbugs_results.preTestLocalActionDone = 1
376 " XXX: Notify the spotbugs compiler about success or failure.
377 cc
378 endfunc
379 defer execute('delfunction g:SpotBugsPreTestLocalAction')
380
381 func! g:SpotBugsPostAction() abort
382 let s:spotbugs_results.postActionDone = 1
383 endfunc
384 defer execute('delfunction g:SpotBugsPostAction')
385
386 func! g:SpotBugsPreCommand(arguments) abort
387 let s:spotbugs_results.preActionDone = 1
388 let s:spotbugs_results.preCommandArguments = a:arguments
389 " XXX: Notify the spotbugs compiler about success or failure.
390 cc
391 endfunc
392 defer execute('delfunction g:SpotBugsPreCommand')
393
394 func! g:SpotBugsPreTestCommand(arguments) abort
395 let s:spotbugs_results.preTestActionDone = 1
396 let s:spotbugs_results.preTestCommandArguments = a:arguments
397 " XXX: Notify the spotbugs compiler about success or failure.
398 cc
399 endfunc
400 defer execute('delfunction g:SpotBugsPreTestCommand')
401
402 func! g:SpotBugsPostCommand(arguments) abort
403 let s:spotbugs_results.postActionDone = 1
404 let s:spotbugs_results.postCommandArguments = a:arguments
405 endfunc
406 defer execute('delfunction g:SpotBugsPostCommand')
407
Aliaksei Budavei2e252472024-12-27 16:46:36 +0100408 func! g:SpotBugsPostCompilerActionExecutor(action) abort
409 try
410 " XXX: Notify the spotbugs compiler about success or failure.
411 cc
412 catch /\<E42:/
413 execute a:action
414 endtry
415 endfunc
416 defer execute('delfunction g:SpotBugsPostCompilerActionExecutor')
417
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100418 " TEST INTEGRATION WITH A SUPPORTED COMPILER PLUGIN.
419 if filereadable($VIMRUNTIME .. '/compiler/maven.vim')
420 if !executable('mvn')
421 if has('win32')
422 " This is what ":help executable()" suggests.
Aliaksei Budavei2e252472024-12-27 16:46:36 +0100423 call writefile([], 'Xspotbugs/mvn.cmd')
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100424 else
425 let $PATH = 'Xspotbugs:' .. $PATH
426 call writefile([], 'Xspotbugs/mvn')
427 call setfperm('Xspotbugs/mvn', 'rwx------')
428 endif
429 endif
430
431 let g:spotbugs_properties = {
432 \ 'compiler': 'maven',
433 \ 'PreCompilerAction': function('g:SpotBugsPreAction'),
434 \ 'PreCompilerTestAction': function('g:SpotBugsPreTestAction'),
435 \ 'PostCompilerAction': function('g:SpotBugsPostAction'),
436 \ }
437 " XXX: In case this is a runner-up ":edit".
438 call s:SpotBugsBeforeFileTypeTryPluginAndClearCache({
439 \ 'compiler': g:spotbugs_properties.compiler,
440 \ })
441 execute 'edit ' .. type_file
442 call assert_equal('java', &l:filetype)
443 call assert_equal('maven', g:spotbugs#state.compiler)
444 call assert_false(has_key(g:spotbugs_properties, 'compiler'))
445 call assert_false(empty(g:spotbugs_properties))
446 " Query default implementations.
447 call assert_true(exists('*spotbugs#DefaultProperties'))
448 call assert_equal(sort([
449 \ 'PreCompilerAction',
450 \ 'PreCompilerTestAction',
451 \ 'PostCompilerAction',
452 \ 'sourceDirPath',
453 \ 'classDirPath',
454 \ 'testSourceDirPath',
455 \ 'testClassDirPath',
456 \ ]),
457 \ sort(keys(spotbugs#DefaultProperties())))
458 " Some ":autocmd"s with one of "PreCompiler*Action", "PostCompilerAction".
459 call assert_true(exists('#java_spotbugs'))
460 call assert_true(exists('#java_spotbugs#Syntax'))
461 call assert_true(exists('#java_spotbugs#User'))
462 call assert_equal(2, exists(':SpotBugsDefineBufferAutocmd'))
463 SpotBugsDefineBufferAutocmd SigUSR1 User SigUSR1 User SigUSR1 User
464 call assert_true(exists('#java_spotbugs#SigUSR1'))
465 call assert_true(exists('#java_spotbugs#Syntax'))
466 call assert_true(exists('#java_spotbugs#User'))
467 call assert_equal(2, exists(':SpotBugsRemoveBufferAutocmd'))
468 SpotBugsRemoveBufferAutocmd SigUSR1 User SigUSR1 User UserGettingBored
469 call assert_false(exists('#java_spotbugs#SigUSR1'))
470 call assert_true(exists('#java_spotbugs#Syntax'))
471 call assert_true(exists('#java_spotbugs#User'))
472
473 let s:spotbugs_results.preActionDone = 0
474 let s:spotbugs_results.preTestActionDone = 0
475 let s:spotbugs_results.postActionDone = 0
476
477 doautocmd java_spotbugs Syntax
478 call assert_false(exists('#java_spotbugs#Syntax'))
479
480 " No match: "type_file !~# 'src/main/java'".
481 call assert_false(s:spotbugs_results.preActionDone)
482 " No match: "type_file !~# 'src/test/java'".
483 call assert_false(s:spotbugs_results.preTestActionDone)
484 " No pre-match, no post-action.
485 call assert_false(s:spotbugs_results.postActionDone)
486 " Without a match, confirm that ":compiler spotbugs" has NOT run.
487 call assert_true(empty(&l:makeprg))
488
489 let s:spotbugs_results.preActionDone = 0
490 let s:spotbugs_results.preTestActionDone = 0
491 let s:spotbugs_results.postActionDone = 0
492 " Update path entries. (Note that we cannot use just "src" because there
493 " is another "src" directory nearer the filesystem root directory, i.e.
494 " "vim/vim/src/testdir/Xspotbugs/src", and "s:DispatchAction()" (see
495 " "ftplugin/java.vim") will match "vim/vim/src/testdir/Xspotbugs/tests"
496 " against "src".)
497 let g:spotbugs_properties.sourceDirPath = ['Xspotbugs/src']
498 let g:spotbugs_properties.classDirPath = ['Xspotbugs/src']
499 let g:spotbugs_properties.testSourceDirPath = ['tests']
500 let g:spotbugs_properties.testClassDirPath = ['tests']
501
502 doautocmd java_spotbugs User
503 " No match: "type_file !~# 'src/main/java'" (with old "*DirPath" values
504 " cached).
505 call assert_false(s:spotbugs_results.preActionDone)
506 " No match: "type_file !~# 'src/test/java'" (with old "*DirPath" values
507 " cached).
508 call assert_false(s:spotbugs_results.preTestActionDone)
509 " No pre-match, no post-action.
510 call assert_false(s:spotbugs_results.postActionDone)
511 " Without a match, confirm that ":compiler spotbugs" has NOT run.
512 call assert_true(empty(&l:makeprg))
513
514 let s:spotbugs_results.preActionDone = 0
515 let s:spotbugs_results.preTestActionDone = 0
516 let s:spotbugs_results.postActionDone = 0
517 " XXX: Re-build ":autocmd"s from scratch with new values applied.
518 doautocmd FileType
519
520 call assert_true(exists('b:spotbugs_syntax_once'))
521 doautocmd java_spotbugs User
522 " A match: "type_file =~# 'Xspotbugs/src'" (with new "*DirPath" values
523 " cached).
524 call assert_true(s:spotbugs_results.preActionDone)
525 " No match: "type_file !~# 'tests'" (with new "*DirPath" values cached).
526 call assert_false(s:spotbugs_results.preTestActionDone)
527 " For a pre-match, a post-action.
528 call assert_true(s:spotbugs_results.postActionDone)
529
530 " With a match, confirm that ":compiler spotbugs" has run.
531 if has('win32')
532 call assert_match('^spotbugs\.bat\s', &l:makeprg)
533 else
534 call assert_match('^spotbugs\s', &l:makeprg)
535 endif
536
537 bwipeout
538 setlocal makeprg=
539 let s:spotbugs_results.preActionDone = 0
540 let s:spotbugs_results.preTestActionDone = 0
541 let s:spotbugs_results.preTestLocalActionDone = 0
542 let s:spotbugs_results.postActionDone = 0
543
544 execute 'edit ' .. test_file
545 " Prepare a buffer-local, incomplete variant of properties, relying on
546 " "ftplugin/java.vim" to take care of merging in unique entries, if any,
547 " from "g:spotbugs_properties".
548 let b:spotbugs_properties = {
549 \ 'PreCompilerTestAction': function('g:SpotBugsPreTestLocalAction'),
550 \ }
551 call assert_equal('java', &l:filetype)
552 call assert_true(exists('#java_spotbugs'))
553 call assert_true(exists('#java_spotbugs#Syntax'))
554 call assert_true(exists('#java_spotbugs#User'))
555 call assert_fails('doautocmd java_spotbugs Syntax', 'Oops')
556 call assert_false(exists('#java_spotbugs#Syntax'))
557 " No match: "test_file !~# 'Xspotbugs/src'".
558 call assert_false(s:spotbugs_results.preActionDone)
559 " A match: "test_file =~# 'tests'".
560 call assert_true(s:spotbugs_results.preTestActionDone)
561 call assert_false(s:spotbugs_results.preTestLocalActionDone)
562 " No action after pre-failure (the thrown "Oops" doesn't qualify for ":cc").
563 call assert_false(s:spotbugs_results.postActionDone)
564 " No ":compiler spotbugs" will be run after pre-failure.
565 call assert_true(empty(&l:makeprg))
566
567 let s:spotbugs_results.preActionDone = 0
568 let s:spotbugs_results.preTestActionDone = 0
569 let s:spotbugs_results.preTestLocalActionDone = 0
570 let s:spotbugs_results.postActionDone = 0
571 " XXX: Re-build ":autocmd"s from scratch with buffer-local values applied.
572 doautocmd FileType
573
574 call assert_true(exists('b:spotbugs_syntax_once'))
575 doautocmd java_spotbugs User
576 " No match: "test_file !~# 'Xspotbugs/src'".
577 call assert_false(s:spotbugs_results.preActionDone)
578 " A match: "test_file =~# 'tests'".
579 call assert_true(s:spotbugs_results.preTestLocalActionDone)
580 call assert_false(s:spotbugs_results.preTestActionDone)
581 " For a pre-match, a post-action.
582 call assert_true(s:spotbugs_results.postActionDone)
583
584 " With a match, confirm that ":compiler spotbugs" has run.
585 if has('win32')
586 call assert_match('^spotbugs\.bat\s', &l:makeprg)
587 else
588 call assert_match('^spotbugs\s', &l:makeprg)
589 endif
590
591 setlocal makeprg=
592 let s:spotbugs_results.preActionDone = 0
593 let s:spotbugs_results.preTestActionDone = 0
594 let s:spotbugs_results.preTestLocalActionDone = 0
595 let s:spotbugs_results.postActionDone = 0
596 let s:spotbugs_results.preCommandArguments = ''
597 let s:spotbugs_results.preTestCommandArguments = ''
598 let s:spotbugs_results.postCommandArguments = ''
599 " XXX: Compose the assigned "*Command"s with the default Maven "*Action"s.
600 let b:spotbugs_properties = {
601 \ 'compiler': 'maven',
602 \ 'DefaultPreCompilerTestCommand': function('g:SpotBugsPreTestCommand'),
603 \ 'DefaultPreCompilerCommand': function('g:SpotBugsPreCommand'),
604 \ 'DefaultPostCompilerCommand': function('g:SpotBugsPostCommand'),
Aliaksei Budavei2e252472024-12-27 16:46:36 +0100605 \ 'PostCompilerActionExecutor': function('g:SpotBugsPostCompilerActionExecutor'),
606 \ 'augroupForPostCompilerAction': 'java_spotbugs_test',
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100607 \ 'sourceDirPath': ['Xspotbugs/src'],
608 \ 'classDirPath': ['Xspotbugs/src'],
609 \ 'testSourceDirPath': ['tests'],
610 \ 'testClassDirPath': ['tests'],
611 \ }
612 unlet g:spotbugs_properties
613 " XXX: Re-build ":autocmd"s from scratch with buffer-local values applied.
614 call s:SpotBugsBeforeFileTypeTryPluginAndClearCache({
615 \ 'compiler': b:spotbugs_properties.compiler,
616 \ 'commands': {
617 \ 'DefaultPreCompilerTestCommand':
618 \ b:spotbugs_properties.DefaultPreCompilerTestCommand,
619 \ 'DefaultPreCompilerCommand':
620 \ b:spotbugs_properties.DefaultPreCompilerCommand,
621 \ 'DefaultPostCompilerCommand':
622 \ b:spotbugs_properties.DefaultPostCompilerCommand,
623 \ },
624 \ })
625 doautocmd FileType
626
627 call assert_equal('maven', g:spotbugs#state.compiler)
628 call assert_equal(sort([
629 \ 'DefaultPreCompilerTestCommand',
630 \ 'DefaultPreCompilerCommand',
631 \ 'DefaultPostCompilerCommand',
632 \ ]),
633 \ sort(keys(g:spotbugs#state.commands)))
634 call assert_true(exists('b:spotbugs_syntax_once'))
635 doautocmd java_spotbugs User
636 " No match: "test_file !~# 'Xspotbugs/src'".
637 call assert_false(s:spotbugs_results.preActionDone)
638 call assert_true(empty(s:spotbugs_results.preCommandArguments))
639 " A match: "test_file =~# 'tests'".
640 call assert_true(s:spotbugs_results.preTestActionDone)
641 call assert_equal('test-compile', s:spotbugs_results.preTestCommandArguments)
642 " For a pre-match, a post-action.
643 call assert_true(s:spotbugs_results.postActionDone)
644 call assert_equal('%:S', s:spotbugs_results.postCommandArguments)
645
646 " With a match, confirm that ":compiler spotbugs" has run.
647 if has('win32')
648 call assert_match('^spotbugs\.bat\s', &l:makeprg)
649 else
650 call assert_match('^spotbugs\s', &l:makeprg)
651 endif
652
Aliaksei Budavei2e252472024-12-27 16:46:36 +0100653 setlocal makeprg=
654 let s:spotbugs_results.preActionDone = 0
655 let s:spotbugs_results.preTestActionOtherDone = 0
656 let s:spotbugs_results.preTestLocalActionDone = 0
657 let s:spotbugs_results.postActionDone = 0
658 let s:spotbugs_results.preCommandArguments = ''
659 let s:spotbugs_results.preTestCommandArguments = ''
660 let s:spotbugs_results.postCommandArguments = ''
661
662 " When "PostCompilerActionExecutor", "Pre*Action" and/or "Pre*TestAction",
663 " and "Post*Action" are available, "#java_spotbugs_post" must be defined.
664 call assert_true(exists('#java_spotbugs_post'))
665 call assert_true(exists('#java_spotbugs_post#User'))
666 call assert_false(exists('#java_spotbugs_post#ShellCmdPost'))
667 call assert_false(exists('#java_spotbugs_test#ShellCmdPost'))
668
669 " Re-link a Funcref on the fly.
670 func! g:SpotBugsPreTestCommand(arguments) abort
671 let s:spotbugs_results.preTestActionOtherDone = 1
672 let s:spotbugs_results.preTestCommandArguments = a:arguments
673 " Define a once-only ":autocmd" for "#java_spotbugs_test#ShellCmdPost".
674 doautocmd java_spotbugs_post User
675 " XXX: Do NOT use ":cc" to notify the spotbugs compiler about success or
676 " failure, and assume the transfer of control to a ShellCmdPost command.
677 endfunc
678
679 doautocmd java_spotbugs User
680 " No match: "test_file !~# 'Xspotbugs/src'".
681 call assert_false(s:spotbugs_results.preActionDone)
682 call assert_true(empty(s:spotbugs_results.preCommandArguments))
683 " A match: "test_file =~# 'tests'".
684 call assert_true(s:spotbugs_results.preTestActionOtherDone)
685 call assert_equal('test-compile', s:spotbugs_results.preTestCommandArguments)
686 " For a pre-match, no post-action (without ":cc") UNLESS a ShellCmdPost
687 " event is consumed whose command will invoke "PostCompilerActionExecutor"
688 " and the latter will accept a post-compiler action argument.
689 call assert_false(s:spotbugs_results.postActionDone)
690 call assert_true(exists('#java_spotbugs_test#ShellCmdPost'))
691 doautocmd ShellCmdPost
692 call assert_false(exists('#java_spotbugs_test#ShellCmdPost'))
693 call assert_true(s:spotbugs_results.postActionDone)
694 call assert_equal('%:S', s:spotbugs_results.postCommandArguments)
695
696 " With a match, confirm that ":compiler spotbugs" has run.
697 if has('win32')
698 call assert_match('^spotbugs\.bat\s', &l:makeprg)
699 else
700 call assert_match('^spotbugs\s', &l:makeprg)
701 endif
702
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100703 bwipeout
704 setlocal makeprg=
705 endif
706
707 filetype plugin off
708 setlocal makeprg=
709 let &shellslash = save_shellslash
710endfunc
711
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200712" vim: shiftwidth=2 sts=2 expandtab