use std::path::Path;
use rustc_hash::{FxHashMap, FxHashSet};
use fallow_types::extract::ModuleInfo;
use crate::discover::FileId;
use crate::graph::ModuleGraph;
use crate::results::{AnalysisResults, UnusedServerAction, UnusedServerActionFinding};
use crate::suppress::{IssueKind, SuppressionContext};
pub fn reclassify_unused_server_actions(
graph: &ModuleGraph,
modules: &[ModuleInfo],
declared_deps: &FxHashSet<String>,
suppressions: &SuppressionContext<'_>,
results: &mut AnalysisResults,
) {
if !declared_deps.contains("next") {
return;
}
let use_server_ids: FxHashSet<FileId> = modules
.iter()
.filter(|m| m.directives.iter().any(|d| d == "use server"))
.map(|m| m.file_id)
.collect();
if use_server_ids.is_empty() {
return;
}
let file_id_by_path: FxHashMap<&Path, FileId> = graph
.modules
.iter()
.map(|node| (node.path.as_path(), node.file_id))
.collect();
let mut reclassified: Vec<UnusedServerAction> = Vec::new();
results.unused_exports.retain(|finding| {
let export = &finding.export;
if export.is_type_only || export.is_re_export {
return true;
}
let Some(&file_id) = file_id_by_path.get(export.path.as_path()) else {
return true;
};
if !use_server_ids.contains(&file_id) {
return true;
}
if suppressions.is_suppressed(file_id, export.line, IssueKind::UnusedServerAction)
|| suppressions.is_file_suppressed(file_id, IssueKind::UnusedServerAction)
{
return false;
}
reclassified.push(UnusedServerAction {
path: export.path.clone(),
action_name: export.export_name.clone(),
line: export.line,
col: export.col,
});
false
});
results.unused_server_actions = reclassified
.into_iter()
.map(UnusedServerActionFinding::with_actions)
.collect();
}