diff --git a/crates/vite_task_graph/src/lib.rs b/crates/vite_task_graph/src/lib.rs index 103987a0..5e68b458 100644 --- a/crates/vite_task_graph/src/lib.rs +++ b/crates/vite_task_graph/src/lib.rs @@ -17,25 +17,8 @@ use vite_workspace::{PackageNodeIndex, WorkspaceRoot, package_graph::IndexedPack use crate::display::TaskDisplay; -/// The type of a task dependency edge in the task graph. -/// -/// Currently only `Explicit` is produced (from `dependsOn` in `vite-task.json`). -/// Topological ordering is handled at query time via the package subgraph rather -/// than by pre-computing edges in the task graph. -#[derive(Debug, Clone, Copy, Serialize)] -pub struct TaskDependencyType; - -impl TaskDependencyType { - /// Returns `true` — all task graph edges are explicit `dependsOn` dependencies. - /// - /// Kept as an associated function for use as a filter predicate in - /// `add_dependencies`. Always returns `true` since `TaskDependencyType` - /// only represents explicit edges now. - #[must_use] - pub const fn is_explicit() -> bool { - true - } -} +// Task dependency edges are all explicit `dependsOn` dependencies. +// Topological ordering is handled at query time via the package subgraph. /// Uniquely identifies a task, by its name and the package where it's defined. #[derive(Debug, PartialEq, Eq, Hash, Clone, PartialOrd, Ord)] @@ -180,7 +163,7 @@ pub type TaskEdgeIndex = EdgeIndex; /// External factors (e.g. additional args from cli, current working directory, environmental variables) are not stored here. #[derive(Debug)] pub struct IndexedTaskGraph { - task_graph: DiGraph, + task_graph: DiGraph, /// Preserve the package graph for two purposes: /// - `self.task_graph` refers packages via `PackageNodeIndex`. To display package names and paths, we need to lookup them in `package_graph`. @@ -200,7 +183,7 @@ pub struct IndexedTaskGraph { pre_post_scripts_enabled: bool, } -pub type TaskGraph = DiGraph; +pub type TaskGraph = DiGraph; impl IndexedTaskGraph { /// Load the task graph from a discovered workspace using the provided config loader. @@ -219,7 +202,7 @@ impl IndexedTaskGraph { workspace_root: &WorkspaceRoot, config_loader: &dyn loader::UserConfigLoader, ) -> Result { - let mut task_graph = DiGraph::::default(); + let mut task_graph = DiGraph::::default(); let package_graph = vite_workspace::load_package_graph(workspace_root)?; @@ -227,10 +210,11 @@ impl IndexedTaskGraph { let mut task_ids_with_dependency_specifiers: Vec<(TaskId, Option>)> = Vec::new(); // index tasks by ids + let estimated_task_count = package_graph.node_count() * 2; let mut node_indices_by_task_id: FxHashMap = - FxHashMap::with_capacity_and_hasher(task_graph.node_count(), FxBuildHasher); + FxHashMap::with_capacity_and_hasher(estimated_task_count, FxBuildHasher); let mut task_ids_by_node_index: FxHashMap = - FxHashMap::with_capacity_and_hasher(task_graph.node_count(), FxBuildHasher); + FxHashMap::with_capacity_and_hasher(estimated_task_count, FxBuildHasher); // First pass: load all configs, extract root cache config, validate let mut root_cache = None; @@ -305,6 +289,12 @@ impl IndexedTaskGraph { let dependency_specifiers = task_user_config.options.depends_on.clone(); + let task_display = TaskDisplay { + package_name: package.package_json.name.clone(), + task_name: task_name.clone(), + package_path: Arc::clone(&package_dir), + }; + // Resolve the task configuration from the user config let resolved_config = ResolvedTaskConfig::resolve( task_user_config, @@ -313,22 +303,11 @@ impl IndexedTaskGraph { ) .map_err(|err| TaskGraphLoadError::ResolveConfigError { error: err, - task_display: TaskDisplay { - package_name: package.package_json.name.clone(), - task_name: task_name.clone(), - package_path: Arc::clone(&package_dir), - }, + task_display: task_display.clone(), })?; - let task_node = TaskNode { - task_display: TaskDisplay { - package_name: package.package_json.name.clone(), - task_name: task_name.clone(), - package_path: Arc::clone(&package_dir), - }, - resolved_config, - source: TaskSource::TaskConfig, - }; + let task_node = + TaskNode { task_display, resolved_config, source: TaskSource::TaskConfig }; let node_index = task_graph.add_node(task_node); task_ids_with_dependency_specifiers.push((task_id.clone(), dependency_specifiers)); @@ -339,6 +318,11 @@ impl IndexedTaskGraph { // For remaining package.json scripts not in the tasks map, create tasks with default config for (script_name, package_json_script) in package_json_scripts { let task_id = TaskId { task_name: Str::from(script_name), package_index }; + let task_display = TaskDisplay { + package_name: package.package_json.name.clone(), + task_name: script_name.into(), + package_path: Arc::clone(&package_dir), + }; let resolved_config = ResolvedTaskConfig::resolve_package_json_script( &package_dir, package_json_script, @@ -346,18 +330,10 @@ impl IndexedTaskGraph { ) .map_err(|err| TaskGraphLoadError::ResolveConfigError { error: err, - task_display: TaskDisplay { - package_name: package.package_json.name.clone(), - task_name: script_name.into(), - package_path: Arc::clone(&package_dir), - }, + task_display: task_display.clone(), })?; let node_index = task_graph.add_node(TaskNode { - task_display: TaskDisplay { - package_name: package.package_json.name.clone(), - task_name: script_name.into(), - package_path: Arc::clone(&package_dir), - }, + task_display, resolved_config, source: TaskSource::PackageJsonScript, }); @@ -390,7 +366,7 @@ impl IndexedTaskGraph { specifier, task_display: me.display_task(from_node_index), })?; - me.task_graph.update_edge(from_node_index, to_node_index, TaskDependencyType); + me.task_graph.update_edge(from_node_index, to_node_index, ()); } } diff --git a/crates/vite_task_graph/src/query/mod.rs b/crates/vite_task_graph/src/query/mod.rs index 8d99ec9d..070fbc48 100644 --- a/crates/vite_task_graph/src/query/mod.rs +++ b/crates/vite_task_graph/src/query/mod.rs @@ -22,7 +22,7 @@ use vite_str::Str; use vite_workspace::PackageNodeIndex; pub use vite_workspace::package_graph::{PackageQuery, PackageQueryResolveError}; -use crate::{IndexedTaskGraph, TaskDependencyType, TaskId, TaskNodeIndex}; +use crate::{IndexedTaskGraph, TaskId, TaskNodeIndex}; /// A task execution graph queried from a `TaskQuery`. /// @@ -109,7 +109,7 @@ impl IndexedTaskGraph { // Expand explicit dependsOn edges (may add new task nodes from outside the subgraph). if query.include_explicit_deps { - self.add_dependencies(&mut execution_graph, |_| TaskDependencyType::is_explicit()); + self.add_dependencies(&mut execution_graph); } Ok(TaskQueryResult { execution_graph, unmatched_selectors: resolution.unmatched_selectors }) @@ -177,16 +177,11 @@ impl IndexedTaskGraph { } } - /// Recursively add dependencies to the execution graph based on filtered edges. + /// Recursively add explicit `dependsOn` dependencies to the execution graph. /// - /// Starts from the current nodes in `execution_graph` and follows outgoing edges - /// that match `filter_edge`, adding new nodes to the frontier until no new nodes - /// are discovered. - fn add_dependencies( - &self, - execution_graph: &mut TaskExecutionGraph, - mut filter_edge: impl FnMut(TaskDependencyType) -> bool, - ) { + /// Starts from the current nodes in `execution_graph` and follows outgoing edges, + /// adding new nodes to the frontier until no new nodes are discovered. + fn add_dependencies(&self, execution_graph: &mut TaskExecutionGraph) { let mut frontier: FxHashSet = execution_graph.nodes().collect(); // Continue until no new nodes are added to the frontier. @@ -196,13 +191,10 @@ impl IndexedTaskGraph { for from_node in frontier { for edge_ref in self.task_graph.edges(from_node) { let to_node = edge_ref.target(); - let dep_type = *edge_ref.weight(); - if filter_edge(dep_type) { - let is_new = !execution_graph.contains_node(to_node); - execution_graph.add_edge(from_node, to_node, ()); - if is_new { - next_frontier.insert(to_node); - } + let is_new = !execution_graph.contains_node(to_node); + execution_graph.add_edge(from_node, to_node, ()); + if is_new { + next_frontier.insert(to_node); } } }