You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
138 lines
4.7 KiB
138 lines
4.7 KiB
/** |
|
* @fileoverview Codeframe reporter |
|
* @author Vitor Balocco |
|
*/ |
|
"use strict"; |
|
|
|
const chalk = require("chalk"); |
|
const { codeFrameColumns } = require("@babel/code-frame"); |
|
const path = require("path"); |
|
|
|
//------------------------------------------------------------------------------ |
|
// Helpers |
|
//------------------------------------------------------------------------------ |
|
|
|
/** |
|
* Given a word and a count, append an s if count is not one. |
|
* @param {string} word A word in its singular form. |
|
* @param {number} count A number controlling whether word should be pluralized. |
|
* @returns {string} The original word with an s on the end if count is not one. |
|
*/ |
|
function pluralize(word, count) { |
|
return (count === 1 ? word : `${word}s`); |
|
} |
|
|
|
/** |
|
* Gets a formatted relative file path from an absolute path and a line/column in the file. |
|
* @param {string} filePath The absolute file path to format. |
|
* @param {number} line The line from the file to use for formatting. |
|
* @param {number} column The column from the file to use for formatting. |
|
* @returns {string} The formatted file path. |
|
*/ |
|
function formatFilePath(filePath, line, column) { |
|
let relPath = path.relative(process.cwd(), filePath); |
|
|
|
if (line && column) { |
|
relPath += `:${line}:${column}`; |
|
} |
|
|
|
return chalk.green(relPath); |
|
} |
|
|
|
/** |
|
* Gets the formatted output for a given message. |
|
* @param {Object} message The object that represents this message. |
|
* @param {Object} parentResult The result object that this message belongs to. |
|
* @returns {string} The formatted output. |
|
*/ |
|
function formatMessage(message, parentResult) { |
|
const type = (message.fatal || message.severity === 2) ? chalk.red("error") : chalk.yellow("warning"); |
|
const msg = `${chalk.bold(message.message.replace(/([^ ])\.$/u, "$1"))}`; |
|
const ruleId = message.fatal ? "" : chalk.dim(`(${message.ruleId})`); |
|
const filePath = formatFilePath(parentResult.filePath, message.line, message.column); |
|
const sourceCode = parentResult.output ? parentResult.output : parentResult.source; |
|
|
|
const firstLine = [ |
|
`${type}:`, |
|
`${msg}`, |
|
ruleId ? `${ruleId}` : "", |
|
sourceCode ? `at ${filePath}:` : `at ${filePath}` |
|
].filter(String).join(" "); |
|
|
|
const result = [firstLine]; |
|
|
|
if (sourceCode) { |
|
result.push( |
|
codeFrameColumns(sourceCode, { start: { line: message.line, column: message.column } }, { highlightCode: false }) |
|
); |
|
} |
|
|
|
return result.join("\n"); |
|
} |
|
|
|
/** |
|
* Gets the formatted output summary for a given number of errors and warnings. |
|
* @param {number} errors The number of errors. |
|
* @param {number} warnings The number of warnings. |
|
* @param {number} fixableErrors The number of fixable errors. |
|
* @param {number} fixableWarnings The number of fixable warnings. |
|
* @returns {string} The formatted output summary. |
|
*/ |
|
function formatSummary(errors, warnings, fixableErrors, fixableWarnings) { |
|
const summaryColor = errors > 0 ? "red" : "yellow"; |
|
const summary = []; |
|
const fixablesSummary = []; |
|
|
|
if (errors > 0) { |
|
summary.push(`${errors} ${pluralize("error", errors)}`); |
|
} |
|
|
|
if (warnings > 0) { |
|
summary.push(`${warnings} ${pluralize("warning", warnings)}`); |
|
} |
|
|
|
if (fixableErrors > 0) { |
|
fixablesSummary.push(`${fixableErrors} ${pluralize("error", fixableErrors)}`); |
|
} |
|
|
|
if (fixableWarnings > 0) { |
|
fixablesSummary.push(`${fixableWarnings} ${pluralize("warning", fixableWarnings)}`); |
|
} |
|
|
|
let output = chalk[summaryColor].bold(`${summary.join(" and ")} found.`); |
|
|
|
if (fixableErrors || fixableWarnings) { |
|
output += chalk[summaryColor].bold(`\n${fixablesSummary.join(" and ")} potentially fixable with the \`--fix\` option.`); |
|
} |
|
|
|
return output; |
|
} |
|
|
|
//------------------------------------------------------------------------------ |
|
// Public Interface |
|
//------------------------------------------------------------------------------ |
|
|
|
module.exports = function(results) { |
|
let errors = 0; |
|
let warnings = 0; |
|
let fixableErrors = 0; |
|
let fixableWarnings = 0; |
|
|
|
const resultsWithMessages = results.filter(result => result.messages.length > 0); |
|
|
|
let output = resultsWithMessages.reduce((resultsOutput, result) => { |
|
const messages = result.messages.map(message => `${formatMessage(message, result)}\n\n`); |
|
|
|
errors += result.errorCount; |
|
warnings += result.warningCount; |
|
fixableErrors += result.fixableErrorCount; |
|
fixableWarnings += result.fixableWarningCount; |
|
|
|
return resultsOutput.concat(messages); |
|
}, []).join("\n"); |
|
|
|
output += "\n"; |
|
output += formatSummary(errors, warnings, fixableErrors, fixableWarnings); |
|
|
|
return (errors + warnings) > 0 ? output : ""; |
|
};
|
|
|