Bug 1405304 - Add Unix formatter for mozlint. r=ahal

This patch introduces a new report formatter for the mozlint
framework used by "./mach lint" that respects Unix output conventions,
popularised by grep(1), compilers, and preprocessors.

The output format looks like this:

	testing/marionette/driver.js:1153:48: no-unused-vars error: 'resp' is defined but never used.

Many editors (ed, Emacs, vi, Acme) recognise this format, allowing
users to interact with the output like a hyperlink to jump to the
specified location in a file.

MozReview-Commit-ID: 3IyiFmNbtMY

--HG--
extra : rebase_source : a2628a999c187a1c43f3cc5d32e6db835028eca4
This commit is contained in:
Andreas Tolfsen 2017-10-03 14:45:17 +01:00
parent 38aca4f5a9
commit 894334f11e
3 changed files with 49 additions and 0 deletions

View File

@ -10,6 +10,7 @@ from ..result import ResultEncoder
from .compact import CompactFormatter
from .stylish import StylishFormatter
from .treeherder import TreeherderFormatter
from .unix import UnixFormatter
class JSONFormatter(object):
@ -22,6 +23,7 @@ all_formatters = {
'json': JSONFormatter,
'stylish': StylishFormatter,
'treeherder': TreeherderFormatter,
'unix': UnixFormatter,
}

View File

@ -0,0 +1,34 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from __future__ import absolute_import, unicode_literals
import os
from ..result import ResultContainer
class UnixFormatter(object):
"""Formatter that respects Unix output conventions frequently
employed by preprocessors and compilers. The format is
`<FILENAME>:<LINE>[:<COL>]: <RULE> <LEVEL>: <MESSAGE>`.
"""
fmt = "{path}:{lineno}:{column} {rule} {level}: {message}"
def __call__(self, result, **kwargs):
msg = []
for path, errors in sorted(result.iteritems()):
for err in errors:
assert isinstance(err, ResultContainer)
slots = {s: getattr(err, s) for s in err.__slots__}
slots["path"] = os.path.relpath(slots["path"])
slots["column"] = "%d:" % slots["column"] if slots["column"] else ""
slots["rule"] = slots["rule"] or slots["linter"]
msg.append(self.fmt.format(**slots))
return "\n".join(msg)

View File

@ -5,6 +5,7 @@
from __future__ import absolute_import, unicode_literals
import json
import os
from collections import defaultdict
import mozunit
@ -13,6 +14,10 @@ import pytest
from mozlint import ResultContainer
from mozlint import formatters
NORMALISED_PATHS = {
'abc': os.path.normpath('a/b/c.txt'),
'def': os.path.normpath('d/e/f.txt'),
}
EXPECTED = {
'compact': {
@ -48,6 +53,14 @@ TEST-UNEXPECTED-ERROR | a/b/c.txt:4 | oh no baz (baz)
TEST-UNEXPECTED-WARNING | d/e/f.txt:4:2 | oh no bar (bar-not-allowed)
""".strip(),
},
'unix': {
'kwargs': {},
'format': """
{abc}:1: foo error: oh no foo
{abc}:4: baz error: oh no baz
{def}:4:2: bar-not-allowed warning: oh no bar
""".format(**NORMALISED_PATHS).strip(),
},
}