Skip to content

Commit

Permalink
fix: handle suggestions in helper function outside rule or inside nes…
Browse files Browse the repository at this point in the history
…ted spread/ternary in `require-meta-has-suggestions` rule (#291)
  • Loading branch information
bmish committed Aug 17, 2022
1 parent 9b8b29f commit aa133a9
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 26 deletions.
10 changes: 3 additions & 7 deletions lib/rules/require-meta-fixable.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,9 @@ module.exports = {
let contextIdentifiers;
let usesFixFunctions;

// ----------------------------------------------------------------------
// Helpers
// ----------------------------------------------------------------------

// ----------------------------------------------------------------------
// Public
// ----------------------------------------------------------------------
if (!ruleInfo) {
return {};
}

return {
Program(ast) {
Expand Down
59 changes: 40 additions & 19 deletions lib/rules/require-meta-has-suggestions.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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
Expand Down
2 changes: 2 additions & 0 deletions tests/lib/rules/require-meta-fixable.js
Original file line number Diff line number Diff line change
Expand Up @@ -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: [
Expand Down
36 changes: 36 additions & 0 deletions tests/lib/rules/require-meta-has-suggestions.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down Expand Up @@ -205,6 +239,8 @@ ruleTester.run('require-meta-has-suggestions', rule, {
}
};
`,
// No rule present.
`const foo = { suggest: [{}]}; context.report({node,message,suggest});`,
],

invalid: [
Expand Down

0 comments on commit aa133a9

Please sign in to comment.