Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vim errorformat for phpunit

Tags:

vim

phpunit

I'm working on a Vim compiler plugin for PHPUnit.

I've written the following errorformat. The error message is correctly extracted, but file and line numbers are not.

CompilerSet errorformat=%E%n)\ %.%#,
                       \%C%m,
                       \%+C%$,
                       \%C%f:%l,
                       \%Z%$

PHPUnit's output looks something like this:

PHPUnit 3.5.12 by Sebastian Bergmann.

...............................................................  63 / 134 ( 47%)
.........................E.....

Time: 0 seconds, Memory: 11.25Mb

There was 1 error:

1) SomeClassTest::testSomething
Undefined property: SomeClass::$var

/path/to/SomeClass.php:99
/path/to/SomeClassTest.php:15

FAILURES!
Tests: 94, Assertions: 170, Errors: 1.

Press ENTER or type command to continue

I'm happy for the reported file and line to be either the first or last entry in the stack trace. The deepest call is the actual source of the issue. Jumping to the top-level call means I can use to step down into the call stack. I would prefer the latter, SomeClassTest.php:15 in the example above.

like image 777
afternoon Avatar asked Mar 09 '11 11:03

afternoon


1 Answers

I think the problem is the phrasing of the %Z rule. First I came up with this:

:set errorformat=%E%n)\ %.%#,%Z%f:%l,%C%m,%-G%.%#

That'll catch the first filename and associate that with the error message.

For some reason, association the last filename mentioned was a whole lot harder. I wasn't able to do it with efm, but instead hacked together this Python filter:

import sys                                                                  
import re
errors = []
OTHER = 0
MESSAGE = 1
FILE_LINE = 2
next_is = OTHER
lines = sys.stdin.readlines()
for line in lines:
    line = line.strip()
    if (next_is == OTHER):
        if (re.search("^[0-9]+\)", line)):
            next_is = MESSAGE
    elif (next_is == MESSAGE):
        errors.append([line, ''])
        next_is = FILE_LINE
    elif (next_is == FILE_LINE):
        if (re.search("^.+:[0-9]+", line)):
            errors[-1][1] = line
        elif (len(line) == 0 and len(errors[-1][1]) > 0):
            next_is = OTHER

for error in errors:
    print "{0}:{1}".format(error[1], error[0])

This will capture all the errors and output them in a single-line format. The associated filename and line number are the last ones mentioned for the error. This script clobbers all other output, but that'd be solved by adding e.g. a print line after line = line.strip().

like image 129
Ilkka Avatar answered Oct 11 '22 06:10

Ilkka