use super::green::{GreenElement, GreenNode, GreenToken};
use crate::types::{FieldId, FromSyntaxKind, IntoSyntaxKind, Span, SyntaxKind};
use std::sync::Arc;
#[derive(Clone, Debug)]
pub enum SyntaxElement {
Node(SyntaxNode),
Token(SyntaxToken),
}
impl SyntaxElement {
#[must_use]
pub fn text_range(&self) -> Span {
match self {
Self::Node(n) => n.text_range(),
Self::Token(t) => t.text_range(),
}
}
#[must_use]
pub fn kind(&self) -> SyntaxKind {
match self {
Self::Node(n) => n.kind(),
Self::Token(t) => t.kind(),
}
}
#[must_use]
#[inline]
pub fn kind_as<K: FromSyntaxKind>(&self) -> Option<K> {
K::from_syntax_kind(self.kind())
}
#[must_use]
pub fn is_trivia(&self) -> bool {
match self {
Self::Token(t) => t.is_trivia(),
Self::Node(_) => false,
}
}
#[must_use]
pub fn into_node(self) -> Option<SyntaxNode> {
if let Self::Node(n) = self {
Some(n)
} else {
None
}
}
#[must_use]
pub fn into_token(self) -> Option<SyntaxToken> {
if let Self::Token(t) = self {
Some(t)
} else {
None
}
}
#[must_use]
pub const fn as_node(&self) -> Option<&SyntaxNode> {
if let Self::Node(n) = self {
Some(n)
} else {
None
}
}
#[must_use]
pub const fn as_token(&self) -> Option<&SyntaxToken> {
if let Self::Token(t) = self {
Some(t)
} else {
None
}
}
}
#[derive(Clone, Debug)]
pub struct SyntaxToken {
green: Arc<GreenToken>,
offset: u32,
}
impl SyntaxToken {
#[must_use]
pub(crate) const fn new(green: Arc<GreenToken>, offset: u32) -> Self {
Self { green, offset }
}
#[must_use]
#[inline]
pub fn kind(&self) -> SyntaxKind {
self.green.kind
}
#[must_use]
#[inline]
pub fn kind_as<K: FromSyntaxKind>(&self) -> Option<K> {
K::from_syntax_kind(self.green.kind)
}
#[must_use]
#[inline]
pub fn is_trivia(&self) -> bool {
self.green.is_trivia
}
#[must_use]
#[inline]
pub fn text_len(&self) -> u32 {
self.green.text_len
}
#[must_use]
#[inline]
pub fn text_range(&self) -> Span {
Span::new(self.offset, self.offset + self.green.text_len)
}
#[must_use]
#[inline]
pub fn text(&self) -> &str {
&self.green.text
}
#[must_use]
#[inline]
pub fn text_bytes<'src>(&self, source: &'src [u8]) -> &'src [u8] {
self.text_range().as_slice(source)
}
#[must_use]
pub const fn green(&self) -> &Arc<GreenToken> {
&self.green
}
#[must_use]
#[inline]
pub const fn offset(&self) -> u32 {
self.offset
}
}
#[derive(Clone, Debug)]
pub struct SyntaxNode {
green: Arc<GreenNode>,
offset: u32,
}
impl SyntaxNode {
#[must_use]
pub const fn new_root(green: Arc<GreenNode>) -> Self {
Self { green, offset: 0 }
}
#[must_use]
#[inline]
pub const fn new(green: Arc<GreenNode>, offset: u32) -> Self {
Self { green, offset }
}
#[must_use]
#[inline]
pub fn kind(&self) -> SyntaxKind {
self.green.kind
}
#[must_use]
#[inline]
pub fn kind_as<K: FromSyntaxKind>(&self) -> Option<K> {
K::from_syntax_kind(self.green.kind)
}
#[must_use]
#[inline]
pub fn text_len(&self) -> u32 {
self.green.text_len
}
#[must_use]
#[inline]
pub fn text_range(&self) -> Span {
Span::new(self.offset, self.offset + self.green.text_len)
}
#[must_use]
#[inline]
pub fn text<'src>(&self, source: &'src [u8]) -> &'src [u8] {
self.text_range().as_slice(source)
}
#[must_use]
pub fn collect_text(&self) -> String {
self.green.collect_text()
}
#[must_use]
#[inline]
pub const fn offset(&self) -> u32 {
self.offset
}
#[must_use]
pub const fn green(&self) -> &Arc<GreenNode> {
&self.green
}
pub fn children(&self) -> impl Iterator<Item = SyntaxElement> + '_ {
let mut off = self.offset;
self.green.children.iter().map(move |child| {
let start = off;
off += child.text_len();
match child {
GreenElement::Node(n) => SyntaxElement::Node(Self::new(Arc::clone(n), start)),
GreenElement::Token(t) => {
SyntaxElement::Token(SyntaxToken::new(Arc::clone(t), start))
}
}
})
}
pub fn child_nodes(&self) -> impl Iterator<Item = Self> + '_ {
self.children().filter_map(SyntaxElement::into_node)
}
#[must_use]
pub fn first_child_node(&self) -> Option<Self> {
self.child_nodes().next()
}
#[must_use]
pub fn child_by_kind(&self, kind: SyntaxKind) -> Option<Self> {
self.child_nodes().find(|n| n.kind() == kind)
}
#[must_use]
pub fn child_node_by_kind<K: IntoSyntaxKind>(&self, kind: K) -> Option<Self> {
self.child_by_kind(kind.into_syntax_kind())
}
#[must_use]
pub fn field_by_id(&self, id: FieldId) -> Option<Self> {
let fields = self.green.child_fields.as_ref()?;
let mut off = self.offset;
for (i, child) in self.green.children.iter().enumerate() {
let start = off;
off += child.text_len();
if fields.get(i).copied().flatten() != Some(id) {
continue;
}
if let GreenElement::Node(n) = child {
return Some(Self::new(Arc::clone(n), start));
}
}
None
}
#[must_use]
pub fn field_by_name(&self, field_names: &[&str], name: &str) -> Option<Self> {
let id = field_names.iter().position(|&n| n == name)?;
let id = FieldId::try_from(id).ok()?;
self.field_by_id(id)
}
#[must_use]
pub fn field_by_graph(
&self,
graph: &crate::parse::insn::ParseGraph<'_>,
name: &str,
) -> Option<Self> {
let id = graph.field_id(name)?;
self.field_by_id(id)
}
#[must_use]
pub fn descendant_nodes(&self) -> DescendantNodes {
DescendantNodes::new(self)
}
pub fn child_tokens(&self) -> impl Iterator<Item = SyntaxToken> + '_ {
self.children().filter_map(SyntaxElement::into_token)
}
pub fn non_trivia_tokens(&self) -> impl Iterator<Item = SyntaxToken> + '_ {
self.child_tokens().filter(|t| !t.is_trivia())
}
#[must_use]
pub fn leading_trivia(&self) -> Vec<SyntaxToken> {
let mut trivia = Vec::new();
for tok in self.child_tokens() {
if tok.is_trivia() {
trivia.push(tok);
} else {
break;
}
}
trivia
}
#[must_use]
pub fn trailing_trivia(&self) -> Vec<SyntaxToken> {
let all: Vec<SyntaxToken> = self.child_tokens().collect();
let mut trivia = Vec::new();
for tok in all.iter().rev() {
if tok.is_trivia() {
trivia.push(tok.clone());
} else {
break;
}
}
trivia.reverse();
trivia
}
#[must_use]
pub fn token_groups(&self) -> Vec<TokenWithTrivia> {
let tokens: Vec<SyntaxToken> = self.child_tokens().collect();
let mut groups: Vec<TokenWithTrivia> = Vec::new();
let mut i = 0;
while i < tokens.len() {
let mut leading = Vec::new();
while i < tokens.len() && tokens[i].is_trivia() {
leading.push(tokens[i].clone());
i += 1;
}
if i >= tokens.len() {
if let Some(last) = groups.last_mut() {
last.trailing.extend(leading);
}
break;
}
let token = tokens[i].clone();
i += 1;
let next_semantic_rel = tokens[i..].iter().position(|t| !t.is_trivia());
let trivia_end = next_semantic_rel.map_or(tokens.len(), |rel| i + rel);
let trailing: Vec<SyntaxToken> = tokens[i..trivia_end].to_vec();
i = trivia_end; groups.push(TokenWithTrivia {
leading,
token,
trailing,
});
}
groups
}
#[must_use]
pub fn find_node(&self, kind: SyntaxKind) -> Option<Self> {
if self.kind() == kind {
return Some(self.clone());
}
self.child_nodes().find_map(|n| n.find_node(kind))
}
#[must_use]
pub fn find_all_nodes(&self, kind: SyntaxKind) -> Vec<Self> {
let mut out = Vec::new();
self.collect_nodes(kind, &mut out);
out
}
fn collect_nodes(&self, kind: SyntaxKind, out: &mut Vec<Self>) {
if self.kind() == kind {
out.push(self.clone());
}
for child in self.child_nodes() {
child.collect_nodes(kind, out);
}
}
#[must_use]
pub fn descendant_tokens(&self) -> Vec<SyntaxToken> {
let mut out = Vec::new();
self.collect_tokens_into(&mut out);
out
}
fn collect_tokens_into(&self, out: &mut Vec<SyntaxToken>) {
for child in self.children() {
match child {
SyntaxElement::Token(t) => out.push(t),
SyntaxElement::Node(n) => n.collect_tokens_into(out),
}
}
}
#[must_use]
pub fn descendant_semantic_tokens(&self) -> Vec<SyntaxToken> {
self.descendant_tokens()
.into_iter()
.filter(|t| !t.is_trivia())
.collect()
}
#[must_use]
pub fn first_token(&self) -> Option<SyntaxToken> {
for child in self.children() {
match child {
SyntaxElement::Token(t) if !t.is_trivia() => return Some(t),
SyntaxElement::Token(_) => {}
SyntaxElement::Node(n) => {
if let Some(t) = n.first_token() {
return Some(t);
}
}
}
}
None
}
#[must_use]
pub fn last_token(&self) -> Option<SyntaxToken> {
let children: Vec<SyntaxElement> = self.children().collect();
for child in children.into_iter().rev() {
match child {
SyntaxElement::Token(t) if !t.is_trivia() => return Some(t),
SyntaxElement::Token(_) => {}
SyntaxElement::Node(n) => {
if let Some(t) = n.last_token() {
return Some(t);
}
}
}
}
None
}
#[must_use]
pub fn find_ancestor(&self, root: &Self, kind: SyntaxKind) -> Option<Self> {
self.ancestors(root).into_iter().find(|a| a.kind() == kind)
}
#[must_use]
pub fn node_at_offset(&self, offset: u32) -> Option<Self> {
if !self.text_range().contains_offset(offset) {
return None;
}
let mut off = self.offset;
for child in &self.green.children {
let end = off + child.text_len();
if offset < end {
return match child {
GreenElement::Node(n) => {
let child_red = Self::new(Arc::clone(n), off);
child_red.node_at_offset(offset).or(Some(child_red))
}
GreenElement::Token(_) => Some(self.clone()),
};
}
off = end;
}
Some(self.clone())
}
#[must_use]
pub fn token_at_offset(&self, offset: u32) -> Option<SyntaxToken> {
let range = self.text_range();
if offset < range.start || offset >= range.end {
return None;
}
let mut off = self.offset;
for child in &self.green.children {
let end = off + child.text_len();
if offset < end {
return match child {
GreenElement::Token(t) => Some(SyntaxToken::new(Arc::clone(t), off)),
GreenElement::Node(n) => Self::new(Arc::clone(n), off).token_at_offset(offset),
};
}
off = end;
}
None
}
#[must_use]
pub fn semantic_token_at_offset(&self, offset: u32) -> Option<SyntaxToken> {
self.token_at_offset(offset).filter(|t| !t.is_trivia())
}
#[must_use]
pub fn ancestors(&self, root: &Self) -> Vec<Self> {
let mut path = Vec::new();
find_path(
root,
self.offset,
self.green.kind,
self.text_len(),
&mut path,
);
path
}
}
fn find_path(
node: &SyntaxNode,
target_off: u32,
target_kind: SyntaxKind,
target_len: u32,
path: &mut Vec<SyntaxNode>,
) -> bool {
for child in node.child_nodes() {
let r = child.text_range();
if r.start <= target_off && target_off + target_len <= r.end {
if child.offset == target_off
&& child.kind() == target_kind
&& child.text_len() == target_len
{
return true; }
if find_path(&child, target_off, target_kind, target_len, path) {
path.push(node.clone());
return true;
}
}
}
false
}
#[derive(Clone)]
pub struct DescendantNodes {
stack: Vec<SyntaxNode>,
}
impl DescendantNodes {
fn new(node: &SyntaxNode) -> Self {
let mut stack: Vec<SyntaxNode> = node.child_nodes().collect();
stack.reverse();
Self { stack }
}
}
impl Iterator for DescendantNodes {
type Item = SyntaxNode;
fn next(&mut self) -> Option<Self::Item> {
let node = self.stack.pop()?;
let mut children: Vec<SyntaxNode> = node.child_nodes().collect();
children.reverse();
self.stack.extend(children);
Some(node)
}
}
#[derive(Debug)]
pub struct TokenWithTrivia {
pub leading: Vec<SyntaxToken>,
pub token: SyntaxToken,
pub trailing: Vec<SyntaxToken>,
}
impl TokenWithTrivia {
#[must_use]
pub fn full_range(&self) -> Span {
let start = self.leading.first().map_or(self.token.offset, |t| t.offset);
let end = self.trailing.last().map_or_else(
|| self.token.offset + self.token.green.text_len,
|t| t.offset + t.green.text_len,
);
Span::new(start, end)
}
#[must_use]
pub fn full_text(&self) -> String {
let mut s = String::new();
for t in &self.leading {
s.push_str(t.text());
}
s.push_str(self.token.text());
for t in &self.trailing {
s.push_str(t.text());
}
s
}
}