vimerrorformat

errorformat where the type is in the middle of the message


Given a C# compiler message like this, when warnings-as-errors is turned on:

File.cs(3,1415): error CS1572: Warning as Error: XML comment on 'FooLibrary.Foo.Foo()' has a param tag for 'foo', but there is no parameter by that name

I would like to have my errorformat marking it as type warning rather than type error.

I already have such values in my errorformat as:

%f(%l\\,%c):\ %trror\ %m^M
%f(%l\\,%c):\ %trror\ %m

(Whenever you see ^M, know that it is the actual control code in my file, but it doesn't transmit well to the web. Suffice it to indicate that the C# compiler outputs \r\n rather than just \n, and this is a Mild Nuisance.)

Here is what I first tried:

%f(%l\\,%c):\ error\ %m: %tarning\ as\ Error:\ %m^M
%f(%l\\,%c):\ error\ %m: %tarning\ as\ Error:\ %m

Vim bemoaned the fact that it couldn't deal with multiple occurrences of %m in the one string.

So then I started getting fancy with unusual regular expressions incorporating assertions. Here is what I tried:

%f(%l\\,%c):\ error\ %\\(%[A-Z0-9]%#:\ %tarning\ as\ Error:\ %[%^^M]%#%\\)%\\@=%m^M
%f(%l\\,%c):\ error\ %\\(%[A-Z0-9]%#:\ %tarning\ as\ Error:\ %[%^^M]%#%\\)%\\@=%m

This didn't work; it gets type "C" (presumably from "CS1572") and message "W" (the value which %t should be consuming). (In some other experimentation, omitting the %t, it proved necessary to consume the rest of the string inside the assertion, or else it stopped its match of %m at that point. Very strange.)

Perceiving that it was not treating them as regular expression groups, as they might be, but rather in a peculiar linear manner, I then tried reversing the assertions and wound up with this:

%f(%l\\,%c):\ error\ %\\(%m^M%\\)%\\@=%[A-Z0-9]%#:\ %tarning\ as\ Error:\ %.%#^M
%f(%l\\,%c):\ error\ %\\(%m^M%\\)%\\@=%[A-Z0-9]%#:\ %tarning\ as\ Error:\ %.%#

Unfortunately, these also fail, getting type "C" rather than "warning" and (though getting the message intact, at last) leaving the ^M on the end of the string.

I've exhausted the possibilities that I can think of inside the errorformat command; is there aught else which might resolve this matter, or would I need to resort to running another script to wrap it which would turn the format into something that Vim could cope with?

(All that for getting the word "warning" rather than "error" in the quickfix list. Sad, isn't it?)


Solution

  • If you are not fine with

    set efm=%f(%l\\,%c):\ error\ %[A-Z0-9]%#:\ %tarning\ as\ Error:\ %m
    

    which will drop error number then I can suggest you using

    set efm=%f(%l\\,%c):\ %m
    

    and post-processing the list with

    function QFPostProc(location)
        let qflist=[]
        for entry in (a:location?getloclist(0):getqflist())
            " Using the fact that “%tarning” can match only warnings 
            " thus unconditionally setting type to 'W'
    
            " Replace 'W' with something like
            "     matchstr(entry.text, '\u\ze\a\+ as Error')
            " if this is not true.
            call add(qflist, extend(entry, {'type': 'W'}))
        endfor
        if a:location
            call setloclist(0, qflist, 'r')
        else
            call setqflist(qflist, 'r')
        endif
    endfunction
    

    . This should be called like

    :make | call QFPostProc(0)
    

    or

    :lmake | call QFPostProc(1)