1use crate::ast::AstNode;
2use crate::fix::Fix;
3use crate::kind::SyntaxKind;
4use crate::set::SyntaxSet;
5use crate::span::Span;
6use compose_error_codes::ErrorCode;
7use compose_utils::trace_log;
8use ecow::{eco_vec, EcoString, EcoVec};
9use std::fmt::{Debug, Formatter};
10use std::ops::Range;
11use std::sync::Arc;
12
13#[derive(Clone, Eq, PartialEq, Hash)]
14pub struct SyntaxNode(Repr);
15
16impl SyntaxNode {
17 pub(crate) fn erroneous(&self) -> bool {
18 match &self.0 {
19 Repr::Leaf(_) => false,
20 Repr::Inner(i) => i.erroneous,
21 Repr::Error(e) => e.error.severity == SyntaxErrorSeverity::Error,
22 }
23 }
24 pub fn errors(&self) -> Vec<SyntaxError> {
25 if !self.erroneous() {
26 return vec![];
27 }
28
29 if let Repr::Error(node) = &self.0 {
30 vec![node.error.clone()]
31 } else {
32 self.children()
33 .filter(|node| node.erroneous())
34 .flat_map(|node| node.errors())
35 .collect()
36 }
37 }
38
39 pub fn warnings(&self) -> Vec<SyntaxError> {
40 match &self.0 {
41 Repr::Error(node) => {
42 if node.error.severity == SyntaxErrorSeverity::Warning {
43 vec![node.error.clone()]
44 } else {
45 vec![]
46 }
47 }
48 Repr::Inner(i) => i.children.iter().flat_map(|node| node.warnings()).collect(),
49 Repr::Leaf(_) => vec![],
50 }
51 }
52
53 pub fn error_mut(&mut self) -> Option<&mut SyntaxError> {
54 match &mut self.0 {
55 Repr::Error(e) => Some(&mut Arc::make_mut(e).error),
56 _ => None,
57 }
58 }
59
60 pub(crate) fn descendents(&self) -> usize {
61 match &self.0 {
62 Repr::Leaf(_) | Repr::Error(_) => 1,
63 Repr::Inner(i) => i.descendents,
64 }
65 }
66
67 pub(crate) fn len(&self) -> usize {
68 match &self.0 {
69 Repr::Leaf(l) => l.len(),
70 Repr::Inner(i) => i.len,
71 Repr::Error(e) => e.len(),
72 }
73 }
74}
75
76impl SyntaxNode {
78 pub fn is<'a, T: AstNode<'a>>(&'a self) -> bool {
79 self.cast::<T>().is_some()
80 }
81
82 pub fn cast<'a, T: AstNode<'a>>(&'a self) -> Option<T> {
84 T::from_untyped(self)
85 }
86
87 pub fn try_cast_first<'a, T: AstNode<'a>>(&'a self) -> Option<T> {
88 self.children().find_map(Self::cast)
89 }
90
91 pub fn try_cast_last<'a, T: AstNode<'a>>(&'a self) -> Option<T> {
92 self.children().rev().find_map(Self::cast)
93 }
94
95 pub(crate) fn cast_first<'a, T: AstNode<'a> + Default>(&'a self) -> T {
96 self.try_cast_first().unwrap_or_default()
97 }
98
99 pub(crate) fn cast_last<'a, T: AstNode<'a> + Default>(&'a self) -> T {
100 self.try_cast_last().unwrap_or_default()
101 }
102}
103
104impl SyntaxNode {
105 pub(crate) fn error(error: SyntaxError, text: impl Into<EcoString>) -> Self {
106 Self(Repr::Error(Arc::new(ErrorNode::new(error, text))))
107 }
108 pub(crate) fn leaf(kind: SyntaxKind, text: impl Into<EcoString>, span: Span) -> Self {
109 Self(Repr::Leaf(LeafNode::new(kind, text, span)))
110 }
111
112 pub(crate) fn inner(kind: SyntaxKind, children: Vec<SyntaxNode>) -> Self {
113 Self(Repr::Inner(Arc::new(InnerNode::new(kind, children))))
114 }
115
116 pub(crate) const fn placeholder(kind: SyntaxKind) -> Self {
117 if matches!(kind, SyntaxKind::Error) {
118 panic!("cannot create error placeholder");
119 }
120 Self(Repr::Leaf(LeafNode {
121 kind,
122 text: EcoString::new(),
123 span: Span::detached(),
124 }))
125 }
126
127 pub fn kind(&self) -> SyntaxKind {
128 match &self.0 {
129 Repr::Leaf(l) => l.kind,
130 Repr::Inner(i) => i.kind,
131 Repr::Error(_) => SyntaxKind::Error,
132 }
133 }
134
135 pub fn text(&self) -> &EcoString {
136 static EMPTY: EcoString = EcoString::new();
137 match &self.0 {
138 Repr::Leaf(l) => &l.text,
139 Repr::Inner(_) => &EMPTY,
140 Repr::Error(e) => &e.text,
141 }
142 }
143
144 pub fn to_text(&self) -> EcoString {
148 let mut str = EcoString::new();
149
150 fn inner(node: &SyntaxNode, str: &mut EcoString) {
151 match &node.0 {
152 Repr::Leaf(l) => str.push_str(&l.text),
153 Repr::Inner(i) => {
154 for child in &i.children {
155 inner(child, str);
156 }
157 }
158 Repr::Error(e) => str.push_str(&e.text),
159 }
160 }
161
162 inner(self, &mut str);
163 str
164 }
165
166 pub fn children(&self) -> std::slice::Iter<'_, SyntaxNode> {
167 match &self.0 {
168 Repr::Leaf(_) | Repr::Error(_) => [].iter(),
169 Repr::Inner(i) => i.children.iter(),
170 }
171 }
172
173 pub(crate) fn convert_to_kind(&mut self, kind: SyntaxKind) {
177 match &mut self.0 {
178 Repr::Leaf(l) => l.kind = kind,
179 Repr::Inner(i) => Arc::make_mut(i).kind = kind,
180 Repr::Error(_) => panic!("cannot convert error node to kind"),
181 }
182 }
183
184 pub(crate) fn convert_to_error(&mut self, message: impl Into<EcoString>) -> &mut SyntaxError {
186 if self.kind() != SyntaxKind::Error {
187 let span = self.span();
188 let text = std::mem::take(self).into_text();
189 *self = SyntaxNode::error(SyntaxError::new(message, span), text);
190 }
191
192 self.error_mut().unwrap()
193 }
194
195 fn into_text(self) -> EcoString {
196 match self.0 {
197 Repr::Leaf(l) => l.text,
198 Repr::Inner(i) => i.children.iter().cloned().map(Self::into_text).collect(),
199 Repr::Error(e) => e.text.clone(),
200 }
201 }
202
203 pub(crate) fn expected(&mut self, expected: impl Into<EcoString>) {
204 let kind = self.kind();
205 let expected = expected.into();
206 self.convert_to_error(format!("expected {}, found {:?}", &expected, kind));
207 trace_log!("expected {}, found {:?}", &expected, kind);
208 }
209
210 pub fn span(&self) -> Span {
211 match &self.0 {
212 Repr::Leaf(l) => l.span,
213 Repr::Inner(i) => i.span,
214 Repr::Error(e) => e.error.span,
215 }
216 }
217}
218
219impl Default for SyntaxNode {
220 fn default() -> Self {
221 Self::leaf(SyntaxKind::End, EcoString::new(), Span::detached())
222 }
223}
224
225#[derive(Clone, Eq, PartialEq, Hash)]
226enum Repr {
227 Leaf(LeafNode),
228 Inner(Arc<InnerNode>),
229 Error(Arc<ErrorNode>),
230}
231
232impl Debug for SyntaxNode {
233 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
234 match &self.0 {
235 Repr::Leaf(leaf) => leaf.fmt(f),
236 Repr::Inner(inner) => inner.fmt(f),
237 Repr::Error(node) => node.fmt(f),
238 }
239 }
240}
241
242#[derive(Clone, Eq, PartialEq, Hash)]
243struct LeafNode {
244 kind: SyntaxKind,
246 span: Span,
248 text: EcoString,
250}
251
252impl LeafNode {
253 pub(crate) fn len(&self) -> usize {
254 self.text.len()
255 }
256}
257
258impl LeafNode {
259 fn new(kind: SyntaxKind, text: impl Into<EcoString>, span: Span) -> LeafNode {
260 Self {
261 kind,
262 span,
263 text: text.into(),
264 }
265 }
266}
267
268impl Debug for LeafNode {
269 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
270 write!(
271 f,
272 "{:?} ({}): {:?}",
273 self.kind,
274 match self.span.range() {
275 None => "".to_string(),
276 Some(r) => format!("{r:?}"),
277 },
278 self.text
279 )
280 }
281}
282
283#[derive(Clone, Eq, PartialEq, Hash)]
285struct InnerNode {
286 kind: SyntaxKind,
289 len: usize,
291 span: Span,
293 erroneous: bool,
295 children: Vec<SyntaxNode>,
297 descendents: usize,
299}
300
301impl InnerNode {
302 fn new(kind: SyntaxKind, children: Vec<SyntaxNode>) -> InnerNode {
303 debug_assert!(kind != SyntaxKind::Error);
304
305 let mut len = 0;
306 let mut descendents = 1;
307 let mut erroneous = false;
308
309 for child in &children {
310 len += child.len();
311 descendents += child.descendents();
312 erroneous |= child.erroneous();
313 }
314
315 let span = if children.is_empty() {
316 Span::detached()
317 } else {
318 let first_span = children.first().unwrap().span();
319 let last_span = children.last().unwrap().span();
320
321 match (first_span.id(), first_span.range(), last_span.range()) {
322 (Some(id), Some(start), Some(end)) => Span::new(id, start.start..end.end),
323 (Some(id), Some(start), _) => Span::new(id, start),
324 _ => Span::detached(),
325 }
326 };
327
328 Self {
329 kind,
330 len,
331 span,
332 erroneous,
333 children,
334 descendents,
335 }
336 }
337}
338
339impl Debug for InnerNode {
340 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
341 write!(
342 f,
343 "{:?}{} ({:?}): {}",
344 self.kind,
345 if self.erroneous { " (err)" } else { "" },
346 self.span,
347 self.len
348 )?;
349 if !self.children.is_empty() {
350 f.write_str(" ")?;
351 f.debug_list().entries(&self.children).finish()?;
352 }
353 Ok(())
354 }
355}
356
357#[derive(Clone, Eq, PartialEq, Hash)]
359struct ErrorNode {
360 text: EcoString,
362 error: SyntaxError,
364}
365
366impl ErrorNode {
367 fn new(error: SyntaxError, text: impl Into<EcoString>) -> ErrorNode {
368 Self {
369 text: text.into(),
370 error,
371 }
372 }
373
374 fn len(&self) -> usize {
375 self.text.len()
376 }
377}
378
379impl Debug for ErrorNode {
380 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
381 write!(
382 f,
383 "{} {:?}: {:?} ({})",
384 match self.error.severity {
385 SyntaxErrorSeverity::Error => "error",
386 SyntaxErrorSeverity::Warning => "warning",
387 },
388 self.error.span,
389 self.text,
390 self.error.message
391 )
392 }
393}
394
395#[derive(Debug, Clone, Eq, PartialEq, Hash)]
397pub struct SyntaxError {
398 pub span: Span,
400 pub message: EcoString,
402 pub hints: EcoVec<EcoString>,
405 pub notes: EcoVec<EcoString>,
407 pub label_message: Option<EcoString>,
411 pub labels: EcoVec<Label>,
413 pub code: Option<&'static ErrorCode>,
414
415 pub fixes: EcoVec<Fix>,
416
417 pub severity: SyntaxErrorSeverity,
418}
419
420#[derive(Debug, Clone, Eq, PartialEq, Hash)]
421pub enum SyntaxErrorSeverity {
422 Error,
423 Warning,
424}
425
426#[derive(Debug, Clone, Eq, PartialEq, Hash)]
427pub struct Label {
428 pub span: Span,
429 pub message: EcoString,
430 pub ty: LabelType,
431}
432
433impl Label {
434 pub fn primary(span: Span, message: impl Into<EcoString>) -> Label {
435 Label {
436 span,
437 message: message.into(),
438 ty: LabelType::Primary,
439 }
440 }
441
442 pub fn secondary(span: Span, message: impl Into<EcoString>) -> Label {
443 Label {
444 span,
445 message: message.into(),
446 ty: LabelType::Secondary,
447 }
448 }
449}
450
451#[derive(Debug, Clone, Eq, PartialEq, Hash)]
452pub enum LabelType {
453 Primary,
454 Secondary,
455}
456
457impl SyntaxError {
458 pub fn with_message(&mut self, message: impl Into<EcoString>) -> &mut Self {
459 self.message = message.into();
460 self
461 }
462
463 pub fn with_note(&mut self, note: impl Into<EcoString>) -> &mut Self {
464 self.notes.push(note.into());
465 self
466 }
467
468 pub fn with_hint(&mut self, hint: impl Into<EcoString>) -> &mut Self {
469 self.hints.push(hint.into());
470 self
471 }
472
473 pub fn with_label_message(&mut self, message: impl Into<EcoString>) -> &mut Self {
474 self.label_message = Some(message.into());
475 self
476 }
477
478 pub fn with_label(&mut self, label: Label) -> &mut Self {
479 self.labels.push(label);
480 self
481 }
482
483 pub fn with_code(&mut self, code: &'static ErrorCode) -> &mut Self {
484 self.code = Some(code);
485 self
486 }
487
488 pub fn with_severity(&mut self, severity: SyntaxErrorSeverity) -> &mut Self {
489 self.severity = severity;
490 self
491 }
492
493 pub fn with_fix(&mut self, fix: Fix) -> &mut Self {
494 self.fixes.push(fix);
495 self
496 }
497}
498
499impl SyntaxError {
500 pub(crate) fn new(message: impl Into<EcoString>, span: Span) -> SyntaxError {
501 SyntaxError {
502 span,
503 message: message.into(),
504 hints: eco_vec![],
505 label_message: None,
506 labels: eco_vec![],
507 notes: eco_vec![],
508 code: None,
509 severity: SyntaxErrorSeverity::Error,
510 fixes: eco_vec![],
511 }
512 }
513}
514
515#[derive(Debug, Clone, Eq, PartialEq, Hash)]
516pub struct LinkedNode<'a> {
517 node: &'a SyntaxNode,
518 parent: Option<Arc<LinkedNode<'a>>>,
519 index: usize,
521 byte_offset: usize,
523}
524
525impl<'a> LinkedNode<'a> {
526 pub fn new(node: &'a SyntaxNode) -> Self {
527 Self {
528 node,
529 parent: None,
530 index: 0,
531 byte_offset: node.span().range().map(|r| r.start).unwrap_or(0),
532 }
533 }
534
535 pub fn node(&self) -> &'a SyntaxNode {
537 self.node
538 }
539
540 pub fn index(&self) -> usize {
542 self.index
543 }
544
545 pub fn byte_offset(&self) -> usize {
547 self.byte_offset
548 }
549
550 pub fn span(&self) -> Span {
551 self.node.span()
552 }
553
554 pub fn range(&self) -> Range<usize> {
555 self.byte_offset..(self.byte_offset + self.node.len())
556 }
557
558 pub fn find(&self, span: Span) -> Option<LinkedNode<'a>> {
559 let self_span = self.span();
560 if self_span == span {
561 return Some(self.clone());
562 }
563
564 let span_range = span.range()?;
565
566 if let Some(self_range) = self_span.range() {
567 if self_range.start > span_range.end {
569 return None;
570 }
571
572 if self_range.end < span_range.start {
574 return None;
575 }
576 }
577
578 for child in self.children() {
579 if let Some(found) = child.find(span) {
580 return Some(found);
581 }
582 }
583
584 None
585 }
586}
587
588impl<'a> LinkedNode<'a> {
589 pub fn children(&self) -> LinkedChildren<'a> {
590 LinkedChildren {
591 parent: Arc::new(self.clone()),
592 iter: self.node.children().enumerate(),
593 front: self.byte_offset,
594 back: self.byte_offset + self.node.len(),
595 }
596 }
597
598 pub fn parent(&self) -> Option<&LinkedNode<'a>> {
599 self.parent.as_deref()
600 }
601
602 pub fn closest_parent(&self, kind: SyntaxKind) -> Option<&LinkedNode<'a>> {
603 let mut node = self;
604 while let Some(parent) = node.parent() {
605 if parent.node().kind() == kind {
606 return Some(parent);
607 }
608 node = parent;
609 }
610 None
611 }
612
613 pub fn closest_parent_any_of(&self, kind_set: SyntaxSet) -> Option<&LinkedNode<'a>> {
614 let mut node = self;
615 while let Some(parent) = node.parent() {
616 if kind_set.contains(parent.node().kind()) {
617 return Some(parent);
618 }
619 node = parent;
620 }
621 None
622 }
623
624 pub fn closest_parent_as<T: AstNode<'a>>(&self) -> Option<T> {
625 let mut node = self;
626 while let Some(parent) = node.parent() {
627 if let Some(val) = T::from_untyped(parent.node()) {
628 return Some(val);
629 }
630 node = parent;
631 }
632
633 None
634 }
635
636 pub fn first_child_of_kind(&self, kind: SyntaxKind) -> Option<LinkedNode<'a>> {
637 self.children().find(|child| child.node().kind() == kind)
638 }
639
640 pub fn last_child_of_kind(&self, kind: SyntaxKind) -> Option<LinkedNode<'a>> {
641 self.children()
642 .rev()
643 .find(|child| child.node().kind() == kind)
644 }
645}
646
647pub struct LinkedChildren<'a> {
649 parent: Arc<LinkedNode<'a>>,
650 iter: std::iter::Enumerate<std::slice::Iter<'a, SyntaxNode>>,
651 front: usize,
652 back: usize,
653}
654
655impl<'a> Iterator for LinkedChildren<'a> {
656 type Item = LinkedNode<'a>;
657
658 fn next(&mut self) -> Option<Self::Item> {
659 self.iter.next().map(|(index, node)| {
660 let offset = self.front;
661 self.front += node.len();
662 LinkedNode {
663 node,
664 parent: Some(self.parent.clone()),
665 index,
666 byte_offset: offset,
667 }
668 })
669 }
670
671 fn size_hint(&self) -> (usize, Option<usize>) {
672 self.iter.size_hint()
673 }
674}
675
676impl DoubleEndedIterator for LinkedChildren<'_> {
677 fn next_back(&mut self) -> Option<Self::Item> {
678 self.iter.next_back().map(|(index, node)| {
679 self.back -= node.len();
680 LinkedNode {
681 node,
682 parent: Some(self.parent.clone()),
683 index,
684 byte_offset: self.back,
685 }
686 })
687 }
688}
689
690impl ExactSizeIterator for LinkedChildren<'_> {}