Skip to content

Commit a74d1f6

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

File tree

4 files changed

+188
-10
lines changed

4 files changed

+188
-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

+61
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}}';
@@ -283,5 +329,20 @@ ruleTester.run('no-missing-placeholders', rule, {
283329
`,
284330
errors: [error('hasOwnProperty')],
285331
},
332+
{
333+
// messageId.
334+
code: `
335+
module.exports = {
336+
meta: { messages: { myMessageId: 'foo {{bar}}' } },
337+
create(context) {
338+
context.report({
339+
node,
340+
messageId: 'myMessageId'
341+
});
342+
}
343+
};
344+
`,
345+
errors: [error('bar')],
346+
},
286347
],
287348
});

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

+53
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,43 @@ ruleTester.run('no-unused-placeholders', rule, {
122122
}
123123
};
124124
`,
125+
// messageId but no placeholder.
126+
`
127+
module.exports = {
128+
meta: {
129+
messages: { myMessageId: 'foo' }
130+
},
131+
create(context) {
132+
context.report({ node, messageId: 'myMessageId' });
133+
}
134+
};
135+
`,
136+
// messageId but the message property doesn't exist yet.
137+
`
138+
module.exports = {
139+
meta: {
140+
messages: { }
141+
},
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+
`,
125162
],
126163

127164
invalid: [
@@ -197,6 +234,22 @@ ruleTester.run('no-unused-placeholders', rule, {
197234
`,
198235
errors: [error('baz')],
199236
},
237+
{
238+
// messageId.
239+
code: `
240+
module.exports = {
241+
meta: { messages: { myMessageId: 'foo' } },
242+
create(context) {
243+
context.report({
244+
node,
245+
messageId: 'myMessageId',
246+
data: { bar }
247+
});
248+
}
249+
};
250+
`,
251+
errors: [error('bar')],
252+
},
200253
{
201254
// Suggestion
202255
code: `

0 commit comments

Comments
 (0)