@@ -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,13 +142,6 @@ 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 ) ]
154147#[ expect(
@@ -157,7 +150,7 @@ fn serialize_execution_graph_by_key<S: Serializer>(
157150) ]
158151pub enum ExecutionItemKind {
159152 /// Expanded from a known vp subcommand, like `vp run ...` or a synthesized task.
160- Expanded ( # [ serde ( serialize_with = "serialize_execution_graph_by_key" ) ] ExecutionGraph ) ,
153+ Expanded ( ExecutionGraph ) ,
161154 /// A normal execution that spawns a child process, like `tsc --noEmit`.
162155 Leaf ( LeafExecutionKind ) ,
163156}
@@ -190,127 +183,54 @@ pub trait TaskGraphLoader {
190183 ) -> Result < & vite_task_graph:: IndexedTaskGraph , TaskGraphLoadError > ;
191184}
192185
193- #[ derive( Debug , Serialize ) ]
194- pub struct ExecutionPlan {
195- root_node : ExecutionItemKind ,
186+ /// Plan a query execution: load the task graph, query it, and build the execution graph.
187+ ///
188+ /// # Errors
189+ /// Returns an error if task graph loading, query, or execution planning fails.
190+ #[ expect( clippy:: future_not_send, reason = "PlanRequestParser and TaskGraphLoader are !Send" ) ]
191+ #[ expect( clippy:: implicit_hasher, reason = "FxHashMap is the only hasher used in this codebase" ) ]
192+ pub async fn plan_query (
193+ query_plan_request : QueryPlanRequest ,
194+ workspace_path : & Arc < AbsolutePath > ,
195+ cwd : & Arc < AbsolutePath > ,
196+ envs : & FxHashMap < Arc < OsStr > , Arc < OsStr > > ,
197+ plan_request_parser : & mut ( dyn PlanRequestParser + ' _ ) ,
198+ task_graph_loader : & mut ( dyn TaskGraphLoader + ' _ ) ,
199+ ) -> Result < ExecutionGraph , Error > {
200+ let indexed_task_graph = task_graph_loader. load_task_graph ( ) . await ?;
201+
202+ let context = PlanContext :: new (
203+ workspace_path,
204+ Arc :: clone ( cwd) ,
205+ envs. clone ( ) ,
206+ plan_request_parser,
207+ indexed_task_graph,
208+ ) ;
209+ plan_query_request ( query_plan_request, context) . await
196210}
197211
198- impl ExecutionPlan {
199- #[ must_use]
200- pub const fn root_node ( & self ) -> & ExecutionItemKind {
201- & self . root_node
202- }
203-
204- #[ must_use]
205- pub fn into_root_node ( self ) -> ExecutionItemKind {
206- self . root_node
207- }
208-
209- /// Returns `true` if the plan contains no tasks to execute.
210- #[ must_use]
211- pub fn is_empty ( & self ) -> bool {
212- match & self . root_node {
213- ExecutionItemKind :: Expanded ( graph) => graph. node_count ( ) == 0 ,
214- ExecutionItemKind :: Leaf ( _) => false ,
215- }
216- }
217-
218- /// Create an execution plan from an execution graph.
219- #[ must_use]
220- pub const fn from_execution_graph ( execution_graph : ExecutionGraph ) -> Self {
221- Self { root_node : ExecutionItemKind :: Expanded ( execution_graph) }
222- }
223-
224- /// Plan a query execution: load the task graph, query it, and build the execution graph.
225- ///
226- /// # Errors
227- /// Returns an error if task graph loading, query, or execution planning fails.
228- #[ expect( clippy:: future_not_send, reason = "PlanRequestParser and TaskGraphLoader are !Send" ) ]
229- pub async fn plan_query (
230- query_plan_request : QueryPlanRequest ,
231- workspace_path : & Arc < AbsolutePath > ,
232- cwd : & Arc < AbsolutePath > ,
233- envs : & FxHashMap < Arc < OsStr > , Arc < OsStr > > ,
234- plan_request_parser : & mut ( dyn PlanRequestParser + ' _ ) ,
235- task_graph_loader : & mut ( dyn TaskGraphLoader + ' _ ) ,
236- ) -> Result < ExecutionGraph , Error > {
237- let indexed_task_graph = task_graph_loader. load_task_graph ( ) . await ?;
238-
239- let context = PlanContext :: new (
240- workspace_path,
241- Arc :: clone ( cwd) ,
242- envs. clone ( ) ,
243- plan_request_parser,
244- indexed_task_graph,
245- ) ;
246- plan_query_request ( query_plan_request, context) . await
247- }
248-
249- /// Plan an execution from a plan request.
250- ///
251- /// # Errors
252- /// Returns an error if task graph loading, query, or execution planning fails.
253- #[ expect( clippy:: future_not_send, reason = "PlanRequestParser and TaskGraphLoader are !Send" ) ]
254- pub async fn plan (
255- plan_request : PlanRequest ,
256- workspace_path : & Arc < AbsolutePath > ,
257- cwd : & Arc < AbsolutePath > ,
258- envs : & FxHashMap < Arc < OsStr > , Arc < OsStr > > ,
259- plan_request_parser : & mut ( dyn PlanRequestParser + ' _ ) ,
260- task_graph_loader : & mut ( dyn TaskGraphLoader + ' _ ) ,
261- ) -> Result < Self , Error > {
262- let root_node = match plan_request {
263- PlanRequest :: Query ( query_plan_request) => {
264- let execution_graph = Self :: plan_query (
265- query_plan_request,
266- workspace_path,
267- cwd,
268- envs,
269- plan_request_parser,
270- task_graph_loader,
271- )
272- . await ?;
273- ExecutionItemKind :: Expanded ( execution_graph)
274- }
275- PlanRequest :: Synthetic ( synthetic_plan_request) => {
276- let execution = plan_synthetic_request (
277- workspace_path,
278- & BTreeMap :: default ( ) ,
279- synthetic_plan_request,
280- None ,
281- cwd,
282- ParentCacheConfig :: None ,
283- ) ?;
284- ExecutionItemKind :: Leaf ( LeafExecutionKind :: Spawn ( execution) )
285- }
286- } ;
287- Ok ( Self { root_node } )
288- }
289-
290- /// Plan a synthetic task execution, returning the resolved [`SpawnExecution`] directly.
291- ///
292- /// Unlike `plan_query` which returns a full execution graph, synthetic executions
293- /// are always a single spawned process. The caller can execute it directly using
294- /// `execute_spawn`.
295- ///
296- /// # Errors
297- /// Returns an error if the program is not found or path fingerprinting fails.
298- #[ expect( clippy:: result_large_err, reason = "Error is large for diagnostics" ) ]
299- pub fn plan_synthetic (
300- workspace_path : & Arc < AbsolutePath > ,
301- cwd : & Arc < AbsolutePath > ,
302- synthetic_plan_request : SyntheticPlanRequest ,
303- cache_key : Arc < [ Str ] > ,
304- ) -> Result < Self , Error > {
305- let execution_cache_key = cache_metadata:: ExecutionCacheKey :: ExecAPI ( cache_key) ;
306- let execution = plan_synthetic_request (
307- workspace_path,
308- & BTreeMap :: default ( ) ,
309- synthetic_plan_request,
310- Some ( execution_cache_key) ,
311- cwd,
312- ParentCacheConfig :: None ,
313- ) ?;
314- Ok ( Self { root_node : ExecutionItemKind :: Leaf ( LeafExecutionKind :: Spawn ( execution) ) } )
315- }
212+ /// Plan a synthetic task execution, returning the resolved [`SpawnExecution`] directly.
213+ ///
214+ /// Unlike [`plan_query`] which returns a full execution graph, synthetic executions
215+ /// are always a single spawned process. The caller can execute it directly using
216+ /// `execute_spawn`.
217+ ///
218+ /// # Errors
219+ /// Returns an error if the program is not found or path fingerprinting fails.
220+ #[ expect( clippy:: result_large_err, reason = "Error is large for diagnostics" ) ]
221+ pub fn plan_synthetic (
222+ workspace_path : & Arc < AbsolutePath > ,
223+ cwd : & Arc < AbsolutePath > ,
224+ synthetic_plan_request : SyntheticPlanRequest ,
225+ cache_key : Arc < [ Str ] > ,
226+ ) -> Result < SpawnExecution , Error > {
227+ let execution_cache_key = cache_metadata:: ExecutionCacheKey :: ExecAPI ( cache_key) ;
228+ plan_synthetic_request (
229+ workspace_path,
230+ & BTreeMap :: default ( ) ,
231+ synthetic_plan_request,
232+ Some ( execution_cache_key) ,
233+ cwd,
234+ ParentCacheConfig :: None ,
235+ )
316236}
0 commit comments