dense-analysis / ale

Check syntax in Vim/Neovim asynchronously and fix files, with Language Server Protocol (LSP) support
BSD 2-Clause "Simplified" License
13.55k stars 1.44k forks source link

msgfmt linter should check format strings as well #3729

Open kovidgoyal opened 3 years ago

kovidgoyal commented 3 years ago

The msgfmt tool has the ability to check language dependent format strings in .po files. This feature is activated by --check-format. An example showing some error messages

msgfmt --check-format sv.po                                                                                                          
sv.po:465: a format specification for argument '0' doesn't exist in 'msgstr'
sv.po:474: number of format specifications in 'msgid' and 'msgstr' does not match
msgfmt: found 2 fatal errors
kovidgoyal commented 3 years ago

And here is a patch to implement it:

diff --git a/ale_linters/po/msgfmt.vim b/ale_linters/po/msgfmt.vim
index 8279ccdc..17ccb5c1 100644
--- a/ale_linters/po/msgfmt.vim
+++ b/ale_linters/po/msgfmt.vim
@@ -2,29 +2,27 @@
 " Description: msgfmt for PO files

 function! ale_linters#po#msgfmt#Handle(buffer, lines) abort
-    let l:results = ale#handlers#unix#HandleAsWarning(a:buffer, a:lines)
-    let l:index = 0
+    " Example output:
+    " /tmp/vpqkkrq/1/sv.po:465: a format specification for argument '0' doesn't exist in 'msgstr'
+    let l:pattern = '^[^:]\+:\(\d\+\):\(.\+\)'
+    let l:output = []

-    for l:item in l:results
-        if l:index > 0 && l:item.text =~? 'this is the location of the first definition'
-            let l:last_item = l:results[l:index - 1]
-
-            if l:last_item.text =~? 'duplicate message definition'
-                let l:last_item.text = 'duplicate of message at line ' . l:item.lnum
-                let l:item.text = 'first location of duplicate of message at line ' . l:last_item.lnum
-            endif
-        endif
-
-        let l:index += 1
+    for l:match in ale#util#GetMatches(a:lines, l:pattern)
+        call add(l:output, {
+        \   'lnum': l:match[1] + 0,
+        \   'text': l:match[2],
+        \   'type': 'E',
+        \})
     endfor

-    return l:results
+    return l:output
+
 endfunction

 call ale#linter#Define('po', {
 \   'name': 'msgfmt',
 \   'executable': 'msgfmt',
 \   'output_stream': 'stderr',
-\   'command': 'msgfmt --statistics --output-file=- %t',
+\   'command': 'msgfmt --check-format --output-file=- %t',
 \   'callback': 'ale_linters#po#msgfmt#Handle',
 \})