Skip to content

Commit 6bf4356

Browse files
committed
Breaking: Update no-missing-placeholders rule to also apply to suggestion messages
1 parent d85c446 commit 6bf4356

File tree

2 files changed

+99
-22
lines changed

2 files changed

+99
-22
lines changed

lib/rules/no-missing-placeholders.js

+41-22
Original file line numberDiff line numberDiff line change
@@ -45,33 +45,52 @@ module.exports = {
4545
node.callee.property.type === 'Identifier' && node.callee.property.name === 'report'
4646
) {
4747
const reportInfo = utils.getReportInfo(node.arguments, context);
48-
if (!reportInfo || !reportInfo.message) {
48+
if (!reportInfo) {
4949
return;
5050
}
5151

52-
const messageStaticValue = getStaticValue(reportInfo.message, context.getScope());
53-
if (
54-
(
55-
(reportInfo.message.type === 'Literal' && typeof reportInfo.message.value === 'string') ||
56-
(messageStaticValue && typeof messageStaticValue.value === 'string')
57-
) &&
58-
(!reportInfo.data || reportInfo.data.type === 'ObjectExpression')
59-
) {
60-
// Same regex as the one ESLint uses
61-
// https://github.com/eslint/eslint/blob/e5446449d93668ccbdb79d78cc69f165ce4fde07/lib/eslint.js#L990
62-
const PLACEHOLDER_MATCHER = /{{\s*([^{}]+?)\s*}}/g;
63-
let match;
52+
// Collect all violation/suggestion message nodes into a standardized array.
53+
const messagesAndDataArray = [
54+
// Violation message
55+
{ message: reportInfo.message, data: reportInfo.data },
56+
// Suggestion messages
57+
...((reportInfo.suggest && reportInfo.suggest.elements) || [])
58+
.map(suggestObjNode => {
59+
const propertyNodeDesc = suggestObjNode.properties.find(prop => prop.key.type === 'Identifier' && prop.key.name === 'desc');
60+
const propertyNodeData = suggestObjNode.properties.find(prop => prop.key.type === 'Identifier' && prop.key.name === 'data');
61+
return {
62+
message: propertyNodeDesc ? propertyNodeDesc.value : undefined,
63+
data: propertyNodeData ? propertyNodeData.value : undefined,
64+
};
65+
}
66+
),
67+
].filter(obj => obj.message);
68+
69+
for (const { message, data } of messagesAndDataArray) {
70+
const messageStaticValue = getStaticValue(message, context.getScope());
71+
if (
72+
(
73+
(message.type === 'Literal' && typeof message.value === 'string') ||
74+
(messageStaticValue && typeof messageStaticValue.value === 'string')
75+
) &&
76+
(!data || data.type === 'ObjectExpression')
77+
) {
78+
// Same regex as the one ESLint uses
79+
// https://github.com/eslint/eslint/blob/e5446449d93668ccbdb79d78cc69f165ce4fde07/lib/eslint.js#L990
80+
const PLACEHOLDER_MATCHER = /{{\s*([^{}]+?)\s*}}/g;
81+
let match;
6482

65-
while ((match = PLACEHOLDER_MATCHER.exec(reportInfo.message.value || messageStaticValue.value))) { // eslint-disable-line no-extra-parens
66-
const matchingProperty = reportInfo.data &&
67-
reportInfo.data.properties.find(prop => utils.getKeyName(prop) === match[1]);
83+
while ((match = PLACEHOLDER_MATCHER.exec(message.value || messageStaticValue.value))) { // eslint-disable-line no-extra-parens
84+
const matchingProperty = data &&
85+
data.properties.find(prop => utils.getKeyName(prop) === match[1]);
6886

69-
if (!matchingProperty) {
70-
context.report({
71-
node: reportInfo.message,
72-
messageId: 'placeholderDoesNotExist',
73-
data: { missingKey: match[1] },
74-
});
87+
if (!matchingProperty) {
88+
context.report({
89+
node: message,
90+
messageId: 'placeholderDoesNotExist',
91+
data: { missingKey: match[1] },
92+
});
93+
}
7594
}
7695
}
7796
}

tests/lib/rules/no-missing-placeholders.js

+58
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,24 @@ ruleTester.run('no-missing-placeholders', rule, {
128128
context.report(node, MESSAGE, { baz: 'qux' });
129129
};
130130
`,
131+
// Suggestion with placeholder
132+
`
133+
module.exports = {
134+
create(context) {
135+
context.report({
136+
node,
137+
suggest: [
138+
{
139+
desc: 'Remove {{functionName}}',
140+
data: {
141+
functionName: 'foo'
142+
}
143+
}
144+
]
145+
});
146+
}
147+
};
148+
`,
131149
],
132150

133151
invalid: [
@@ -212,5 +230,45 @@ ruleTester.run('no-missing-placeholders', rule, {
212230
`,
213231
errors: [error('bar')],
214232
},
233+
234+
{
235+
// Suggestion (no `data`)
236+
code: `
237+
module.exports = {
238+
create(context) {
239+
context.report({
240+
node,
241+
suggest: [
242+
{
243+
desc: 'Remove {{bar}}'
244+
}
245+
]
246+
});
247+
}
248+
};
249+
`,
250+
errors: [error('bar')],
251+
},
252+
{
253+
// Suggestion (`data` but missing placeholder)
254+
code: `
255+
module.exports = {
256+
create(context) {
257+
context.report({
258+
node,
259+
suggest: [
260+
{
261+
desc: 'Remove {{bar}}',
262+
data: {
263+
notBar: 'abc'
264+
}
265+
}
266+
]
267+
});
268+
}
269+
};
270+
`,
271+
errors: [error('bar')],
272+
},
215273
],
216274
});

0 commit comments

Comments
 (0)