function rule(context) {
  const sourceCode = context.getSourceCode();

  return {
    BinaryExpression(node) {
      if (node.operator === '===' || node.operator === '!==') {
        if (isTargetedNode(node.left)) {
          reportStrict(
            node,
            node.right,
            sourceCode.getTokenAfter(node.left),
            node.left,
          );
        } else if (isTargetedNode(node.right)) {
          reportStrict(
            node,
            node.left,
            sourceCode.getTokenAfter(node.left),
            node.right,
          );
        }
      } else if (node.operator === '==' || node.operator === '!=') {
        if (isUndefinedNode(node.left) || isVoidNode(node.left)) {
          reportWeak(
            node,
            node.right,
            sourceCode.getTokenAfter(node.left),
            node.left,
          );
        } else if (isUndefinedNode(node.right) || isVoidNode(node.right)) {
          reportWeak(
            node,
            node.left,
            sourceCode.getTokenAfter(node.left),
            node.right,
          );
        }
      }
    },
  };

  function reportStrict(parent, childToKeep, eqToken, childToDitch) {
    context.report({
      node: parent,
      messageId: 'WEAK_NULL',
      fix: createAutofixer(parent, childToKeep, eqToken, childToDitch),
    });
  }
  function reportWeak(parent, childToKeep, eqToken, childToDitch) {
    context.report({
      node: parent,
      messageId: 'CHECK_NULL',
      fix: createAutofixer(parent, childToKeep, eqToken, childToDitch),
    });
  }
  function createAutofixer(parent, childToKeep, eqToken, childToDitch) {
    // If the node was wrapped in a group then that won't show up here
    // so make sure to skip past the group-closing tokens first.
    while (eqToken.value === ')') {
      eqToken = sourceCode.getTokenAfter(eqToken);
    }
    if (
      eqToken.value !== '==' &&
      eqToken.value !== '===' &&
      eqToken.value !== '!=' &&
      eqToken.value !== '!=='
    ) {
      // Unexpected token value. Returning to prevent accidental clobbering.
      return null;
    }
    // Note: make sure `(a||b)===null` does not become `a||b==null` !
    return fixer => [
      fixer.replaceText(
        eqToken,
        eqToken.value === '===' || eqToken.value === '==' ? '==' : '!=',
      ),
      fixer.replaceText(childToDitch, 'null'),
    ];
  }
}
A lint rule to require `null` and `undefined` checks to be `== null` (or !=)
Enforces that all `undefined` and `null` checks use `== null` / `!= null`