/**
 * This file is part of the NocoBase (R) project.
 * Copyright (c) 2020-2024 NocoBase Co., Ltd.
 * Authors: NocoBase Team.
 *
 * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
 * For more information, please refer to: https://www.nocobase.com/agreement.
 */

var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var react_render_exports = {};
__export(react_render_exports, {
  collectAstReactComponentCtxRenderCallsFromAst: () => collectAstReactComponentCtxRenderCallsFromAst,
  collectAstReactComponentUsagesFromNodes: () => collectAstReactComponentUsagesFromNodes,
  collectAstReactComponentUsagesFromRenderCall: () => collectAstReactComponentUsagesFromRenderCall,
  collectAstReactComponentUsagesOnFunctionRenderPath: () => collectAstReactComponentUsagesOnFunctionRenderPath,
  collectAstTopLevelReachableCtxRenderCallsFromAst: () => collectAstTopLevelReachableCtxRenderCallsFromAst,
  collectCtxRenderCallsInFunction: () => collectCtxRenderCallsInFunction,
  dedupeAstFunctionUsageEntries: () => dedupeAstFunctionUsageEntries,
  findCtxRenderCallInFunction: () => findCtxRenderCallInFunction,
  findNearestAstFunctionAncestor: () => findNearestAstFunctionAncestor,
  getAstJSXIdentifierName: () => getAstJSXIdentifierName,
  isAstFunctionBindingScopedInsideNode: () => isAstFunctionBindingScopedInsideNode,
  resolveAstFunctionBinding: () => resolveAstFunctionBinding
});
module.exports = __toCommonJS(react_render_exports);
var import_walk = require("../ast/walk");
var import_bindings = require("../ast/bindings");
var import_static_values = require("../ast/static-values");
var import_react = require("./react");
function collectAstReactComponentCtxRenderCallsFromAst(renderCalls, ctxMethodAliases, reactCreateElementAliases, identifierBindings, functionBindings) {
  if (!renderCalls.length) {
    return [];
  }
  const entries = [];
  const pending = renderCalls.flatMap(
    (call) => collectAstReactComponentUsagesFromRenderCall(call, reactCreateElementAliases, identifierBindings, functionBindings)
  );
  const visitedComponents = /* @__PURE__ */ new Set();
  while (pending.length) {
    const usage = pending.shift();
    if (!usage) {
      continue;
    }
    const componentKey = `${usage.functionBinding.name}:${usage.functionBinding.declarationStart}`;
    if (visitedComponents.has(componentKey)) {
      continue;
    }
    visitedComponents.add(componentKey);
    const renderCall = findCtxRenderCallInFunction(
      usage.functionBinding.functionNode,
      ctxMethodAliases,
      identifierBindings,
      functionBindings,
      { bindingMode: "lexical" }
    );
    if (!renderCall) {
      pending.push(
        ...collectAstReactComponentUsagesOnFunctionRenderPath(
          usage.functionBinding.functionNode,
          reactCreateElementAliases,
          identifierBindings,
          functionBindings
        )
      );
      continue;
    }
    entries.push({
      capability: renderCall.capability,
      component: usage.functionBinding.name,
      index: renderCall.index
    });
  }
  return (0, import_bindings.dedupeIndexedEntries)(entries).sort((left, right) => left.index - right.index);
}
function collectAstReactComponentUsagesFromRenderCall(renderCall, reactCreateElementAliases, identifierBindings, functionBindings) {
  const usages = collectAstReactComponentUsagesFromNodes(
    renderCall.args,
    reactCreateElementAliases,
    identifierBindings,
    functionBindings
  );
  renderCall.args.forEach((arg) => {
    (0, import_walk.walkAstAncestor)(arg, {
      CallExpression(node) {
        const callee = (0, import_bindings.unwrapAstChainExpression)(node.callee);
        if ((callee == null ? void 0 : callee.type) !== "Identifier") {
          return;
        }
        const helper = resolveAstFunctionBinding(callee.name, node.start || 0, functionBindings, identifierBindings, {
          bindingMode: "initialized",
          initializedIndex: renderCall.index
        });
        if (!helper) {
          return;
        }
        usages.push(
          ...collectAstReactComponentUsagesOnFunctionRenderPath(
            helper.functionNode,
            reactCreateElementAliases,
            identifierBindings,
            functionBindings
          )
        );
      }
    });
  });
  return dedupeAstFunctionUsageEntries(usages).sort((left, right) => left.index - right.index);
}
function collectAstReactComponentUsagesFromNodes(nodes, reactCreateElementAliases, identifierBindings, functionBindings, options = {}) {
  const usages = [];
  const addUsage = (name, index) => {
    if (!name || !/^[A-Z][\w$]*$/.test(name)) {
      return;
    }
    const functionBinding = resolveAstFunctionBinding(name, index, functionBindings, identifierBindings, {
      bindingMode: "lexical"
    });
    if (functionBinding) {
      usages.push({ functionBinding, index });
    }
  };
  nodes.forEach((rootNode) => {
    if (!rootNode) {
      return;
    }
    (0, import_walk.walkAstAncestor)(rootNode, {
      JSXOpeningElement(node, ancestors) {
        if (options.nearestFunction && findNearestAstFunctionAncestor(ancestors) !== options.nearestFunction) {
          return;
        }
        addUsage(getAstJSXIdentifierName(node.name), node.start || 0);
      },
      CallExpression(node, ancestors) {
        var _a;
        if (options.nearestFunction && findNearestAstFunctionAncestor(ancestors) !== options.nearestFunction) {
          return;
        }
        if (!(0, import_react.getReactCreateElementCallCapabilityFromAst)(node, reactCreateElementAliases, identifierBindings)) {
          return;
        }
        const component = (0, import_bindings.unwrapAstChainExpression)((_a = node.arguments) == null ? void 0 : _a[0]);
        if ((component == null ? void 0 : component.type) === "Identifier") {
          addUsage(component.name, component.start || node.start || 0);
        }
      }
    });
  });
  return dedupeAstFunctionUsageEntries(usages).sort((left, right) => left.index - right.index);
}
function collectAstReactComponentUsagesOnFunctionRenderPath(functionNode, reactCreateElementAliases, identifierBindings, functionBindings, visited = /* @__PURE__ */ new Set()) {
  if (visited.has(functionNode)) {
    return [];
  }
  visited.add(functionNode);
  const usages = collectAstReactComponentUsagesFromNodes(
    [functionNode],
    reactCreateElementAliases,
    identifierBindings,
    functionBindings,
    { nearestFunction: functionNode }
  );
  (0, import_walk.walkAstAncestor)(functionNode, {
    CallExpression(node, ancestors) {
      const nearestFunction = findNearestAstFunctionAncestor(ancestors);
      if (nearestFunction !== functionNode) {
        return;
      }
      const callee = (0, import_bindings.unwrapAstChainExpression)(node.callee);
      if ((callee == null ? void 0 : callee.type) !== "Identifier") {
        return;
      }
      const helper = resolveAstFunctionBinding(callee.name, node.start || 0, functionBindings, identifierBindings, {
        bindingMode: "lexical"
      });
      if (!helper) {
        return;
      }
      usages.push(
        ...collectAstReactComponentUsagesOnFunctionRenderPath(
          helper.functionNode,
          reactCreateElementAliases,
          identifierBindings,
          functionBindings,
          visited
        )
      );
    }
  });
  return dedupeAstFunctionUsageEntries(usages).sort((left, right) => left.index - right.index);
}
function collectAstTopLevelReachableCtxRenderCallsFromAst(ast, ctxMethodAliases, identifierBindings, functionBindings) {
  const entries = [];
  (0, import_walk.walkAstAncestor)(ast, {
    CallExpression(node, ancestors) {
      if (findNearestAstFunctionAncestor(ancestors)) {
        return;
      }
      const method = (0, import_static_values.resolveCtxMethodCall)(node, ctxMethodAliases, identifierBindings);
      if ((method == null ? void 0 : method.method) === "render") {
        entries.push({
          args: [...node.arguments || []],
          capability: method.capability,
          index: node.start || 0
        });
        return;
      }
      if (!functionBindings.length) {
        return;
      }
      if (!(0, import_bindings.isAstAlwaysExecutedInCurrentExecutionScope)(ancestors)) {
        return;
      }
      const callee = (0, import_bindings.unwrapAstChainExpression)(node.callee);
      if ((callee == null ? void 0 : callee.type) !== "Identifier") {
        return;
      }
      const helper = resolveAstFunctionBinding(callee.name, node.start || 0, functionBindings, identifierBindings);
      if (!helper) {
        return;
      }
      const helperRenderCalls = collectCtxRenderCallsInFunction(
        helper.functionNode,
        ctxMethodAliases,
        identifierBindings,
        functionBindings,
        {
          bindingMode: "initialized",
          initializedIndex: node.start || 0
        }
      );
      helperRenderCalls.forEach((renderCall) => {
        entries.push({
          ...renderCall,
          index: node.start || renderCall.index
        });
      });
    }
  });
  return (0, import_bindings.dedupeIndexedEntries)(entries).sort((left, right) => left.index - right.index);
}
function getAstJSXIdentifierName(node) {
  if ((node == null ? void 0 : node.type) === "JSXIdentifier") {
    return node.name;
  }
  return void 0;
}
function findNearestAstFunctionAncestor(ancestors) {
  for (let index = ancestors.length - 1; index >= 0; index -= 1) {
    if ((0, import_bindings.isAstFunctionLike)(ancestors[index])) {
      return ancestors[index];
    }
  }
  return void 0;
}
function collectCtxRenderCallsInFunction(functionNode, ctxMethodAliases, identifierBindings, functionBindings, options, visited = /* @__PURE__ */ new Set()) {
  if (visited.has(functionNode)) {
    return [];
  }
  visited.add(functionNode);
  const renderCalls = [];
  (0, import_walk.walkAstAncestor)(functionNode, {
    CallExpression(node, ancestors) {
      const nearestFunction = findNearestAstFunctionAncestor(ancestors);
      if (nearestFunction !== functionNode) {
        return;
      }
      const method = (0, import_static_values.resolveCtxMethodCall)(node, ctxMethodAliases, identifierBindings);
      if ((method == null ? void 0 : method.method) === "render") {
        renderCalls.push({
          args: [...node.arguments || []],
          capability: method.capability,
          index: node.start || 0
        });
        return;
      }
      const callee = (0, import_bindings.unwrapAstChainExpression)(node.callee);
      if ((callee == null ? void 0 : callee.type) !== "Identifier") {
        return;
      }
      const helper = resolveAstFunctionBinding(callee.name, node.start || 0, functionBindings, identifierBindings, {
        bindingMode: options.bindingMode,
        initializedIndex: options.initializedIndex,
        currentFunctionNode: functionNode
      });
      if (!helper) {
        return;
      }
      renderCalls.push(
        ...collectCtxRenderCallsInFunction(
          helper.functionNode,
          ctxMethodAliases,
          identifierBindings,
          functionBindings,
          options,
          visited
        )
      );
    }
  });
  return renderCalls;
}
function findCtxRenderCallInFunction(functionNode, ctxMethodAliases, identifierBindings, functionBindings, options) {
  return collectCtxRenderCallsInFunction(
    functionNode,
    ctxMethodAliases,
    identifierBindings,
    functionBindings,
    options
  )[0];
}
function resolveAstFunctionBinding(name, index, functionBindings, identifierBindings, options = {}) {
  if (options.bindingMode === "lexical" || options.bindingMode === "initialized") {
    const candidates = functionBindings.filter((entry) => entry.name === name && index >= entry.scopeStart && index < entry.end).filter((entry) => {
      if (options.bindingMode !== "initialized") {
        return true;
      }
      const initializedIndex = isAstFunctionBindingScopedInsideNode(entry, options.currentFunctionNode) ? index : options.initializedIndex ?? index;
      return entry.hoisted || entry.declarationStart <= initializedIndex;
    }).sort((left, right) => right.scopeStart - left.scopeStart || right.declarationStart - left.declarationStart);
    return candidates.find(
      (entry) => !(0, import_static_values.hasAstShadowBinding)(
        name,
        index,
        {
          start: entry.scopeStart,
          end: entry.end
        },
        identifierBindings
      )
    );
  }
  return (0, import_static_values.resolveAstAliasBinding)(name, index, functionBindings, identifierBindings);
}
function isAstFunctionBindingScopedInsideNode(entry, node) {
  return typeof (node == null ? void 0 : node.start) === "number" && typeof (node == null ? void 0 : node.end) === "number" && entry.scopeStart >= node.start && entry.end <= node.end;
}
function dedupeAstFunctionUsageEntries(entries) {
  const seen = /* @__PURE__ */ new Set();
  return entries.filter((entry) => {
    const key = `${entry.functionBinding.name}:${entry.functionBinding.declarationStart}:${entry.index}`;
    if (seen.has(key)) {
      return false;
    }
    seen.add(key);
    return true;
  });
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  collectAstReactComponentCtxRenderCallsFromAst,
  collectAstReactComponentUsagesFromNodes,
  collectAstReactComponentUsagesFromRenderCall,
  collectAstReactComponentUsagesOnFunctionRenderPath,
  collectAstTopLevelReachableCtxRenderCallsFromAst,
  collectCtxRenderCallsInFunction,
  dedupeAstFunctionUsageEntries,
  findCtxRenderCallInFunction,
  findNearestAstFunctionAncestor,
  getAstJSXIdentifierName,
  isAstFunctionBindingScopedInsideNode,
  resolveAstFunctionBinding
});
