blob: d86c55f1c7dfc986485f92f22cae8a7094d40eed [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([])
zeertzjq5e8b2262025-02-28 17:32:07 +010020
Bram Moolenaar10561fe2018-05-19 15:01:10 +020021 compiler perl
22 call assert_equal('perl', b:current_compiler)
23 call assert_fails('let g:current_compiler', 'E121:')
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)
zeertzjq5e8b2262025-02-28 17:32:07 +010026 " Not using the global value
27 call assert_notequal('', &l:efm)
Bram Moolenaar58ef8a32021-11-12 11:25:11 +000028
Bram Moolenaar10561fe2018-05-19 15:01:10 +020029 call setline(1, ['#!/usr/bin/perl -w', 'use strict;', 'my $foo=1'])
30 w!
31 call feedkeys(":make\<CR>\<CR>", 'tx')
32 call assert_fails('clist', 'E42:')
33
34 call setline(1, ['#!/usr/bin/perl -w', 'use strict;', '$foo=1'])
35 w!
36 call feedkeys(":make\<CR>\<CR>", 'tx')
37 let a=execute('clist')
Bram Moolenaarcebfcff2019-09-18 21:42:38 +020038 call assert_match('\n \d\+ Xfoo.pl:3: Global symbol "$foo" '
39 \ . 'requires explicit package name', a)
40
zeertzjq5e8b2262025-02-28 17:32:07 +010041 compiler make
42 call assert_fails('let b:current_compiler', 'E121:')
43 call assert_fails('let g:current_compiler', 'E121:')
44 let verbose_efm = execute('verbose set efm')
45 call assert_match('Last set from .*[/\\]compiler[/\\]make.vim ', verbose_efm)
46
47 compiler! perl
48 call assert_equal('perl', b:current_compiler)
49 call assert_equal('perl', g:current_compiler)
50 let verbose_efm = execute('verbose set efm')
51 call assert_match('Last set from .*[/\\]compiler[/\\]perl.vim ', verbose_efm)
52 call assert_equal(verbose_efm, execute('verbose setglobal efm'))
53 " Using the global value
54 call assert_equal('', &l:efm)
55
56 compiler! make
57 call assert_fails('let b:current_compiler', 'E121:')
58 call assert_fails('let g:current_compiler', 'E121:')
59 let verbose_efm = execute('verbose set efm')
60 call assert_match('Last set from .*[/\\]compiler[/\\]make.vim ', verbose_efm)
61 call assert_equal(verbose_efm, execute('verbose setglobal efm'))
62 " Using the global value
63 call assert_equal('', &l:efm)
Bram Moolenaar10561fe2018-05-19 15:01:10 +020064
Bram Moolenaardff2adc2019-07-31 22:18:22 +020065 let &shellslash = save_shellslash
Bram Moolenaar10561fe2018-05-19 15:01:10 +020066 call delete('Xfoo.pl')
67 bw!
Dominique Pelléca0ffc02023-09-24 22:57:41 +020068 let $LC_ALL = save_LC_ALL
Bram Moolenaar10561fe2018-05-19 15:01:10 +020069endfunc
70
Bram Moolenaar60bc8e72020-11-23 21:24:58 +010071func GetCompilerNames()
72 return glob('$VIMRUNTIME/compiler/*.vim', 0, 1)
Bram Moolenaar142f2352020-11-23 21:39:14 +010073 \ ->map({i, v -> substitute(v, '.*[\\/]\([a-zA-Z0-9_\-]*\).vim', '\1', '')})
74 \ ->sort()
Bram Moolenaar60bc8e72020-11-23 21:24:58 +010075endfunc
76
Bram Moolenaar10561fe2018-05-19 15:01:10 +020077func Test_compiler_without_arg()
Bram Moolenaarc25e7022019-10-10 14:08:26 +020078 let runtime = substitute($VIMRUNTIME, '\\', '/', 'g')
79 let a = split(execute('compiler'))
Bram Moolenaar60bc8e72020-11-23 21:24:58 +010080 let exp = GetCompilerNames()
81 call assert_match(runtime .. '/compiler/' .. exp[0] .. '.vim$', a[0])
82 call assert_match(runtime .. '/compiler/' .. exp[1] .. '.vim$', a[1])
83 call assert_match(runtime .. '/compiler/' .. exp[-1] .. '.vim$', a[-1])
Bram Moolenaar10561fe2018-05-19 15:01:10 +020084endfunc
85
Bram Moolenaar16531552020-02-08 16:00:46 +010086" Test executing :compiler from the command line, not from a script
87func Test_compiler_commandline()
88 call system(GetVimCommandClean() .. ' --not-a-term -c "compiler gcc" -c "call writefile([b:current_compiler], ''XcompilerOut'')" -c "quit"')
89 call assert_equal(0, v:shell_error)
90 call assert_equal(["gcc"], readfile('XcompilerOut'))
91
92 call delete('XcompilerOut')
93endfunc
94
Bram Moolenaar10561fe2018-05-19 15:01:10 +020095func Test_compiler_completion()
Bram Moolenaar60bc8e72020-11-23 21:24:58 +010096 let clist = GetCompilerNames()->join(' ')
Bram Moolenaar10561fe2018-05-19 15:01:10 +020097 call feedkeys(":compiler \<C-A>\<C-B>\"\<CR>", 'tx')
Bram Moolenaar60bc8e72020-11-23 21:24:58 +010098 call assert_match('^"compiler ' .. clist .. '$', @:)
Bram Moolenaar10561fe2018-05-19 15:01:10 +020099
100 call feedkeys(":compiler p\<C-A>\<C-B>\"\<CR>", 'tx')
Konfekt3c2596a2024-11-30 11:32:49 +0100101 call assert_match('"compiler pandoc pbx perl\( p[a-z_]\+\)\+ pyunit', @:)
Bram Moolenaar10561fe2018-05-19 15:01:10 +0200102
103 call feedkeys(":compiler! p\<C-A>\<C-B>\"\<CR>", 'tx')
Konfekt3c2596a2024-11-30 11:32:49 +0100104 call assert_match('"compiler! pandoc pbx perl\( p[a-z_]\+\)\+ pyunit', @:)
Bram Moolenaar10561fe2018-05-19 15:01:10 +0200105endfunc
106
107func Test_compiler_error()
Bram Moolenaare20b9ec2020-02-03 21:40:04 +0100108 let g:current_compiler = 'abc'
Bram Moolenaar10561fe2018-05-19 15:01:10 +0200109 call assert_fails('compiler doesnotexist', 'E666:')
Bram Moolenaare20b9ec2020-02-03 21:40:04 +0100110 call assert_equal('abc', g:current_compiler)
111 call assert_fails('compiler! doesnotexist', 'E666:')
112 unlet! g:current_compiler
Bram Moolenaar10561fe2018-05-19 15:01:10 +0200113endfunc
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200114
Aliaksei Budavei60ddb1a2024-11-28 22:05:37 +0100115func s:SpotBugsParseFilterMakePrg(dirname, makeprg)
116 let result = {}
117 let result.sourcepath = ''
118 let result.classfiles = []
119
120 " Get the argument after the rightmost occurrence of "-sourcepath".
121 let offset = strridx(a:makeprg, '-sourcepath')
122 if offset < 0
123 return result
124 endif
125 let offset += 1 + strlen('-sourcepath')
126 let result.sourcepath = matchstr(strpart(a:makeprg, offset), '.\{-}\ze[ \t]')
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100127 let offset += 1 + strlen(result.sourcepath)
Aliaksei Budavei60ddb1a2024-11-28 22:05:37 +0100128
129 " Get the class file arguments, dropping the pathname prefix.
130 let offset = stridx(a:makeprg, a:dirname, offset)
131 if offset < 0
132 return result
133 endif
134
135 while offset > -1
136 let candidate = matchstr(a:makeprg, '[^ \t]\{-}\.class\>', offset)
137 if empty(candidate)
138 break
139 endif
140 call add(result.classfiles, candidate)
141 let offset = stridx(a:makeprg, a:dirname, (1 + strlen(candidate) + offset))
142 endwhile
143
144 call sort(result.classfiles)
145 return result
146endfunc
147
148func Test_compiler_spotbugs_makeprg()
149 let save_shellslash = &shellslash
150 set shellslash
151
152 call assert_true(mkdir('Xspotbugs/src/tests/α/β/γ/δ', 'pR'))
153 call assert_true(mkdir('Xspotbugs/tests/α/β/γ/δ', 'pR'))
154
155 let lines =<< trim END
156 // EOL comment. /*
157 abstract class
158 𐌂1 /* Multiline comment. */ {
159 /* Multiline comment. */ // EOL comment. /*
160 static final String COMMENT_A_LIKE = "/*";
161 { new Object() {/* Try globbing. */}; }
162 static { interface 𐌉𐌉1 {} }
163 static class 𐌂11 { interface 𐌉𐌉2 {} }
164 }
165 /* Multiline comment. */ // EOL comment. /*
166 final class 𐌂2 {
167 public static void main(String... aa) {
168 record 𐌓() {}
169 enum 𐌄 {}
170 }
171 } // class
172 END
173
174 " THE EXPECTED RESULTS.
175 let results = {}
176 let results['Xspotbugs/src/tests/𐌂1.java'] = {
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100177 \ 'Sourcepath': {-> fnamemodify('Xspotbugs/src/tests/𐌂1.java',
178 \ ':p:h:S')},
Aliaksei Budavei60ddb1a2024-11-28 22:05:37 +0100179 \ 'classfiles': sort([
180 \ 'Xspotbugs/tests/𐌂1$1.class',
181 \ 'Xspotbugs/tests/𐌂1$1𐌉𐌉1.class',
182 \ 'Xspotbugs/tests/𐌂1$𐌂11$𐌉𐌉2.class',
183 \ 'Xspotbugs/tests/𐌂1$𐌂11.class',
184 \ 'Xspotbugs/tests/𐌂1.class',
185 \ 'Xspotbugs/tests/𐌂2$1𐌄.class',
186 \ 'Xspotbugs/tests/𐌂2$1𐌓.class',
187 \ 'Xspotbugs/tests/𐌂2.class']),
188 \ }
189 " No class file for an empty source file even with "-Xpkginfo:always".
190 let results['Xspotbugs/src/tests/package-info.java'] = {
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100191 \ 'Sourcepath': {-> ''},
Aliaksei Budavei60ddb1a2024-11-28 22:05:37 +0100192 \ 'classfiles': [],
193 \ }
194 let results['Xspotbugs/src/tests/α/𐌂1.java'] = {
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100195 \ 'Sourcepath': {-> fnamemodify('Xspotbugs/src/tests/α/𐌂1.java',
196 \ ':p:h:h:S')},
Aliaksei Budavei60ddb1a2024-11-28 22:05:37 +0100197 \ 'classfiles': sort([
198 \ 'Xspotbugs/tests/α/𐌂1$1.class',
199 \ 'Xspotbugs/tests/α/𐌂1$1𐌉𐌉1.class',
200 \ 'Xspotbugs/tests/α/𐌂1$𐌂11$𐌉𐌉2.class',
201 \ 'Xspotbugs/tests/α/𐌂1$𐌂11.class',
202 \ 'Xspotbugs/tests/α/𐌂1.class',
203 \ 'Xspotbugs/tests/α/𐌂2$1𐌄.class',
204 \ 'Xspotbugs/tests/α/𐌂2$1𐌓.class',
205 \ 'Xspotbugs/tests/α/𐌂2.class']),
206 \ }
207 let results['Xspotbugs/src/tests/α/package-info.java'] = {
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100208 \ 'Sourcepath': {-> fnamemodify('Xspotbugs/src/tests/α/package-info.java',
209 \ ':p:h:S')},
Aliaksei Budavei60ddb1a2024-11-28 22:05:37 +0100210 \ 'classfiles': ['Xspotbugs/tests/α/package-info.class'],
211 \ }
212 let results['Xspotbugs/src/tests/α/β/𐌂1.java'] = {
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100213 \ 'Sourcepath': {-> fnamemodify('Xspotbugs/src/tests/α/β/𐌂1.java',
214 \ ':p:h:h:h:S')},
Aliaksei Budavei60ddb1a2024-11-28 22:05:37 +0100215 \ 'classfiles': sort([
216 \ 'Xspotbugs/tests/α/β/𐌂1$1.class',
217 \ 'Xspotbugs/tests/α/β/𐌂1$1𐌉𐌉1.class',
218 \ 'Xspotbugs/tests/α/β/𐌂1$𐌂11$𐌉𐌉2.class',
219 \ 'Xspotbugs/tests/α/β/𐌂1$𐌂11.class',
220 \ 'Xspotbugs/tests/α/β/𐌂1.class',
221 \ 'Xspotbugs/tests/α/β/𐌂2$1𐌄.class',
222 \ 'Xspotbugs/tests/α/β/𐌂2$1𐌓.class',
223 \ 'Xspotbugs/tests/α/β/𐌂2.class']),
224 \ }
225 let results['Xspotbugs/src/tests/α/β/package-info.java'] = {
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100226 \ 'Sourcepath': {-> fnamemodify('Xspotbugs/src/tests/α/β/package-info.java',
227 \ ':p:h:S')},
Aliaksei Budavei60ddb1a2024-11-28 22:05:37 +0100228 \ 'classfiles': ['Xspotbugs/tests/α/β/package-info.class'],
229 \ }
230 let results['Xspotbugs/src/tests/α/β/γ/𐌂1.java'] = {
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100231 \ 'Sourcepath': {-> fnamemodify('Xspotbugs/src/tests/α/β/γ/𐌂1.java',
232 \ ':p:h:h:h:h:S')},
Aliaksei Budavei60ddb1a2024-11-28 22:05:37 +0100233 \ 'classfiles': sort([
234 \ 'Xspotbugs/tests/α/β/γ/𐌂1$1.class',
235 \ 'Xspotbugs/tests/α/β/γ/𐌂1$1𐌉𐌉1.class',
236 \ 'Xspotbugs/tests/α/β/γ/𐌂1$𐌂11$𐌉𐌉2.class',
237 \ 'Xspotbugs/tests/α/β/γ/𐌂1$𐌂11.class',
238 \ 'Xspotbugs/tests/α/β/γ/𐌂1.class',
239 \ 'Xspotbugs/tests/α/β/γ/𐌂2$1𐌄.class',
240 \ 'Xspotbugs/tests/α/β/γ/𐌂2$1𐌓.class',
241 \ 'Xspotbugs/tests/α/β/γ/𐌂2.class']),
242 \ }
243 let results['Xspotbugs/src/tests/α/β/γ/package-info.java'] = {
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100244 \ 'Sourcepath': {-> fnamemodify('Xspotbugs/src/tests/α/β/γ/package-info.java',
245 \ ':p:h:S')},
Aliaksei Budavei60ddb1a2024-11-28 22:05:37 +0100246 \ 'classfiles': ['Xspotbugs/tests/α/β/γ/package-info.class'],
247 \ }
248 let results['Xspotbugs/src/tests/α/β/γ/δ/𐌂1.java'] = {
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100249 \ 'Sourcepath': {-> fnamemodify('Xspotbugs/src/tests/α/β/γ/δ/𐌂1.java',
250 \ ':p:h:h:h:h:h:S')},
Aliaksei Budavei60ddb1a2024-11-28 22:05:37 +0100251 \ 'classfiles': sort([
252 \ 'Xspotbugs/tests/α/β/γ/δ/𐌂1$1.class',
253 \ 'Xspotbugs/tests/α/β/γ/δ/𐌂1$1𐌉𐌉1.class',
254 \ 'Xspotbugs/tests/α/β/γ/δ/𐌂1$𐌂11$𐌉𐌉2.class',
255 \ 'Xspotbugs/tests/α/β/γ/δ/𐌂1$𐌂11.class',
256 \ 'Xspotbugs/tests/α/β/γ/δ/𐌂1.class',
257 \ 'Xspotbugs/tests/α/β/γ/δ/𐌂2$1𐌄.class',
258 \ 'Xspotbugs/tests/α/β/γ/δ/𐌂2$1𐌓.class',
259 \ 'Xspotbugs/tests/α/β/γ/δ/𐌂2.class']),
260 \ }
261 let results['Xspotbugs/src/tests/α/β/γ/δ/package-info.java'] = {
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100262 \ 'Sourcepath': {-> fnamemodify('Xspotbugs/src/tests/α/β/γ/δ/package-info.java',
263 \ ':p:h:S')},
Aliaksei Budavei60ddb1a2024-11-28 22:05:37 +0100264 \ 'classfiles': ['Xspotbugs/tests/α/β/γ/δ/package-info.class'],
265 \ }
266
267 " MAKE CLASS FILES DISCOVERABLE!
268 let g:spotbugs_properties = {
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100269 \ 'sourceDirPath': ['src/tests'],
270 \ 'classDirPath': ['tests'],
Aliaksei Budavei60ddb1a2024-11-28 22:05:37 +0100271 \ }
272
273 call assert_true(has_key(s:SpotBugsParseFilterMakePrg('Xspotbugs', ''), 'sourcepath'))
274 call assert_true(has_key(s:SpotBugsParseFilterMakePrg('Xspotbugs', ''), 'classfiles'))
275
276 " Write 45 mock-up class files for 10 source files.
277 for [class_dir, src_dir, package] in [
278 \ ['Xspotbugs/tests/', 'Xspotbugs/src/tests/', ''],
279 \ ['Xspotbugs/tests/α/', 'Xspotbugs/src/tests/α/', 'package α;'],
280 \ ['Xspotbugs/tests/α/β/', 'Xspotbugs/src/tests/α/β/', 'package α.β;'],
281 \ ['Xspotbugs/tests/α/β/γ/', 'Xspotbugs/src/tests/α/β/γ/', 'package α.β.γ;'],
282 \ ['Xspotbugs/tests/α/β/γ/δ/', 'Xspotbugs/src/tests/α/β/γ/δ/', 'package α.β.γ.δ;']]
283 for class_file in ['𐌂1$1.class', '𐌂1$1𐌉𐌉1.class', '𐌂1$𐌂11$𐌉𐌉2.class',
284 \ '𐌂1$𐌂11.class', '𐌂1.class', '𐌂2$1𐌄.class', '𐌂2$1𐌓.class', '𐌂2.class']
285 call writefile(0zcafe.babe.0000.0041, class_dir .. class_file)
286 endfor
287 call writefile(0zcafe.babe.0000.0041, class_dir .. 'package-info.class')
288
289 " Write Java source files.
290 let type_file = src_dir .. '𐌂1.java'
291 call writefile(insert(copy(lines), package), type_file)
292 let package_file = src_dir .. 'package-info.java'
293 call writefile([package], src_dir .. 'package-info.java')
294
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100295 " Note that using "off" for the first _outer_ iteration is preferable
296 " because only then "hlexists()" may be 0 (see "compiler/spotbugs.vim").
297 for s in ['off', 'on']
Aliaksei Budavei60ddb1a2024-11-28 22:05:37 +0100298 execute 'syntax ' .. s
299
300 execute 'edit ' .. type_file
301 compiler spotbugs
302 let result = s:SpotBugsParseFilterMakePrg('Xspotbugs', &l:makeprg)
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100303 call assert_equal(results[type_file].Sourcepath(), result.sourcepath)
Aliaksei Budavei60ddb1a2024-11-28 22:05:37 +0100304 call assert_equal(results[type_file].classfiles, result.classfiles)
305 bwipeout
306
307 execute 'edit ' .. package_file
308 compiler spotbugs
309 let result = s:SpotBugsParseFilterMakePrg('Xspotbugs', &l:makeprg)
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100310 call assert_equal(results[package_file].Sourcepath(), result.sourcepath)
Aliaksei Budavei60ddb1a2024-11-28 22:05:37 +0100311 call assert_equal(results[package_file].classfiles, result.classfiles)
312 bwipeout
313 endfor
314 endfor
315
316 let &shellslash = save_shellslash
317endfunc
318
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100319func s:SpotBugsBeforeFileTypeTryPluginAndClearCache(state)
320 " Ponder over "extend(spotbugs#DefaultProperties(), g:spotbugs_properties)"
321 " in "ftplugin/java.vim".
322 let g:spotbugs#state = a:state
323 runtime autoload/spotbugs.vim
324endfunc
325
326func Test_compiler_spotbugs_properties()
327 let save_shellslash = &shellslash
328 set shellslash
329 setlocal makeprg=
330 filetype plugin on
331
332 call assert_true(mkdir('Xspotbugs/src', 'pR'))
333 call assert_true(mkdir('Xspotbugs/tests', 'pR'))
334 let type_file = 'Xspotbugs/src/𐌄.java'
335 let test_file = 'Xspotbugs/tests/𐌄$.java'
336 call writefile(['enum 𐌄{}'], type_file)
337 call writefile(['class 𐌄${}'], test_file)
338
339 " TEST INTEGRATION WITH A BOGUS COMPILER PLUGIN.
340 if !filereadable($VIMRUNTIME .. '/compiler/foo.vim') && !executable('foo')
341 let g:spotbugs_properties = {'compiler': 'foo'}
342 " XXX: In case this "if" block is no longer first.
343 call s:SpotBugsBeforeFileTypeTryPluginAndClearCache({
344 \ 'compiler': g:spotbugs_properties.compiler,
345 \ })
346 execute 'edit ' .. type_file
347 call assert_equal('java', &l:filetype)
348 " This variable will indefinitely keep the compiler name.
349 call assert_equal('foo', g:spotbugs#state.compiler)
350 " The "compiler" entry should be gone after FileType and default entries
351 " should only appear for a supported compiler.
352 call assert_false(has_key(g:spotbugs_properties, 'compiler'))
353 call assert_true(empty(g:spotbugs_properties))
354 " Query default implementations.
355 call assert_true(exists('*spotbugs#DefaultProperties'))
356 call assert_true(exists('*spotbugs#DefaultPreCompilerAction'))
357 call assert_true(exists('*spotbugs#DefaultPreCompilerTestAction'))
358 call assert_true(empty(spotbugs#DefaultProperties()))
359 " Get a ":message".
360 redir => out
361 call spotbugs#DefaultPreCompilerAction()
362 redir END
363 call assert_equal('Not supported: "foo"', out[stridx(out, 'Not') :])
364 " Get a ":message".
365 redir => out
366 call spotbugs#DefaultPreCompilerTestAction()
367 redir END
368 call assert_equal('Not supported: "foo"', out[stridx(out, 'Not') :])
369 " No ":autocmd"s without one of "PreCompiler*Action", "PostCompilerAction".
370 call assert_false(exists('#java_spotbugs'))
371 bwipeout
372 endif
373
374 let s:spotbugs_results = {
375 \ 'preActionDone': 0,
376 \ 'preTestActionDone': 0,
377 \ 'preTestLocalActionDone': 0,
378 \ 'postActionDone': 0,
379 \ 'preCommandArguments': '',
380 \ 'preTestCommandArguments': '',
381 \ 'postCommandArguments': '',
382 \ }
383 defer execute('unlet s:spotbugs_results')
384
385 func! g:SpotBugsPreAction() abort
386 let s:spotbugs_results.preActionDone = 1
387 " XXX: Notify the spotbugs compiler about success or failure.
388 cc
389 endfunc
390 defer execute('delfunction g:SpotBugsPreAction')
391
392 func! g:SpotBugsPreTestAction() abort
393 let s:spotbugs_results.preTestActionDone = 1
394 " XXX: Let see compilation fail.
395 throw 'Oops'
396 endfunc
397 defer execute('delfunction g:SpotBugsPreTestAction')
398
399 func! g:SpotBugsPreTestLocalAction() abort
400 let s:spotbugs_results.preTestLocalActionDone = 1
401 " XXX: Notify the spotbugs compiler about success or failure.
402 cc
403 endfunc
404 defer execute('delfunction g:SpotBugsPreTestLocalAction')
405
406 func! g:SpotBugsPostAction() abort
407 let s:spotbugs_results.postActionDone = 1
408 endfunc
409 defer execute('delfunction g:SpotBugsPostAction')
410
411 func! g:SpotBugsPreCommand(arguments) abort
412 let s:spotbugs_results.preActionDone = 1
413 let s:spotbugs_results.preCommandArguments = a:arguments
414 " XXX: Notify the spotbugs compiler about success or failure.
415 cc
416 endfunc
417 defer execute('delfunction g:SpotBugsPreCommand')
418
419 func! g:SpotBugsPreTestCommand(arguments) abort
420 let s:spotbugs_results.preTestActionDone = 1
421 let s:spotbugs_results.preTestCommandArguments = a:arguments
422 " XXX: Notify the spotbugs compiler about success or failure.
423 cc
424 endfunc
425 defer execute('delfunction g:SpotBugsPreTestCommand')
426
427 func! g:SpotBugsPostCommand(arguments) abort
428 let s:spotbugs_results.postActionDone = 1
429 let s:spotbugs_results.postCommandArguments = a:arguments
430 endfunc
431 defer execute('delfunction g:SpotBugsPostCommand')
432
Aliaksei Budavei2e252472024-12-27 16:46:36 +0100433 func! g:SpotBugsPostCompilerActionExecutor(action) abort
434 try
435 " XXX: Notify the spotbugs compiler about success or failure.
436 cc
437 catch /\<E42:/
438 execute a:action
439 endtry
440 endfunc
441 defer execute('delfunction g:SpotBugsPostCompilerActionExecutor')
442
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100443 " TEST INTEGRATION WITH A SUPPORTED COMPILER PLUGIN.
444 if filereadable($VIMRUNTIME .. '/compiler/maven.vim')
zeertzjq23da16d2025-02-03 18:53:28 +0100445 let save_PATH = $PATH
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100446 if !executable('mvn')
447 if has('win32')
zeertzjq23da16d2025-02-03 18:53:28 +0100448 let $PATH = 'Xspotbugs;' .. $PATH
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100449 " This is what ":help executable()" suggests.
Aliaksei Budavei2e252472024-12-27 16:46:36 +0100450 call writefile([], 'Xspotbugs/mvn.cmd')
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100451 else
452 let $PATH = 'Xspotbugs:' .. $PATH
453 call writefile([], 'Xspotbugs/mvn')
454 call setfperm('Xspotbugs/mvn', 'rwx------')
455 endif
456 endif
457
458 let g:spotbugs_properties = {
459 \ 'compiler': 'maven',
460 \ 'PreCompilerAction': function('g:SpotBugsPreAction'),
461 \ 'PreCompilerTestAction': function('g:SpotBugsPreTestAction'),
462 \ 'PostCompilerAction': function('g:SpotBugsPostAction'),
463 \ }
464 " XXX: In case this is a runner-up ":edit".
465 call s:SpotBugsBeforeFileTypeTryPluginAndClearCache({
466 \ 'compiler': g:spotbugs_properties.compiler,
467 \ })
468 execute 'edit ' .. type_file
469 call assert_equal('java', &l:filetype)
470 call assert_equal('maven', g:spotbugs#state.compiler)
471 call assert_false(has_key(g:spotbugs_properties, 'compiler'))
472 call assert_false(empty(g:spotbugs_properties))
473 " Query default implementations.
474 call assert_true(exists('*spotbugs#DefaultProperties'))
475 call assert_equal(sort([
476 \ 'PreCompilerAction',
477 \ 'PreCompilerTestAction',
478 \ 'PostCompilerAction',
479 \ 'sourceDirPath',
480 \ 'classDirPath',
481 \ 'testSourceDirPath',
482 \ 'testClassDirPath',
483 \ ]),
484 \ sort(keys(spotbugs#DefaultProperties())))
485 " Some ":autocmd"s with one of "PreCompiler*Action", "PostCompilerAction".
486 call assert_true(exists('#java_spotbugs'))
487 call assert_true(exists('#java_spotbugs#Syntax'))
488 call assert_true(exists('#java_spotbugs#User'))
489 call assert_equal(2, exists(':SpotBugsDefineBufferAutocmd'))
490 SpotBugsDefineBufferAutocmd SigUSR1 User SigUSR1 User SigUSR1 User
491 call assert_true(exists('#java_spotbugs#SigUSR1'))
492 call assert_true(exists('#java_spotbugs#Syntax'))
493 call assert_true(exists('#java_spotbugs#User'))
494 call assert_equal(2, exists(':SpotBugsRemoveBufferAutocmd'))
495 SpotBugsRemoveBufferAutocmd SigUSR1 User SigUSR1 User UserGettingBored
496 call assert_false(exists('#java_spotbugs#SigUSR1'))
497 call assert_true(exists('#java_spotbugs#Syntax'))
498 call assert_true(exists('#java_spotbugs#User'))
499
500 let s:spotbugs_results.preActionDone = 0
501 let s:spotbugs_results.preTestActionDone = 0
502 let s:spotbugs_results.postActionDone = 0
503
504 doautocmd java_spotbugs Syntax
505 call assert_false(exists('#java_spotbugs#Syntax'))
506
507 " No match: "type_file !~# 'src/main/java'".
508 call assert_false(s:spotbugs_results.preActionDone)
509 " No match: "type_file !~# 'src/test/java'".
510 call assert_false(s:spotbugs_results.preTestActionDone)
511 " No pre-match, no post-action.
512 call assert_false(s:spotbugs_results.postActionDone)
513 " Without a match, confirm that ":compiler spotbugs" has NOT run.
514 call assert_true(empty(&l:makeprg))
515
516 let s:spotbugs_results.preActionDone = 0
517 let s:spotbugs_results.preTestActionDone = 0
518 let s:spotbugs_results.postActionDone = 0
519 " Update path entries. (Note that we cannot use just "src" because there
520 " is another "src" directory nearer the filesystem root directory, i.e.
521 " "vim/vim/src/testdir/Xspotbugs/src", and "s:DispatchAction()" (see
522 " "ftplugin/java.vim") will match "vim/vim/src/testdir/Xspotbugs/tests"
523 " against "src".)
524 let g:spotbugs_properties.sourceDirPath = ['Xspotbugs/src']
525 let g:spotbugs_properties.classDirPath = ['Xspotbugs/src']
526 let g:spotbugs_properties.testSourceDirPath = ['tests']
527 let g:spotbugs_properties.testClassDirPath = ['tests']
528
529 doautocmd java_spotbugs User
530 " No match: "type_file !~# 'src/main/java'" (with old "*DirPath" values
531 " cached).
532 call assert_false(s:spotbugs_results.preActionDone)
533 " No match: "type_file !~# 'src/test/java'" (with old "*DirPath" values
534 " cached).
535 call assert_false(s:spotbugs_results.preTestActionDone)
536 " No pre-match, no post-action.
537 call assert_false(s:spotbugs_results.postActionDone)
538 " Without a match, confirm that ":compiler spotbugs" has NOT run.
539 call assert_true(empty(&l:makeprg))
540
541 let s:spotbugs_results.preActionDone = 0
542 let s:spotbugs_results.preTestActionDone = 0
543 let s:spotbugs_results.postActionDone = 0
544 " XXX: Re-build ":autocmd"s from scratch with new values applied.
545 doautocmd FileType
546
547 call assert_true(exists('b:spotbugs_syntax_once'))
548 doautocmd java_spotbugs User
549 " A match: "type_file =~# 'Xspotbugs/src'" (with new "*DirPath" values
550 " cached).
551 call assert_true(s:spotbugs_results.preActionDone)
552 " No match: "type_file !~# 'tests'" (with new "*DirPath" values cached).
553 call assert_false(s:spotbugs_results.preTestActionDone)
554 " For a pre-match, a post-action.
555 call assert_true(s:spotbugs_results.postActionDone)
556
557 " With a match, confirm that ":compiler spotbugs" has run.
558 if has('win32')
559 call assert_match('^spotbugs\.bat\s', &l:makeprg)
560 else
561 call assert_match('^spotbugs\s', &l:makeprg)
562 endif
563
564 bwipeout
565 setlocal makeprg=
566 let s:spotbugs_results.preActionDone = 0
567 let s:spotbugs_results.preTestActionDone = 0
568 let s:spotbugs_results.preTestLocalActionDone = 0
569 let s:spotbugs_results.postActionDone = 0
570
571 execute 'edit ' .. test_file
572 " Prepare a buffer-local, incomplete variant of properties, relying on
573 " "ftplugin/java.vim" to take care of merging in unique entries, if any,
574 " from "g:spotbugs_properties".
575 let b:spotbugs_properties = {
576 \ 'PreCompilerTestAction': function('g:SpotBugsPreTestLocalAction'),
577 \ }
578 call assert_equal('java', &l:filetype)
579 call assert_true(exists('#java_spotbugs'))
580 call assert_true(exists('#java_spotbugs#Syntax'))
581 call assert_true(exists('#java_spotbugs#User'))
582 call assert_fails('doautocmd java_spotbugs Syntax', 'Oops')
583 call assert_false(exists('#java_spotbugs#Syntax'))
584 " No match: "test_file !~# 'Xspotbugs/src'".
585 call assert_false(s:spotbugs_results.preActionDone)
586 " A match: "test_file =~# 'tests'".
587 call assert_true(s:spotbugs_results.preTestActionDone)
588 call assert_false(s:spotbugs_results.preTestLocalActionDone)
589 " No action after pre-failure (the thrown "Oops" doesn't qualify for ":cc").
590 call assert_false(s:spotbugs_results.postActionDone)
591 " No ":compiler spotbugs" will be run after pre-failure.
592 call assert_true(empty(&l:makeprg))
593
594 let s:spotbugs_results.preActionDone = 0
595 let s:spotbugs_results.preTestActionDone = 0
596 let s:spotbugs_results.preTestLocalActionDone = 0
597 let s:spotbugs_results.postActionDone = 0
598 " XXX: Re-build ":autocmd"s from scratch with buffer-local values applied.
599 doautocmd FileType
600
601 call assert_true(exists('b:spotbugs_syntax_once'))
602 doautocmd java_spotbugs User
603 " No match: "test_file !~# 'Xspotbugs/src'".
604 call assert_false(s:spotbugs_results.preActionDone)
605 " A match: "test_file =~# 'tests'".
606 call assert_true(s:spotbugs_results.preTestLocalActionDone)
607 call assert_false(s:spotbugs_results.preTestActionDone)
608 " For a pre-match, a post-action.
609 call assert_true(s:spotbugs_results.postActionDone)
610
611 " With a match, confirm that ":compiler spotbugs" has run.
612 if has('win32')
613 call assert_match('^spotbugs\.bat\s', &l:makeprg)
614 else
615 call assert_match('^spotbugs\s', &l:makeprg)
616 endif
617
618 setlocal makeprg=
619 let s:spotbugs_results.preActionDone = 0
620 let s:spotbugs_results.preTestActionDone = 0
621 let s:spotbugs_results.preTestLocalActionDone = 0
622 let s:spotbugs_results.postActionDone = 0
623 let s:spotbugs_results.preCommandArguments = ''
624 let s:spotbugs_results.preTestCommandArguments = ''
625 let s:spotbugs_results.postCommandArguments = ''
626 " XXX: Compose the assigned "*Command"s with the default Maven "*Action"s.
627 let b:spotbugs_properties = {
628 \ 'compiler': 'maven',
629 \ 'DefaultPreCompilerTestCommand': function('g:SpotBugsPreTestCommand'),
630 \ 'DefaultPreCompilerCommand': function('g:SpotBugsPreCommand'),
631 \ 'DefaultPostCompilerCommand': function('g:SpotBugsPostCommand'),
Aliaksei Budavei2e252472024-12-27 16:46:36 +0100632 \ 'PostCompilerActionExecutor': function('g:SpotBugsPostCompilerActionExecutor'),
633 \ 'augroupForPostCompilerAction': 'java_spotbugs_test',
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100634 \ 'sourceDirPath': ['Xspotbugs/src'],
635 \ 'classDirPath': ['Xspotbugs/src'],
636 \ 'testSourceDirPath': ['tests'],
637 \ 'testClassDirPath': ['tests'],
638 \ }
639 unlet g:spotbugs_properties
640 " XXX: Re-build ":autocmd"s from scratch with buffer-local values applied.
641 call s:SpotBugsBeforeFileTypeTryPluginAndClearCache({
642 \ 'compiler': b:spotbugs_properties.compiler,
643 \ 'commands': {
644 \ 'DefaultPreCompilerTestCommand':
645 \ b:spotbugs_properties.DefaultPreCompilerTestCommand,
646 \ 'DefaultPreCompilerCommand':
647 \ b:spotbugs_properties.DefaultPreCompilerCommand,
648 \ 'DefaultPostCompilerCommand':
649 \ b:spotbugs_properties.DefaultPostCompilerCommand,
650 \ },
651 \ })
652 doautocmd FileType
653
654 call assert_equal('maven', g:spotbugs#state.compiler)
655 call assert_equal(sort([
656 \ 'DefaultPreCompilerTestCommand',
657 \ 'DefaultPreCompilerCommand',
658 \ 'DefaultPostCompilerCommand',
659 \ ]),
660 \ sort(keys(g:spotbugs#state.commands)))
661 call assert_true(exists('b:spotbugs_syntax_once'))
662 doautocmd java_spotbugs User
663 " No match: "test_file !~# 'Xspotbugs/src'".
664 call assert_false(s:spotbugs_results.preActionDone)
665 call assert_true(empty(s:spotbugs_results.preCommandArguments))
666 " A match: "test_file =~# 'tests'".
667 call assert_true(s:spotbugs_results.preTestActionDone)
668 call assert_equal('test-compile', s:spotbugs_results.preTestCommandArguments)
669 " For a pre-match, a post-action.
670 call assert_true(s:spotbugs_results.postActionDone)
671 call assert_equal('%:S', s:spotbugs_results.postCommandArguments)
672
673 " With a match, confirm that ":compiler spotbugs" has run.
674 if has('win32')
675 call assert_match('^spotbugs\.bat\s', &l:makeprg)
676 else
677 call assert_match('^spotbugs\s', &l:makeprg)
678 endif
679
Aliaksei Budavei2e252472024-12-27 16:46:36 +0100680 setlocal makeprg=
681 let s:spotbugs_results.preActionDone = 0
682 let s:spotbugs_results.preTestActionOtherDone = 0
683 let s:spotbugs_results.preTestLocalActionDone = 0
684 let s:spotbugs_results.postActionDone = 0
685 let s:spotbugs_results.preCommandArguments = ''
686 let s:spotbugs_results.preTestCommandArguments = ''
687 let s:spotbugs_results.postCommandArguments = ''
688
689 " When "PostCompilerActionExecutor", "Pre*Action" and/or "Pre*TestAction",
690 " and "Post*Action" are available, "#java_spotbugs_post" must be defined.
691 call assert_true(exists('#java_spotbugs_post'))
692 call assert_true(exists('#java_spotbugs_post#User'))
693 call assert_false(exists('#java_spotbugs_post#ShellCmdPost'))
694 call assert_false(exists('#java_spotbugs_test#ShellCmdPost'))
695
696 " Re-link a Funcref on the fly.
697 func! g:SpotBugsPreTestCommand(arguments) abort
698 let s:spotbugs_results.preTestActionOtherDone = 1
699 let s:spotbugs_results.preTestCommandArguments = a:arguments
700 " Define a once-only ":autocmd" for "#java_spotbugs_test#ShellCmdPost".
701 doautocmd java_spotbugs_post User
702 " XXX: Do NOT use ":cc" to notify the spotbugs compiler about success or
703 " failure, and assume the transfer of control to a ShellCmdPost command.
704 endfunc
705
706 doautocmd java_spotbugs User
707 " No match: "test_file !~# 'Xspotbugs/src'".
708 call assert_false(s:spotbugs_results.preActionDone)
709 call assert_true(empty(s:spotbugs_results.preCommandArguments))
710 " A match: "test_file =~# 'tests'".
711 call assert_true(s:spotbugs_results.preTestActionOtherDone)
712 call assert_equal('test-compile', s:spotbugs_results.preTestCommandArguments)
713 " For a pre-match, no post-action (without ":cc") UNLESS a ShellCmdPost
714 " event is consumed whose command will invoke "PostCompilerActionExecutor"
715 " and the latter will accept a post-compiler action argument.
716 call assert_false(s:spotbugs_results.postActionDone)
717 call assert_true(exists('#java_spotbugs_test#ShellCmdPost'))
718 doautocmd ShellCmdPost
719 call assert_false(exists('#java_spotbugs_test#ShellCmdPost'))
720 call assert_true(s:spotbugs_results.postActionDone)
721 call assert_equal('%:S', s:spotbugs_results.postCommandArguments)
722
723 " With a match, confirm that ":compiler spotbugs" has run.
724 if has('win32')
725 call assert_match('^spotbugs\.bat\s', &l:makeprg)
726 else
727 call assert_match('^spotbugs\s', &l:makeprg)
728 endif
729
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100730 bwipeout
731 setlocal makeprg=
zeertzjq23da16d2025-02-03 18:53:28 +0100732 let $PATH = save_PATH
Aliaksei Budavei368ef5a2024-12-16 21:37:54 +0100733 endif
734
735 filetype plugin off
736 setlocal makeprg=
737 let &shellslash = save_shellslash
738endfunc
739
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200740" vim: shiftwidth=2 sts=2 expandtab