@@ -18,7 +18,7 @@ pub use path_env::{get_path_env, prepend_path_env};
1818use plan:: { ParentCacheConfig , plan_query_request, plan_synthetic_request} ;
1919use plan_request:: { PlanRequest , QueryPlanRequest , SyntheticPlanRequest } ;
2020use rustc_hash:: FxHashMap ;
21- use serde:: { Serialize , Serializer , ser:: SerializeMap as _} ;
21+ use serde:: { Serialize , ser:: SerializeMap as _} ;
2222use vite_path:: AbsolutePath ;
2323use vite_str:: Str ;
2424use vite_task_graph:: { TaskGraphLoadError , display:: TaskDisplay } ;
@@ -142,18 +142,11 @@ pub enum LeafExecutionKind {
142142///
143143/// `vite_graph_ser::serialize_by_key` expects `&DiGraph<N, E, Ix>`, so we call `.inner()`
144144/// to get the underlying `DiGraph` reference.
145- fn serialize_execution_graph_by_key < S : Serializer > (
146- graph : & ExecutionGraph ,
147- serializer : S ,
148- ) -> Result < S :: Ok , S :: Error > {
149- vite_graph_ser:: serialize_by_key ( graph. inner ( ) , serializer)
150- }
151-
152145/// An execution item, from a split subcommand in a task's command (`item1 && item2 && ...`).
153146#[ derive( Debug , Serialize ) ]
154147pub enum ExecutionItemKind {
155148 /// Expanded from a known vp subcommand, like `vp run ...` or a synthesized task.
156- Expanded ( # [ serde ( serialize_with = "serialize_execution_graph_by_key" ) ] ExecutionGraph ) ,
149+ Expanded ( ExecutionGraph ) ,
157150 /// A normal execution that spawns a child process, like `tsc --noEmit`.
158151 Leaf ( LeafExecutionKind ) ,
159152}
@@ -186,127 +179,54 @@ pub trait TaskGraphLoader {
186179 ) -> Result < & vite_task_graph:: IndexedTaskGraph , TaskGraphLoadError > ;
187180}
188181
189- #[ derive( Debug , Serialize ) ]
190- pub struct ExecutionPlan {
191- root_node : ExecutionItemKind ,
182+ /// Plan a query execution: load the task graph, query it, and build the execution graph.
183+ ///
184+ /// # Errors
185+ /// Returns an error if task graph loading, query, or execution planning fails.
186+ #[ expect( clippy:: future_not_send, reason = "PlanRequestParser and TaskGraphLoader are !Send" ) ]
187+ #[ expect( clippy:: implicit_hasher, reason = "FxHashMap is the only hasher used in this codebase" ) ]
188+ pub async fn plan_query (
189+ query_plan_request : QueryPlanRequest ,
190+ workspace_path : & Arc < AbsolutePath > ,
191+ cwd : & Arc < AbsolutePath > ,
192+ envs : & FxHashMap < Arc < OsStr > , Arc < OsStr > > ,
193+ plan_request_parser : & mut ( dyn PlanRequestParser + ' _ ) ,
194+ task_graph_loader : & mut ( dyn TaskGraphLoader + ' _ ) ,
195+ ) -> Result < ExecutionGraph , Error > {
196+ let indexed_task_graph = task_graph_loader. load_task_graph ( ) . await ?;
197+
198+ let context = PlanContext :: new (
199+ workspace_path,
200+ Arc :: clone ( cwd) ,
201+ envs. clone ( ) ,
202+ plan_request_parser,
203+ indexed_task_graph,
204+ ) ;
205+ plan_query_request ( query_plan_request, context) . await
192206}
193207
194- impl ExecutionPlan {
195- #[ must_use]
196- pub const fn root_node ( & self ) -> & ExecutionItemKind {
197- & self . root_node
198- }
199-
200- #[ must_use]
201- pub fn into_root_node ( self ) -> ExecutionItemKind {
202- self . root_node
203- }
204-
205- /// Returns `true` if the plan contains no tasks to execute.
206- #[ must_use]
207- pub fn is_empty ( & self ) -> bool {
208- match & self . root_node {
209- ExecutionItemKind :: Expanded ( graph) => graph. node_count ( ) == 0 ,
210- ExecutionItemKind :: Leaf ( _) => false ,
211- }
212- }
213-
214- /// Create an execution plan from an execution graph.
215- #[ must_use]
216- pub const fn from_execution_graph ( execution_graph : ExecutionGraph ) -> Self {
217- Self { root_node : ExecutionItemKind :: Expanded ( execution_graph) }
218- }
219-
220- /// Plan a query execution: load the task graph, query it, and build the execution graph.
221- ///
222- /// # Errors
223- /// Returns an error if task graph loading, query, or execution planning fails.
224- #[ expect( clippy:: future_not_send, reason = "PlanRequestParser and TaskGraphLoader are !Send" ) ]
225- pub async fn plan_query (
226- query_plan_request : QueryPlanRequest ,
227- workspace_path : & Arc < AbsolutePath > ,
228- cwd : & Arc < AbsolutePath > ,
229- envs : & FxHashMap < Arc < OsStr > , Arc < OsStr > > ,
230- plan_request_parser : & mut ( dyn PlanRequestParser + ' _ ) ,
231- task_graph_loader : & mut ( dyn TaskGraphLoader + ' _ ) ,
232- ) -> Result < ExecutionGraph , Error > {
233- let indexed_task_graph = task_graph_loader. load_task_graph ( ) . await ?;
234-
235- let context = PlanContext :: new (
236- workspace_path,
237- Arc :: clone ( cwd) ,
238- envs. clone ( ) ,
239- plan_request_parser,
240- indexed_task_graph,
241- ) ;
242- plan_query_request ( query_plan_request, context) . await
243- }
244-
245- /// Plan an execution from a plan request.
246- ///
247- /// # Errors
248- /// Returns an error if task graph loading, query, or execution planning fails.
249- #[ expect( clippy:: future_not_send, reason = "PlanRequestParser and TaskGraphLoader are !Send" ) ]
250- pub async fn plan (
251- plan_request : PlanRequest ,
252- workspace_path : & Arc < AbsolutePath > ,
253- cwd : & Arc < AbsolutePath > ,
254- envs : & FxHashMap < Arc < OsStr > , Arc < OsStr > > ,
255- plan_request_parser : & mut ( dyn PlanRequestParser + ' _ ) ,
256- task_graph_loader : & mut ( dyn TaskGraphLoader + ' _ ) ,
257- ) -> Result < Self , Error > {
258- let root_node = match plan_request {
259- PlanRequest :: Query ( query_plan_request) => {
260- let execution_graph = Self :: plan_query (
261- query_plan_request,
262- workspace_path,
263- cwd,
264- envs,
265- plan_request_parser,
266- task_graph_loader,
267- )
268- . await ?;
269- ExecutionItemKind :: Expanded ( execution_graph)
270- }
271- PlanRequest :: Synthetic ( synthetic_plan_request) => {
272- let execution = plan_synthetic_request (
273- workspace_path,
274- & BTreeMap :: default ( ) ,
275- synthetic_plan_request,
276- None ,
277- cwd,
278- ParentCacheConfig :: None ,
279- ) ?;
280- ExecutionItemKind :: Leaf ( LeafExecutionKind :: Spawn ( execution) )
281- }
282- } ;
283- Ok ( Self { root_node } )
284- }
285-
286- /// Plan a synthetic task execution, returning the resolved [`SpawnExecution`] directly.
287- ///
288- /// Unlike `plan_query` which returns a full execution graph, synthetic executions
289- /// are always a single spawned process. The caller can execute it directly using
290- /// `execute_spawn`.
291- ///
292- /// # Errors
293- /// Returns an error if the program is not found or path fingerprinting fails.
294- #[ expect( clippy:: result_large_err, reason = "Error is large for diagnostics" ) ]
295- pub fn plan_synthetic (
296- workspace_path : & Arc < AbsolutePath > ,
297- cwd : & Arc < AbsolutePath > ,
298- synthetic_plan_request : SyntheticPlanRequest ,
299- cache_key : Arc < [ Str ] > ,
300- ) -> Result < Self , Error > {
301- let execution_cache_key = cache_metadata:: ExecutionCacheKey :: ExecAPI ( cache_key) ;
302- let execution = plan_synthetic_request (
303- workspace_path,
304- & BTreeMap :: default ( ) ,
305- synthetic_plan_request,
306- Some ( execution_cache_key) ,
307- cwd,
308- ParentCacheConfig :: None ,
309- ) ?;
310- Ok ( Self { root_node : ExecutionItemKind :: Leaf ( LeafExecutionKind :: Spawn ( execution) ) } )
311- }
208+ /// Plan a synthetic task execution, returning the resolved [`SpawnExecution`] directly.
209+ ///
210+ /// Unlike [`plan_query`] which returns a full execution graph, synthetic executions
211+ /// are always a single spawned process. The caller can execute it directly using
212+ /// `execute_spawn`.
213+ ///
214+ /// # Errors
215+ /// Returns an error if the program is not found or path fingerprinting fails.
216+ #[ expect( clippy:: result_large_err, reason = "Error is large for diagnostics" ) ]
217+ pub fn plan_synthetic (
218+ workspace_path : & Arc < AbsolutePath > ,
219+ cwd : & Arc < AbsolutePath > ,
220+ synthetic_plan_request : SyntheticPlanRequest ,
221+ cache_key : Arc < [ Str ] > ,
222+ ) -> Result < SpawnExecution , Error > {
223+ let execution_cache_key = cache_metadata:: ExecutionCacheKey :: ExecAPI ( cache_key) ;
224+ plan_synthetic_request (
225+ workspace_path,
226+ & BTreeMap :: default ( ) ,
227+ synthetic_plan_request,
228+ Some ( execution_cache_key) ,
229+ cwd,
230+ ParentCacheConfig :: None ,
231+ )
312232}
0 commit comments