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