mod framework;
mod package_json;
use crate::config::Config;
use crate::core::{CallGraph, Result};
use std::path::Path;
pub fn discover_entry_points(
call_graph: &mut CallGraph,
root_path: &Path,
config: &Config,
) -> Result<()> {
for entry_file in &config.entry.files {
mark_file_exports_as_entry_points(call_graph, entry_file);
}
for pattern in &config.entry.patterns {
mark_pattern_as_entry_points(call_graph, root_path, pattern);
}
if config.entry.auto_detect {
let package_json_path = root_path.join("package.json");
if package_json_path.exists() {
package_json::mark_package_json_entry_points(call_graph, &package_json_path)?;
}
}
if config.plugins.auto_detect || !config.plugins.enabled.is_empty() {
framework::discover_framework_entry_points(call_graph, root_path, config)?;
}
for export_name in &config.entry.exports {
mark_export_as_entry_point(call_graph, export_name);
}
mark_side_effect_files_as_entry_points(call_graph);
Ok(())
}
fn mark_file_exports_as_entry_points(call_graph: &mut CallGraph, file_path: &Path) {
let file_id = call_graph
.files
.values()
.find(|f| f.path == file_path)
.map(|f| f.id);
if let Some(file_id) = file_id {
let symbols_to_mark: Vec<_> = call_graph
.symbols
.values()
.filter(|s| s.file_id == file_id && s.exported)
.map(|s| s.id)
.collect();
for id in symbols_to_mark {
call_graph.mark_entry_point(id);
}
}
}
fn mark_pattern_as_entry_points(call_graph: &mut CallGraph, root_path: &Path, pattern: &str) {
let full_pattern = root_path.join(pattern).display().to_string();
if let Ok(glob_pattern) = glob::Pattern::new(&full_pattern) {
let matching_files: Vec<_> = call_graph
.files
.values()
.filter(|f| glob_pattern.matches_path(&f.path))
.map(|f| f.id)
.collect();
for file_id in matching_files {
let symbols_to_mark: Vec<_> = call_graph
.symbols
.values()
.filter(|s| s.file_id == file_id && s.exported)
.map(|s| s.id)
.collect();
for id in symbols_to_mark {
call_graph.mark_entry_point(id);
}
}
}
}
fn mark_export_as_entry_point(call_graph: &mut CallGraph, export_name: &str) {
let symbols_to_mark: Vec<_> = call_graph
.symbols
.values()
.filter(|s| s.exported && s.name == export_name)
.map(|s| s.id)
.collect();
for id in symbols_to_mark {
call_graph.mark_entry_point(id);
}
}
fn mark_side_effect_files_as_entry_points(call_graph: &mut CallGraph) {
let side_effect_file_ids: Vec<_> = call_graph
.files
.values()
.filter(|f| f.has_side_effects)
.map(|f| f.id)
.collect();
for file_id in side_effect_file_ids {
let symbols_to_mark: Vec<_> = call_graph
.symbols
.values()
.filter(|s| s.file_id == file_id)
.map(|s| s.id)
.collect();
for id in symbols_to_mark {
call_graph.mark_entry_point(id);
}
}
}