]> git.madduck.net Git - etc/vim.git/blob - ale_linters/d/dmd.vim

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

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.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

Squashed '.vim/bundle/ale/' content from commit 22185c4c
[etc/vim.git] / ale_linters / d / dmd.vim
1 " Author: w0rp <devw0rp@gmail.com>
2 " Description: "dmd for D files"
3
4 function! s:GetDUBCommand(buffer) abort
5     " If we can't run dub, then skip this command.
6     if executable('dub')
7         " Returning an empty string skips to the DMD command.
8         let l:config = ale#d#FindDUBConfig(a:buffer)
9
10         " To support older dub versions, we just change the directory to the
11         " directory where we found the dub config, and then run `dub describe`
12         " from that directory.
13         if !empty(l:config)
14             return [fnamemodify(l:config, ':h'), 'dub describe --data-list
15             \ --data=import-paths
16             \ --data=string-import-paths
17             \ --data=versions
18             \ --data=debug-versions
19             \']
20         endif
21     endif
22
23     return ['', '']
24 endfunction
25
26 function! ale_linters#d#dmd#RunDUBCommand(buffer) abort
27     let [l:cwd, l:command] = s:GetDUBCommand(a:buffer)
28
29     if empty(l:command)
30         " If we can't run DUB, just run DMD.
31         return ale_linters#d#dmd#DMDCommand(a:buffer, [], {})
32     endif
33
34     return ale#command#Run(
35     \   a:buffer,
36     \   l:command,
37     \   function('ale_linters#d#dmd#DMDCommand'),
38     \   {'cwd': l:cwd},
39     \)
40 endfunction
41
42 function! ale_linters#d#dmd#DMDCommand(buffer, dub_output, meta) abort
43     let l:import_list = []
44     let l:str_import_list = []
45     let l:versions_list = []
46     let l:deb_versions_list = []
47     let l:list_ind = 1
48     let l:seen_line = 0
49
50     " Build a list of options generated from DUB, if available.
51     " DUB output each path or version on a single line.
52     " Each list is separated by a blank line.
53     " Empty list are represented by a blank line (followed and/or
54     " preceded by a separation blank line)
55     for l:line in a:dub_output
56         " line still has end of line char on windows
57         let l:line = substitute(l:line, '[\r\n]*$', '', '')
58
59         if !empty(l:line)
60             if l:list_ind == 1
61                 call add(l:import_list, '-I' . ale#Escape(l:line))
62             elseif l:list_ind == 2
63                 call add(l:str_import_list, '-J' . ale#Escape(l:line))
64             elseif l:list_ind == 3
65                 call add(l:versions_list, '-version=' . ale#Escape(l:line))
66             elseif l:list_ind == 4
67                 call add(l:deb_versions_list, '-debug=' . ale#Escape(l:line))
68             endif
69
70             let l:seen_line = 1
71         elseif !l:seen_line
72             " if list is empty must skip one empty line
73             let l:seen_line = 1
74         else
75             let l:seen_line = 0
76             let l:list_ind += 1
77         endif
78     endfor
79
80     return 'dmd ' . join(l:import_list) . ' ' .
81     \   join(l:str_import_list) . ' ' .
82     \   join(l:versions_list) . ' ' .
83     \   join(l:deb_versions_list) . ' -o- -wi -vcolumns -c %t'
84 endfunction
85
86 function! ale_linters#d#dmd#Handle(buffer, lines) abort
87     " Matches patterns lines like the following:
88     " /tmp/tmp.qclsa7qLP7/file.d(1): Error: function declaration without return type. (Note that constructors are always named 'this')
89     " /tmp/tmp.G1L5xIizvB.d(8,8): Error: module weak_reference is in file 'dstruct/weak_reference.d' which cannot be read
90     let l:pattern = '\v^(\f+)\((\d+)(,(\d+))?\): (\w+): (.+)$'
91     let l:output = []
92     let l:dir = expand('#' . a:buffer . ':p:h')
93
94     for l:match in ale#util#GetMatches(a:lines, l:pattern)
95         " If dmd was invoked with relative path, match[1] is relative, otherwise it is absolute.
96         " As we invoke dmd with the buffer path (in /tmp), this will generally be absolute already
97         let l:fname = ale#path#GetAbsPath(l:dir, l:match[1])
98         call add(l:output, {
99         \   'filename': l:fname,
100         \   'lnum': l:match[2],
101         \   'col': l:match[4],
102         \   'type': l:match[5] is# 'Warning' || l:match[5] is# 'Deprecation' ? 'W' : 'E',
103         \   'text': l:match[6],
104         \})
105     endfor
106
107     return l:output
108 endfunction
109
110 call ale#linter#Define('d', {
111 \   'name': 'dmd',
112 \   'executable': 'dmd',
113 \   'command': function('ale_linters#d#dmd#RunDUBCommand'),
114 \   'callback': 'ale_linters#d#dmd#Handle',
115 \   'output_stream': 'stderr',
116 \})