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