diff --git a/CHANGELOG.md b/CHANGELOG.md index e3e3919f..9dfb6926 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ +### [5.0.2](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/compare/v5.0.1...v5.0.2) (2022-08-04) + + +### Bug Fixes + +* allow additional schema types in require-meta-schema ([#277](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/issues/277)) ([5bf0648](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/commit/5bf0648f50213fa30e9b623a8db376f41a3af411)) +* clarify report messages for no-missing-placeholders and no-unused-placeholders ([#278](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/issues/278)) ([f5a5c24](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/commit/f5a5c2458e79c405f5a47c802dbca111301f635c)) +* Improve violation reporting location for `no-unused-placeholders` ([#279](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/issues/279)) ([27c0b65](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/commit/27c0b6558a9531c3b87a2776b1553adf29834e87)) +* reporting location in no-missing-placeholders ([#280](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/issues/280)) ([31ff45c](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/commit/31ff45c8840b90f575800ccbb7a35d1ba09c2ba8)) + ### [5.0.1](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/compare/v5.0.0...v5.0.1) (2022-07-18) diff --git a/lib/rules/no-missing-placeholders.js b/lib/rules/no-missing-placeholders.js index 6523d2a8..78b40491 100644 --- a/lib/rules/no-missing-placeholders.js +++ b/lib/rules/no-missing-placeholders.js @@ -26,7 +26,7 @@ module.exports = { schema: [], messages: { placeholderDoesNotExist: - 'The placeholder {{{{missingKey}}}} does not exist.', + "The placeholder {{{{missingKey}}}} is missing (must provide it in the report's `data` object).", }, }, @@ -80,9 +80,11 @@ module.exports = { }); } - for (const { message, data } of reportMessagesAndDataArray.filter( - (obj) => obj.message - )) { + for (const { + message, + messageId, + data, + } of reportMessagesAndDataArray.filter((obj) => obj.message)) { const messageStaticValue = getStaticValue( message, context.getScope() @@ -112,7 +114,7 @@ module.exports = { if (!matchingProperty) { context.report({ - node: message, + node: data || messageId || message, messageId: 'placeholderDoesNotExist', data: { missingKey: match[1] }, }); diff --git a/lib/rules/no-unused-placeholders.js b/lib/rules/no-unused-placeholders.js index 61f17adb..97a66312 100644 --- a/lib/rules/no-unused-placeholders.js +++ b/lib/rules/no-unused-placeholders.js @@ -25,7 +25,8 @@ module.exports = { fixable: null, schema: [], messages: { - placeholderUnused: 'The placeholder {{{{unusedKey}}}} is unused.', + placeholderUnused: + 'The placeholder {{{{unusedKey}}}} is unused (does not exist in the actual message).', }, }, @@ -107,7 +108,7 @@ module.exports = { const key = utils.getKeyName(prop); if (!placeholdersInMessage.has(key)) { context.report({ - node: message, + node: prop, messageId: 'placeholderUnused', data: { unusedKey: key }, }); diff --git a/lib/rules/require-meta-schema.js b/lib/rules/require-meta-schema.js index 0789bc6a..2d0d3000 100644 --- a/lib/rules/require-meta-schema.js +++ b/lib/rules/require-meta-schema.js @@ -104,7 +104,10 @@ module.exports = { hasEmptySchema = true; } - if (!['ArrayExpression', 'ObjectExpression'].includes(value.type)) { + if ( + value.type === 'Literal' || + (value.type === 'Identifier' && value.name === 'undefined') + ) { context.report({ node: value, messageId: 'wrongType' }); } }, diff --git a/package.json b/package.json index 2ae93985..65bff0f4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eslint-plugin-eslint-plugin", - "version": "5.0.1", + "version": "5.0.2", "description": "An ESLint plugin for linting ESLint plugins", "author": "Teddy Katz", "main": "./lib/index.js", diff --git a/tests/lib/rules/no-missing-placeholders.js b/tests/lib/rules/no-missing-placeholders.js index fb2aafb6..4a42b5ab 100644 --- a/tests/lib/rules/no-missing-placeholders.js +++ b/tests/lib/rules/no-missing-placeholders.js @@ -17,8 +17,12 @@ const RuleTester = require('eslint').RuleTester; * @param {string} missingKey The placeholder that is missing * @returns {object} An expected error */ -function error(missingKey, type = 'Literal') { - return { type, message: `The placeholder {{${missingKey}}} does not exist.` }; +function error(missingKey, type, extra) { + return { + type, + message: `The placeholder {{${missingKey}}} is missing (must provide it in the report's \`data\` object).`, + ...extra, + }; } // ------------------------------------------------------------------------------ @@ -232,7 +236,19 @@ ruleTester.run('no-missing-placeholders', rule, { } }; `, - errors: [error('bar')], + errors: [ + error( + 'bar', + 'Literal', + // report on `message` + { + line: 6, + endLine: 6, + column: 24, + endColumn: 37, + } + ), + ], }, { code: ` @@ -246,7 +262,7 @@ ruleTester.run('no-missing-placeholders', rule, { } }; `, - errors: [error('bar')], + errors: [error('bar', 'ObjectExpression')], }, { code: ` @@ -260,7 +276,7 @@ ruleTester.run('no-missing-placeholders', rule, { } }; `, - errors: [error('hasOwnProperty')], + errors: [error('hasOwnProperty', 'ObjectExpression')], }, { code: ` @@ -268,7 +284,7 @@ ruleTester.run('no-missing-placeholders', rule, { context.report(node, 'foo {{bar}}', { baz: 'qux' }); return {}; }; `, - errors: [error('bar')], + errors: [error('bar', 'ObjectExpression')], }, { // Message in variable. @@ -278,7 +294,7 @@ ruleTester.run('no-missing-placeholders', rule, { context.report(node, MESSAGE, { baz: 'qux' }); return {}; }; `, - errors: [error('bar', 'Identifier')], + errors: [error('bar', 'ObjectExpression')], }, { code: ` @@ -286,7 +302,7 @@ ruleTester.run('no-missing-placeholders', rule, { context.report(node, { line: 1, column: 3 }, 'foo {{bar}}', { baz: 'baz' }); return {}; }; `, - errors: [error('bar')], + errors: [error('bar', 'ObjectExpression')], }, { code: ` @@ -300,7 +316,19 @@ ruleTester.run('no-missing-placeholders', rule, { } }; `, - errors: [error('bar')], + errors: [ + error( + 'bar', + 'ObjectExpression', + // report on data + { + line: 7, + endLine: 7, + column: 21, + endColumn: 39, + } + ), + ], }, { @@ -340,7 +368,7 @@ ruleTester.run('no-missing-placeholders', rule, { } }; `, - errors: [error('bar')], + errors: [error('bar', 'ObjectExpression')], }, { // Suggestion and messageId @@ -359,7 +387,7 @@ ruleTester.run('no-missing-placeholders', rule, { } }; `, - errors: [error('bar')], + errors: [error('bar', 'Literal')], }, { // `create` in variable. @@ -373,7 +401,7 @@ ruleTester.run('no-missing-placeholders', rule, { } module.exports = { create }; `, - errors: [error('hasOwnProperty')], + errors: [error('hasOwnProperty', 'ObjectExpression')], }, { // messageId. @@ -388,7 +416,19 @@ ruleTester.run('no-missing-placeholders', rule, { } }; `, - errors: [error('bar')], + errors: [ + error( + 'bar', + 'Literal', + // report on the messageId + { + line: 7, + endLine: 7, + column: 26, + endColumn: 39, + } + ), + ], }, ], }); diff --git a/tests/lib/rules/no-unused-placeholders.js b/tests/lib/rules/no-unused-placeholders.js index 8679d0c4..a3c0f6c5 100644 --- a/tests/lib/rules/no-unused-placeholders.js +++ b/tests/lib/rules/no-unused-placeholders.js @@ -17,8 +17,12 @@ const RuleTester = require('eslint').RuleTester; * @param {string} unusedKey The placeholder that is unused * @returns {object} An expected error */ -function error(unusedKey, type = 'Literal') { - return { type, message: `The placeholder {{${unusedKey}}} is unused.` }; +function error(unusedKey, extra) { + return { + type: 'Property', // The property in the report's `data` object for the unused placeholder. + message: `The placeholder {{${unusedKey}}} is unused (does not exist in the actual message).`, + ...extra, + }; } // ------------------------------------------------------------------------------ @@ -208,7 +212,18 @@ ruleTester.run('no-unused-placeholders', rule, { } }; `, - errors: [error('bar')], + errors: [ + error( + 'bar', + // report on property in data object + { + line: 7, + endLine: 7, + column: 23, + endColumn: 26, + } + ), + ], }, { // With `create` as variable. @@ -238,7 +253,7 @@ ruleTester.run('no-unused-placeholders', rule, { } }; `, - errors: [error('bar', 'Identifier')], + errors: [error('bar')], }, { code: ` diff --git a/tests/lib/rules/require-meta-schema.js b/tests/lib/rules/require-meta-schema.js index a0c2a4d0..8558c7d7 100644 --- a/tests/lib/rules/require-meta-schema.js +++ b/tests/lib/rules/require-meta-schema.js @@ -63,6 +63,7 @@ ruleTester.run('require-meta-schema', rule, { `, parserOptions: { sourceType: 'module' }, }, + // Variable schema with array value. ` const schema = []; module.exports = { @@ -70,6 +71,7 @@ ruleTester.run('require-meta-schema', rule, { create(context) {} }; `, + // Variable schema with object value. ` const foo = {}; module.exports = { @@ -77,6 +79,41 @@ ruleTester.run('require-meta-schema', rule, { create(context) {} }; `, + // Variable schema with no static value. + ` + module.exports = { + meta: { schema }, + create(context) {} + }; + `, + // Variable schema pointing to unknown variable chain. + ` + module.exports = { + meta: { schema: baseRule.meta.schema }, + create(context) {} + }; + `, + // Schema with function call as value. + ` + module.exports = { + meta: { schema: getSchema() }, + create(context) {} + }; + `, + // Schema with ternary (conditional) expression. + ` + module.exports = { + meta: { schema: foo ? [] : {} }, + create(context) {} + }; + `, + // Schema with logical expression. + ` + module.exports = { + meta: { schema: foo || {} }, + create(context) {} + }; + `, ` let schema; schema = foo ? [] : {}; @@ -296,6 +333,28 @@ schema: [] }, output: null, errors: [{ messageId: 'wrongType', type: 'Identifier', suggestions: [] }], }, + { + // Schema with number literal value. + code: ` + module.exports = { + meta: { schema: 123 }, + create(context) {} + }; + `, + output: null, + errors: [{ messageId: 'wrongType', type: 'Literal', suggestions: [] }], + }, + { + // Schema with string literal value. + code: ` + module.exports = { + meta: { schema: 'hello world' }, + create(context) {} + }; + `, + output: null, + errors: [{ messageId: 'wrongType', type: 'Literal', suggestions: [] }], + }, { code: ` const schema = null;