Skip to content

Commit 15635b5

Browse files
committed
refactor: extract ExecutionPlan::plan_query returning ExecutionGraph
Extract the query planning logic from ExecutionPlan::plan into a new plan_query method that accepts QueryPlanRequest and returns Result<ExecutionGraph, Error> directly. Session::plan_from_cli now returns ExecutionGraph instead of ExecutionPlan, and callers wrap it via the new ExecutionPlan::from_execution_graph constructor. Also narrows RunCommand::into_plan_request to into_query_plan_request, since it always produced a Query variant.
1 parent 15aaa2c commit 15635b5

4 files changed

Lines changed: 74 additions & 40 deletions

File tree

crates/vite_task/src/cli/mod.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use clap::Parser;
44
use vite_path::AbsolutePath;
55
use vite_str::Str;
66
use vite_task_graph::{TaskSpecifier, query::TaskQueryKind};
7-
use vite_task_plan::plan_request::{PlanOptions, PlanRequest, QueryPlanRequest};
7+
use vite_task_plan::plan_request::{PlanOptions, QueryPlanRequest};
88

99
#[derive(Debug, Clone, clap::Subcommand)]
1010
pub enum CacheSubcommand {
@@ -70,16 +70,16 @@ pub enum CLITaskQueryError {
7070
}
7171

7272
impl RunCommand {
73-
/// Convert to `PlanRequest`, or return an error if invalid.
73+
/// Convert to `QueryPlanRequest`, or return an error if invalid.
7474
///
7575
/// # Errors
7676
///
7777
/// Returns an error if `--recursive` and `--transitive` are both set,
7878
/// or if a package name is specified with `--recursive`.
79-
pub fn into_plan_request(
79+
pub fn into_query_plan_request(
8080
self,
8181
cwd: &Arc<AbsolutePath>,
82-
) -> Result<PlanRequest, CLITaskQueryError> {
82+
) -> Result<QueryPlanRequest, CLITaskQueryError> {
8383
let Self {
8484
task_specifier,
8585
flags: RunFlags { recursive, transitive, ignore_depends_on },
@@ -110,9 +110,9 @@ impl RunCommand {
110110
include_topological_deps: transitive,
111111
}
112112
};
113-
Ok(PlanRequest::Query(QueryPlanRequest {
113+
Ok(QueryPlanRequest {
114114
query: vite_task_graph::query::TaskQuery { kind: query_kind, include_explicit_deps },
115115
plan_options: PlanOptions { extra_args: additional_args.into() },
116-
}))
116+
})
117117
}
118118
}

crates/vite_task/src/session/mod.rs

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use vite_task_graph::{
2121
loader::UserConfigLoader,
2222
};
2323
use vite_task_plan::{
24-
ExecutionPlan, TaskGraphLoader, TaskPlanErrorKind,
24+
ExecutionGraph, ExecutionPlan, TaskGraphLoader, TaskPlanErrorKind,
2525
plan_request::{PlanRequest, ScriptCommand, SyntheticPlanRequest},
2626
prepend_path_env,
2727
};
@@ -102,15 +102,17 @@ impl vite_task_plan::PlanRequestParser for PlanRequestParser<'_> {
102102
Command::Cache { .. } => Ok(Some(PlanRequest::Synthetic(
103103
command.to_synthetic_plan_request(UserCacheConfig::disabled()),
104104
))),
105-
Command::Run(run_command) => match run_command.into_plan_request(&command.cwd) {
106-
Ok(plan_request) => Ok(Some(plan_request)),
107-
Err(crate::cli::CLITaskQueryError::MissingTaskSpecifier) => {
108-
Ok(Some(PlanRequest::Synthetic(
109-
command.to_synthetic_plan_request(UserCacheConfig::disabled()),
110-
)))
105+
Command::Run(run_command) => {
106+
match run_command.into_query_plan_request(&command.cwd) {
107+
Ok(query_plan_request) => Ok(Some(PlanRequest::Query(query_plan_request))),
108+
Err(crate::cli::CLITaskQueryError::MissingTaskSpecifier) => {
109+
Ok(Some(PlanRequest::Synthetic(
110+
command.to_synthetic_plan_request(UserCacheConfig::disabled()),
111+
)))
112+
}
113+
Err(err) => Err(err.into()),
111114
}
112-
Err(err) => Err(err.into()),
113-
},
115+
}
114116
},
115117
HandledCommand::Verbatim => Ok(None),
116118
}
@@ -238,7 +240,7 @@ impl<'a> Session<'a> {
238240
let additional_args = run_command.additional_args.clone();
239241

240242
match self.plan_from_cli(cwd, run_command).await {
241-
Ok(plan) if plan.is_empty() => {
243+
Ok(ref graph) if graph.node_count() == 0 => {
242244
// No tasks matched the query — show task selector / "did you mean"
243245
self.handle_no_task(
244246
is_interactive,
@@ -248,7 +250,8 @@ impl<'a> Session<'a> {
248250
)
249251
.await
250252
}
251-
Ok(plan) => {
253+
Ok(graph) => {
254+
let plan = ExecutionPlan::from_execution_graph(graph);
252255
let reporter =
253256
LabeledReporter::new(std::io::stdout(), self.workspace_path());
254257
Ok(self
@@ -398,7 +401,8 @@ impl<'a> Session<'a> {
398401
RunCommand { task_specifier: Some(task_specifier), flags, additional_args };
399402

400403
let cwd = Arc::clone(&self.cwd);
401-
let plan = self.plan_from_cli(cwd, run_command).await?;
404+
let graph = self.plan_from_cli(cwd, run_command).await?;
405+
let plan = ExecutionPlan::from_execution_graph(graph);
402406
let reporter = LabeledReporter::new(std::io::stdout(), self.workspace_path());
403407
Ok(self.execute(plan, Box::new(reporter)).await.err().unwrap_or(ExitStatus::SUCCESS))
404408
}
@@ -480,9 +484,9 @@ impl<'a> Session<'a> {
480484
&mut self,
481485
cwd: Arc<AbsolutePath>,
482486
command: RunCommand,
483-
) -> Result<ExecutionPlan, vite_task_plan::Error> {
484-
let plan_request = match command.into_plan_request(&cwd) {
485-
Ok(plan_request) => plan_request,
487+
) -> Result<ExecutionGraph, vite_task_plan::Error> {
488+
let query_plan_request = match command.into_query_plan_request(&cwd) {
489+
Ok(query_plan_request) => query_plan_request,
486490
Err(crate::cli::CLITaskQueryError::MissingTaskSpecifier) => {
487491
return Err(TaskPlanErrorKind::MissingTaskSpecifier.with_empty_call_stack());
488492
}
@@ -496,15 +500,14 @@ impl<'a> Session<'a> {
496500
.with_empty_call_stack());
497501
}
498502
};
499-
let plan = ExecutionPlan::plan(
500-
plan_request,
503+
ExecutionPlan::plan_query(
504+
query_plan_request,
501505
&self.workspace_path,
502506
&cwd,
503507
&self.envs,
504508
&mut self.plan_request_parser,
505509
&mut self.lazy_task_graph,
506510
)
507-
.await?;
508-
Ok(plan)
511+
.await
509512
}
510513
}

crates/vite_task_plan/src/lib.rs

Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ use std::{collections::BTreeMap, ffi::OsStr, fmt::Debug, sync::Arc};
1313
use context::PlanContext;
1414
use error::TaskPlanErrorKindResultExt;
1515
pub use error::{Error, TaskPlanErrorKind};
16-
use execution_graph::ExecutionGraph;
16+
pub use execution_graph::ExecutionGraph;
1717
use in_process::InProcessExecution;
1818
pub use path_env::{get_path_env, prepend_path_env};
1919
use plan::{ParentCacheConfig, plan_query_request, plan_synthetic_request};
20-
use plan_request::{PlanRequest, SyntheticPlanRequest};
20+
use plan_request::{PlanRequest, QueryPlanRequest, SyntheticPlanRequest};
2121
use rustc_hash::FxHashMap;
2222
use serde::{Serialize, ser::SerializeMap as _};
2323
use vite_graph_ser::serialize_by_key;
@@ -201,6 +201,41 @@ impl ExecutionPlan {
201201
}
202202
}
203203

204+
/// Create an execution plan from an execution graph.
205+
#[must_use]
206+
pub const fn from_execution_graph(execution_graph: ExecutionGraph) -> Self {
207+
Self { root_node: ExecutionItemKind::Expanded(execution_graph) }
208+
}
209+
210+
/// Plan a query execution: load the task graph, query it, and build the execution graph.
211+
///
212+
/// # Errors
213+
/// Returns an error if task graph loading, query, or execution planning fails.
214+
#[expect(clippy::future_not_send, reason = "PlanRequestParser and TaskGraphLoader are !Send")]
215+
pub async fn plan_query(
216+
query_plan_request: QueryPlanRequest,
217+
workspace_path: &Arc<AbsolutePath>,
218+
cwd: &Arc<AbsolutePath>,
219+
envs: &FxHashMap<Arc<OsStr>, Arc<OsStr>>,
220+
plan_request_parser: &mut (dyn PlanRequestParser + '_),
221+
task_graph_loader: &mut (dyn TaskGraphLoader + '_),
222+
) -> Result<ExecutionGraph, Error> {
223+
let indexed_task_graph = task_graph_loader
224+
.load_task_graph()
225+
.await
226+
.map_err(TaskPlanErrorKind::TaskGraphLoadError)
227+
.with_empty_call_stack()?;
228+
229+
let context = PlanContext::new(
230+
workspace_path,
231+
Arc::clone(cwd),
232+
envs.clone(),
233+
plan_request_parser,
234+
indexed_task_graph,
235+
);
236+
plan_query_request(query_plan_request, context).await
237+
}
238+
204239
/// Plan an execution from a plan request.
205240
///
206241
/// # Errors
@@ -216,20 +251,15 @@ impl ExecutionPlan {
216251
) -> Result<Self, Error> {
217252
let root_node = match plan_request {
218253
PlanRequest::Query(query_plan_request) => {
219-
let indexed_task_graph = task_graph_loader
220-
.load_task_graph()
221-
.await
222-
.map_err(TaskPlanErrorKind::TaskGraphLoadError)
223-
.with_empty_call_stack()?;
224-
225-
let context = PlanContext::new(
254+
let execution_graph = Self::plan_query(
255+
query_plan_request,
226256
workspace_path,
227-
Arc::clone(cwd),
228-
envs.clone(),
257+
cwd,
258+
envs,
229259
plan_request_parser,
230-
indexed_task_graph,
231-
);
232-
let execution_graph = plan_query_request(query_plan_request, context).await?;
260+
task_graph_loader,
261+
)
262+
.await?;
233263
ExecutionItemKind::Expanded(execution_graph)
234264
}
235265
PlanRequest::Synthetic(synthetic_plan_request) => {

crates/vite_task_plan/tests/plan_snapshots/main.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use tokio::runtime::Runtime;
1111
use vite_path::{AbsolutePath, AbsolutePathBuf, RelativePathBuf};
1212
use vite_str::Str;
1313
use vite_task::{Command, Session};
14+
use vite_task_plan::ExecutionPlan;
1415
use vite_workspace::find_workspace_root;
1516

1617
/// Local parser wrapper for `BuiltInCommand`
@@ -183,7 +184,7 @@ fn run_case_inner(
183184
session.plan_from_cli(workspace_root.path.join(plan.cwd).into(), run_command).await;
184185

185186
let plan = match plan_result {
186-
Ok(plan) => plan,
187+
Ok(graph) => ExecutionPlan::from_execution_graph(graph),
187188
Err(err) => {
188189
#[expect(
189190
clippy::disallowed_macros,

0 commit comments

Comments
 (0)