text: const experimental_utils_1 = require("@typescript-eslint/experimental-utils");
  const getFunction_1 = require("../utils/getFunction");
  module.exports = {
      name: "test-for-null-using-isNullObject",
      meta: {
          type: "problem",
          messages: {
              useIsNullObject: "Test the isNullObject property of '{{name}}'.",
          },
          docs: {
              description: "Do not test the truthiness of an object returned by an OrNullObject method or property. Test it's isNullObject property.",
              category: "Possible Errors",
              recommended: false,
              url: "https://docs.microsoft.com/office/dev/add-ins/develop/application-specific-api-model#ornullobject-methods-and-properties",
          },
          schema: [],
          fixable: "code",
      },
      create: function (context) {
          function isConditionalTestExpression(node) {
              return (node.parent != undefined &&
                  (node.parent.type === experimental_utils_1.AST_NODE_TYPES.IfStatement ||
                      node.parent.type === experimental_utils_1.AST_NODE_TYPES.WhileStatement ||
                      node.parent.type === experimental_utils_1.AST_NODE_TYPES.DoWhileStatement ||
                      node.parent.type === experimental_utils_1.AST_NODE_TYPES.ForStatement ||
                      node.parent.type === experimental_utils_1.AST_NODE_TYPES.ConditionalExpression) &&
                  node === node.parent.test);
          }
          function isInUnaryNullTest(node) {
              return (node.parent != undefined &&
                  node.parent.type === experimental_utils_1.AST_NODE_TYPES.UnaryExpression &&
                  node.parent.operator === "!" &&
                  node.parent.argument === node);
          }
          function isInBinaryNullTest(node) {
              return (node.parent != undefined &&
                  node.parent.type === experimental_utils_1.AST_NODE_TYPES.BinaryExpression &&
                  ((node.parent.left === node &&
                      node.parent.right.type === experimental_utils_1.AST_NODE_TYPES.Literal &&
                      node.parent.right.raw === "null") ||
                      (node.parent.right === node &&
                          node.parent.left.type === experimental_utils_1.AST_NODE_TYPES.Literal &&
                          node.parent.left.raw === "null")));
          }
          function isInNullTest(node) {
              var _a;
              return (isConditionalTestExpression(node) ||
                  ((_a = node.parent) === null || _a === void 0 ? void 0 : _a.type) === experimental_utils_1.AST_NODE_TYPES.LogicalExpression ||
                  isInUnaryNullTest(node) ||
                  isInBinaryNullTest(node));
          }
          function isNullObjectNode(node) {
              if (node &&
                  ((node.type === experimental_utils_1.AST_NODE_TYPES.VariableDeclarator &&
                      node.init &&
                      (0, getFunction_1.isGetOrNullObjectFunction)(node.init) &&
                      node.id.type === experimental_utils_1.AST_NODE_TYPES.Identifier) ||
                      (node.type === experimental_utils_1.AST_NODE_TYPES.AssignmentExpression &&
                          (0, getFunction_1.isGetOrNullObjectFunction)(node.right) &&
                          node.left.type === experimental_utils_1.AST_NODE_TYPES.Identifier))) {
                  return true;
              }
              return false;
          }
          function findNullObjectNullTests(scope) {
              const variables = scope.variables;
              const childScopes = scope.childScopes;
              for (let i = 0; i < variables.length; i++) {
                  const variable = variables[i];
                  const references = variable.references;
                  let nullObjectCall = false;
                  const nullTests = [];
                  for (let ref = 0; ref < references.length; ref++) {
                      const identifier = references[ref].identifier;
                      if (isNullObjectNode(identifier.parent)) {
                          nullObjectCall = true;
                      }
                      if (isInNullTest(identifier)) {
                          nullTests.push(identifier);
                      }
                  }
                  if (nullObjectCall === true && nullTests.length > 0) {
                      nullTests.forEach((identifier) => {
                          context.report({
                              node: identifier,
                              messageId: "useIsNullObject",
                              data: { name: identifier.name },
                              fix: function (fixer) {
                                  var ruleFix;
                                  if (isInBinaryNullTest(identifier) && identifier.parent) {
                                      let newTest = identifier.name + ".isNullObject";
                                      ruleFix = fixer.replaceText(identifier.parent, newTest);
                                  }
                                  else {
                                      ruleFix = fixer.insertTextAfter(identifier, ".isNullObject");
                                  }
                                  return ruleFix;
                              },
                          });
                      });
                  }
              }
              for (let i = 0; i < childScopes.length; ++i) {
                  findNullObjectNullTests(childScopes[i]);
              }
          }
          return {
              "Program:exit"() {
                  findNullObjectNullTests(context.getScope());
              },
          };
      },
  };
  //# sourceMappingURL=test-for-null-using-isNullObject.js.map