Reporters
A reporter turns CoffeeLint's findings into output. The default reporter is designed for people reading a terminal; the others produce CSV, XML, or JSON for editors, CI servers, and code-quality dashboards. You can also write your own. This page shows the output of each built-in reporter for the same input and explains how to build a custom one.
Selecting a Reporter
coffeelint --reporter <name> src
| Name | Format | Typical use |
|---|---|---|
default |
Human-readable text | Terminals |
csv |
Comma-separated values | Spreadsheets, simple scripts |
jslint |
JSLint-style XML | Tools that understand JSLint reports |
checkstyle |
Checkstyle XML | CI servers and quality dashboards |
raw |
JSON | Custom tooling |
Every built-in reporter honors -q/--quiet by leaving out warnings. The exit code is computed independently of the reporter: it is 1 whenever any error-level finding exists. See Command-Line Usage.
The examples below lint this file, cart.coffee, with the default configuration:
class shoppingCart
constructor: ->
@items = []
add: (item) ->
@items.push(item);
debugger
default
✗ cart.coffee
✗ #1: Class name should be UpperCamelCased. class name: shoppingCart.
✗ #6: Line contains a trailing semicolon.
⚡ #7: Found debugging code. found 'STATEMENT'.
✗ Lint! » 2 errors and 1 warning in 1 file
- Each file gets a header line with an overall status symbol:
✓(clean),⚡(warnings only), or✗(errors). - Each finding shows its symbol, the line number (or a range such as
#12-48for findings that span lines, likecyclomatic_complexity), the rule's message, and the optional context. - The summary starts with
✓ Ok!,⚡ Warning!, or✗ Lint!. - Colors are applied when the output is a terminal, or as forced by
--color. - With
-q, files without errors are omitted, and nothing at all is printed when there are no errors.
csv
path,lineNumber,lineNumberEnd,level,message
cart.coffee,1,,error,Class name should be UpperCamelCased class name: shoppingCart.
cart.coffee,6,,error,Line contains a trailing semicolon
cart.coffee,7,,warn,Found debugging code found 'STATEMENT'.
- The header row is always printed.
lineNumberEndis empty unless the finding spans several lines.- The context, when present, is appended to the message.
Warning: Fields are not quoted or escaped. A message or path that contains a comma will shift the columns, so use
rawor one of the XML formats when you need robust parsing.
jslint
<?xml version="1.0" encoding="utf-8"?><jslint>
<file name="cart.coffee">
<issue line="1"
lineEnd="1"
reason="[error] Class name should be UpperCamelCased"
evidence="class name: shoppingCart"/>
<issue line="6"
lineEnd="6"
reason="[error] Line contains a trailing semicolon"
evidence="undefined"/>
<issue line="7"
lineEnd="7"
reason="[warn] Found debugging code"
evidence="found 'STATEMENT'"/>
</file>
</jslint>
- Only files with findings get a
<file>element. lineEndfalls back tolinewhen the finding does not span lines.- The level is embedded in
reasonas a[error]or[warn]prefix. - The context goes into
evidence. When a finding has no context,evidencecontains the literal textundefined. - XML special characters (
&,",<,>,') are escaped.
checkstyle
<?xml version="1.0" encoding="utf-8"?>
<checkstyle version="4.3">
<file name="cart.coffee">
<error line="1"
severity="error"
message="Class name should be UpperCamelCased; context: class name: shoppingCart"
source="coffeelint"/>
<error line="6"
severity="error"
message="Line contains a trailing semicolon; context: "
source="coffeelint"/>
<error line="7"
severity="warning"
message="Found debugging code; context: found 'STATEMENT'"
source="coffeelint"/>
</file>
</checkstyle>
- The format declares Checkstyle version 4.3, which most CI plugins accept.
warnis translated to Checkstyle'swarningseverity.- The message always has the form
<message>; context: <context>, with an empty context when there is none. sourceis alwayscoffeelint.
raw
The raw reporter prints a JSON object mapping each path to its array of findings, indented with two spaces. Each finding is the complete error object CoffeeLint produced (see API Reference), including the rule's name, level, message, description, and options. For example (the description is shortened here):
{
"cart.coffee": [
{
"name": "no_trailing_semicolons",
"level": "error",
"message": "Line contains a trailing semicolon",
"description": "This rule prohibits trailing semicolons...",
"lineNumber": 6,
"rule": "no_trailing_semicolons"
}
]
}
Findings from token-based rules also include a line property with the source line. Because raw is valid JSON and includes everything, it is the best starting point for custom tooling.
Writing a Custom Reporter
A reporter is a class (or constructor function) that CoffeeLint instantiates with new and then calls publish() on:
new Reporter(errorReport, { colorize: Boolean, quiet: Boolean })
reporter.publish()
errorReportis anErrorReportinstance. Itspathsproperty maps each linted path to an array of error objects, and it offers helpers such asgetSummary(),pathHasError(path), andhasError(). See the API Reference.colorizereflects--colorand whether the output is a terminal.quietistruewhen-qwas given; respect it by skipping warnings.
Example: A One-Line Summary (CoffeeScript)
# summary_reporter.coffee
module.exports = class SummaryReporter
constructor: (@errorReport, options = {}) ->
{ @quiet } = options
publish: ->
{ errorCount, warningCount, pathCount } = @errorReport.getSummary()
# coffeelint: disable=no_debugger
console.log "#{pathCount} files: #{errorCount} errors, #{warningCount} warnings"
# coffeelint: enable=no_debugger
coffeelint --reporter ./summary_reporter.coffee src
Example: CI Annotations (JavaScript)
This reporter prints one line per finding in the ::error file=...,line=...::message format that GitHub Actions turns into inline annotations:
// annotations-reporter.js
class AnnotationsReporter {
constructor(errorReport, options) {
this.errorReport = errorReport;
this.quiet = Boolean(options && options.quiet);
}
publish() {
const paths = this.errorReport.paths;
for (const path of Object.keys(paths)) {
for (const e of paths[path]) {
if (this.quiet && e.level !== 'error') continue;
const kind = e.level === 'error' ? 'error' : 'warning';
const detail = e.context ? `${e.message} (${e.context})` : e.message;
console.log(`::${kind} file=${path},line=${e.lineNumber}::[${e.rule}] ${detail}`);
}
}
}
}
module.exports = AnnotationsReporter;
coffeelint --reporter ./annotations-reporter.js src
How Reporter Names Are Resolved
If the --reporter value is not a built-in name, CoffeeLint resolves it from the current working directory, trying the extensions .js, .coffee, .litcoffee, and .coffee.md. This works for both relative paths (./reporters/mine) and the names of reporter packages installed in your project. If resolution fails, the value is passed to require as-is. Since the command-line tool registers the CoffeeScript compiler, reporters written in CoffeeScript load without a build step.
Best Practices
- Use
checkstylefor CI dashboards andrawfor scripts. Avoid parsing the default output, which is meant for people and may contain color codes. - Redirect machine-readable output to a file (
> report.xml) so that logs and reports stay separate. - Combine
-qwith any reporter to focus CI output on blocking problems.