Skip to content

Commit 0e87b5c

Browse files
vitorbalilyavolodin
authored andcommitted
New: Codeframe formatter (fixes #5860) (#7437)
0 parents  commit 0e87b5c

File tree

2 files changed

+445
-0
lines changed

2 files changed

+445
-0
lines changed

index.js

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/**
2+
* @fileoverview Codeframe reporter
3+
* @author Vitor Balocco
4+
*/
5+
"use strict";
6+
7+
const chalk = require("chalk");
8+
const codeFrame = require("babel-code-frame");
9+
const path = require("path");
10+
11+
//------------------------------------------------------------------------------
12+
// Helpers
13+
//------------------------------------------------------------------------------
14+
15+
/**
16+
* Given a word and a count, append an s if count is not one.
17+
* @param {string} word A word in its singular form.
18+
* @param {number} count A number controlling whether word should be pluralized.
19+
* @returns {string} The original word with an s on the end if count is not one.
20+
*/
21+
function pluralize(word, count) {
22+
return (count === 1 ? word : `${word}s`);
23+
}
24+
25+
/**
26+
* Gets a formatted relative file path from an absolute path and a line/column in the file.
27+
* @param {string} filePath The absolute file path to format.
28+
* @param {number} line The line from the file to use for formatting.
29+
* @param {number} column The column from the file to use for formatting.
30+
* @returns {string} The formatted file path.
31+
*/
32+
function formatFilePath(filePath, line, column) {
33+
let relPath = path.relative(process.cwd(), filePath);
34+
35+
if (line && column) {
36+
relPath += `:${line}:${column}`;
37+
}
38+
39+
return chalk.green(relPath);
40+
}
41+
42+
/**
43+
* Gets the formatted output for a given message.
44+
* @param {Object} message The object that represents this message.
45+
* @param {Object} parentResult The result object that this message belongs to.
46+
* @returns {string} The formatted output.
47+
*/
48+
function formatMessage(message, parentResult) {
49+
const type = (message.fatal || message.severity === 2) ? chalk.red("error") : chalk.yellow("warning");
50+
const msg = `${chalk.bold(message.message.replace(/\.$/, ""))}`;
51+
const ruleId = message.fatal ? "" : chalk.dim(`(${message.ruleId})`);
52+
const filePath = formatFilePath(parentResult.filePath, message.line, message.column);
53+
const sourceCode = parentResult.output ? parentResult.output : parentResult.source;
54+
55+
const firstLine = [
56+
`${type}:`,
57+
`${msg}`,
58+
ruleId ? `${ruleId}` : "",
59+
sourceCode ? `at ${filePath}:` : `at ${filePath}`,
60+
].filter(String).join(" ");
61+
62+
const result = [ firstLine ];
63+
64+
if (sourceCode) {
65+
result.push(
66+
codeFrame(sourceCode, message.line, message.column, { highlightCode: false })
67+
);
68+
}
69+
70+
return result.join("\n");
71+
}
72+
73+
/**
74+
* Gets the formatted output summary for a given number of errors and warnings.
75+
* @param {number} errors The number of errors.
76+
* @param {number} warnings The number of warnings.
77+
* @returns {string} The formatted output summary.
78+
*/
79+
function formatSummary(errors, warnings) {
80+
const summaryColor = errors > 0 ? "red" : "yellow";
81+
const summary = [];
82+
83+
if (errors > 0) {
84+
summary.push(`${errors} ${pluralize("error", errors)}`);
85+
}
86+
87+
if (warnings > 0) {
88+
summary.push(`${warnings} ${pluralize("warning", warnings)}`);
89+
}
90+
91+
return chalk[summaryColor].bold(`${summary.join(" and ")} found.`);
92+
}
93+
94+
//------------------------------------------------------------------------------
95+
// Public Interface
96+
//------------------------------------------------------------------------------
97+
98+
module.exports = function(results) {
99+
let errors = 0;
100+
let warnings = 0;
101+
const resultsWithMessages = results.filter(result => result.messages.length > 0);
102+
103+
let output = resultsWithMessages.reduce((resultsOutput, result) => {
104+
const messages = result.messages.map(message => {
105+
if (message.fatal || message.severity === 2) {
106+
errors++;
107+
} else {
108+
warnings++;
109+
}
110+
111+
return `${formatMessage(message, result)}\n\n`;
112+
});
113+
114+
return resultsOutput.concat(messages);
115+
}, []).join("\n");
116+
117+
output += "\n";
118+
output += formatSummary(errors, warnings);
119+
120+
return (errors + warnings) > 0 ? output : "";
121+
};

0 commit comments

Comments
 (0)