Skip to content

Commit a5b17cc

Browse files
committed
breaking: update no-missing-placeholders and no-unused-placeholders to handle messageIds
1 parent f8268f2 commit a5b17cc

File tree

4 files changed

+263
-10
lines changed

4 files changed

+263
-10
lines changed

lib/rules/no-missing-placeholders.js

+37-5
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ module.exports = {
3131
},
3232

3333
create(context) {
34+
const sourceCode = context.getSourceCode();
3435
let contextIdentifiers;
3536

3637
// ----------------------------------------------------------------------
@@ -39,7 +40,6 @@ module.exports = {
3940

4041
return {
4142
Program(ast) {
42-
const sourceCode = context.getSourceCode();
4343
contextIdentifiers = utils.getContextIdentifiers(
4444
sourceCode.scopeManager,
4545
ast
@@ -57,10 +57,42 @@ module.exports = {
5757
return;
5858
}
5959

60-
const reportMessagesAndDataArray = utils
61-
.collectReportViolationAndSuggestionData(reportInfo)
62-
.filter((obj) => obj.message);
63-
for (const { message, data } of reportMessagesAndDataArray) {
60+
const info = utils.getRuleInfo(sourceCode);
61+
const metaNode = info.meta;
62+
const messagesNode =
63+
metaNode &&
64+
metaNode.properties &&
65+
metaNode.properties.find(
66+
(p) => p.type === 'Property' && utils.getKeyName(p) === 'messages'
67+
);
68+
69+
const reportMessagesAndDataArray =
70+
utils.collectReportViolationAndSuggestionData(reportInfo);
71+
72+
// Check for any potential instances where we can use the messageId to fill in the message for convenience.
73+
reportMessagesAndDataArray.forEach((obj) => {
74+
if (
75+
!obj.message &&
76+
obj.messageId &&
77+
obj.messageId.type === 'Literal'
78+
) {
79+
const correspondingMessage =
80+
messagesNode &&
81+
messagesNode.value.properties &&
82+
messagesNode.value.properties.find(
83+
(p) =>
84+
p.type === 'Property' &&
85+
utils.getKeyName(p) === obj.messageId.value
86+
);
87+
if (correspondingMessage) {
88+
obj.message = correspondingMessage.value;
89+
}
90+
}
91+
});
92+
93+
for (const { message, data } of reportMessagesAndDataArray.filter(
94+
(obj) => obj.message
95+
)) {
6496
const messageStaticValue = getStaticValue(
6597
message,
6698
context.getScope()

lib/rules/no-unused-placeholders.js

+37-5
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ module.exports = {
3030
},
3131

3232
create(context) {
33+
const sourceCode = context.getSourceCode();
3334
let contextIdentifiers;
3435

3536
// ----------------------------------------------------------------------
@@ -38,7 +39,6 @@ module.exports = {
3839

3940
return {
4041
Program(ast) {
41-
const sourceCode = context.getSourceCode();
4242
contextIdentifiers = utils.getContextIdentifiers(
4343
sourceCode.scopeManager,
4444
ast
@@ -56,10 +56,42 @@ module.exports = {
5656
return;
5757
}
5858

59-
const reportMessagesAndDataArray = utils
60-
.collectReportViolationAndSuggestionData(reportInfo)
61-
.filter((obj) => obj.message);
62-
for (const { message, data } of reportMessagesAndDataArray) {
59+
const info = utils.getRuleInfo(sourceCode);
60+
const metaNode = info.meta;
61+
const messagesNode =
62+
metaNode &&
63+
metaNode.properties &&
64+
metaNode.properties.find(
65+
(p) => p.type === 'Property' && utils.getKeyName(p) === 'messages'
66+
);
67+
68+
const reportMessagesAndDataArray =
69+
utils.collectReportViolationAndSuggestionData(reportInfo);
70+
71+
// Check for any potential instances where we can use the messageId to fill in the message for convenience.
72+
reportMessagesAndDataArray.forEach((obj) => {
73+
if (
74+
!obj.message &&
75+
obj.messageId &&
76+
obj.messageId.type === 'Literal'
77+
) {
78+
const correspondingMessage =
79+
messagesNode &&
80+
messagesNode.value.properties &&
81+
messagesNode.value.properties.find(
82+
(p) =>
83+
p.type === 'Property' &&
84+
utils.getKeyName(p) === obj.messageId.value
85+
);
86+
if (correspondingMessage) {
87+
obj.message = correspondingMessage.value;
88+
}
89+
}
90+
});
91+
92+
for (const { message, data } of reportMessagesAndDataArray.filter(
93+
(obj) => obj.message
94+
)) {
6395
const messageStaticValue = getStaticValue(
6496
message,
6597
context.getScope()

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

+99
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,52 @@ ruleTester.run('no-missing-placeholders', rule, {
113113
}
114114
};
115115
`,
116+
// messageId but no placeholder.
117+
`
118+
module.exports = {
119+
meta: {
120+
messages: { myMessageId: 'foo' }
121+
},
122+
create(context) {
123+
context.report({ node, messageId: 'myMessageId' });
124+
}
125+
};
126+
`,
127+
// messageId but the message property doesn't exist yet.
128+
`
129+
module.exports = {
130+
meta: {
131+
messages: { }
132+
},
133+
create(context) {
134+
context.report({ node, messageId: 'myMessageId' });
135+
}
136+
};
137+
`,
138+
// messageId but no messages object doesn't exist yet.
139+
`
140+
module.exports = {
141+
meta: { },
142+
create(context) {
143+
context.report({ node, messageId: 'myMessageId' });
144+
}
145+
};
146+
`,
147+
// messageId with correctly-used placeholder.
148+
`
149+
module.exports = {
150+
meta: {
151+
messages: { myMessageId: 'foo {{bar}}' }
152+
},
153+
create(context) {
154+
context.report({
155+
node,
156+
messageId: 'myMessageId',
157+
data: { bar: 'baz' }
158+
});
159+
}
160+
};
161+
`,
116162
// Message in variable.
117163
`
118164
const MESSAGE = 'foo {{bar}}';
@@ -145,6 +191,25 @@ ruleTester.run('no-missing-placeholders', rule, {
145191
}
146192
};
147193
`,
194+
// Suggestion with messageId
195+
`
196+
module.exports = {
197+
meta: { messages: { myMessageId: 'Remove {{functionName}}' } },
198+
create(context) {
199+
context.report({
200+
node,
201+
suggest: [
202+
{
203+
messageId: 'myMessageId',
204+
data: {
205+
functionName: 'foo'
206+
}
207+
}
208+
]
209+
});
210+
}
211+
};
212+
`,
148213
],
149214

150215
invalid: [
@@ -269,6 +334,25 @@ ruleTester.run('no-missing-placeholders', rule, {
269334
`,
270335
errors: [error('bar')],
271336
},
337+
{
338+
// Suggestion and messageId
339+
code: `
340+
module.exports = {
341+
meta: { messages: { myMessageId: 'foo {{bar}}' } },
342+
create(context) {
343+
context.report({
344+
node,
345+
suggest: [
346+
{
347+
messageId: 'myMessageId',
348+
}
349+
]
350+
});
351+
}
352+
};
353+
`,
354+
errors: [error('bar')],
355+
},
272356
{
273357
// `create` in variable.
274358
code: `
@@ -283,5 +367,20 @@ ruleTester.run('no-missing-placeholders', rule, {
283367
`,
284368
errors: [error('hasOwnProperty')],
285369
},
370+
{
371+
// messageId.
372+
code: `
373+
module.exports = {
374+
meta: { messages: { myMessageId: 'foo {{bar}}' } },
375+
create(context) {
376+
context.report({
377+
node,
378+
messageId: 'myMessageId'
379+
});
380+
}
381+
};
382+
`,
383+
errors: [error('bar')],
384+
},
286385
],
287386
});

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

+90
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,60 @@ ruleTester.run('no-unused-placeholders', rule, {
122122
}
123123
};
124124
`,
125+
// Suggestion with messageId
126+
`
127+
module.exports = {
128+
meta: { messages: { myMessageId: 'foo {{bar}}' } },
129+
create(context) {
130+
context.report({
131+
node,
132+
suggest: [
133+
{
134+
messageId: 'myMessageId',
135+
data: { 'bar': 'baz' }
136+
}
137+
]
138+
});
139+
}
140+
};
141+
`,
142+
// messageId but no placeholder.
143+
`
144+
module.exports = {
145+
meta: {
146+
messages: { myMessageId: 'foo' }
147+
},
148+
create(context) {
149+
context.report({ node, messageId: 'myMessageId' });
150+
}
151+
};
152+
`,
153+
// messageId but the message property doesn't exist yet.
154+
`
155+
module.exports = {
156+
meta: {
157+
messages: { }
158+
},
159+
create(context) {
160+
context.report({ node, messageId: 'myMessageId' });
161+
}
162+
};
163+
`,
164+
// messageId with correctly-used placeholder.
165+
`
166+
module.exports = {
167+
meta: {
168+
messages: { myMessageId: 'foo {{bar}}' }
169+
},
170+
create(context) {
171+
context.report({
172+
node,
173+
messageId: 'myMessageId',
174+
data: { bar: 'baz' }
175+
});
176+
}
177+
};
178+
`,
125179
],
126180

127181
invalid: [
@@ -197,6 +251,22 @@ ruleTester.run('no-unused-placeholders', rule, {
197251
`,
198252
errors: [error('baz')],
199253
},
254+
{
255+
// messageId.
256+
code: `
257+
module.exports = {
258+
meta: { messages: { myMessageId: 'foo' } },
259+
create(context) {
260+
context.report({
261+
node,
262+
messageId: 'myMessageId',
263+
data: { bar }
264+
});
265+
}
266+
};
267+
`,
268+
errors: [error('bar')],
269+
},
200270
{
201271
// Suggestion
202272
code: `
@@ -216,5 +286,25 @@ ruleTester.run('no-unused-placeholders', rule, {
216286
`,
217287
errors: [error('bar')],
218288
},
289+
{
290+
// Suggestion and messageId
291+
code: `
292+
module.exports = {
293+
meta: { messages: { myMessageId: 'foo' } },
294+
create(context) {
295+
context.report({
296+
node,
297+
suggest: [
298+
{
299+
messageId: 'myMessageId',
300+
data: { bar }
301+
}
302+
]
303+
});
304+
}
305+
};
306+
`,
307+
errors: [error('bar')],
308+
},
219309
],
220310
});

0 commit comments

Comments
 (0)