From e7b9b843100674bef18ad6614d1c55e40e1ab4ad Mon Sep 17 00:00:00 2001 From: Bryan Mishkin <698306+bmish@users.noreply.github.com> Date: Thu, 29 Jul 2021 14:51:26 -0700 Subject: [PATCH] Fix: False negative in `prefer-message-ids` rule --- lib/rules/prefer-message-ids.js | 29 +++++++++++ tests/lib/rules/prefer-message-ids.js | 75 +++++++++++++++++++++++++++ 2 files changed, 104 insertions(+) diff --git a/lib/rules/prefer-message-ids.js b/lib/rules/prefer-message-ids.js index 2c35aeec..8fddd35e 100644 --- a/lib/rules/prefer-message-ids.js +++ b/lib/rules/prefer-message-ids.js @@ -1,6 +1,7 @@ 'use strict'; const utils = require('../utils'); +const { getStaticValue } = require('eslint-utils'); // ------------------------------------------------------------------------------ // Rule Definition @@ -17,11 +18,15 @@ module.exports = { fixable: null, schema: [], messages: { + messagesMissing: '`meta.messages` must contain at least one violation message.', foundMessage: 'Use `messageId` instead of `message`.', }, }, create (context) { + const sourceCode = context.getSourceCode(); + const info = utils.getRuleInfo(sourceCode); + let contextIdentifiers; // ---------------------------------------------------------------------- @@ -31,6 +36,30 @@ module.exports = { return { Program (ast) { contextIdentifiers = utils.getContextIdentifiers(context, ast); + + if (info === null || info.meta === null) { + return; + } + + const metaNode = info.meta; + const messagesNode = + metaNode && + metaNode.properties && + metaNode.properties.find(p => p.type === 'Property' && utils.getKeyName(p) === 'messages'); + + if (!messagesNode) { + context.report({ node: metaNode, messageId: 'messagesMissing' }); + return; + } + + const staticValue = getStaticValue(messagesNode.value, context.getScope()); + if (!staticValue) { + return; + } + + if (typeof staticValue.value === 'object' && staticValue.value.constructor === Object && Object.keys(staticValue.value).length === 0) { + context.report({ node: messagesNode.value, messageId: 'messagesMissing' }); + } }, CallExpression (node) { if ( diff --git a/tests/lib/rules/prefer-message-ids.js b/tests/lib/rules/prefer-message-ids.js index 81d299e4..cfabcef4 100644 --- a/tests/lib/rules/prefer-message-ids.js +++ b/tests/lib/rules/prefer-message-ids.js @@ -58,6 +58,26 @@ ruleTester.run('prefer-message-ids', rule, { ] }); `, + + // `meta.messages` has a message + ` + module.exports = { + meta: { messages: { someMessageId: 'some message' } }, + create(context) { + context.report({ node, messageId: 'someMessageId' }); + } + }; + `, + // `meta.messages` has a message (in variable) + ` + const messages = { someMessageId: 'some message' }; + module.exports = { + meta: { messages }, + create(context) { + context.report({ node, messageId: 'someMessageId' }); + } + }; + `, ], invalid: [ @@ -100,5 +120,60 @@ ruleTester.run('prefer-message-ids', rule, { `, errors: [{ messageId: 'foundMessage', type: 'Property' }], }, + + { + // `meta.messages` missing + code: ` + module.exports = { + meta: { description: 'foo' }, + create(context) { } + }; + `, + errors: [{ messageId: 'messagesMissing', type: 'ObjectExpression' }], + }, + { + // `meta.messages` empty + code: ` + module.exports = { + meta: { + description: 'foo', + messages: {}, + }, + create(context) { } + }; + `, + errors: [{ messageId: 'messagesMissing', type: 'ObjectExpression' }], + }, + { + // `meta.messages` empty (in variable) + code: ` + const messages = {}; + module.exports = { + meta: { + description: 'foo', + messages, + }, + create(context) { } + }; + `, + errors: [{ messageId: 'messagesMissing', type: 'Identifier' }], + }, + { + // `meta.messages` missing and using `message` + code: ` + module.exports = { + meta: { + description: 'foo', + }, + create(context) { + context.report({ node, message: 'foo' }); + } + }; + `, + errors: [ + { messageId: 'messagesMissing', type: 'ObjectExpression' }, + { messageId: 'foundMessage', type: 'Property' }, + ], + }, ], });