sqruff_lib_core/parser/segments/
test_functions.rs

1use std::ops::Range;
2
3use super::base::{ErasedSegment, SegmentBuilder, Tables};
4use crate::dialects::base::Dialect;
5use crate::dialects::syntax::SyntaxKind;
6use crate::helpers::Config;
7use crate::parser::lexer::{Lexer, StringOrTemplate};
8use crate::parser::markers::PositionMarker;
9use crate::templaters::base::TemplatedFile;
10
11pub fn bracket_segments() -> Vec<ErasedSegment> {
12    generate_test_segments_func(vec![
13        "bar", " \t ", "(", "foo", "    ", ")", "baar", " \t ", "foo",
14    ])
15}
16
17pub fn lex(dialect: &Dialect, string: &str) -> Vec<ErasedSegment> {
18    let lexer = Lexer::new(dialect.lexer_matchers());
19    let tables = Tables::default();
20    let (segments, errors) = lexer
21        .lex(&tables, StringOrTemplate::String(string))
22        .unwrap();
23    assert_eq!(errors, &[]);
24    segments
25}
26
27/// Roughly generate test segments.
28///
29/// This is a factory function so that it works as a fixture,
30/// but when actually used, this will return the inner function
31/// which is what you actually need.
32pub fn generate_test_segments_func(elems: Vec<&str>) -> Vec<ErasedSegment> {
33    // Placeholder: assuming TemplatedFile, PositionMarker, and other structures
34    // are defined elsewhere in the codebase.
35    let raw_file = elems.concat();
36
37    let templated_file: TemplatedFile = raw_file.into();
38    let mut idx = 0;
39    let mut buff: Vec<ErasedSegment> = Vec::new();
40
41    for elem in elems {
42        if elem == "<indent>" {
43            buff.push(SegmentBuilder::token(0, "", SyntaxKind::Indent).finish());
44            continue;
45        } else if elem == "<dedent>" {
46            buff.push(SegmentBuilder::token(0, "", SyntaxKind::Dedent).finish());
47            continue;
48        }
49
50        let position_marker = PositionMarker::new(
51            idx..idx + elem.len(),
52            idx..idx + elem.len(),
53            templated_file.clone(),
54            None,
55            None,
56        );
57
58        let tables = Tables::default();
59
60        let seg = if elem.chars().all(|c| c == ' ' || c == '\t') {
61            SegmentBuilder::whitespace(tables.next_id(), elem).config(|this| {
62                this.get_mut()
63                    .set_position_marker(position_marker.clone().into())
64            })
65        } else if elem.chars().all(|c| c == '\n') {
66            SegmentBuilder::newline(tables.next_id(), elem)
67        } else if elem == "(" || elem == ")" {
68            SegmentBuilder::token(tables.next_id(), elem, SyntaxKind::RawComparisonOperator)
69                .with_position(position_marker)
70                .finish()
71        } else if elem.starts_with("--") {
72            SegmentBuilder::token(0, elem, SyntaxKind::InlineComment)
73                .with_position(position_marker)
74                .finish()
75        } else if elem.starts_with('\"') {
76            SegmentBuilder::token(0, elem, SyntaxKind::DoubleQuote)
77                .with_position(position_marker)
78                .finish()
79        } else if elem.starts_with('\'') {
80            SegmentBuilder::token(0, elem, SyntaxKind::SingleQuote)
81                .with_position(position_marker)
82                .finish()
83        } else {
84            SegmentBuilder::token(0, elem, SyntaxKind::RawComparisonOperator)
85                .with_position(position_marker)
86                .finish()
87        };
88
89        buff.push(seg);
90        idx += elem.len();
91    }
92
93    buff
94}
95
96/// Construct a list of raw segments as a fixture.
97pub fn raw_segments() -> Vec<ErasedSegment> {
98    generate_test_segments_func(["foobar", ".barfoo"].to_vec())
99}
100
101pub fn raw_seg() -> ErasedSegment {
102    raw_segments()[0].clone()
103}
104
105pub fn test_segments() -> Vec<ErasedSegment> {
106    generate_test_segments_func(vec!["bar", " \t ", "foo", "baar", " \t "])
107}
108
109pub fn make_result_tuple(
110    result_slice: Option<Range<usize>>,
111    matcher_keywords: &[&str],
112    test_segments: &[ErasedSegment],
113) -> Vec<ErasedSegment> {
114    // Make a comparison tuple for test matching.
115    // No result slice means no match.
116    match result_slice {
117        None => vec![],
118        Some(slice) => test_segments[slice]
119            .iter()
120            .map(|elem| {
121                let raw = elem.raw();
122                if matcher_keywords.contains(&raw.as_str()) {
123                    SegmentBuilder::keyword(0, raw).config(|this| {
124                        this.get_mut()
125                            .set_position_marker(Some(elem.get_position_marker().unwrap().clone()))
126                    })
127                } else {
128                    elem.clone()
129                }
130            })
131            .collect(),
132    }
133}