Skip to main content

omena_semantic/
selector_references.rs

1//! Source-side selector reference summaries.
2//!
3//! The public contracts connect engine input facts to selector reference sites,
4//! including editable direct references used by rename/refactor and code-lens
5//! consumers.
6
7use engine_input_producers::{
8    EngineInputV2, RangeV2, summarize_selector_usage_evaluator_candidates_input,
9};
10use serde::Serialize;
11
12#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
13#[serde(rename_all = "camelCase")]
14pub struct SelectorReferenceEngineSummaryV0 {
15    pub schema_version: &'static str,
16    pub product: &'static str,
17    pub style_path: Option<String>,
18    pub selector_count: usize,
19    pub referenced_selector_count: usize,
20    pub unreferenced_selector_count: usize,
21    pub total_reference_sites: usize,
22    pub selectors: Vec<SelectorReferenceSummaryV0>,
23}
24
25#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
26#[serde(rename_all = "camelCase")]
27pub struct SelectorReferenceSummaryV0 {
28    pub canonical_id: String,
29    pub file_path: String,
30    pub local_name: String,
31    pub total_references: usize,
32    pub direct_reference_count: usize,
33    pub editable_direct_reference_count: usize,
34    pub exact_reference_count: usize,
35    pub inferred_or_better_reference_count: usize,
36    pub has_expanded_references: bool,
37    pub has_style_dependency_references: bool,
38    pub has_any_references: bool,
39    pub sites: Vec<SelectorReferenceSiteV0>,
40    pub editable_direct_sites: Vec<SelectorEditableDirectReferenceSiteV0>,
41}
42
43#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
44#[serde(rename_all = "camelCase")]
45pub struct SelectorReferenceSiteV0 {
46    pub file_path: String,
47    pub range: RangeV2,
48    pub expansion: String,
49    pub reference_kind: String,
50}
51
52#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
53#[serde(rename_all = "camelCase")]
54pub struct SelectorEditableDirectReferenceSiteV0 {
55    pub file_path: String,
56    pub range: RangeV2,
57    pub class_name: String,
58}
59
60pub fn summarize_selector_reference_engine(
61    input: &EngineInputV2,
62    style_path: Option<&str>,
63) -> SelectorReferenceEngineSummaryV0 {
64    let candidates = summarize_selector_usage_evaluator_candidates_input(input);
65    let selectors = candidates
66        .results
67        .into_iter()
68        .filter(|candidate| match style_path {
69            Some(path) => candidate.file_path == path,
70            None => true,
71        })
72        .map(|candidate| {
73            let payload = candidate.payload;
74            SelectorReferenceSummaryV0 {
75                canonical_id: format!("selector:{}", payload.canonical_name),
76                file_path: candidate.file_path,
77                local_name: payload.canonical_name,
78                total_references: payload.total_references,
79                direct_reference_count: payload.direct_reference_count,
80                editable_direct_reference_count: payload.editable_direct_reference_count,
81                exact_reference_count: payload.exact_reference_count,
82                inferred_or_better_reference_count: payload.inferred_or_better_reference_count,
83                has_expanded_references: payload.has_expanded_references,
84                has_style_dependency_references: payload.has_style_dependency_references,
85                has_any_references: payload.has_any_references,
86                sites: payload
87                    .all_sites
88                    .into_iter()
89                    .map(|site| SelectorReferenceSiteV0 {
90                        file_path: site.file_path,
91                        range: site.range,
92                        expansion: site.expansion,
93                        reference_kind: site.reference_kind,
94                    })
95                    .collect(),
96                editable_direct_sites: payload
97                    .editable_direct_sites
98                    .into_iter()
99                    .map(|site| SelectorEditableDirectReferenceSiteV0 {
100                        file_path: site.file_path,
101                        range: site.range,
102                        class_name: site.class_name,
103                    })
104                    .collect(),
105            }
106        })
107        .collect::<Vec<_>>();
108
109    let referenced_selector_count = selectors
110        .iter()
111        .filter(|selector| selector.has_any_references)
112        .count();
113    let total_reference_sites = selectors
114        .iter()
115        .map(|selector| selector.sites.len())
116        .sum::<usize>();
117
118    SelectorReferenceEngineSummaryV0 {
119        schema_version: "0",
120        product: "omena-semantic.selector-references",
121        style_path: style_path.map(ToOwned::to_owned),
122        selector_count: selectors.len(),
123        referenced_selector_count,
124        unreferenced_selector_count: selectors.len() - referenced_selector_count,
125        total_reference_sites,
126        selectors,
127    }
128}