1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
use std::fmt;

use crate::{
    TextUnit, SmolStr, TextRange, SyntaxKind,
    SyntaxNode, SyntaxElement, SyntaxIndex,
    GreenToken, GreenNode, GreenElement, GreenIndex,
};

/// A token (leaf node) in a syntax tree.
///
/// A token can't exist in isolation, it is always attached to a parent Node.
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct SyntaxToken<'a> {
    pub(crate) parent: &'a SyntaxNode,
    pub(crate) start_offset: TextUnit,
    /// Index of this token in the green node
    pub(crate) index_in_green: GreenIndex,
    /// Index of the following SyntaxNode in the parent. 0 for tokens which come
    /// before the first non-token child.
    pub(crate) index_in_parent: SyntaxIndex,
}

impl<'a> fmt::Debug for SyntaxToken<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{:?}@{:?}", self.kind(), self.range())
    }
}
impl<'a> fmt::Display for SyntaxToken<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.write_str(self.text())
    }
}

impl<'a> SyntaxToken<'a> {
    /// Kind of this token.
    #[inline]
    pub fn kind(&self) -> SyntaxKind {
        self.green().kind()
    }
    /// Text of this token.
    #[inline]
    pub fn text(&self) -> &'a SmolStr {
        self.green().text()
    }
    /// Text range, covered by this token.
    #[inline]
    pub fn range(&self) -> TextRange {
        TextRange::offset_len(self.start_offset, self.green().text_len())
    }
    /// Parent node, containing this token.
    #[inline]
    pub fn parent(&self) -> &'a SyntaxNode {
        self.parent
    }
    /// Next sibling of this tokens, including both nodes and tokens.
    pub fn next_sibling_or_token(&self) -> Option<SyntaxElement<'a>> {
        let index_in_green = self.index_in_green.next();
        let green = self.parent().green.get_child(index_in_green)?;
        let element = match green {
            GreenElement::Token(_) => {
                let token = SyntaxToken {
                    parent: self.parent(),
                    start_offset: self.start_offset + self.green().text_len(),
                    index_in_green,
                    index_in_parent: self.index_in_parent,
                };
                token.into()
            }
            GreenElement::Node(_) => self.parent().get_child(self.index_in_parent).unwrap().into(),
        };
        Some(element)
    }
    /// Previous sibling of this tokens, including both nodes and tokens.
    pub fn prev_sibling_or_token(&self) -> Option<SyntaxElement<'a>> {
        let index_in_green = self.index_in_green.prev();
        let green = self.parent().green.get_child(index_in_green)?;
        let element = match green {
            GreenElement::Token(it) => {
                let token = SyntaxToken {
                    parent: self.parent(),
                    start_offset: self.start_offset - it.text_len(),
                    index_in_green,
                    index_in_parent: self.index_in_parent,
                };
                token.into()
            }
            GreenElement::Node(_) => {
                self.parent().get_child(self.index_in_parent.prev()).unwrap().into()
            }
        };
        Some(element)
    }
    /// Next token in the file (i.e, not necessary a sibling)
    pub fn next_token(&self) -> Option<SyntaxToken<'a>> {
        match self.next_sibling_or_token() {
            Some(element) => element.first_token(),
            None => self
                .parent()
                .ancestors()
                .find_map(|it| it.next_sibling_or_token())
                .and_then(|element| element.first_token()),
        }
    }
    /// Previous token in the file (i.e, not necessary a sibling)
    pub fn prev_token(&self) -> Option<SyntaxToken<'a>> {
        match self.prev_sibling_or_token() {
            Some(element) => element.last_token(),
            None => self
                .parent()
                .ancestors()
                .find_map(|it| it.prev_sibling_or_token())
                .and_then(|element| element.last_token()),
        }
    }

    /// Returns a green tree, equal to the green tree this token
    /// belongs two, except with this token substitute. The complexity
    /// of operation is proportional to the depth of the tree
    pub fn replace_with(&self, replacement: GreenToken) -> GreenNode {
        assert_eq!(self.kind(), replacement.kind());
        let mut replacement = Some(replacement);
        let parent = self.parent();
        let me = self.index_in_green;

        let children: Box<[_]> =
            parent
                .green()
                .children()
                .iter()
                .enumerate()
                .map(|(i, child)| {
                    if i as u32 == me.0 {
                        replacement.take().unwrap().into()
                    } else {
                        child.clone()
                    }
                })
                .collect();
        assert!(replacement.is_none());
        let new_parent = GreenNode::new(parent.kind(), children);
        parent.replace_with(new_parent)
    }

    fn green(&self) -> &'a GreenToken {
        match self.parent.green.get_child(self.index_in_green) {
            Some(GreenElement::Token(it)) => it,
            _ => unreachable!(),
        }
    }
}