Skip to content

Commit

Permalink
New: Add context.report({ messageId }) (fixes eslint#6740)
Browse files Browse the repository at this point in the history
  • Loading branch information
j-f1 committed Sep 3, 2017
1 parent f9b7544 commit 4479c7b
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 4 deletions.
3 changes: 2 additions & 1 deletion lib/linter.js
Expand Up @@ -942,6 +942,7 @@ class Linter {
this.rules.define(ruleId, ruleCreator);
}

const messageIds = ruleCreator && ruleCreator.meta && ruleCreator.meta.messages;
const severity = getRuleSeverity(config.rules[ruleId]);
const ruleContext = Object.freeze(
Object.assign(
Expand All @@ -950,7 +951,7 @@ class Linter {
id: ruleId,
options: getRuleOptions(config.rules[ruleId]),
report: lodash.flow([
createReportTranslator({ ruleId, severity, sourceCode: this.sourceCode }),
createReportTranslator({ ruleId, severity, sourceCode: this.sourceCode, messageIds }),
problem => {
if (problem.fix && ruleCreator.meta && !ruleCreator.meta.fixable) {
throw new Error("Fixable rules should export a `meta.fixable` property.");
Expand Down
26 changes: 24 additions & 2 deletions lib/report-translator.js
Expand Up @@ -216,6 +216,12 @@ function createProblem(options) {
source: options.sourceLines[options.loc.start.line - 1] || ""
};

// If this isn’t in the conditional, some of the tests fail
// because `messageId` is present in the problem object
if (options.messageId) {
problem.messageId = options.messageId;
}

if (options.loc.end) {
problem.endLine = options.loc.end.line;
problem.endColumn = options.loc.end.column + 1;
Expand All @@ -231,12 +237,13 @@ function createProblem(options) {
/**
* Returns a function that converts the arguments of a `context.report` call from a rule into a reported
* problem for the Node.js API.
* @param {{ruleId: string, severity: number, sourceCode: SourceCode}} metadata Metadata for the reported problem
* @param {{ruleId: string, severity: number, sourceCode: SourceCode, messageIds: Object}} metadata Metadata for the reported problem
* @param {SourceCode} sourceCode The `SourceCode` instance for the text being linted
* @returns {function(...args): {
* ruleId: string,
* severity: (0|1|2),
* message: string,
* message: (string|undefined),
* messageId: (string|undefined),
* line: number,
* column: number,
* endLine: (number|undefined),
Expand All @@ -261,11 +268,26 @@ module.exports = function createReportTranslator(metadata) {

assertValidNodeInfo(descriptor);

if (descriptor.messageId) {
const id = descriptor.messageId;
const messages = metadata.messageIds;

if (descriptor.message) {
throw new TypeError("context.report() called with a message and a messageId. Please only pass one.");
}
if (!messages || !Object.keys(messages).includes(id)) {
throw new TypeError(`context.report() called with a messageId of '${id}' which is not present in the 'messages' config: ${JSON.stringify(messages, null, 2)}`);
}
descriptor.message = messages[id];
}


return createProblem({
ruleId: metadata.ruleId,
severity: metadata.severity,
node: descriptor.node,
message: normalizeMessagePlaceholders(descriptor),
messageId: descriptor.messageId,
loc: normalizeReportLoc(descriptor),
fix: normalizeFixes(descriptor, metadata.sourceCode),
sourceLines: metadata.sourceCode.lines
Expand Down
57 changes: 56 additions & 1 deletion tests/lib/report-translator.js
Expand Up @@ -48,7 +48,7 @@ describe("createReportTranslator", () => {
node = sourceCode.ast.body[0];
location = sourceCode.ast.body[1].loc.start;
message = "foo";
translateReport = createReportTranslator({ ruleId: "foo-rule", severity: 2, sourceCode });
translateReport = createReportTranslator({ ruleId: "foo-rule", severity: 2, sourceCode, messageIds: { testMessage: message } });
});

describe("old-style call with location", () => {
Expand Down Expand Up @@ -113,6 +113,61 @@ describe("createReportTranslator", () => {
}
);
});
it("should translate the messageId into a message", () => {
const reportDescriptor = {
node,
loc: location,
messageId: "testMessage",
fix: () => ({ range: [1, 2], text: "foo" })
};

assert.deepEqual(
translateReport(reportDescriptor),
{
ruleId: "foo-rule",
severity: 2,
message: "foo",
messageId: "testMessage",
line: 2,
column: 1,
nodeType: "ExpressionStatement",
source: "bar",
fix: {
range: [1, 2],
text: "foo"
}
}
);
});
it("should throw when both messageId and message are provided", () => {
const reportDescriptor = {
node,
loc: location,
messageId: "testMessage",
message: "bar",
fix: () => ({ range: [1, 2], text: "foo" })
};

assert.throws(
() => translateReport(reportDescriptor),
TypeError,
"context.report() called with a message and a messageId. Please only pass one."
);
});
it("should throw when an invalid messageId is provided", () => {
const reportDescriptor = {
node,
loc: location,
messageId: "thisIsNotASpecifiedMessageId",
fix: () => ({ range: [1, 2], text: "foo" })
};

assert.throws(
() => translateReport(reportDescriptor),
TypeError,
/^context\.report\(\) called with a messageId of '[^']+' which is not present in the 'messages' config:/
);
});
});
describe("combining autofixes", () => {
it("should merge fixes to one if 'fix' function returns an array of fixes.", () => {
Expand Down

0 comments on commit 4479c7b

Please sign in to comment.