]> git.madduck.net Git - etc/vim.git/blobdiff - .vim/bundle/ale/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:

Merge commit '76265755a1add77121c8f9dabb3e9bb70fe9a972' as '.vim/bundle/ale'
[etc/vim.git] / .vim / bundle / ale / ale_linters / d / dmd.vim
diff --git a/.vim/bundle/ale/ale_linters/d/dmd.vim b/.vim/bundle/ale/ale_linters/d/dmd.vim
new file mode 100644 (file)
index 0000000..f38e812
--- /dev/null
@@ -0,0 +1,116 @@
+" Author: w0rp <devw0rp@gmail.com>
+" Description: "dmd for D files"
+
+function! s:GetDUBCommand(buffer) abort
+    " If we can't run dub, then skip this command.
+    if executable('dub')
+        " Returning an empty string skips to the DMD command.
+        let l:config = ale#d#FindDUBConfig(a:buffer)
+
+        " To support older dub versions, we just change the directory to the
+        " directory where we found the dub config, and then run `dub describe`
+        " from that directory.
+        if !empty(l:config)
+            return [fnamemodify(l:config, ':h'), 'dub describe --data-list
+            \ --data=import-paths
+            \ --data=string-import-paths
+            \ --data=versions
+            \ --data=debug-versions
+            \']
+        endif
+    endif
+
+    return ['', '']
+endfunction
+
+function! ale_linters#d#dmd#RunDUBCommand(buffer) abort
+    let [l:cwd, l:command] = s:GetDUBCommand(a:buffer)
+
+    if empty(l:command)
+        " If we can't run DUB, just run DMD.
+        return ale_linters#d#dmd#DMDCommand(a:buffer, [], {})
+    endif
+
+    return ale#command#Run(
+    \   a:buffer,
+    \   l:command,
+    \   function('ale_linters#d#dmd#DMDCommand'),
+    \   {'cwd': l:cwd},
+    \)
+endfunction
+
+function! ale_linters#d#dmd#DMDCommand(buffer, dub_output, meta) abort
+    let l:import_list = []
+    let l:str_import_list = []
+    let l:versions_list = []
+    let l:deb_versions_list = []
+    let l:list_ind = 1
+    let l:seen_line = 0
+
+    " Build a list of options generated from DUB, if available.
+    " DUB output each path or version on a single line.
+    " Each list is separated by a blank line.
+    " Empty list are represented by a blank line (followed and/or
+    " preceded by a separation blank line)
+    for l:line in a:dub_output
+        " line still has end of line char on windows
+        let l:line = substitute(l:line, '[\r\n]*$', '', '')
+
+        if !empty(l:line)
+            if l:list_ind == 1
+                call add(l:import_list, '-I' . ale#Escape(l:line))
+            elseif l:list_ind == 2
+                call add(l:str_import_list, '-J' . ale#Escape(l:line))
+            elseif l:list_ind == 3
+                call add(l:versions_list, '-version=' . ale#Escape(l:line))
+            elseif l:list_ind == 4
+                call add(l:deb_versions_list, '-debug=' . ale#Escape(l:line))
+            endif
+
+            let l:seen_line = 1
+        elseif !l:seen_line
+            " if list is empty must skip one empty line
+            let l:seen_line = 1
+        else
+            let l:seen_line = 0
+            let l:list_ind += 1
+        endif
+    endfor
+
+    return 'dmd ' . join(l:import_list) . ' ' .
+    \   join(l:str_import_list) . ' ' .
+    \   join(l:versions_list) . ' ' .
+    \   join(l:deb_versions_list) . ' -o- -wi -vcolumns -c %t'
+endfunction
+
+function! ale_linters#d#dmd#Handle(buffer, lines) abort
+    " Matches patterns lines like the following:
+    " /tmp/tmp.qclsa7qLP7/file.d(1): Error: function declaration without return type. (Note that constructors are always named 'this')
+    " /tmp/tmp.G1L5xIizvB.d(8,8): Error: module weak_reference is in file 'dstruct/weak_reference.d' which cannot be read
+    let l:pattern = '\v^(\f+)\((\d+)(,(\d+))?\): (\w+): (.+)$'
+    let l:output = []
+    let l:dir = expand('#' . a:buffer . ':p:h')
+
+    for l:match in ale#util#GetMatches(a:lines, l:pattern)
+        " If dmd was invoked with relative path, match[1] is relative, otherwise it is absolute.
+        " As we invoke dmd with the buffer path (in /tmp), this will generally be absolute already
+        let l:fname = ale#path#GetAbsPath(l:dir, l:match[1])
+        call add(l:output, {
+        \   'filename': l:fname,
+        \   'lnum': l:match[2],
+        \   'col': l:match[4],
+        \   'type': l:match[5] is# 'Warning' || l:match[5] is# 'Deprecation' ? 'W' : 'E',
+        \   'text': l:match[6],
+        \})
+    endfor
+
+    return l:output
+endfunction
+
+call ale#linter#Define('d', {
+\   'name': 'dmd',
+\   'executable': 'dmd',
+\   'command': function('ale_linters#d#dmd#RunDUBCommand'),
+\   'callback': 'ale_linters#d#dmd#Handle',
+\   'output_stream': 'stderr',
+\})