diff --git a/lib/rules/require-meta-fixable.js b/lib/rules/require-meta-fixable.js index d2ce03d0..9b9752a1 100644 --- a/lib/rules/require-meta-fixable.js +++ b/lib/rules/require-meta-fixable.js @@ -53,13 +53,9 @@ module.exports = { let contextIdentifiers; let usesFixFunctions; - // ---------------------------------------------------------------------- - // Helpers - // ---------------------------------------------------------------------- - - // ---------------------------------------------------------------------- - // Public - // ---------------------------------------------------------------------- + if (!ruleInfo) { + return {}; + } return { Program(ast) { diff --git a/lib/rules/require-meta-has-suggestions.js b/lib/rules/require-meta-has-suggestions.js index 44ea702e..4c8a0cf4 100644 --- a/lib/rules/require-meta-has-suggestions.js +++ b/lib/rules/require-meta-has-suggestions.js @@ -35,6 +35,33 @@ module.exports = { let contextIdentifiers; let ruleReportsSuggestions; + /** + * Check if a "suggest" object property from a rule violation report should be considered to contain suggestions. + * @param {Node} node - the "suggest" object property to check + * @returns {boolean} whether this property should be considered to contain suggestions + */ + function doesPropertyContainSuggestions(node) { + const staticValue = getStaticValue(node.value, context.getScope()); + if ( + !staticValue || + (Array.isArray(staticValue.value) && staticValue.value.length > 0) || + (Array.isArray(staticValue.value) && + staticValue.value.length === 0 && + node.value.type === 'Identifier') // Array variable can have suggestions pushed to it. + ) { + // These are all considered reporting suggestions: + // suggest: [{...}] + // suggest: getSuggestions() + // suggest: MY_SUGGESTIONS + return true; + } + return false; + } + + if (!ruleInfo) { + return {}; + } + return { Program(ast) { contextIdentifiers = utils.getContextIdentifiers(scopeManager, ast); @@ -52,28 +79,22 @@ module.exports = { const suggestProp = utils .evaluateObjectProperties(node.arguments[0], scopeManager) .find((prop) => utils.getKeyName(prop) === 'suggest'); - if (suggestProp) { - const staticValue = getStaticValue( - suggestProp.value, - context.getScope() - ); - if ( - !staticValue || - (Array.isArray(staticValue.value) && - staticValue.value.length > 0) || - (Array.isArray(staticValue.value) && - staticValue.value.length === 0 && - suggestProp.value.type === 'Identifier') // Array variable can have suggestions pushed to it. - ) { - // These are all considered reporting suggestions: - // suggest: [{...}] - // suggest: getSuggestions() - // suggest: MY_SUGGESTIONS - ruleReportsSuggestions = true; - } + if (suggestProp && doesPropertyContainSuggestions(suggestProp)) { + ruleReportsSuggestions = true; } } }, + Property(node) { + // In order to reduce false positives, we will also check for a `suggest` property anywhere in the file. + // This is helpful especially in the event that helper functions are used for reporting violations. + if ( + node.key.type === 'Identifier' && + node.key.name === 'suggest' && + doesPropertyContainSuggestions(node) + ) { + ruleReportsSuggestions = true; + } + }, 'Program:exit'() { const metaNode = ruleInfo && ruleInfo.meta; const hasSuggestionsProperty = utils diff --git a/tests/lib/rules/require-meta-fixable.js b/tests/lib/rules/require-meta-fixable.js index 8dc6e65b..496d2134 100644 --- a/tests/lib/rules/require-meta-fixable.js +++ b/tests/lib/rules/require-meta-fixable.js @@ -212,6 +212,8 @@ ruleTester.run('require-meta-fixable', rule, { `, options: [{ catchNoFixerButFixableProperty: true }], }, + // No rule present. + `const foo = { fix: [{}]}; context.report({node,message,fix});`, ], invalid: [ diff --git a/tests/lib/rules/require-meta-has-suggestions.js b/tests/lib/rules/require-meta-has-suggestions.js index 5b2cceff..69451350 100644 --- a/tests/lib/rules/require-meta-has-suggestions.js +++ b/tests/lib/rules/require-meta-has-suggestions.js @@ -134,6 +134,40 @@ ruleTester.run('require-meta-has-suggestions', rule, { } }; `, + // Provides suggestions, helper function outside rule. + ` + function report() { + context.report({ node, message, suggest: [{}] }); + } + module.exports = { + meta: { hasSuggestions: true }, + create(context) { + report(); + } + }; + `, + // Provides suggestions, with complex spread/ternary in reporting. + ` + module.exports = { + meta: { hasSuggestions: true }, + create(context) { + context.report({ + node: node.id, + messageId: 'noEmptyWithSuper', + ...(useAutoFix + ? { fix } + : { + suggest: [ + { + messageId: 'noEmptyWithSuper', + fix, + }, + ], + }), + }); + } + }; + `, // Provides *dynamic* suggestions, has hasSuggestions property. ` module.exports = { @@ -205,6 +239,8 @@ ruleTester.run('require-meta-has-suggestions', rule, { } }; `, + // No rule present. + `const foo = { suggest: [{}]}; context.report({node,message,suggest});`, ], invalid: [