lex_analysis/
reference_targets.rs

1use crate::utils::session_identifier;
2use lex_core::lex::ast::{Annotation, Definition, Session};
3use lex_core::lex::inlines::ReferenceType;
4
5#[derive(Debug, Clone, PartialEq, Eq, Hash)]
6pub enum ReferenceTarget {
7    AnnotationLabel(String),
8    DefinitionSubject(String),
9    Session(String),
10    CitationKey(String),
11}
12
13pub fn targets_from_reference_type(reference_type: &ReferenceType) -> Vec<ReferenceTarget> {
14    let mut targets = Vec::new();
15    match reference_type {
16        ReferenceType::FootnoteLabeled { label } => {
17            push_unique(
18                &mut targets,
19                ReferenceTarget::AnnotationLabel(label.clone()),
20            );
21        }
22        ReferenceType::FootnoteNumber { number } => {
23            push_unique(
24                &mut targets,
25                ReferenceTarget::AnnotationLabel(number.to_string()),
26            );
27        }
28        ReferenceType::Citation(data) => {
29            for key in &data.keys {
30                push_unique(&mut targets, ReferenceTarget::CitationKey(key.clone()));
31            }
32        }
33        ReferenceType::General { target } => {
34            if !target.trim().is_empty() {
35                push_unique(
36                    &mut targets,
37                    ReferenceTarget::DefinitionSubject(target.trim().to_string()),
38                );
39            }
40        }
41        ReferenceType::ToCome {
42            identifier: Some(id),
43        } if !id.trim().is_empty() => {
44            push_unique(
45                &mut targets,
46                ReferenceTarget::DefinitionSubject(id.trim().to_string()),
47            );
48        }
49        ReferenceType::ToCome { .. } => {}
50        ReferenceType::Session { target } => {
51            if !target.trim().is_empty() {
52                push_unique(
53                    &mut targets,
54                    ReferenceTarget::Session(target.trim().to_string()),
55                );
56            }
57        }
58        _ => {}
59    }
60    targets
61}
62
63pub fn targets_from_annotation(annotation: &Annotation) -> Vec<ReferenceTarget> {
64    let mut targets = Vec::new();
65    let label = annotation.data.label.value.trim();
66    if !label.is_empty() {
67        push_unique(
68            &mut targets,
69            ReferenceTarget::AnnotationLabel(label.to_string()),
70        );
71        push_unique(
72            &mut targets,
73            ReferenceTarget::CitationKey(label.to_string()),
74        );
75    }
76    targets
77}
78
79pub fn targets_from_definition(definition: &Definition) -> Vec<ReferenceTarget> {
80    let mut targets = Vec::new();
81    let subject = definition.subject.as_string().trim();
82    if !subject.is_empty() {
83        push_unique(
84            &mut targets,
85            ReferenceTarget::DefinitionSubject(subject.to_string()),
86        );
87    }
88    targets
89}
90
91pub fn targets_from_session(session: &Session) -> Vec<ReferenceTarget> {
92    let mut targets = Vec::new();
93    if let Some(identifier) = session_identifier(session) {
94        push_unique(&mut targets, ReferenceTarget::Session(identifier));
95    }
96    targets
97}
98
99fn push_unique(targets: &mut Vec<ReferenceTarget>, target: ReferenceTarget) {
100    if targets.iter().any(|existing| existing == &target) {
101        return;
102    }
103    targets.push(target);
104}