1use super::*;
2
3pub fn summarize_omena_query_fragment_bundle(input: &EngineInputV2) -> OmenaQueryFragmentBundleV0 {
4 OmenaQueryFragmentBundleV0 {
5 schema_version: "0",
6 product: "omena-query.fragment-bundle",
7 input_version: input.version.clone(),
8 expression_semantics: summarize_omena_query_expression_semantics_query_fragments(input),
9 source_resolution: summarize_omena_query_source_resolution_query_fragments(input),
10 selector_usage: summarize_omena_query_selector_usage_query_fragments(input),
11 }
12}
13
14pub fn summarize_omena_query_expression_semantics_query_fragments(
15 input: &EngineInputV2,
16) -> ExpressionSemanticsQueryFragmentsV0 {
17 summarize_expression_semantics_query_fragments_input(input)
18}
19
20pub fn summarize_omena_query_expression_domain_flow_analysis(
21 input: &EngineInputV2,
22) -> ExpressionDomainFlowAnalysisV0 {
23 summarize_expression_domain_flow_analysis_input(input)
24}
25
26pub fn summarize_omena_query_expression_domain_control_flow_analysis(
27 input: &EngineInputV2,
28) -> ExpressionDomainControlFlowAnalysisV0 {
29 summarize_expression_domain_control_flow_analysis_input(input)
30}
31
32pub fn summarize_omena_query_expression_domain_call_site_flow_analysis(
33 input: &EngineInputV2,
34) -> ExpressionDomainCallSiteFlowAnalysisV0 {
35 summarize_expression_domain_call_site_flow_analysis_input(input)
36}
37
38pub fn summarize_omena_query_expression_domain_provenance_explanations(
39 input: &EngineInputV2,
40) -> ExpressionDomainProvenanceExplanationsV0 {
41 summarize_expression_domain_provenance_explanations_input(input)
42}
43
44pub fn summarize_omena_query_expression_domain_reduced_product_iteration(
45 input: &EngineInputV2,
46) -> ExpressionDomainReducedProductIterationV0 {
47 summarize_expression_domain_reduced_product_iteration_input(input)
48}
49
50pub fn summarize_omena_query_expression_domain_incremental_flow_analysis(
51 input: &EngineInputV2,
52 runtime: &mut OmenaQueryExpressionDomainFlowRuntimeV0,
53) -> OmenaQueryExpressionDomainIncrementalFlowAnalysisV0 {
54 runtime.analyze_input(input)
55}
56
57pub fn summarize_omena_query_expression_domain_selector_projection(
58 input: &EngineInputV2,
59) -> OmenaQueryExpressionDomainSelectorProjectionV0 {
60 let style_selectors_by_path = style_selector_universe_by_path(input);
61 let expression_targets = expression_target_style_paths(input);
62 let flow_analysis = summarize_omena_query_expression_domain_flow_analysis(input);
63 let mut projections = Vec::new();
64
65 for graph in flow_analysis.analyses {
66 for node in graph.analysis.nodes {
67 let target_style_paths = target_style_paths_for_flow_node(
68 node.id.as_str(),
69 node.predecessor_ids.as_slice(),
70 &expression_targets,
71 );
72 let selector_universe = selector_universe_for_targets(
73 target_style_paths.as_slice(),
74 &style_selectors_by_path,
75 );
76 let projection = project_abstract_value_selectors(&node.value, &selector_universe);
77 projections.push(OmenaQueryExpressionDomainSelectorProjectionEntryV0 {
78 graph_id: graph.graph_id.clone(),
79 file_path: graph.file_path.clone(),
80 node_id: node.id,
81 target_style_paths,
82 value_kind: node.value_kind,
83 reduced_product: summarize_reduced_class_value_product(&node.value),
84 selector_names: projection.selector_names,
85 certainty: projection.certainty,
86 });
87 }
88 }
89
90 OmenaQueryExpressionDomainSelectorProjectionV0 {
91 schema_version: "0",
92 product: "omena-query.expression-domain-selector-projection",
93 input_version: input.version.clone(),
94 projection_count: projections.len(),
95 projections,
96 }
97}
98
99impl OmenaQueryExpressionDomainFlowRuntimeV0 {
100 pub fn revision(&self) -> u64 {
101 self.revision
102 }
103
104 pub fn graph_count(&self) -> usize {
105 self.databases_by_graph_id.len()
106 }
107
108 pub fn analyze_input(
109 &mut self,
110 input: &EngineInputV2,
111 ) -> OmenaQueryExpressionDomainIncrementalFlowAnalysisV0 {
112 self.revision += 1;
113 let revision = self.revision;
114 let flow_graphs = collect_expression_domain_flow_graphs(input);
115 let live_graph_ids = flow_graphs
116 .iter()
117 .map(|entry| entry.graph_id.clone())
118 .collect::<BTreeSet<_>>();
119
120 self.databases_by_graph_id
121 .retain(|graph_id, _| live_graph_ids.contains(graph_id));
122 self.previous_analyses_by_graph_id
123 .retain(|graph_id, _| live_graph_ids.contains(graph_id));
124
125 let analyses = flow_graphs
126 .into_iter()
127 .map(|entry| {
128 let database = self
129 .databases_by_graph_id
130 .entry(entry.graph_id.clone())
131 .or_default();
132 let previous_analysis = self.previous_analyses_by_graph_id.get(&entry.graph_id);
133 let analysis = analyze_class_value_flow_incremental_with_database(
134 &entry.graph,
135 database,
136 previous_analysis,
137 revision,
138 );
139 self.previous_analyses_by_graph_id
140 .insert(entry.graph_id.clone(), analysis.analysis.clone());
141
142 OmenaQueryExpressionDomainIncrementalFlowAnalysisEntryV0 {
143 graph_id: entry.graph_id,
144 file_path: entry.file_path,
145 analysis,
146 }
147 })
148 .collect::<Vec<_>>();
149
150 let dirty_graph_count = analyses
151 .iter()
152 .filter(|entry| entry.analysis.incremental_plan.dirty_node_count > 0)
153 .count();
154 let reused_graph_count = analyses
155 .iter()
156 .filter(|entry| entry.analysis.reused_previous_analysis)
157 .count();
158
159 OmenaQueryExpressionDomainIncrementalFlowAnalysisV0 {
160 schema_version: "0",
161 product: "omena-query.expression-domain-incremental-flow-analysis",
162 input_version: input.version.clone(),
163 revision,
164 graph_count: analyses.len(),
165 dirty_graph_count,
166 reused_graph_count,
167 analyses,
168 }
169 }
170}
171
172fn expression_target_style_paths(input: &EngineInputV2) -> BTreeMap<String, String> {
173 input
174 .sources
175 .iter()
176 .flat_map(|source| source.document.class_expressions.iter())
177 .map(|expression| (expression.id.clone(), expression.scss_module_path.clone()))
178 .collect()
179}
180
181fn style_selector_universe_by_path(input: &EngineInputV2) -> BTreeMap<String, Vec<String>> {
182 input
183 .styles
184 .iter()
185 .map(|style| {
186 let selector_names = style
187 .document
188 .selectors
189 .iter()
190 .map(|selector| {
191 selector
192 .canonical_name
193 .clone()
194 .unwrap_or_else(|| selector.name.clone())
195 })
196 .collect::<BTreeSet<_>>()
197 .into_iter()
198 .collect::<Vec<_>>();
199 (style.file_path.clone(), selector_names)
200 })
201 .collect()
202}
203
204fn target_style_paths_for_flow_node(
205 node_id: &str,
206 predecessor_ids: &[String],
207 expression_targets: &BTreeMap<String, String>,
208) -> Vec<String> {
209 let mut targets = BTreeSet::new();
210 if let Some(target) = expression_targets.get(node_id) {
211 targets.insert(target.clone());
212 }
213 for predecessor_id in predecessor_ids {
214 if let Some(target) = expression_targets.get(predecessor_id) {
215 targets.insert(target.clone());
216 }
217 }
218 targets.into_iter().collect()
219}
220
221fn selector_universe_for_targets(
222 target_style_paths: &[String],
223 style_selectors_by_path: &BTreeMap<String, Vec<String>>,
224) -> Vec<String> {
225 let mut selectors = BTreeSet::new();
226 if target_style_paths.is_empty() {
227 for selector_names in style_selectors_by_path.values() {
228 selectors.extend(selector_names.iter().cloned());
229 }
230 } else {
231 for target_style_path in target_style_paths {
232 if let Some(selector_names) = style_selectors_by_path.get(target_style_path) {
233 selectors.extend(selector_names.iter().cloned());
234 }
235 }
236 }
237 selectors.into_iter().collect()
238}
239
240pub fn summarize_omena_query_source_resolution_query_fragments(
241 input: &EngineInputV2,
242) -> SourceResolutionQueryFragmentsV0 {
243 summarize_omena_resolver_query_fragments(input)
244}
245
246pub fn summarize_omena_query_selector_usage_query_fragments(
247 input: &EngineInputV2,
248) -> SelectorUsageQueryFragmentsV0 {
249 summarize_selector_usage_query_fragments_input(input)
250}
251
252pub fn summarize_omena_query_source_resolution_canonical_producer_signal(
253 input: &EngineInputV2,
254) -> SourceResolutionCanonicalProducerSignalV0 {
255 summarize_omena_resolver_canonical_producer_signal(input)
256}
257
258pub fn summarize_omena_query_source_resolution_runtime(
259 input: &EngineInputV2,
260) -> OmenaResolverSourceResolutionRuntimeIndexV0 {
261 summarize_omena_resolver_source_resolution_runtime(input)
262}
263
264pub fn summarize_omena_query_expression_semantics_canonical_producer_signal(
265 input: &EngineInputV2,
266) -> ExpressionSemanticsCanonicalProducerSignalV0 {
267 summarize_expression_semantics_canonical_producer_signal_input(input)
268}
269
270pub fn summarize_omena_query_selector_usage_canonical_producer_signal(
271 input: &EngineInputV2,
272) -> SelectorUsageCanonicalProducerSignalV0 {
273 summarize_selector_usage_canonical_producer_signal_input(input)
274}