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 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 && !has_descendant_source_fixes {
394 return acc;
396 }
397 if self.get_position_marker().is_none() {
400 return Vec::new();
401 }
402
403 let pos_marker = self.get_position_marker().unwrap();
404 if pos_marker.is_literal() && !has_descendant_source_fixes {
405 acc.extend(self.iter_source_fix_patches(templated_file));
406 acc.push(FixPatch::new(
407 pos_marker.templated_slice.clone(),
408 self.raw().clone(),
409 pos_marker.source_slice.clone(),
411 templated_file.templated_str.as_ref().unwrap()[pos_marker.templated_slice.clone()]
412 .to_string(),
413 templated_file.source_str[pos_marker.source_slice.clone()].to_string(),
414 ));
415 } else if self.segments().is_empty() {
416 return acc;
417 } else {
418 let mut segments = self.segments();
419
420 while !segments.is_empty()
421 && matches!(
422 segments.last().unwrap().get_type(),
423 SyntaxKind::EndOfFile
424 | SyntaxKind::Indent
425 | SyntaxKind::Dedent
426 | SyntaxKind::Implicit
427 )
428 {
429 segments = &segments[..segments.len() - 1];
430 }
431
432 let pos = self.get_position_marker().unwrap();
433 let mut source_idx = pos.source_slice.start;
434 let mut templated_idx = pos.templated_slice.start;
435 let mut insert_buff = String::new();
436
437 for segment in segments {
438 let pos_marker = segment.get_position_marker().unwrap();
439 if !segment.raw().is_empty() && pos_marker.is_point() {
440 insert_buff.push_str(segment.raw().as_ref());
441 continue;
442 }
443
444 let start_diff = pos_marker.templated_slice.start - templated_idx;
445
446 if start_diff > 0 || !insert_buff.is_empty() {
447 let fixed_raw = std::mem::take(&mut insert_buff);
448 let raw_segments = segment.get_raw_segments();
449 let first_segment_pos = raw_segments[0].get_position_marker().unwrap();
450
451 acc.push(FixPatch::new(
452 templated_idx..first_segment_pos.templated_slice.start,
453 fixed_raw.into(),
454 source_idx..first_segment_pos.source_slice.start,
455 String::new(),
456 String::new(),
457 ));
458 }
459
460 acc.extend(segment.iter_patches(templated_file));
461
462 source_idx = pos_marker.source_slice.end;
463 templated_idx = pos_marker.templated_slice.end;
464 }
465
466 let end_diff = pos.templated_slice.end - templated_idx;
467 if end_diff != 0 || !insert_buff.is_empty() {
468 let source_slice = source_idx..pos.source_slice.end;
469 let templated_slice = templated_idx..pos.templated_slice.end;
470
471 let templated_str = templated_file.templated_str.as_ref().unwrap()
472 [templated_slice.clone()]
473 .to_owned();
474 let source_str = templated_file.source_str[source_slice.clone()].to_owned();
475
476 acc.push(FixPatch::new(
477 templated_slice,
478 insert_buff.into(),
479 source_slice,
480 templated_str,
481 source_str,
482 ));
483 }
484 }
485
486 acc
487 }
488
489 pub fn descendant_type_set(&self) -> &SyntaxSet {
490 match &self.value.kind {
491 NodeOrTokenKind::Node(node) => node.descendant_type_set.get_or_init(|| {
492 self.segments()
493 .iter()
494 .flat_map(|segment| {
495 segment
496 .descendant_type_set()
497 .clone()
498 .union(segment.class_types())
499 })
500 .collect()
501 }),
502 NodeOrTokenKind::Token(_) => const { &SyntaxSet::EMPTY },
503 }
504 }
505
506 pub fn is_comment(&self) -> bool {
507 matches!(
508 self.value.syntax_kind,
509 SyntaxKind::Comment | SyntaxKind::InlineComment | SyntaxKind::BlockComment
510 )
511 }
512
513 pub fn is_whitespace(&self) -> bool {
514 matches!(
515 self.value.syntax_kind,
516 SyntaxKind::Whitespace | SyntaxKind::Newline
517 )
518 }
519
520 pub fn is_indent(&self) -> bool {
521 matches!(
522 self.value.syntax_kind,
523 SyntaxKind::Indent | SyntaxKind::Implicit | SyntaxKind::Dedent
524 )
525 }
526
527 pub fn get_position_marker(&self) -> Option<&PositionMarker> {
528 self.value.position_marker.as_ref()
529 }
530
531 pub(crate) fn iter_source_fix_patches(&self, templated_file: &TemplatedFile) -> Vec<FixPatch> {
532 let source_fixes = self.get_source_fixes();
533 let mut patches = Vec::with_capacity(source_fixes.len());
534
535 for source_fix in &source_fixes {
536 patches.push(FixPatch::new(
537 source_fix.templated_slice.clone(),
538 source_fix.edit.clone(),
539 source_fix.source_slice.clone(),
541 templated_file.templated_str.clone().unwrap()[source_fix.templated_slice.clone()]
542 .to_string(),
543 templated_file.source_str[source_fix.source_slice.clone()].to_string(),
544 ));
545 }
546
547 patches
548 }
549
550 pub fn id(&self) -> u32 {
551 self.value.id
552 }
553
554 pub fn get_source_fixes(&self) -> Vec<SourceFix> {
556 match &self.value.kind {
557 NodeOrTokenKind::Node(node) => node.source_fixes.clone(),
558 NodeOrTokenKind::Token(_) => Vec::new(),
559 }
560 }
561
562 pub fn get_all_source_fixes(&self) -> Vec<SourceFix> {
564 let mut fixes = self.get_source_fixes();
565 for segment in self.segments() {
566 fixes.extend(segment.get_all_source_fixes());
567 }
568 fixes
569 }
570
571 pub fn edit(
572 &self,
573 id: u32,
574 raw: Option<String>,
575 _source_fixes: Option<Vec<SourceFix>>,
576 ) -> ErasedSegment {
577 match &self.value.kind {
578 NodeOrTokenKind::Node(_node) => {
579 todo!()
580 }
581 NodeOrTokenKind::Token(token) => {
582 let raw = raw.as_deref().unwrap_or(token.raw.as_ref());
583 SegmentBuilder::token(id, raw, self.value.syntax_kind)
584 .with_position(self.get_position_marker().unwrap().clone())
585 .finish()
586 }
587 }
588 }
589
590 pub fn class_types(&self) -> &SyntaxSet {
591 &self.value.class_types
592 }
593
594 pub(crate) fn first_non_whitespace_segment_raw_upper(&self) -> Option<String> {
595 for seg in self.get_raw_segments() {
596 if !seg.raw().is_empty() {
597 return Some(seg.raw().to_uppercase());
598 }
599 }
600 None
601 }
602
603 pub fn is(&self, other: &ErasedSegment) -> bool {
604 Rc::ptr_eq(&self.value, &other.value)
605 }
606
607 pub fn addr(&self) -> usize {
608 Rc::as_ptr(&self.value).addr()
609 }
610
611 pub fn direct_descendant_type_set(&self) -> SyntaxSet {
612 self.segments()
613 .iter()
614 .fold(SyntaxSet::EMPTY, |set, it| set.union(it.class_types()))
615 }
616
617 pub fn is_keyword(&self, p0: &str) -> bool {
618 self.is_type(SyntaxKind::Keyword) && self.raw().eq_ignore_ascii_case(p0)
619 }
620
621 pub fn hash_value(&self) -> u64 {
622 *self.value.hash.get_or_init(|| {
623 let mut hasher = ahash::AHasher::default();
624 self.get_type().hash(&mut hasher);
625 self.raw().hash(&mut hasher);
626
627 if let Some(marker) = &self.get_position_marker() {
628 marker.source_position().hash(&mut hasher);
629 } else {
630 None::<usize>.hash(&mut hasher);
631 }
632
633 hasher.finish()
634 })
635 }
636
637 pub fn deep_clone(&self) -> Self {
638 Self {
639 value: Rc::new(self.value.as_ref().clone()),
640 }
641 }
642
643 #[track_caller]
644 pub(crate) fn get_mut(&mut self) -> &mut NodeOrToken {
645 Rc::get_mut(&mut self.value).unwrap()
646 }
647
648 #[track_caller]
649 pub(crate) fn make_mut(&mut self) -> &mut NodeOrToken {
650 Rc::make_mut(&mut self.value)
651 }
652
653 pub fn reference(&self) -> ObjectReferenceSegment {
654 ObjectReferenceSegment(
655 self.clone(),
656 match self.get_type() {
657 SyntaxKind::TableReference => ObjectReferenceKind::Table,
658 SyntaxKind::WildcardIdentifier => ObjectReferenceKind::WildcardIdentifier,
659 _ => ObjectReferenceKind::Object,
660 },
661 )
662 }
663
664 pub fn recursive_crawl_all(&self, reverse: bool) -> Vec<ErasedSegment> {
665 let mut result = Vec::with_capacity(self.segments().len() + 1);
666
667 if reverse {
668 for seg in self.segments().iter().rev() {
669 result.append(&mut seg.recursive_crawl_all(reverse));
670 }
671 result.push(self.clone());
672 } else {
673 result.push(self.clone());
674 for seg in self.segments() {
675 result.append(&mut seg.recursive_crawl_all(reverse));
676 }
677 }
678
679 result
680 }
681
682 pub fn raw_segments_with_ancestors(&self) -> &[(ErasedSegment, Vec<PathStep>)] {
683 match &self.value.kind {
684 NodeOrTokenKind::Node(node) => node.raw_segments_with_ancestors.get_or_init(|| {
685 let mut buffer: Vec<(ErasedSegment, Vec<PathStep>)> =
686 Vec::with_capacity(self.segments().len());
687 let code_idxs = self.code_indices();
688
689 for (idx, seg) in self.segments().iter().enumerate() {
690 let new_step = vec![PathStep {
691 segment: self.clone(),
692 idx,
693 len: self.segments().len(),
694 code_idxs: code_idxs.clone(),
695 }];
696
697 if seg.segments().is_empty() {
703 buffer.push((seg.clone(), new_step));
704 } else {
705 let extended =
706 seg.raw_segments_with_ancestors()
707 .iter()
708 .map(|(raw_seg, stack)| {
709 let mut new_step = new_step.clone();
710 new_step.extend_from_slice(stack);
711 (raw_seg.clone(), new_step)
712 });
713
714 buffer.extend(extended);
715 }
716 }
717
718 buffer
719 }),
720 NodeOrTokenKind::Token(_) => &[],
721 }
722 }
723
724 pub fn path_to(&self, other: &ErasedSegment) -> Vec<PathStep> {
725 let midpoint = other;
726
727 for (idx, seg) in enumerate(self.segments()) {
728 let mut steps = vec![PathStep {
729 segment: self.clone(),
730 idx,
731 len: self.segments().len(),
732 code_idxs: self.code_indices(),
733 }];
734
735 if seg.eq(midpoint) {
736 return steps;
737 }
738
739 let res = seg.path_to(midpoint);
740
741 if !res.is_empty() {
742 steps.extend(res);
743 return steps;
744 }
745 }
746
747 Vec::new()
748 }
749
750 pub fn apply_fixes(
751 &self,
752 fixes: &mut FxHashMap<u32, AnchorEditInfo>,
753 ) -> (ErasedSegment, Vec<ErasedSegment>, Vec<ErasedSegment>) {
754 if fixes.is_empty() || self.segments().is_empty() {
755 return (self.clone(), Vec::new(), Vec::new());
756 }
757
758 let mut seg_buffer = Vec::new();
759 let mut has_applied_fixes = false;
760 let mut _requires_validate = false;
761
762 for seg in self.segments() {
763 let Some(mut anchor_info) = fixes.remove(&seg.id()) else {
767 seg_buffer.push(seg.clone());
768 continue;
769 };
770
771 if anchor_info.fixes.len() == 2
772 && matches!(anchor_info.fixes[0], LintFix::CreateAfter { .. })
773 {
774 anchor_info.fixes.reverse();
775 }
776
777 let fixes_count = anchor_info.fixes.len();
778 for lint_fix in anchor_info.fixes {
779 has_applied_fixes = true;
780
781 if matches!(lint_fix, LintFix::Delete { .. }) {
783 _requires_validate = true;
785 continue;
787 }
788
789 assert!(matches!(
791 lint_fix,
792 LintFix::Replace { .. }
793 | LintFix::CreateBefore { .. }
794 | LintFix::CreateAfter { .. }
795 ));
796
797 match lint_fix {
798 LintFix::CreateAfter { edit, .. } => {
799 if fixes_count == 1 {
800 seg_buffer.push(seg.clone());
804 }
805 for s in edit {
806 seg_buffer.push(s);
807 }
808 _requires_validate = true;
809 }
810 LintFix::CreateBefore { edit, .. } => {
811 for s in edit {
812 seg_buffer.push(s);
813 }
814 seg_buffer.push(seg.clone());
815 _requires_validate = true;
816 }
817 LintFix::Replace { edit, .. } => {
818 let mut consumed_pos = false;
819 let is_single_same_type =
820 edit.len() == 1 && edit[0].class_types() == seg.class_types();
821
822 for mut s in edit {
823 if !consumed_pos && s.raw() == seg.raw() {
824 consumed_pos = true;
825 s.make_mut()
826 .set_position_marker(seg.get_position_marker().cloned());
827 }
828 seg_buffer.push(s);
829 }
830
831 if !is_single_same_type {
832 _requires_validate = true;
833 }
834 }
835 LintFix::Delete { .. } => {
836 unreachable!()
838 }
839 }
840 }
841 }
842
843 if has_applied_fixes {
844 seg_buffer =
845 position_segments(&seg_buffer, self.get_position_marker().as_ref().unwrap());
846 }
847
848 let seg_queue = seg_buffer;
849 let mut seg_buffer = Vec::new();
850 for seg in seg_queue {
851 let (mid, pre, post) = seg.apply_fixes(fixes);
852
853 seg_buffer.extend(pre);
854 seg_buffer.push(mid);
855 seg_buffer.extend(post);
856 }
857
858 let seg_buffer =
859 position_segments(&seg_buffer, self.get_position_marker().as_ref().unwrap());
860 (self.new(seg_buffer), Vec::new(), Vec::new())
861 }
862}
863
864#[cfg(any(test, feature = "serde"))]
865pub mod serde {
866 use serde::ser::SerializeMap;
867 use serde::{Deserialize, Serialize};
868
869 use crate::parser::segments::ErasedSegment;
870
871 #[derive(Serialize, Deserialize)]
872 #[serde(untagged)]
873 pub enum SerialisedSegmentValue {
874 Single(String),
875 Nested(Vec<TupleSerialisedSegment>),
876 }
877
878 #[derive(Deserialize)]
879 pub struct TupleSerialisedSegment(String, SerialisedSegmentValue);
880
881 impl Serialize for TupleSerialisedSegment {
882 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
883 where
884 S: serde::Serializer,
885 {
886 let mut map = serializer.serialize_map(None)?;
887 map.serialize_key(&self.0)?;
888 map.serialize_value(&self.1)?;
889 map.end()
890 }
891 }
892
893 impl TupleSerialisedSegment {
894 pub fn sinlge(key: String, value: String) -> Self {
895 Self(key, SerialisedSegmentValue::Single(value))
896 }
897
898 pub fn nested(key: String, segments: Vec<TupleSerialisedSegment>) -> Self {
899 Self(key, SerialisedSegmentValue::Nested(segments))
900 }
901 }
902
903 impl ErasedSegment {
904 pub fn to_serialised(&self, code_only: bool, show_raw: bool) -> TupleSerialisedSegment {
905 if show_raw && self.segments().is_empty() {
906 TupleSerialisedSegment::sinlge(
907 self.get_type().as_str().to_string(),
908 self.raw().to_string(),
909 )
910 } else if code_only {
911 let segments = self
912 .segments()
913 .iter()
914 .filter(|seg| seg.is_code() && !seg.is_meta())
915 .map(|seg| seg.to_serialised(code_only, show_raw))
916 .collect::<Vec<_>>();
917
918 TupleSerialisedSegment::nested(self.get_type().as_str().to_string(), segments)
919 } else {
920 let segments = self
921 .segments()
922 .iter()
923 .map(|seg| seg.to_serialised(code_only, show_raw))
924 .collect::<Vec<_>>();
925
926 TupleSerialisedSegment::nested(self.get_type().as_str().to_string(), segments)
927 }
928 }
929 }
930}
931
932impl PartialEq for ErasedSegment {
933 fn eq(&self, other: &Self) -> bool {
934 if self.id() == other.id() {
935 return true;
936 }
937
938 let pos_self = self.get_position_marker();
939 let pos_other = other.get_position_marker();
940 if let Some((pos_self, pos_other)) = pos_self.zip(pos_other) {
941 self.get_type() == other.get_type()
942 && pos_self.working_loc() == pos_other.working_loc()
943 && self.raw() == other.raw()
944 } else {
945 false
946 }
947 }
948}
949
950pub fn position_segments(
951 segments: &[ErasedSegment],
952 parent_pos: &PositionMarker,
953) -> Vec<ErasedSegment> {
954 if segments.is_empty() {
955 return Vec::new();
956 }
957
958 let (mut line_no, mut line_pos) = { (parent_pos.working_line_no, parent_pos.working_line_pos) };
959
960 let mut segment_buffer: Vec<ErasedSegment> = Vec::new();
961 for (idx, segment) in enumerate(segments) {
962 let old_position = segment.get_position_marker();
963
964 let mut new_position = match old_position {
965 Some(pos_marker) => pos_marker.clone(),
966 None => {
967 let start_point = if idx > 0 {
968 let prev_seg = segment_buffer[idx - 1].clone();
969 Some(prev_seg.get_position_marker().unwrap().end_point_marker())
970 } else {
971 Some(parent_pos.start_point_marker())
972 };
973
974 let mut end_point = None;
975 for fwd_seg in &segments[idx + 1..] {
976 if fwd_seg.get_position_marker().is_some() {
977 end_point = Some(
978 fwd_seg.get_raw_segments()[0]
979 .get_position_marker()
980 .unwrap()
981 .start_point_marker(),
982 );
983 break;
984 }
985 }
986
987 if let Some((start_point, end_point)) = start_point
988 .as_ref()
989 .zip(end_point.as_ref())
990 .filter(|(start_point, end_point)| start_point != end_point)
991 {
992 PositionMarker::from_points(start_point, end_point)
993 } else if let Some(start_point) = start_point.as_ref() {
994 start_point.clone()
995 } else if let Some(end_point) = end_point.as_ref() {
996 end_point.clone()
997 } else {
998 unimplemented!("Unable to position new segment")
999 }
1000 }
1001 };
1002
1003 new_position = new_position.with_working_position(line_no, line_pos);
1004 (line_no, line_pos) = PositionMarker::infer_next_position(segment.raw(), line_no, line_pos);
1005
1006 let mut new_seg = if !segment.segments().is_empty() && old_position != Some(&new_position) {
1007 let child_segments = position_segments(segment.segments(), &new_position);
1008 segment.change_segments(child_segments)
1009 } else {
1010 segment.deep_clone()
1011 };
1012
1013 new_seg.get_mut().set_position_marker(new_position.into());
1014 segment_buffer.push(new_seg);
1015 }
1016
1017 segment_buffer
1018}
1019
1020#[derive(Debug, Clone)]
1021pub struct NodeOrToken {
1022 id: u32,
1023 syntax_kind: SyntaxKind,
1024 class_types: SyntaxSet,
1025 position_marker: Option<PositionMarker>,
1026 kind: NodeOrTokenKind,
1027 code_idx: OnceCell<Rc<Vec<usize>>>,
1028 hash: OnceCell<u64>,
1029}
1030
1031#[derive(Debug, Clone)]
1032pub enum NodeOrTokenKind {
1033 Node(NodeData),
1034 Token(TokenData),
1035}
1036
1037impl NodeOrToken {
1038 pub fn set_position_marker(&mut self, position_marker: Option<PositionMarker>) {
1039 self.position_marker = position_marker;
1040 }
1041
1042 pub fn set_id(&mut self, id: u32) {
1043 self.id = id;
1044 }
1045}
1046
1047#[derive(Debug, Clone)]
1048pub struct NodeData {
1049 dialect: DialectKind,
1050 segments: Vec<ErasedSegment>,
1051 raw: OnceCell<SmolStr>,
1052 source_fixes: Vec<SourceFix>,
1053 descendant_type_set: OnceCell<SyntaxSet>,
1054 raw_segments_with_ancestors: OnceCell<Vec<(ErasedSegment, Vec<PathStep>)>>,
1055}
1056
1057#[derive(Debug, Clone, PartialEq)]
1058pub struct TokenData {
1059 raw: SmolStr,
1060}
1061
1062#[track_caller]
1063pub fn pos_marker(segments: &[ErasedSegment]) -> PositionMarker {
1064 let markers = segments.iter().filter_map(|seg| seg.get_position_marker());
1065
1066 PositionMarker::from_child_markers(markers)
1067}
1068
1069#[derive(Debug, Clone)]
1070pub struct PathStep {
1071 pub segment: ErasedSegment,
1072 pub idx: usize,
1073 pub len: usize,
1074 pub code_idxs: Rc<Vec<usize>>,
1075}
1076
1077fn class_types(syntax_kind: SyntaxKind) -> SyntaxSet {
1078 match syntax_kind {
1079 SyntaxKind::ColumnReference => SyntaxSet::new(&[SyntaxKind::ObjectReference, syntax_kind]),
1080 SyntaxKind::WildcardIdentifier => {
1081 SyntaxSet::new(&[SyntaxKind::WildcardIdentifier, SyntaxKind::ObjectReference])
1082 }
1083 SyntaxKind::TableReference => SyntaxSet::new(&[SyntaxKind::ObjectReference, syntax_kind]),
1084 _ => SyntaxSet::single(syntax_kind),
1085 }
1086}
1087
1088#[cfg(test)]
1089mod tests {
1090 use super::*;
1091 use crate::lint_fix::LintFix;
1092 use crate::linter::compute_anchor_edit_info;
1093 use crate::parser::segments::test_functions::{raw_seg, raw_segments};
1094
1095 #[test]
1096 fn test_parser_base_segments_raw_compare() {
1098 let template: TemplatedFile = "foobar".into();
1099 let rs1 = SegmentBuilder::token(0, "foobar", SyntaxKind::Word)
1100 .with_position(PositionMarker::new(
1101 0..6,
1102 0..6,
1103 template.clone(),
1104 None,
1105 None,
1106 ))
1107 .finish();
1108 let rs2 = SegmentBuilder::token(0, "foobar", SyntaxKind::Word)
1109 .with_position(PositionMarker::new(
1110 0..6,
1111 0..6,
1112 template.clone(),
1113 None,
1114 None,
1115 ))
1116 .finish();
1117
1118 assert_eq!(rs1, rs2)
1119 }
1120
1121 #[test]
1122 fn test_parser_base_segments_raw() {
1125 let raw_seg = raw_seg();
1126
1127 assert_eq!(raw_seg.raw(), "foobar");
1128 }
1129
1130 #[test]
1131 fn test_parser_base_segments_compute_anchor_edit_info() {
1133 let raw_segs = raw_segments();
1134 let tables = Tables::default();
1135
1136 let fixes = vec![
1140 LintFix::replace(
1141 raw_segs[0].clone(),
1142 vec![raw_segs[0].edit(tables.next_id(), Some("a".to_string()), None)],
1143 None,
1144 ),
1145 LintFix::replace(
1146 raw_segs[0].clone(),
1147 vec![raw_segs[0].edit(tables.next_id(), Some("a".to_string()), None)],
1148 None,
1149 ),
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 let mut anchor_edit_info = Default::default();
1158 compute_anchor_edit_info(&mut anchor_edit_info, fixes);
1159
1160 assert_eq!(
1162 anchor_edit_info.keys().collect::<Vec<_>>(),
1163 vec![&raw_segs[0].id()]
1164 );
1165
1166 let anchor_info = anchor_edit_info.get(&raw_segs[0].id()).unwrap();
1167
1168 assert_eq!(anchor_info.replace, 2);
1170
1171 assert_eq!(
1174 anchor_info.fixes[0],
1175 LintFix::replace(
1176 raw_segs[0].clone(),
1177 vec![raw_segs[0].edit(tables.next_id(), Some("a".to_string()), None)],
1178 None,
1179 )
1180 );
1181 assert_eq!(
1182 anchor_info.fixes[1],
1183 LintFix::replace(
1184 raw_segs[0].clone(),
1185 vec![raw_segs[0].edit(tables.next_id(), Some("b".to_string()), None)],
1186 None,
1187 )
1188 );
1189
1190 assert_eq!(
1192 anchor_info.fixes[anchor_info.first_replace.unwrap()],
1193 LintFix::replace(
1194 raw_segs[0].clone(),
1195 vec![raw_segs[0].edit(tables.next_id(), Some("a".to_string()), None)],
1196 None,
1197 )
1198 );
1199 }
1200}