eslint-rule-composer icon indicating copy to clipboard operation
eslint-rule-composer copied to clipboard

filterReports by parsing sourceCode.

Open DianaSuvorova opened this issue 7 years ago • 3 comments
trafficstars

Hello,

I am looking for a help. I am trying to use filterReports, although my predicate function has to be a bit more involved then any readme example or tests I saw in the lib. I actually need to parse a whole sourceCode in similar way I would have parsed for a eslint rule.

Here is somewhat pseudocode to illustrate what I need.

const ruleComposer = require('eslint-rule-composer');

const noUnusedPropTypesReact = require('eslint-plugin-react').rules['no-unused-prop-types'];

const getPropsUsedInRedux = (sourceCode) => {
  const usedInRedux = [];

  somehowRunThis({
    FunctionDeclaration(node) {
      if (node.id && node.id.name === 'mapDispatchToProps') {
        usedInRedux.push[node.body];
      }
    },
  });

  return usedInRedux;
};


module.exports = ruleComposer.filterReports(
  noUnusedPropTypesReact,
  (problem, metadata) => {
    const usedInRedux = getPropsUsedInRedux(metadata.sourceCode);
    return !usedInRedux.contains(problem.node)
  },
);

It seems like I need some combination of filterReports and joinReports. Or maybe there is some other obvious way or another util I can use. Would be very grateful for any suggestions.

Thanks, Diana

DianaSuvorova avatar Oct 25 '18 23:10 DianaSuvorova

Hi, thanks for creating an issue.

Would it work to put the mapDispatchToProps check inside the filterReports call? Then you wouldn't need to have the separate FunctionDeclaration listener.

module.exports = ruleComposer.filterReports(
  noUnusedPropTypesReact,
  (problem, metadata) => {
    const node = problem.node;
    if (node.parent.body !== node) {
        return true;
    }
    return !(node.parent.id && node.parent.id.name === 'mapDispatchToProps');
  },
);

not-an-aardvark avatar Oct 25 '18 23:10 not-an-aardvark

I do need that FunctionDeclaration listener and some others. I pretty much need to filter result of one rule by the result of another rule. Just problem.node is not enough, I need to analyze whole sourceCode to make a decision.

Here is particular issue I am working on: https://github.com/DianaSuvorova/eslint-plugin-react-redux/issues/28

DianaSuvorova avatar Oct 26 '18 00:10 DianaSuvorova

I have created a function for what I need to get done.

It unfortunately requires a lot of helper functions copied from your lib and might not be generic enough, but it works for my purpose. I will follow up if I get to cleaning it up, so I can offer it as a contribution for your library.

const filterReports = (rule, filterNode, filterAll) => Object.freeze({
  create(context) {
    const removeNodesFromReport = [];
    let allNodesFiltered = false;
    return getRuleCreateFunc(rule)(Object.freeze(Object.create(
      context,
      {
        report: {
          enumerable: true,
          value() {
            const reportDescriptor = getReportNormalizer(rule)(...arguments);
            if (filterAll(reportDescriptor)) {
              allNodesFiltered = true;
            }
            if (filterNode(reportDescriptor)) {
              removeNodesFromReport.push(reportDescriptor.node);
            } else if (!allNodesFiltered && !removeNodesFromReport.includes(reportDescriptor.node)) {
              context.report(removeMessageIfMessageIdPresent(reportDescriptor));
            }
          },
        },
      },
    )));
  },
  schema: rule.schema,
  meta: getRuleMeta(rule),
});

module.exports = (rules, filterNode, filterAll) => filterReports(ruleComposer.joinReports(rules), filterNode, filterAll);

Thanks a lot for creating this library - it was super helpful for me! Diana

DianaSuvorova avatar Nov 13 '18 21:11 DianaSuvorova