omena_parser/facts/
at_rules.rs1use cstree::text::TextRange;
7use omena_syntax::{StyleDialect, SyntaxKind};
8
9use crate::{ParseResult, at_rule_spec, scss_at_rule_spec};
10
11#[derive(Debug, Clone, PartialEq, Eq)]
12pub struct ParsedAtRuleFact {
13 pub name: String,
14 pub node_kind: Option<SyntaxKind>,
15 pub range: TextRange,
16}
17
18pub(crate) fn collect_at_rule_facts_from_cst(
19 text: &str,
20 parsed: &ParseResult,
21) -> Vec<ParsedAtRuleFact> {
22 parsed
23 .syntax_token_views()
24 .iter()
25 .filter(|token| token.kind == SyntaxKind::AtKeyword)
26 .map(|token| at_rule_fact_from_cst_token(text, token.range, parsed.dialect()))
27 .collect()
28}
29
30fn at_rule_fact_from_cst_token(
31 text: &str,
32 range: TextRange,
33 dialect: StyleDialect,
34) -> ParsedAtRuleFact {
35 let start = u32::from(range.start()) as usize;
36 let end = u32::from(range.end()) as usize;
37 let source_text = text.get(start..end).unwrap_or_default();
38 let css_spec = at_rule_spec(source_text);
39 let node_kind = css_spec
40 .or_else(|| match dialect {
41 StyleDialect::Scss | StyleDialect::Sass => scss_at_rule_spec(source_text),
42 StyleDialect::Css | StyleDialect::Less => None,
43 })
44 .map(|spec| spec.node_kind);
45 let name = if css_spec.is_some() {
46 source_text.to_ascii_lowercase()
47 } else {
48 source_text.to_string()
49 };
50 ParsedAtRuleFact {
51 name,
52 node_kind,
53 range,
54 }
55}