Skip to content

Commit 0cfb471

Browse files
committed
Merge branch 'main' into no-unused-placeholders-report-loc
* main: fix: reporting location in no-missing-placeholders (eslint-community#280) fix: clarify report messages for no-missing-placeholders and no-unused-placeholders (eslint-community#278) fix: allow additional schema types in require-meta-schema (eslint-community#277)
2 parents 03c53c6 + 31ff45c commit 0cfb471

6 files changed

+114
-21
lines changed

lib/rules/no-missing-placeholders.js

+7-5
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ module.exports = {
2626
schema: [],
2727
messages: {
2828
placeholderDoesNotExist:
29-
'The placeholder {{{{missingKey}}}} does not exist.',
29+
"The placeholder {{{{missingKey}}}} is missing (must provide it in the report's `data` object).",
3030
},
3131
},
3232

@@ -80,9 +80,11 @@ module.exports = {
8080
});
8181
}
8282

83-
for (const { message, data } of reportMessagesAndDataArray.filter(
84-
(obj) => obj.message
85-
)) {
83+
for (const {
84+
message,
85+
messageId,
86+
data,
87+
} of reportMessagesAndDataArray.filter((obj) => obj.message)) {
8688
const messageStaticValue = getStaticValue(
8789
message,
8890
context.getScope()
@@ -112,7 +114,7 @@ module.exports = {
112114

113115
if (!matchingProperty) {
114116
context.report({
115-
node: message,
117+
node: data || messageId || message,
116118
messageId: 'placeholderDoesNotExist',
117119
data: { missingKey: match[1] },
118120
});

lib/rules/no-unused-placeholders.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ module.exports = {
2525
fixable: null,
2626
schema: [],
2727
messages: {
28-
placeholderUnused: 'The placeholder {{{{unusedKey}}}} is unused.',
28+
placeholderUnused:
29+
'The placeholder {{{{unusedKey}}}} is unused (does not exist in the actual message).',
2930
},
3031
},
3132

lib/rules/require-meta-schema.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,10 @@ module.exports = {
104104
hasEmptySchema = true;
105105
}
106106

107-
if (!['ArrayExpression', 'ObjectExpression'].includes(value.type)) {
107+
if (
108+
value.type === 'Literal' ||
109+
(value.type === 'Identifier' && value.name === 'undefined')
110+
) {
108111
context.report({ node: value, messageId: 'wrongType' });
109112
}
110113
},

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

+41-13
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,12 @@ const RuleTester = require('eslint').RuleTester;
1717
* @param {string} missingKey The placeholder that is missing
1818
* @returns {object} An expected error
1919
*/
20-
function error(missingKey, type = 'Literal') {
21-
return { type, message: `The placeholder {{${missingKey}}} does not exist.` };
20+
function error(missingKey, type, extra) {
21+
return {
22+
type,
23+
message: `The placeholder {{${missingKey}}} is missing (must provide it in the report's \`data\` object).`,
24+
...extra,
25+
};
2226
}
2327

2428
// ------------------------------------------------------------------------------
@@ -232,7 +236,7 @@ ruleTester.run('no-missing-placeholders', rule, {
232236
}
233237
};
234238
`,
235-
errors: [error('bar')],
239+
errors: [error('bar', 'Literal')],
236240
},
237241
{
238242
code: `
@@ -246,7 +250,7 @@ ruleTester.run('no-missing-placeholders', rule, {
246250
}
247251
};
248252
`,
249-
errors: [error('bar')],
253+
errors: [error('bar', 'ObjectExpression')],
250254
},
251255
{
252256
code: `
@@ -260,15 +264,15 @@ ruleTester.run('no-missing-placeholders', rule, {
260264
}
261265
};
262266
`,
263-
errors: [error('hasOwnProperty')],
267+
errors: [error('hasOwnProperty', 'ObjectExpression')],
264268
},
265269
{
266270
code: `
267271
module.exports = context => {
268272
context.report(node, 'foo {{bar}}', { baz: 'qux' }); return {};
269273
};
270274
`,
271-
errors: [error('bar')],
275+
errors: [error('bar', 'ObjectExpression')],
272276
},
273277
{
274278
// Message in variable.
@@ -278,15 +282,15 @@ ruleTester.run('no-missing-placeholders', rule, {
278282
context.report(node, MESSAGE, { baz: 'qux' }); return {};
279283
};
280284
`,
281-
errors: [error('bar', 'Identifier')],
285+
errors: [error('bar', 'ObjectExpression')],
282286
},
283287
{
284288
code: `
285289
module.exports = context => {
286290
context.report(node, { line: 1, column: 3 }, 'foo {{bar}}', { baz: 'baz' }); return {};
287291
};
288292
`,
289-
errors: [error('bar')],
293+
errors: [error('bar', 'ObjectExpression')],
290294
},
291295
{
292296
code: `
@@ -300,7 +304,19 @@ ruleTester.run('no-missing-placeholders', rule, {
300304
}
301305
};
302306
`,
303-
errors: [error('bar')],
307+
errors: [
308+
error(
309+
'bar',
310+
'ObjectExpression',
311+
// report on data
312+
{
313+
line: 7,
314+
endLine: 7,
315+
column: 21,
316+
endColumn: 39,
317+
}
318+
),
319+
],
304320
},
305321

306322
{
@@ -340,7 +356,7 @@ ruleTester.run('no-missing-placeholders', rule, {
340356
}
341357
};
342358
`,
343-
errors: [error('bar')],
359+
errors: [error('bar', 'ObjectExpression')],
344360
},
345361
{
346362
// Suggestion and messageId
@@ -359,7 +375,7 @@ ruleTester.run('no-missing-placeholders', rule, {
359375
}
360376
};
361377
`,
362-
errors: [error('bar')],
378+
errors: [error('bar', 'Literal')],
363379
},
364380
{
365381
// `create` in variable.
@@ -373,7 +389,7 @@ ruleTester.run('no-missing-placeholders', rule, {
373389
}
374390
module.exports = { create };
375391
`,
376-
errors: [error('hasOwnProperty')],
392+
errors: [error('hasOwnProperty', 'ObjectExpression')],
377393
},
378394
{
379395
// messageId.
@@ -388,7 +404,19 @@ ruleTester.run('no-missing-placeholders', rule, {
388404
}
389405
};
390406
`,
391-
errors: [error('bar')],
407+
errors: [
408+
error(
409+
'bar',
410+
'Literal',
411+
// report on the messageId
412+
{
413+
line: 7,
414+
endLine: 7,
415+
column: 26,
416+
endColumn: 39,
417+
}
418+
),
419+
],
392420
},
393421
],
394422
});

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ const RuleTester = require('eslint').RuleTester;
2020
function error(unusedKey, extra) {
2121
return {
2222
type: 'Property', // The property in the report's `data` object for the unused placeholder.
23-
message: `The placeholder {{${unusedKey}}} is unused.`,
23+
message: `The placeholder {{${unusedKey}}} is unused (does not exist in the actual message).`,
2424
...extra,
2525
};
2626
}

tests/lib/rules/require-meta-schema.js

+59
Original file line numberDiff line numberDiff line change
@@ -63,20 +63,57 @@ ruleTester.run('require-meta-schema', rule, {
6363
`,
6464
parserOptions: { sourceType: 'module' },
6565
},
66+
// Variable schema with array value.
6667
`
6768
const schema = [];
6869
module.exports = {
6970
meta: { schema },
7071
create(context) {}
7172
};
7273
`,
74+
// Variable schema with object value.
7375
`
7476
const foo = {};
7577
module.exports = {
7678
meta: { schema: foo },
7779
create(context) {}
7880
};
7981
`,
82+
// Variable schema with no static value.
83+
`
84+
module.exports = {
85+
meta: { schema },
86+
create(context) {}
87+
};
88+
`,
89+
// Variable schema pointing to unknown variable chain.
90+
`
91+
module.exports = {
92+
meta: { schema: baseRule.meta.schema },
93+
create(context) {}
94+
};
95+
`,
96+
// Schema with function call as value.
97+
`
98+
module.exports = {
99+
meta: { schema: getSchema() },
100+
create(context) {}
101+
};
102+
`,
103+
// Schema with ternary (conditional) expression.
104+
`
105+
module.exports = {
106+
meta: { schema: foo ? [] : {} },
107+
create(context) {}
108+
};
109+
`,
110+
// Schema with logical expression.
111+
`
112+
module.exports = {
113+
meta: { schema: foo || {} },
114+
create(context) {}
115+
};
116+
`,
80117
`
81118
let schema;
82119
schema = foo ? [] : {};
@@ -296,6 +333,28 @@ schema: [] },
296333
output: null,
297334
errors: [{ messageId: 'wrongType', type: 'Identifier', suggestions: [] }],
298335
},
336+
{
337+
// Schema with number literal value.
338+
code: `
339+
module.exports = {
340+
meta: { schema: 123 },
341+
create(context) {}
342+
};
343+
`,
344+
output: null,
345+
errors: [{ messageId: 'wrongType', type: 'Literal', suggestions: [] }],
346+
},
347+
{
348+
// Schema with string literal value.
349+
code: `
350+
module.exports = {
351+
meta: { schema: 'hello world' },
352+
create(context) {}
353+
};
354+
`,
355+
output: null,
356+
errors: [{ messageId: 'wrongType', type: 'Literal', suggestions: [] }],
357+
},
299358
{
300359
code: `
301360
const schema = null;

0 commit comments

Comments
 (0)