// src/actions/dead/evaluateRules.ts
import path from "node:path";

// src/lib/match.ts
import { minimatch } from "minimatch";
function makeMatcher(pattern, options = {}) {
  const patterns = Array.isArray(pattern) ? pattern : [pattern];
  return (input) => patterns.some((p) => minimatch(input, p, options));
}
function isMatch(input, pattern, options = {}) {
  return makeMatcher(pattern, options)(input);
}

// src/actions/dead/ruleConfig.ts
function isPackageIgnoredByRule(packageName, options) {
  return options?.ignore?.some((pattern) => pattern === packageName || isMatch(packageName, pattern)) ?? false;
}

// src/actions/dead/evaluateRules.ts
var SCOPE_NARROWNESS = {
  package: 0,
  repo: 1,
  workspace: 2
};
function isConsumed(name, pkgUsage) {
  if (pkgUsage.hasNamespace) return true;
  if (name === "default" && pkgUsage.hasDefault) return true;
  return pkgUsage.named.has(name);
}
function makeFinding(analysis, rule, scope, file, symbol, line, column, detail, isDeprecated) {
  return {
    column,
    deprecated: isDeprecated,
    detail,
    file: path.relative(analysis.location, file),
    line,
    pkg: analysis.packageName,
    rule,
    scope,
    symbol
  };
}
function symbolDeprecated(analysis, file, line, column, symbol) {
  return analysis.symbols.find((candidate) => candidate.file === file && candidate.line === line && candidate.column === column && candidate.name === symbol)?.deprecated;
}
function makeExportFinding(analysis, rule, scope, exp, detail) {
  return makeFinding(
    analysis,
    rule,
    scope,
    exp.file,
    exp.name,
    exp.line,
    exp.column,
    detail,
    symbolDeprecated(analysis, exp.file, exp.line, exp.column, exp.name)
  );
}
function findingDedupeKey(finding) {
  return `${finding.pkg}\0${finding.file}\0${finding.line}\0${finding.column}\0${finding.symbol}`;
}
function dedupeToNarrowestScope(findings) {
  const best = /* @__PURE__ */ new Map();
  for (const finding of findings) {
    const key = findingDedupeKey(finding);
    const existing = best.get(key);
    if (!existing || SCOPE_NARROWNESS[finding.scope] < SCOPE_NARROWNESS[existing.scope]) {
      best.set(key, finding);
    }
  }
  return best.values().toArray();
}
function isRuleApplicableToPackage(rule, analysis) {
  if (isPackageIgnoredByRule(analysis.packageName, rule.options)) return false;
  if (!rule.appliesToVisibility) return true;
  return rule.appliesToVisibility.includes(analysis.visibility);
}
function evaluateInternalRule(analysis, rule, shouldUseMonorepoRefs) {
  const findings = [];
  for (const symbol of analysis.symbols) {
    const isReferenced = symbol[shouldUseMonorepoRefs ? "usedInMonorepo" : "isUsedInPackage"];
    if (symbol.onPublicSurface || isReferenced) continue;
    findings.push(makeFinding(
      analysis,
      rule.id,
      rule.meta.scope,
      symbol.file,
      symbol.name,
      symbol.line,
      symbol.column,
      void 0,
      symbol.deprecated
    ));
  }
  return findings;
}
function evaluateExportRule(analysis, rule, usage, detail) {
  const pkgUsage = usage.get(analysis.packageName);
  const findings = [];
  for (const exp of analysis.publicExports) {
    if (pkgUsage && isConsumed(exp.name, pkgUsage)) continue;
    findings.push(makeExportFinding(analysis, rule.id, rule.meta.scope, exp, detail));
  }
  return findings;
}
function evaluatePackageRules(analysis, rule) {
  if (rule.id === "dead.package.internal") {
    return evaluateInternalRule(analysis, rule, false);
  }
  return [];
}
function evaluateRepoRules(analysis, rule, repoUsage) {
  if (rule.id === "dead.repo.internal") {
    return evaluateInternalRule(analysis, rule, true);
  }
  if (rule.id === "dead.repo.export") {
    return evaluateExportRule(analysis, rule, repoUsage, "no consumer in monorepo");
  }
  return [];
}
function evaluateWorkspaceRules(analysis, rule, workspaceUsage) {
  if (rule.id === "dead.workspace.export" || rule.id === "dead.workspace.export-published") {
    return evaluateExportRule(analysis, rule, workspaceUsage, "no consumer in workspace");
  }
  return [];
}
function evaluateRuleForAnalysis(analysis, rule, repoUsage, workspaceUsage) {
  if (!isRuleApplicableToPackage(rule, analysis)) return [];
  if (rule.meta.scope === "package") {
    return evaluatePackageRules(analysis, rule);
  }
  if (rule.meta.scope === "repo") {
    return evaluateRepoRules(analysis, rule, repoUsage);
  }
  if (rule.meta.scope === "workspace" && workspaceUsage !== void 0) {
    return evaluateWorkspaceRules(analysis, rule, workspaceUsage);
  }
  return [];
}
function evaluateDeadRules(analyses, rules, repoUsage, workspaceUsage) {
  const findings = [];
  const enabledRules = rules.filter((rule) => rule.enabled);
  for (const analysis of analyses) {
    for (const rule of enabledRules) {
      findings.push(...evaluateRuleForAnalysis(analysis, rule, repoUsage, workspaceUsage));
    }
  }
  return dedupeToNarrowestScope(findings);
}
function getDisabledWorkspaceRules(rules, hasCodeWorkspace) {
  if (hasCodeWorkspace) return [];
  return rules.filter((rule) => rule.requiresCodeWorkspace === true && rule.enabled).map((rule) => rule.id);
}
export {
  dedupeToNarrowestScope,
  evaluateDeadRules,
  getDisabledWorkspaceRules
};
//# sourceMappingURL=evaluateRules.mjs.map
