1use super::*;
2
3use super::parser_facade::parse_omena_query_omena_parser_style_source;
4
5mod context;
6mod css_modules;
7mod design_tokens;
8mod imports;
9mod static_stylesheet;
10
11use context::{
12 find_target_style_source, merge_target_options_transform_context, merge_transform_context,
13};
14use css_modules::{
15 derive_class_name_rewrites_for_transform_context,
16 derive_css_module_composes_resolutions_for_transform_context,
17 derive_css_module_value_resolutions_for_transform_context,
18};
19use design_tokens::derive_design_token_routes_for_transform_context;
20use imports::derive_import_inlines_for_transform_context;
21use static_stylesheet::{
22 derive_static_scss_module_use_evaluations_for_transform_context,
23 derive_static_stylesheet_module_evaluation_for_transform_context,
24};
25
26pub fn summarize_omena_query_transform_plan_from_source(
27 style_path: &str,
28 style_source: &str,
29 target_label: &str,
30 target_support: OmenaQueryTargetFeatureSupportV0,
31 target_options: OmenaQueryTargetTransformOptionsV0,
32 print_options: OmenaQueryTransformPrintOptionsV0,
33) -> OmenaQueryTransformPlanSummaryV0 {
34 summarize_omena_query_transform_plan_from_source_with_context(
35 style_path,
36 style_source,
37 target_label,
38 target_support,
39 target_options,
40 print_options,
41 &TransformExecutionContextV0::default(),
42 )
43}
44
45pub fn summarize_omena_query_transform_plan_from_source_with_context(
46 style_path: &str,
47 style_source: &str,
48 target_label: &str,
49 target_support: OmenaQueryTargetFeatureSupportV0,
50 target_options: OmenaQueryTargetTransformOptionsV0,
51 print_options: OmenaQueryTransformPrintOptionsV0,
52 context: &TransformExecutionContextV0,
53) -> OmenaQueryTransformPlanSummaryV0 {
54 let dialect = omena_parser_dialect_for_style_path(style_path);
55 let bundle = summarize_omena_transform_bundle_from_source(style_path, style_source, dialect);
56 let target = plan_target_transforms(target_label, target_support, target_options);
57 let execution_context = merge_target_options_transform_context(context, target_options);
58 summarize_omena_query_transform_plan_from_parts(TransformPlanPartsV0 {
59 style_path,
60 style_source,
61 dialect,
62 bundle,
63 target,
64 target_query: None,
65 print_options,
66 context: &execution_context,
67 })
68}
69
70pub fn summarize_omena_query_transform_plan_from_target_query(
71 style_path: &str,
72 style_source: &str,
73 target_query: &str,
74 target_options: OmenaQueryTargetTransformOptionsV0,
75 print_options: OmenaQueryTransformPrintOptionsV0,
76) -> OmenaQueryTransformPlanSummaryV0 {
77 summarize_omena_query_transform_plan_from_target_query_with_context(
78 style_path,
79 style_source,
80 target_query,
81 target_options,
82 print_options,
83 &TransformExecutionContextV0::default(),
84 )
85}
86
87pub fn summarize_omena_query_transform_plan_from_target_query_with_context(
88 style_path: &str,
89 style_source: &str,
90 target_query: &str,
91 target_options: OmenaQueryTargetTransformOptionsV0,
92 print_options: OmenaQueryTransformPrintOptionsV0,
93 context: &TransformExecutionContextV0,
94) -> OmenaQueryTransformPlanSummaryV0 {
95 let dialect = omena_parser_dialect_for_style_path(style_path);
96 let bundle = summarize_omena_transform_bundle_from_source(style_path, style_source, dialect);
97 let target_query_plan = plan_target_transforms_from_query(target_query, target_options);
98 let target = target_query_plan.transform_plan.clone();
99 let execution_context = merge_target_options_transform_context(context, target_options);
100 summarize_omena_query_transform_plan_from_parts(TransformPlanPartsV0 {
101 style_path,
102 style_source,
103 dialect,
104 bundle,
105 target,
106 target_query: Some(target_query_plan),
107 print_options,
108 context: &execution_context,
109 })
110}
111
112struct TransformPlanPartsV0<'a> {
113 style_path: &'a str,
114 style_source: &'a str,
115 dialect: OmenaParserStyleDialect,
116 bundle: TransformBundleSourceSummaryV0,
117 target: TransformTargetPlanV0,
118 target_query: Option<OmenaQueryTransformTargetQueryPlanV0>,
119 print_options: OmenaQueryTransformPrintOptionsV0,
120 context: &'a TransformExecutionContextV0,
121}
122
123fn summarize_omena_query_transform_plan_from_parts(
124 parts: TransformPlanPartsV0<'_>,
125) -> OmenaQueryTransformPlanSummaryV0 {
126 let egg = plan_egg_rewrite_passes_for_source(parts.style_source);
127 let custom_property_fixed_point = summarize_static_css_custom_property_fixed_point_from_source(
128 parts.style_source,
129 parts.dialect,
130 );
131
132 let mut combined_passes = Vec::new();
133 extend_passes_from_ids(&parts.bundle.planned_pass_ids, &mut combined_passes);
134 extend_passes_from_ids(&parts.target.planned_pass_ids, &mut combined_passes);
135 extend_passes_from_ids(&egg.planned_pass_ids, &mut combined_passes);
136 combined_passes.push(TransformPassKind::PrintCss);
137 combined_passes.sort_by_key(|pass| pass.ordinal());
138 combined_passes.dedup();
139
140 let combined_plan = plan_transform_passes(&combined_passes);
141 let semantic_signature = format!(
142 "omena-query-transform:{}:{}",
143 parts.style_path,
144 parts.style_source.len()
145 );
146 let execution = execute_transform_passes_on_source_with_dialect_and_context(
147 parts.style_source,
148 parts.dialect,
149 &combined_passes,
150 parts.context,
151 );
152 let print = print_transform_execution_artifact_with_dialect_and_source(
153 parts.style_path,
154 parts.style_source,
155 parts.dialect,
156 semantic_signature,
157 &combined_passes,
158 parts.print_options,
159 &execution,
160 );
161 let egg_witnesses = execute_egg_rewrite_witnesses_for_css_source(
162 parts.style_source,
163 &execution.output_css,
164 &egg.planned_pass_ids,
165 );
166 let semantic_removal_count = execution.semantic_removals.len();
167 let combined_pass_ids = combined_plan.ordered_pass_ids.clone();
168 let combined_violated_dag_edge_count = combined_plan.violated_dag_edge_count;
169
170 OmenaQueryTransformPlanSummaryV0 {
171 schema_version: "0",
172 product: "omena-query.transform-plan",
173 style_path: parts.style_path.to_string(),
174 dialect: omena_parser_style_dialect_label(parts.dialect),
175 bundle: parts.bundle,
176 target: parts.target,
177 target_query: parts.target_query,
178 egg,
179 egg_witnesses,
180 custom_property_fixed_point,
181 print,
182 execution,
183 semantic_removal_count,
184 combined_plan,
185 combined_pass_ids,
186 combined_violated_dag_edge_count,
187 ready_surfaces: vec![
188 "transformBundlePlan",
189 "transformTargetPlan",
190 "transformEggPlan",
191 "transformEggExecutionWitnesses",
192 "customPropertyLeastFixedPoint",
193 "transformPrintArtifact",
194 "transformExecutionRuntime",
195 "cascadeProofObligations",
196 "combinedTransformPassPlan",
197 ],
198 }
199}
200
201pub fn execute_omena_query_transform_passes_from_source(
202 style_path: &str,
203 style_source: &str,
204 requested_pass_ids: &[String],
205) -> OmenaQueryTransformExecuteSummaryV0 {
206 execute_omena_query_transform_passes_from_source_with_context(
207 style_path,
208 style_source,
209 requested_pass_ids,
210 &TransformExecutionContextV0::default(),
211 )
212}
213
214pub fn summarize_omena_query_consumer_check_style_source(
215 style_path: &str,
216 style_source: &str,
217) -> OmenaQueryConsumerCheckSummaryV0 {
218 let dialect = omena_parser_dialect_for_style_path(style_path);
219 let parse_result = parse_omena_query_omena_parser_style_source(style_source, dialect);
220 let style_facts = summarize_omena_query_omena_parser_style_facts(style_source, dialect);
221
222 OmenaQueryConsumerCheckSummaryV0 {
223 schema_version: "0",
224 product: "omena-query.consumer-check-style-source",
225 style_path: style_path.to_string(),
226 dialect: omena_parser_style_dialect_label(dialect),
227 token_count: parse_result.token_count(),
228 parser_error_count: parse_result.errors().len(),
229 class_selector_count: style_facts.class_selector_names.len(),
230 custom_property_count: style_facts.custom_property_names.len(),
231 keyframe_count: style_facts.keyframe_names.len(),
232 ready_surfaces: vec![
233 "consumerCheckFacade",
234 "parserFactSummary",
235 "styleDocumentDiagnostics",
236 ],
237 }
238}
239
240pub fn execute_omena_query_consumer_build_style_source(
241 style_path: &str,
242 style_source: &str,
243 requested_pass_ids: &[String],
244) -> OmenaQueryConsumerBuildSummaryV0 {
245 execute_omena_query_consumer_build_style_source_with_context(
246 style_path,
247 style_source,
248 requested_pass_ids,
249 &TransformExecutionContextV0::default(),
250 )
251}
252
253pub fn execute_omena_query_consumer_build_style_source_with_context(
254 style_path: &str,
255 style_source: &str,
256 requested_pass_ids: &[String],
257 context: &TransformExecutionContextV0,
258) -> OmenaQueryConsumerBuildSummaryV0 {
259 let pass_ids = if requested_pass_ids.is_empty() {
260 all_transform_pass_kinds()
261 .into_iter()
262 .map(|pass| pass.id().to_string())
263 .collect::<Vec<_>>()
264 } else {
265 requested_pass_ids.to_vec()
266 };
267 let context = merge_single_source_transform_context(style_path, style_source, context);
268 let execution_summary = execute_omena_query_transform_passes_from_source_with_context(
269 style_path,
270 style_source,
271 &pass_ids,
272 &context,
273 );
274
275 OmenaQueryConsumerBuildSummaryV0 {
276 schema_version: "0",
277 product: "omena-query.consumer-build-style-source",
278 style_path: style_path.to_string(),
279 dialect: omena_parser_style_dialect_label(omena_parser_dialect_for_style_path(style_path)),
280 requested_pass_ids: requested_pass_ids.to_vec(),
281 target_query: None,
282 unknown_pass_ids: execution_summary.unknown_pass_ids,
283 semantic_removal_count: execution_summary.semantic_removal_count,
284 execution: execution_summary.execution,
285 ready_surfaces: vec![
286 "consumerBuildFacade",
287 "singleSourceTransformContextProducer",
288 "transformExecutionRuntime",
289 "transformPassOutcomeContract",
290 ],
291 }
292}
293
294pub fn execute_omena_query_consumer_build_style_source_with_engine_input_context(
295 style_path: &str,
296 style_source: &str,
297 requested_pass_ids: &[String],
298 input: &EngineInputV2,
299 closed_style_world: bool,
300) -> OmenaQueryConsumerBuildSummaryV0 {
301 let context_summary = summarize_omena_query_transform_context_from_engine_input(
302 input,
303 style_path,
304 closed_style_world,
305 );
306 let mut summary = execute_omena_query_consumer_build_style_source_with_context(
307 style_path,
308 style_source,
309 requested_pass_ids,
310 &context_summary.context,
311 );
312 summary
313 .ready_surfaces
314 .push("semanticReachabilityTransformContext");
315 summary
316 .ready_surfaces
317 .push("expressionDomainSelectorProjection");
318 summary
319}
320
321pub fn execute_omena_query_consumer_build_style_sources_with_context(
322 target_style_path: &str,
323 style_sources: &[OmenaQueryStyleSourceInputV0],
324 requested_pass_ids: &[String],
325 context: &TransformExecutionContextV0,
326 package_manifests: &[OmenaQueryStylePackageManifestV0],
327) -> Result<OmenaQueryConsumerBuildSummaryV0, String> {
328 let Some(target_source) = find_target_style_source(target_style_path, style_sources) else {
329 return Err(format!(
330 "target style path {target_style_path:?} was not found in workspace style sources"
331 ));
332 };
333 let context = merge_workspace_transform_context(
334 target_style_path,
335 style_sources,
336 context,
337 package_manifests,
338 );
339 let mut summary = execute_omena_query_consumer_build_style_source_with_context(
340 target_style_path,
341 target_source,
342 requested_pass_ids,
343 &context,
344 );
345 summary
346 .ready_surfaces
347 .push("multiSourceTransformContextProducer");
348 Ok(summary)
349}
350
351pub fn execute_omena_query_consumer_build_style_sources(
352 target_style_path: &str,
353 style_sources: &[OmenaQueryStyleSourceInputV0],
354 requested_pass_ids: &[String],
355 package_manifests: &[OmenaQueryStylePackageManifestV0],
356) -> Result<OmenaQueryConsumerBuildSummaryV0, String> {
357 execute_omena_query_consumer_build_style_sources_with_context(
358 target_style_path,
359 style_sources,
360 requested_pass_ids,
361 &TransformExecutionContextV0::default(),
362 package_manifests,
363 )
364}
365
366pub fn execute_omena_query_consumer_build_style_source_for_target_query(
367 style_path: &str,
368 style_source: &str,
369 target_query: &str,
370) -> OmenaQueryConsumerBuildSummaryV0 {
371 execute_omena_query_consumer_build_style_source_for_target_query_with_options(
372 style_path,
373 style_source,
374 target_query,
375 conservative_omena_query_target_options(),
376 )
377}
378
379pub fn execute_omena_query_consumer_build_style_source_for_target_query_with_options(
380 style_path: &str,
381 style_source: &str,
382 target_query: &str,
383 target_options: OmenaQueryTargetTransformOptionsV0,
384) -> OmenaQueryConsumerBuildSummaryV0 {
385 execute_omena_query_consumer_build_style_source_for_target_query_with_context_and_options(
386 style_path,
387 style_source,
388 target_query,
389 &TransformExecutionContextV0::default(),
390 target_options,
391 )
392}
393
394pub fn execute_omena_query_consumer_build_style_source_for_target_query_with_context_and_options(
395 style_path: &str,
396 style_source: &str,
397 target_query: &str,
398 context: &TransformExecutionContextV0,
399 target_options: OmenaQueryTargetTransformOptionsV0,
400) -> OmenaQueryConsumerBuildSummaryV0 {
401 let context = merge_single_source_transform_context(style_path, style_source, context);
402 let plan = summarize_omena_query_transform_plan_from_target_query_with_context(
403 style_path,
404 style_source,
405 target_query,
406 target_options,
407 default_omena_query_transform_print_options(),
408 &context,
409 );
410 let requested_pass_ids = plan
411 .combined_pass_ids
412 .iter()
413 .map(|pass_id| (*pass_id).to_string())
414 .collect::<Vec<_>>();
415
416 OmenaQueryConsumerBuildSummaryV0 {
417 schema_version: "0",
418 product: "omena-query.consumer-build-style-source",
419 style_path: plan.style_path,
420 dialect: plan.dialect,
421 requested_pass_ids,
422 target_query: plan.target_query,
423 unknown_pass_ids: Vec::new(),
424 semantic_removal_count: plan.semantic_removal_count,
425 execution: plan.execution,
426 ready_surfaces: vec![
427 "consumerBuildFacade",
428 "targetQueryBuildFacade",
429 "singleSourceTransformContextProducer",
430 "transformExecutionRuntime",
431 "transformPassOutcomeContract",
432 ],
433 }
434}
435
436pub fn execute_omena_query_consumer_build_style_sources_for_target_query_with_context_and_options(
437 target_style_path: &str,
438 style_sources: &[OmenaQueryStyleSourceInputV0],
439 target_query: &str,
440 context: &TransformExecutionContextV0,
441 target_options: OmenaQueryTargetTransformOptionsV0,
442 package_manifests: &[OmenaQueryStylePackageManifestV0],
443) -> Result<OmenaQueryConsumerBuildSummaryV0, String> {
444 let Some(target_source) = find_target_style_source(target_style_path, style_sources) else {
445 return Err(format!(
446 "target style path {target_style_path:?} was not found in workspace style sources"
447 ));
448 };
449 let context = merge_workspace_transform_context(
450 target_style_path,
451 style_sources,
452 context,
453 package_manifests,
454 );
455 let mut summary =
456 execute_omena_query_consumer_build_style_source_for_target_query_with_context_and_options(
457 target_style_path,
458 target_source,
459 target_query,
460 &context,
461 target_options,
462 );
463 summary
464 .ready_surfaces
465 .push("multiSourceTransformContextProducer");
466 Ok(summary)
467}
468
469pub fn execute_omena_query_consumer_build_style_sources_for_target_query_with_options(
470 target_style_path: &str,
471 style_sources: &[OmenaQueryStyleSourceInputV0],
472 target_query: &str,
473 target_options: OmenaQueryTargetTransformOptionsV0,
474 package_manifests: &[OmenaQueryStylePackageManifestV0],
475) -> Result<OmenaQueryConsumerBuildSummaryV0, String> {
476 execute_omena_query_consumer_build_style_sources_for_target_query_with_context_and_options(
477 target_style_path,
478 style_sources,
479 target_query,
480 &TransformExecutionContextV0::default(),
481 target_options,
482 package_manifests,
483 )
484}
485
486fn derive_single_source_transform_context(
487 style_path: &str,
488 style_source: &str,
489) -> TransformExecutionContextV0 {
490 summarize_omena_query_transform_context_from_sources(
491 style_path,
492 [(style_path, style_source)],
493 &[],
494 )
495 .context
496}
497
498fn merge_single_source_transform_context(
499 style_path: &str,
500 style_source: &str,
501 context: &TransformExecutionContextV0,
502) -> TransformExecutionContextV0 {
503 merge_transform_context(
504 derive_single_source_transform_context(style_path, style_source),
505 context,
506 )
507}
508
509fn merge_workspace_transform_context(
510 target_style_path: &str,
511 style_sources: &[OmenaQueryStyleSourceInputV0],
512 context: &TransformExecutionContextV0,
513 package_manifests: &[OmenaQueryStylePackageManifestV0],
514) -> TransformExecutionContextV0 {
515 let style_refs = style_sources
516 .iter()
517 .map(|source| (source.style_path.as_str(), source.style_source.as_str()))
518 .collect::<Vec<_>>();
519 let derived = summarize_omena_query_transform_context_from_sources(
520 target_style_path,
521 style_refs,
522 package_manifests,
523 )
524 .context;
525 merge_transform_context(derived, context)
526}
527
528pub fn summarize_omena_query_transform_context_from_engine_input(
529 input: &EngineInputV2,
530 target_style_path: &str,
531 closed_style_world: bool,
532) -> OmenaQueryTransformContextFromEngineInputSummaryV0 {
533 let projection_summary = summarize_omena_query_expression_domain_selector_projection(input);
534 let mut reachable_class_names = BTreeSet::new();
535 let mut reachability_sources = Vec::new();
536
537 for projection in &projection_summary.projections {
538 if projection.target_style_paths.is_empty()
539 || projection
540 .target_style_paths
541 .iter()
542 .any(|path| path == target_style_path)
543 {
544 reachable_class_names.extend(projection.selector_names.iter().cloned());
545 reachability_sources.push(OmenaQuerySemanticReachabilitySourceV0 {
546 graph_id: projection.graph_id.clone(),
547 file_path: projection.file_path.clone(),
548 node_id: projection.node_id.clone(),
549 target_style_paths: projection.target_style_paths.clone(),
550 value_kind: projection.value_kind,
551 reduced_product: projection.reduced_product.clone(),
552 selector_names: projection.selector_names.clone(),
553 certainty: projection.certainty,
554 });
555 }
556 }
557
558 let semantic_context = TransformExecutionContextV0 {
559 closed_style_world,
560 reachable_class_names: reachable_class_names.into_iter().collect(),
561 ..TransformExecutionContextV0::default()
562 };
563 let style_sources = input
564 .styles
565 .iter()
566 .filter_map(|style| {
567 style
568 .source
569 .as_deref()
570 .map(|source| (style.file_path.as_str(), source))
571 })
572 .collect::<Vec<_>>();
573 let source_context_summary = (!style_sources.is_empty()).then(|| {
574 summarize_omena_query_transform_context_from_sources(target_style_path, style_sources, &[])
575 });
576 let context = if let Some(source_context_summary) = &source_context_summary {
577 merge_transform_context(source_context_summary.context.clone(), &semantic_context)
578 } else {
579 semantic_context
580 };
581
582 let mut ready_surfaces = vec![
583 "expressionDomainSelectorProjection",
584 "semanticReachabilityTransformContext",
585 ];
586 if source_context_summary.is_some() {
587 ready_surfaces.push("engineInputStyleSourceTransformContext");
588 }
589
590 OmenaQueryTransformContextFromEngineInputSummaryV0 {
591 schema_version: "0",
592 product: "omena-query.transform-context-from-engine-input",
593 input_version: input.version.clone(),
594 target_style_path: target_style_path.to_string(),
595 closed_style_world,
596 style_source_count: source_context_summary
597 .as_ref()
598 .map_or(0, |summary| summary.style_count),
599 projection_count: projection_summary.projection_count,
600 selected_projection_count: reachability_sources.len(),
601 import_inline_count: context.import_inlines.len(),
602 class_name_rewrite_count: context.class_name_rewrites.len(),
603 css_module_composes_resolution_count: context.css_module_composes_resolutions.len(),
604 css_module_value_resolution_count: context.css_module_value_resolutions.len(),
605 design_token_route_count: context.design_token_routes.len(),
606 reachable_class_name_count: context.reachable_class_names.len(),
607 reachable_keyframe_name_count: context.reachable_keyframe_names.len(),
608 reachable_value_name_count: context.reachable_value_names.len(),
609 reachable_custom_property_name_count: context.reachable_custom_property_names.len(),
610 reachability_sources,
611 context,
612 ready_surfaces,
613 }
614}
615
616pub fn list_omena_query_transform_pass_summaries() -> Vec<OmenaQueryTransformPassSummaryV0> {
617 all_transform_pass_kinds()
618 .into_iter()
619 .map(|kind| OmenaQueryTransformPassSummaryV0 {
620 id: kind.id(),
621 title: kind.title(),
622 reads_semantic_graph: kind.reads_semantic_graph(),
623 reads_cascade_model: kind.reads_cascade_model(),
624 })
625 .collect()
626}
627
628pub fn execute_omena_query_transform_passes_from_source_with_context(
629 style_path: &str,
630 style_source: &str,
631 requested_pass_ids: &[String],
632 context: &TransformExecutionContextV0,
633) -> OmenaQueryTransformExecuteSummaryV0 {
634 let mut requested_passes = Vec::new();
635 let mut unknown_pass_ids = Vec::new();
636
637 for pass_id in requested_pass_ids {
638 match transform_pass_kind_from_id(pass_id) {
639 Some(pass) => requested_passes.push(pass),
640 None => unknown_pass_ids.push(pass_id.clone()),
641 }
642 }
643
644 let dialect = omena_parser_dialect_for_style_path(style_path);
645 let execution = execute_transform_passes_on_source_with_dialect_and_context(
646 style_source,
647 dialect,
648 &requested_passes,
649 context,
650 );
651 let semantic_removal_count = execution.semantic_removals.len();
652
653 OmenaQueryTransformExecuteSummaryV0 {
654 schema_version: "0",
655 product: "omena-query.transform-execute",
656 style_path: style_path.to_string(),
657 requested_pass_ids: requested_pass_ids.to_vec(),
658 unknown_pass_ids,
659 execution,
660 semantic_removal_count,
661 ready_surfaces: vec!["transformExecutionRuntime", "transformPassOutcomeContract"],
662 }
663}
664
665pub fn summarize_omena_query_transform_context_from_sources<'a>(
666 target_style_path: &str,
667 styles: impl IntoIterator<Item = (&'a str, &'a str)>,
668 package_manifests: &[OmenaQueryStylePackageManifestV0],
669) -> OmenaQueryTransformContextFromSourcesSummaryV0 {
670 let style_sources = styles.into_iter().collect::<Vec<_>>();
671 let style_count = style_sources.len();
672 let style_fact_entries = collect_omena_query_style_fact_entries(style_sources.as_slice());
673 let source_by_path = style_sources
674 .iter()
675 .map(|(style_path, style_source)| ((*style_path).to_string(), (*style_source).to_string()))
676 .collect::<BTreeMap<_, _>>();
677 let available_style_paths = style_fact_entries
678 .iter()
679 .map(|entry| entry.style_path.as_str())
680 .collect::<BTreeSet<_>>();
681 let target_entry = style_fact_entries
682 .iter()
683 .find(|entry| entry.style_path == target_style_path);
684
685 let mut context = TransformExecutionContextV0::default();
686
687 if let Some(entry) = target_entry {
688 context.import_inlines = derive_import_inlines_for_transform_context(
689 entry,
690 &style_fact_entries,
691 &available_style_paths,
692 &source_by_path,
693 package_manifests,
694 );
695 let scss_module_uses = derive_static_scss_module_use_evaluations_for_transform_context(
696 entry,
697 &available_style_paths,
698 &source_by_path,
699 package_manifests,
700 );
701 match omena_parser_dialect_for_style_path(entry.style_path.as_str()) {
702 OmenaParserStyleDialect::Scss | OmenaParserStyleDialect::Sass => {
703 let dialect = omena_parser_dialect_for_style_path(entry.style_path.as_str());
704 context.scss_module_evaluation =
705 derive_static_stylesheet_module_evaluation_for_transform_context(
706 entry.style_source.as_str(),
707 dialect,
708 &context.import_inlines,
709 &scss_module_uses,
710 );
711 }
712 OmenaParserStyleDialect::Less => {
713 context.less_module_evaluation =
714 derive_static_stylesheet_module_evaluation_for_transform_context(
715 entry.style_source.as_str(),
716 OmenaParserStyleDialect::Less,
717 &context.import_inlines,
718 &[],
719 );
720 }
721 OmenaParserStyleDialect::Css => {}
722 }
723 context.class_name_rewrites = derive_class_name_rewrites_for_transform_context(entry);
724 context.css_module_composes_resolutions =
725 derive_css_module_composes_resolutions_for_transform_context(
726 entry,
727 &style_fact_entries,
728 &available_style_paths,
729 package_manifests,
730 );
731 context.css_module_value_resolutions =
732 derive_css_module_value_resolutions_for_transform_context(
733 entry,
734 &style_fact_entries,
735 &available_style_paths,
736 &source_by_path,
737 package_manifests,
738 );
739 context.design_token_routes = derive_design_token_routes_for_transform_context(
740 entry,
741 &style_fact_entries,
742 package_manifests,
743 );
744 }
745
746 OmenaQueryTransformContextFromSourcesSummaryV0 {
747 schema_version: "0",
748 product: "omena-query.transform-context",
749 target_style_path: target_style_path.to_string(),
750 style_count,
751 import_inline_count: context.import_inlines.len(),
752 class_name_rewrite_count: context.class_name_rewrites.len(),
753 css_module_composes_resolution_count: context.css_module_composes_resolutions.len(),
754 css_module_value_resolution_count: context.css_module_value_resolutions.len(),
755 design_token_route_count: context.design_token_routes.len(),
756 reachable_class_name_count: context.reachable_class_names.len(),
757 reachable_keyframe_name_count: context.reachable_keyframe_names.len(),
758 reachable_value_name_count: context.reachable_value_names.len(),
759 reachable_custom_property_name_count: context.reachable_custom_property_names.len(),
760 context,
761 ready_surfaces: vec![
762 "transformContextProducer",
763 "stylesheetModuleEvaluationProducer",
764 "cssModuleClassRewriteProducer",
765 "cssModuleComposesResolutionProducer",
766 "cssModuleValueResolutionProducer",
767 "designTokenRouteProducer",
768 "transitiveImportInlineProducer",
769 ],
770 }
771}
772
773fn apply_transform_source_replacements(
774 source: &str,
775 mut replacements: Vec<(usize, usize, String)>,
776) -> (String, usize) {
777 if replacements.is_empty() {
778 return (source.to_string(), 0);
779 }
780 replacements.sort_by_key(|replacement| replacement.0);
781 let mut output = source.to_string();
782 let mut mutation_count = 0usize;
783 for (start, end, replacement) in replacements.into_iter().rev() {
784 if start > end || end > output.len() {
785 continue;
786 }
787 output.replace_range(start..end, replacement.as_str());
788 mutation_count += 1;
789 }
790 (output, mutation_count)
791}
792
793fn transform_token_start(token: &omena_parser::LexedToken) -> usize {
794 let start: u32 = token.range.start().into();
795 start as usize
796}
797
798fn transform_token_end(token: &omena_parser::LexedToken) -> usize {
799 let end: u32 = token.range.end().into();
800 end as usize
801}
802
803fn extend_passes_from_ids(ids: &[&'static str], passes: &mut Vec<TransformPassKind>) {
804 for candidate in all_transform_pass_kinds() {
805 if ids.contains(&candidate.id()) && !passes.contains(&candidate) {
806 passes.push(candidate);
807 }
808 }
809}
810
811fn transform_pass_kind_from_id(pass_id: &str) -> Option<TransformPassKind> {
812 all_transform_pass_kinds()
813 .into_iter()
814 .find(|candidate| candidate.id() == pass_id)
815}