compose_syntax/
node.rs

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
76// Converting from and to typed AST nodes.
77impl SyntaxNode {
78    pub fn is<'a, T: AstNode<'a>>(&'a self) -> bool {
79        self.cast::<T>().is_some()
80    }
81
82    /// Tries to cast the node to type `T`. Returns None if it cannot.
83    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    /// Like text, but also returns the text of inner nodes.
145    ///
146    /// Builds a new string, so is more computationally expensive.
147    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    /// Convert the node to another kind
174    ///
175    /// To convert to an error, use [Self::convert_to_error]
176    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    /// Convert the node to an error with the same span and text
185    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    /// The kind of the node
245    kind: SyntaxKind,
246    /// The span of the node
247    span: Span,
248    /// The source text of the node
249    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/// An inner node in the untyped syntax tree.
284#[derive(Clone, Eq, PartialEq, Hash)]
285struct InnerNode {
286    /// What kind of node this is (each kind would have its own struct in a
287    /// strongly typed AST).
288    kind: SyntaxKind,
289    /// The byte length of the node in the source.
290    len: usize,
291    /// The node's span.
292    span: Span,
293    /// Whether this node or any of its children are erroneous.
294    erroneous: bool,
295    /// This node's children, losslessly make up this node.
296    children: Vec<SyntaxNode>,
297    /// The number of descendents in this node (including itself).
298    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/// An error node in the untyped syntax tree.
358#[derive(Clone, Eq, PartialEq, Hash)]
359struct ErrorNode {
360    /// The source text of the node.
361    text: EcoString,
362    /// The syntax error.
363    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/// A syntactical error.
396#[derive(Debug, Clone, Eq, PartialEq, Hash)]
397pub struct SyntaxError {
398    /// The node's span.
399    pub span: Span,
400    /// The error message.
401    pub message: EcoString,
402    /// Additional hints to the user, indicating how this error could be avoided
403    /// or worked around.
404    pub hints: EcoVec<EcoString>,
405    /// Additional notes to the user, indicating more details about the error.
406    pub notes: EcoVec<EcoString>,
407    /// A message to be displayed as a label for the error. This message is
408    /// shown at the location of the error and can give more locational
409    /// information
410    pub label_message: Option<EcoString>,
411    /// Related labels that provide additional information.
412    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    /// The index of the node in the parent's children.
520    index: usize,
521    /// The byte offset of the node in the source.
522    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    /// The node.
536    pub fn node(&self) -> &'a SyntaxNode {
537        self.node
538    }
539
540    /// The index of the node in the parent's children.
541    pub fn index(&self) -> usize {
542        self.index
543    }
544
545    /// The byte offset of the node in the source.
546    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 this node's span is entirely after the span, it won't be in its children.
568            if self_range.start > span_range.end {
569                return None;
570            }
571
572            // if this node's span is entirely before the span, it won't be in its children.
573            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
647/// An iterator over the children of a linked node.
648pub 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<'_> {}