1pub mod bracketed;
2pub mod file;
3pub mod fix;
4pub mod from;
5pub mod generator;
6pub mod join;
7pub mod meta;
8pub mod object_reference;
9pub mod select;
10pub mod test_functions;
11
12use std::cell::{Cell, OnceCell};
13use std::fmt::Debug;
14use std::hash::{Hash, Hasher};
15use std::rc::Rc;
16
17use itertools::enumerate;
18use rustc_hash::FxHashMap;
19use smol_str::SmolStr;
20
21use crate::dialects::init::DialectKind;
22use crate::dialects::syntax::{SyntaxKind, SyntaxSet};
23use crate::lint_fix::LintFix;
24use crate::parser::markers::PositionMarker;
25use crate::parser::segments::fix::{FixPatch, SourceFix};
26use crate::parser::segments::object_reference::{ObjectReferenceKind, ObjectReferenceSegment};
27use crate::segments::AnchorEditInfo;
28use crate::templaters::TemplatedFile;
29
30pub struct SegmentBuilder {
31 node_or_token: NodeOrToken,
32}
33
34impl SegmentBuilder {
35 pub fn whitespace(id: u32, raw: &str) -> ErasedSegment {
36 SegmentBuilder::token(id, raw, SyntaxKind::Whitespace).finish()
37 }
38
39 pub fn newline(id: u32, raw: &str) -> ErasedSegment {
40 SegmentBuilder::token(id, raw, SyntaxKind::Newline).finish()
41 }
42
43 pub fn keyword(id: u32, raw: &str) -> ErasedSegment {
44 SegmentBuilder::token(id, raw, SyntaxKind::Keyword).finish()
45 }
46
47 pub fn comma(id: u32) -> ErasedSegment {
48 SegmentBuilder::token(id, ",", SyntaxKind::Comma).finish()
49 }
50
51 pub fn symbol(id: u32, raw: &str) -> ErasedSegment {
52 SegmentBuilder::token(id, raw, SyntaxKind::Symbol).finish()
53 }
54
55 pub fn node(
56 id: u32,
57 syntax_kind: SyntaxKind,
58 dialect: DialectKind,
59 segments: Vec<ErasedSegment>,
60 ) -> Self {
61 SegmentBuilder {
62 node_or_token: NodeOrToken {
63 id,
64 syntax_kind,
65 class_types: class_types(syntax_kind),
66 position_marker: None,
67 code_idx: OnceCell::new(),
68 kind: NodeOrTokenKind::Node(NodeData {
69 dialect,
70 segments,
71 raw: Default::default(),
72 source_fixes: vec![],
73 descendant_type_set: Default::default(),
74 raw_segments_with_ancestors: Default::default(),
75 }),
76 hash: OnceCell::new(),
77 },
78 }
79 }
80
81 pub fn token(id: u32, raw: &str, syntax_kind: SyntaxKind) -> Self {
82 SegmentBuilder {
83 node_or_token: NodeOrToken {
84 id,
85 syntax_kind,
86 code_idx: OnceCell::new(),
87 class_types: class_types(syntax_kind),
88 position_marker: None,
89 kind: NodeOrTokenKind::Token(TokenData { raw: raw.into() }),
90 hash: OnceCell::new(),
91 },
92 }
93 }
94
95 pub fn position_from_segments(mut self) -> Self {
96 let segments = match &self.node_or_token.kind {
97 NodeOrTokenKind::Node(node) => &node.segments[..],
98 NodeOrTokenKind::Token(_) => &[],
99 };
100
101 self.node_or_token.position_marker = pos_marker(segments).into();
102 self
103 }
104
105 pub fn with_position(mut self, position: PositionMarker) -> Self {
106 self.node_or_token.position_marker = Some(position);
107 self
108 }
109
110 pub fn finish(self) -> ErasedSegment {
111 ErasedSegment {
112 value: Rc::new(self.node_or_token),
113 }
114 }
115}
116
117#[derive(Debug, Default)]
118pub struct Tables {
119 counter: Cell<u32>,
120}
121
122impl Tables {
123 pub fn next_id(&self) -> u32 {
124 let id = self.counter.get();
125 self.counter.set(id + 1);
126 id
127 }
128}
129
130#[derive(Debug, Clone)]
131pub struct ErasedSegment {
132 pub(crate) value: Rc<NodeOrToken>,
133}
134
135impl Hash for ErasedSegment {
136 fn hash<H: Hasher>(&self, state: &mut H) {
137 self.hash_value().hash(state);
138 }
139}
140
141impl Eq for ErasedSegment {}
142
143impl ErasedSegment {
144 pub fn raw(&self) -> &SmolStr {
145 match &self.value.kind {
146 NodeOrTokenKind::Node(node) => node.raw.get_or_init(|| {
147 SmolStr::from_iter(self.segments().iter().map(|segment| segment.raw().as_str()))
148 }),
149 NodeOrTokenKind::Token(token) => &token.raw,
150 }
151 }
152
153 pub fn segments(&self) -> &[ErasedSegment] {
154 match &self.value.kind {
155 NodeOrTokenKind::Node(node) => &node.segments,
156 NodeOrTokenKind::Token(_) => &[],
157 }
158 }
159
160 pub fn get_type(&self) -> SyntaxKind {
161 self.value.syntax_kind
162 }
163
164 pub fn is_type(&self, kind: SyntaxKind) -> bool {
165 self.get_type() == kind
166 }
167
168 pub fn is_meta(&self) -> bool {
169 matches!(
170 self.value.syntax_kind,
171 SyntaxKind::Indent | SyntaxKind::Implicit | SyntaxKind::Dedent | SyntaxKind::EndOfFile
172 )
173 }
174
175 pub fn is_code(&self) -> bool {
176 match &self.value.kind {
177 NodeOrTokenKind::Node(node) => node.segments.iter().any(|s| s.is_code()),
178 NodeOrTokenKind::Token(_) => {
179 !self.is_comment() && !self.is_whitespace() && !self.is_meta()
180 }
181 }
182 }
183
184 pub fn get_raw_segments(&self) -> Vec<ErasedSegment> {
185 self.recursive_crawl_all(false)
186 .into_iter()
187 .filter(|it| it.segments().is_empty())
188 .collect()
189 }
190
191 #[cfg(feature = "stringify")]
192 pub fn stringify(&self, code_only: bool) -> String {
193 serde_yaml::to_string(&self.to_serialised(code_only, true)).unwrap()
194 }
195
196 pub fn child(&self, seg_types: &SyntaxSet) -> Option<ErasedSegment> {
197 self.segments()
198 .iter()
199 .find(|seg| seg_types.contains(seg.get_type()))
200 .cloned()
201 }
202
203 pub fn recursive_crawl(
204 &self,
205 types: &SyntaxSet,
206 recurse_into: bool,
207 no_recursive_types: &SyntaxSet,
208 allow_self: bool,
209 ) -> Vec<ErasedSegment> {
210 let mut acc = Vec::new();
211
212 let matches = allow_self && self.class_types().intersects(types);
213 if matches {
214 acc.push(self.clone());
215 }
216
217 if !self.descendant_type_set().intersects(types) {
218 return acc;
219 }
220
221 if recurse_into || !matches {
222 for seg in self.segments() {
223 if no_recursive_types.is_empty() || !no_recursive_types.contains(seg.get_type()) {
224 let segments =
225 seg.recursive_crawl(types, recurse_into, no_recursive_types, true);
226 acc.extend(segments);
227 }
228 }
229 }
230
231 acc
232 }
233}
234
235impl ErasedSegment {
236 #[track_caller]
237 pub fn new(&self, segments: Vec<ErasedSegment>) -> ErasedSegment {
238 match &self.value.kind {
239 NodeOrTokenKind::Node(node) => SegmentBuilder::node(
240 self.value.id,
241 self.value.syntax_kind,
242 node.dialect,
243 segments,
244 )
245 .with_position(self.get_position_marker().unwrap().clone())
246 .finish(),
247 NodeOrTokenKind::Token(_) => self.deep_clone(),
248 }
249 }
250
251 fn change_segments(&self, segments: Vec<ErasedSegment>) -> ErasedSegment {
252 let NodeOrTokenKind::Node(node) = &self.value.kind else {
253 unimplemented!()
254 };
255
256 ErasedSegment {
257 value: Rc::new(NodeOrToken {
258 id: self.value.id,
259 syntax_kind: self.value.syntax_kind,
260 class_types: self.value.class_types.clone(),
261 position_marker: None,
262 code_idx: OnceCell::new(),
263 kind: NodeOrTokenKind::Node(NodeData {
264 dialect: node.dialect,
265 segments,
266 raw: node.raw.clone(),
267 source_fixes: node.source_fixes.clone(),
268 descendant_type_set: node.descendant_type_set.clone(),
269 raw_segments_with_ancestors: node.raw_segments_with_ancestors.clone(),
270 }),
271 hash: OnceCell::new(),
272 }),
273 }
274 }
275
276 pub fn indent_val(&self) -> i8 {
277 self.value.syntax_kind.indent_val()
278 }
279
280 pub fn can_start_end_non_code(&self) -> bool {
281 matches!(
282 self.value.syntax_kind,
283 SyntaxKind::File | SyntaxKind::Unparsable
284 )
285 }
286
287 pub(crate) fn dialect(&self) -> DialectKind {
288 match &self.value.kind {
289 NodeOrTokenKind::Node(node) => node.dialect,
290 NodeOrTokenKind::Token(_) => todo!(),
291 }
292 }
293
294 pub fn get_start_loc(&self) -> (usize, usize) {
295 match self.get_position_marker() {
296 Some(pos_marker) => pos_marker.working_loc(),
297 None => unreachable!("{self:?} has no PositionMarker"),
298 }
299 }
300
301 pub fn get_end_loc(&self) -> (usize, usize) {
302 match self.get_position_marker() {
303 Some(pos_marker) => pos_marker.working_loc_after(self.raw()),
304 None => {
305 unreachable!("{self:?} has no PositionMarker")
306 }
307 }
308 }
309
310 pub fn is_templated(&self) -> bool {
311 if let Some(pos_marker) = self.get_position_marker() {
312 pos_marker.source_slice.start != pos_marker.source_slice.end && !pos_marker.is_literal()
313 } else {
314 panic!("PosMarker must be set");
315 }
316 }
317
318 pub fn iter_segments(&self, expanding: &SyntaxSet, pass_through: bool) -> Vec<ErasedSegment> {
319 let capacity = if expanding.is_empty() {
320 self.segments().len()
321 } else {
322 0
323 };
324 let mut result = Vec::with_capacity(capacity);
325 for segment in self.segments() {
326 if expanding.contains(segment.get_type()) {
327 let expanding = if pass_through {
328 expanding
329 } else {
330 &SyntaxSet::EMPTY
331 };
332 result.append(&mut segment.iter_segments(expanding, false));
333 } else {
334 result.push(segment.clone());
335 }
336 }
337 result
338 }
339
340 pub(crate) fn code_indices(&self) -> Rc<Vec<usize>> {
341 self.value
342 .code_idx
343 .get_or_init(|| {
344 Rc::from(
345 self.segments()
346 .iter()
347 .enumerate()
348 .filter(|(_, seg)| seg.is_code())
349 .map(|(idx, _)| idx)
350 .collect::<Vec<_>>(),
351 )
352 })
353 .clone()
354 }
355
356 pub fn children(
357 &self,
358 seg_types: &'static SyntaxSet,
359 ) -> impl Iterator<Item = &ErasedSegment> + '_ {
360 self.segments()
361 .iter()
362 .filter(move |seg| seg_types.contains(seg.get_type()))
363 }
364
365 pub fn iter_patches(&self, templated_file: &TemplatedFile) -> Vec<FixPatch> {
366 let mut acc = Vec::new();
367
368 let templated_raw = &templated_file.templated_str.as_ref().unwrap()
369 [self.get_position_marker().unwrap().templated_slice.clone()];
370 if self.raw() == templated_raw {
371 acc.extend(self.iter_source_fix_patches(templated_file));
372 return acc;
373 }
374
375 if self.get_position_marker().is_none() {
376 return Vec::new();
377 }
378
379 let pos_marker = self.get_position_marker().unwrap();
380 if pos_marker.is_literal() {
381 acc.extend(self.iter_source_fix_patches(templated_file));
382 acc.push(FixPatch::new(
383 pos_marker.templated_slice.clone(),
384 self.raw().clone(),
385 pos_marker.source_slice.clone(),
387 templated_file.templated_str.as_ref().unwrap()[pos_marker.templated_slice.clone()]
388 .to_string(),
389 templated_file.source_str[pos_marker.source_slice.clone()].to_string(),
390 ));
391 } else if self.segments().is_empty() {
392 return acc;
393 } else {
394 let mut segments = self.segments();
395
396 while !segments.is_empty()
397 && matches!(
398 segments.last().unwrap().get_type(),
399 SyntaxKind::EndOfFile
400 | SyntaxKind::Indent
401 | SyntaxKind::Dedent
402 | SyntaxKind::Implicit
403 )
404 {
405 segments = &segments[..segments.len() - 1];
406 }
407
408 let pos = self.get_position_marker().unwrap();
409 let mut source_idx = pos.source_slice.start;
410 let mut templated_idx = pos.templated_slice.start;
411 let mut insert_buff = String::new();
412
413 for segment in segments {
414 let pos_marker = segment.get_position_marker().unwrap();
415 if !segment.raw().is_empty() && pos_marker.is_point() {
416 insert_buff.push_str(segment.raw().as_ref());
417 continue;
418 }
419
420 let start_diff = pos_marker.templated_slice.start - templated_idx;
421
422 if start_diff > 0 || !insert_buff.is_empty() {
423 let fixed_raw = std::mem::take(&mut insert_buff);
424 let raw_segments = segment.get_raw_segments();
425 let first_segment_pos = raw_segments[0].get_position_marker().unwrap();
426
427 acc.push(FixPatch::new(
428 templated_idx..first_segment_pos.templated_slice.start,
429 fixed_raw.into(),
430 source_idx..first_segment_pos.source_slice.start,
431 String::new(),
432 String::new(),
433 ));
434 }
435
436 acc.extend(segment.iter_patches(templated_file));
437
438 source_idx = pos_marker.source_slice.end;
439 templated_idx = pos_marker.templated_slice.end;
440 }
441
442 let end_diff = pos.templated_slice.end - templated_idx;
443 if end_diff != 0 || !insert_buff.is_empty() {
444 let source_slice = source_idx..pos.source_slice.end;
445 let templated_slice = templated_idx..pos.templated_slice.end;
446
447 let templated_str = templated_file.templated_str.as_ref().unwrap()
448 [templated_slice.clone()]
449 .to_owned();
450 let source_str = templated_file.source_str[source_slice.clone()].to_owned();
451
452 acc.push(FixPatch::new(
453 templated_slice,
454 insert_buff.into(),
455 source_slice,
456 templated_str,
457 source_str,
458 ));
459 }
460 }
461
462 acc
463 }
464
465 pub fn descendant_type_set(&self) -> &SyntaxSet {
466 match &self.value.kind {
467 NodeOrTokenKind::Node(node) => node.descendant_type_set.get_or_init(|| {
468 self.segments()
469 .iter()
470 .flat_map(|segment| {
471 segment
472 .descendant_type_set()
473 .clone()
474 .union(segment.class_types())
475 })
476 .collect()
477 }),
478 NodeOrTokenKind::Token(_) => const { &SyntaxSet::EMPTY },
479 }
480 }
481
482 pub fn is_comment(&self) -> bool {
483 matches!(
484 self.value.syntax_kind,
485 SyntaxKind::Comment | SyntaxKind::InlineComment | SyntaxKind::BlockComment
486 )
487 }
488
489 pub fn is_whitespace(&self) -> bool {
490 matches!(
491 self.value.syntax_kind,
492 SyntaxKind::Whitespace | SyntaxKind::Newline
493 )
494 }
495
496 pub fn is_indent(&self) -> bool {
497 matches!(
498 self.value.syntax_kind,
499 SyntaxKind::Indent | SyntaxKind::Implicit | SyntaxKind::Dedent
500 )
501 }
502
503 pub fn get_position_marker(&self) -> Option<&PositionMarker> {
504 self.value.position_marker.as_ref()
505 }
506
507 pub(crate) fn iter_source_fix_patches(&self, templated_file: &TemplatedFile) -> Vec<FixPatch> {
508 let source_fixes = self.get_source_fixes();
509 let mut patches = Vec::with_capacity(source_fixes.len());
510
511 for source_fix in &source_fixes {
512 patches.push(FixPatch::new(
513 source_fix.templated_slice.clone(),
514 source_fix.edit.clone(),
515 source_fix.source_slice.clone(),
517 templated_file.templated_str.clone().unwrap()[source_fix.templated_slice.clone()]
518 .to_string(),
519 templated_file.source_str[source_fix.source_slice.clone()].to_string(),
520 ));
521 }
522
523 patches
524 }
525
526 pub fn id(&self) -> u32 {
527 self.value.id
528 }
529
530 pub fn get_source_fixes(&self) -> Vec<SourceFix> {
532 match &self.value.kind {
533 NodeOrTokenKind::Node(node) => node.source_fixes.clone(),
534 NodeOrTokenKind::Token(_) => Vec::new(),
535 }
536 }
537
538 pub fn edit(
539 &self,
540 id: u32,
541 raw: Option<String>,
542 _source_fixes: Option<Vec<SourceFix>>,
543 ) -> ErasedSegment {
544 match &self.value.kind {
545 NodeOrTokenKind::Node(_node) => {
546 todo!()
547 }
548 NodeOrTokenKind::Token(token) => {
549 let raw = raw.as_deref().unwrap_or(token.raw.as_ref());
550 SegmentBuilder::token(id, raw, self.value.syntax_kind)
551 .with_position(self.get_position_marker().unwrap().clone())
552 .finish()
553 }
554 }
555 }
556
557 pub fn class_types(&self) -> &SyntaxSet {
558 &self.value.class_types
559 }
560
561 pub(crate) fn first_non_whitespace_segment_raw_upper(&self) -> Option<String> {
562 for seg in self.get_raw_segments() {
563 if !seg.raw().is_empty() {
564 return Some(seg.raw().to_uppercase());
565 }
566 }
567 None
568 }
569
570 pub fn is(&self, other: &ErasedSegment) -> bool {
571 Rc::ptr_eq(&self.value, &other.value)
572 }
573
574 pub fn addr(&self) -> usize {
575 Rc::as_ptr(&self.value).addr()
576 }
577
578 pub fn direct_descendant_type_set(&self) -> SyntaxSet {
579 self.segments()
580 .iter()
581 .fold(SyntaxSet::EMPTY, |set, it| set.union(it.class_types()))
582 }
583
584 pub fn is_keyword(&self, p0: &str) -> bool {
585 self.is_type(SyntaxKind::Keyword) && self.raw().eq_ignore_ascii_case(p0)
586 }
587
588 pub fn hash_value(&self) -> u64 {
589 *self.value.hash.get_or_init(|| {
590 let mut hasher = ahash::AHasher::default();
591 self.get_type().hash(&mut hasher);
592 self.raw().hash(&mut hasher);
593
594 if let Some(marker) = &self.get_position_marker() {
595 marker.source_position().hash(&mut hasher);
596 } else {
597 None::<usize>.hash(&mut hasher);
598 }
599
600 hasher.finish()
601 })
602 }
603
604 pub fn deep_clone(&self) -> Self {
605 Self {
606 value: Rc::new(self.value.as_ref().clone()),
607 }
608 }
609
610 #[track_caller]
611 pub(crate) fn get_mut(&mut self) -> &mut NodeOrToken {
612 Rc::get_mut(&mut self.value).unwrap()
613 }
614
615 #[track_caller]
616 pub(crate) fn make_mut(&mut self) -> &mut NodeOrToken {
617 Rc::make_mut(&mut self.value)
618 }
619
620 pub fn reference(&self) -> ObjectReferenceSegment {
621 ObjectReferenceSegment(
622 self.clone(),
623 match self.get_type() {
624 SyntaxKind::TableReference => ObjectReferenceKind::Table,
625 SyntaxKind::WildcardIdentifier => ObjectReferenceKind::WildcardIdentifier,
626 _ => ObjectReferenceKind::Object,
627 },
628 )
629 }
630
631 pub fn recursive_crawl_all(&self, reverse: bool) -> Vec<ErasedSegment> {
632 let mut result = Vec::with_capacity(self.segments().len() + 1);
633
634 if reverse {
635 for seg in self.segments().iter().rev() {
636 result.append(&mut seg.recursive_crawl_all(reverse));
637 }
638 result.push(self.clone());
639 } else {
640 result.push(self.clone());
641 for seg in self.segments() {
642 result.append(&mut seg.recursive_crawl_all(reverse));
643 }
644 }
645
646 result
647 }
648
649 pub fn raw_segments_with_ancestors(&self) -> &[(ErasedSegment, Vec<PathStep>)] {
650 match &self.value.kind {
651 NodeOrTokenKind::Node(node) => node.raw_segments_with_ancestors.get_or_init(|| {
652 let mut buffer: Vec<(ErasedSegment, Vec<PathStep>)> =
653 Vec::with_capacity(self.segments().len());
654 let code_idxs = self.code_indices();
655
656 for (idx, seg) in self.segments().iter().enumerate() {
657 let new_step = vec![PathStep {
658 segment: self.clone(),
659 idx,
660 len: self.segments().len(),
661 code_idxs: code_idxs.clone(),
662 }];
663
664 if seg.segments().is_empty() {
670 buffer.push((seg.clone(), new_step));
671 } else {
672 let extended =
673 seg.raw_segments_with_ancestors()
674 .iter()
675 .map(|(raw_seg, stack)| {
676 let mut new_step = new_step.clone();
677 new_step.extend_from_slice(stack);
678 (raw_seg.clone(), new_step)
679 });
680
681 buffer.extend(extended);
682 }
683 }
684
685 buffer
686 }),
687 NodeOrTokenKind::Token(_) => &[],
688 }
689 }
690
691 pub fn path_to(&self, other: &ErasedSegment) -> Vec<PathStep> {
692 let midpoint = other;
693
694 for (idx, seg) in enumerate(self.segments()) {
695 let mut steps = vec![PathStep {
696 segment: self.clone(),
697 idx,
698 len: self.segments().len(),
699 code_idxs: self.code_indices(),
700 }];
701
702 if seg.eq(midpoint) {
703 return steps;
704 }
705
706 let res = seg.path_to(midpoint);
707
708 if !res.is_empty() {
709 steps.extend(res);
710 return steps;
711 }
712 }
713
714 Vec::new()
715 }
716
717 pub fn apply_fixes(
718 &self,
719 fixes: &mut FxHashMap<u32, AnchorEditInfo>,
720 ) -> (ErasedSegment, Vec<ErasedSegment>, Vec<ErasedSegment>) {
721 if fixes.is_empty() || self.segments().is_empty() {
722 return (self.clone(), Vec::new(), Vec::new());
723 }
724
725 let mut seg_buffer = Vec::new();
726 let mut has_applied_fixes = false;
727 let mut _requires_validate = false;
728
729 for seg in self.segments() {
730 let Some(mut anchor_info) = fixes.remove(&seg.id()) else {
734 seg_buffer.push(seg.clone());
735 continue;
736 };
737
738 if anchor_info.fixes.len() == 2
739 && matches!(anchor_info.fixes[0], LintFix::CreateAfter { .. })
740 {
741 anchor_info.fixes.reverse();
742 }
743
744 let fixes_count = anchor_info.fixes.len();
745 for lint_fix in anchor_info.fixes {
746 has_applied_fixes = true;
747
748 if matches!(lint_fix, LintFix::Delete { .. }) {
750 _requires_validate = true;
752 continue;
754 }
755
756 assert!(matches!(
758 lint_fix,
759 LintFix::Replace { .. }
760 | LintFix::CreateBefore { .. }
761 | LintFix::CreateAfter { .. }
762 ));
763
764 match lint_fix {
765 LintFix::CreateAfter { edit, .. } => {
766 if fixes_count == 1 {
767 seg_buffer.push(seg.clone());
771 }
772 for s in edit {
773 seg_buffer.push(s);
774 }
775 _requires_validate = true;
776 }
777 LintFix::CreateBefore { edit, .. } => {
778 for s in edit {
779 seg_buffer.push(s);
780 }
781 seg_buffer.push(seg.clone());
782 _requires_validate = true;
783 }
784 LintFix::Replace { edit, .. } => {
785 let mut consumed_pos = false;
786 let is_single_same_type =
787 edit.len() == 1 && edit[0].class_types() == seg.class_types();
788
789 for mut s in edit {
790 if !consumed_pos && s.raw() == seg.raw() {
791 consumed_pos = true;
792 s.make_mut()
793 .set_position_marker(seg.get_position_marker().cloned());
794 }
795 seg_buffer.push(s);
796 }
797
798 if !is_single_same_type {
799 _requires_validate = true;
800 }
801 }
802 LintFix::Delete { .. } => {
803 unreachable!()
805 }
806 }
807 }
808 }
809
810 if has_applied_fixes {
811 seg_buffer =
812 position_segments(&seg_buffer, self.get_position_marker().as_ref().unwrap());
813 }
814
815 let seg_queue = seg_buffer;
816 let mut seg_buffer = Vec::new();
817 for seg in seg_queue {
818 let (mid, pre, post) = seg.apply_fixes(fixes);
819
820 seg_buffer.extend(pre);
821 seg_buffer.push(mid);
822 seg_buffer.extend(post);
823 }
824
825 let seg_buffer =
826 position_segments(&seg_buffer, self.get_position_marker().as_ref().unwrap());
827 (self.new(seg_buffer), Vec::new(), Vec::new())
828 }
829}
830
831#[cfg(any(test, feature = "serde"))]
832pub mod serde {
833 use serde::ser::SerializeMap;
834 use serde::{Deserialize, Serialize};
835
836 use crate::parser::segments::ErasedSegment;
837
838 #[derive(Serialize, Deserialize)]
839 #[serde(untagged)]
840 pub enum SerialisedSegmentValue {
841 Single(String),
842 Nested(Vec<TupleSerialisedSegment>),
843 }
844
845 #[derive(Deserialize)]
846 pub struct TupleSerialisedSegment(String, SerialisedSegmentValue);
847
848 impl Serialize for TupleSerialisedSegment {
849 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
850 where
851 S: serde::Serializer,
852 {
853 let mut map = serializer.serialize_map(None)?;
854 map.serialize_key(&self.0)?;
855 map.serialize_value(&self.1)?;
856 map.end()
857 }
858 }
859
860 impl TupleSerialisedSegment {
861 pub fn sinlge(key: String, value: String) -> Self {
862 Self(key, SerialisedSegmentValue::Single(value))
863 }
864
865 pub fn nested(key: String, segments: Vec<TupleSerialisedSegment>) -> Self {
866 Self(key, SerialisedSegmentValue::Nested(segments))
867 }
868 }
869
870 impl ErasedSegment {
871 pub fn to_serialised(&self, code_only: bool, show_raw: bool) -> TupleSerialisedSegment {
872 if show_raw && self.segments().is_empty() {
873 TupleSerialisedSegment::sinlge(
874 self.get_type().as_str().to_string(),
875 self.raw().to_string(),
876 )
877 } else if code_only {
878 let segments = self
879 .segments()
880 .iter()
881 .filter(|seg| seg.is_code() && !seg.is_meta())
882 .map(|seg| seg.to_serialised(code_only, show_raw))
883 .collect::<Vec<_>>();
884
885 TupleSerialisedSegment::nested(self.get_type().as_str().to_string(), segments)
886 } else {
887 let segments = self
888 .segments()
889 .iter()
890 .map(|seg| seg.to_serialised(code_only, show_raw))
891 .collect::<Vec<_>>();
892
893 TupleSerialisedSegment::nested(self.get_type().as_str().to_string(), segments)
894 }
895 }
896 }
897}
898
899impl PartialEq for ErasedSegment {
900 fn eq(&self, other: &Self) -> bool {
901 if self.id() == other.id() {
902 return true;
903 }
904
905 let pos_self = self.get_position_marker();
906 let pos_other = other.get_position_marker();
907 if let Some((pos_self, pos_other)) = pos_self.zip(pos_other) {
908 self.get_type() == other.get_type()
909 && pos_self.working_loc() == pos_other.working_loc()
910 && self.raw() == other.raw()
911 } else {
912 false
913 }
914 }
915}
916
917pub fn position_segments(
918 segments: &[ErasedSegment],
919 parent_pos: &PositionMarker,
920) -> Vec<ErasedSegment> {
921 if segments.is_empty() {
922 return Vec::new();
923 }
924
925 let (mut line_no, mut line_pos) = { (parent_pos.working_line_no, parent_pos.working_line_pos) };
926
927 let mut segment_buffer: Vec<ErasedSegment> = Vec::new();
928 for (idx, segment) in enumerate(segments) {
929 let old_position = segment.get_position_marker();
930
931 let mut new_position = match old_position {
932 Some(pos_marker) => pos_marker.clone(),
933 None => {
934 let start_point = if idx > 0 {
935 let prev_seg = segment_buffer[idx - 1].clone();
936 Some(prev_seg.get_position_marker().unwrap().end_point_marker())
937 } else {
938 Some(parent_pos.start_point_marker())
939 };
940
941 let mut end_point = None;
942 for fwd_seg in &segments[idx + 1..] {
943 if fwd_seg.get_position_marker().is_some() {
944 end_point = Some(
945 fwd_seg.get_raw_segments()[0]
946 .get_position_marker()
947 .unwrap()
948 .start_point_marker(),
949 );
950 break;
951 }
952 }
953
954 if let Some((start_point, end_point)) = start_point
955 .as_ref()
956 .zip(end_point.as_ref())
957 .filter(|(start_point, end_point)| start_point != end_point)
958 {
959 PositionMarker::from_points(start_point, end_point)
960 } else if let Some(start_point) = start_point.as_ref() {
961 start_point.clone()
962 } else if let Some(end_point) = end_point.as_ref() {
963 end_point.clone()
964 } else {
965 unimplemented!("Unable to position new segment")
966 }
967 }
968 };
969
970 new_position = new_position.with_working_position(line_no, line_pos);
971 (line_no, line_pos) = PositionMarker::infer_next_position(segment.raw(), line_no, line_pos);
972
973 let mut new_seg = if !segment.segments().is_empty() && old_position != Some(&new_position) {
974 let child_segments = position_segments(segment.segments(), &new_position);
975 segment.change_segments(child_segments)
976 } else {
977 segment.deep_clone()
978 };
979
980 new_seg.get_mut().set_position_marker(new_position.into());
981 segment_buffer.push(new_seg);
982 }
983
984 segment_buffer
985}
986
987#[derive(Debug, Clone)]
988pub struct NodeOrToken {
989 id: u32,
990 syntax_kind: SyntaxKind,
991 class_types: SyntaxSet,
992 position_marker: Option<PositionMarker>,
993 kind: NodeOrTokenKind,
994 code_idx: OnceCell<Rc<Vec<usize>>>,
995 hash: OnceCell<u64>,
996}
997
998#[derive(Debug, Clone)]
999pub enum NodeOrTokenKind {
1000 Node(NodeData),
1001 Token(TokenData),
1002}
1003
1004impl NodeOrToken {
1005 pub fn set_position_marker(&mut self, position_marker: Option<PositionMarker>) {
1006 self.position_marker = position_marker;
1007 }
1008
1009 pub fn set_id(&mut self, id: u32) {
1010 self.id = id;
1011 }
1012}
1013
1014#[derive(Debug, Clone)]
1015pub struct NodeData {
1016 dialect: DialectKind,
1017 segments: Vec<ErasedSegment>,
1018 raw: OnceCell<SmolStr>,
1019 source_fixes: Vec<SourceFix>,
1020 descendant_type_set: OnceCell<SyntaxSet>,
1021 raw_segments_with_ancestors: OnceCell<Vec<(ErasedSegment, Vec<PathStep>)>>,
1022}
1023
1024#[derive(Debug, Clone, PartialEq)]
1025pub struct TokenData {
1026 raw: SmolStr,
1027}
1028
1029#[track_caller]
1030pub fn pos_marker(segments: &[ErasedSegment]) -> PositionMarker {
1031 let markers = segments.iter().filter_map(|seg| seg.get_position_marker());
1032
1033 PositionMarker::from_child_markers(markers)
1034}
1035
1036#[derive(Debug, Clone)]
1037pub struct PathStep {
1038 pub segment: ErasedSegment,
1039 pub idx: usize,
1040 pub len: usize,
1041 pub code_idxs: Rc<Vec<usize>>,
1042}
1043
1044fn class_types(syntax_kind: SyntaxKind) -> SyntaxSet {
1045 match syntax_kind {
1046 SyntaxKind::ColumnReference => SyntaxSet::new(&[SyntaxKind::ObjectReference, syntax_kind]),
1047 SyntaxKind::WildcardIdentifier => {
1048 SyntaxSet::new(&[SyntaxKind::WildcardIdentifier, SyntaxKind::ObjectReference])
1049 }
1050 SyntaxKind::TableReference => SyntaxSet::new(&[SyntaxKind::ObjectReference, syntax_kind]),
1051 _ => SyntaxSet::single(syntax_kind),
1052 }
1053}
1054
1055#[cfg(test)]
1056mod tests {
1057 use super::*;
1058 use crate::lint_fix::LintFix;
1059 use crate::linter::compute_anchor_edit_info;
1060 use crate::parser::segments::test_functions::{raw_seg, raw_segments};
1061
1062 #[test]
1063 fn test_parser_base_segments_raw_compare() {
1065 let template: TemplatedFile = "foobar".into();
1066 let rs1 = SegmentBuilder::token(0, "foobar", SyntaxKind::Word)
1067 .with_position(PositionMarker::new(
1068 0..6,
1069 0..6,
1070 template.clone(),
1071 None,
1072 None,
1073 ))
1074 .finish();
1075 let rs2 = SegmentBuilder::token(0, "foobar", SyntaxKind::Word)
1076 .with_position(PositionMarker::new(
1077 0..6,
1078 0..6,
1079 template.clone(),
1080 None,
1081 None,
1082 ))
1083 .finish();
1084
1085 assert_eq!(rs1, rs2)
1086 }
1087
1088 #[test]
1089 fn test_parser_base_segments_raw() {
1092 let raw_seg = raw_seg();
1093
1094 assert_eq!(raw_seg.raw(), "foobar");
1095 }
1096
1097 #[test]
1098 fn test_parser_base_segments_compute_anchor_edit_info() {
1100 let raw_segs = raw_segments();
1101 let tables = Tables::default();
1102
1103 let fixes = vec![
1107 LintFix::replace(
1108 raw_segs[0].clone(),
1109 vec![raw_segs[0].edit(tables.next_id(), Some("a".to_string()), None)],
1110 None,
1111 ),
1112 LintFix::replace(
1113 raw_segs[0].clone(),
1114 vec![raw_segs[0].edit(tables.next_id(), Some("a".to_string()), None)],
1115 None,
1116 ),
1117 LintFix::replace(
1118 raw_segs[0].clone(),
1119 vec![raw_segs[0].edit(tables.next_id(), Some("b".to_string()), None)],
1120 None,
1121 ),
1122 ];
1123
1124 let mut anchor_edit_info = Default::default();
1125 compute_anchor_edit_info(&mut anchor_edit_info, fixes);
1126
1127 assert_eq!(
1129 anchor_edit_info.keys().collect::<Vec<_>>(),
1130 vec![&raw_segs[0].id()]
1131 );
1132
1133 let anchor_info = anchor_edit_info.get(&raw_segs[0].id()).unwrap();
1134
1135 assert_eq!(anchor_info.replace, 2);
1137
1138 assert_eq!(
1141 anchor_info.fixes[0],
1142 LintFix::replace(
1143 raw_segs[0].clone(),
1144 vec![raw_segs[0].edit(tables.next_id(), Some("a".to_string()), None)],
1145 None,
1146 )
1147 );
1148 assert_eq!(
1149 anchor_info.fixes[1],
1150 LintFix::replace(
1151 raw_segs[0].clone(),
1152 vec![raw_segs[0].edit(tables.next_id(), Some("b".to_string()), None)],
1153 None,
1154 )
1155 );
1156
1157 assert_eq!(
1159 anchor_info.fixes[anchor_info.first_replace.unwrap()],
1160 LintFix::replace(
1161 raw_segs[0].clone(),
1162 vec![raw_segs[0].edit(tables.next_id(), Some("a".to_string()), None)],
1163 None,
1164 )
1165 );
1166 }
1167}