Skip to main content

m2_syn/cst/
treesitter.rs

1//! Tree-sitter parser adapter.
2//!
3//! Tree-sitter nodes remain backend-local. Complete-file parsing lowers the
4//! grammar's concrete nodes directly into the generated typed graph; it never
5//! reparses their source through the native precedence engine.
6//! [`TreeSitterNode`] is also the generic [`ExternalCstNode`] adapter used for
7//! migrating leaves, operators, and tokens with the generated machinery.
8
9use std::borrow::Cow;
10use std::error::Error;
11use std::fmt::{Display, Formatter};
12use std::ops::Range;
13use std::sync::Arc;
14use std::vec::IntoIter;
15
16use crate::native::{assignment_pack, installation_value, lambda_parameters};
17use crate::nodes::*;
18use crate::{
19    CSTNodeClassLabel, CellStream, CellStreamError, DelimiterKind, DelimiterToken, DoubleSpan,
20    ExternalCstChild, ExternalCstNode, LexError, Migrate, MigrateError, Parser, Punctuated,
21    Recovered, Source, SourceFile, Span, Spanned, TextEdit, TokenStream, TokenTree, Tokenize,
22    lex_str, lex_str_recovering,
23};
24
25#[derive(Debug)]
26/// A failure while parsing or migrating a Tree-sitter syntax tree.
27pub enum ParseError {
28    /// The renaming hook could not inspect the source token stream.
29    Lex(LexError),
30    /// The raw token stream could not be partitioned into complete cells.
31    Tokenize(CellStreamError),
32    /// The bundled grammar could not be installed in the parser.
33    Language(tree_sitter::LanguageError),
34    /// Tree-sitter returned no tree.
35    Cancelled,
36    /// A requested source edit did not lie on valid boundaries of the buffer.
37    InvalidEdit,
38    /// Tree-sitter produced an error or missing node at this span.
39    InvalidSyntax(Span),
40    /// The untyped Tree-sitter node could not migrate typed syntax.
41    Migrate(MigrateError),
42    /// A valid concrete node has no representation in the typed schema.
43    UnsupportedNode {
44        /// The Tree-sitter node kind that could not be lowered.
45        kind: String,
46        /// The complete node range.
47        span: Span,
48    },
49}
50
51impl Display for ParseError {
52    fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
53        match self {
54            Self::Lex(error) => error.fmt(formatter),
55            Self::Tokenize(error) => error.fmt(formatter),
56            Self::Language(error) => error.fmt(formatter),
57            Self::Cancelled => formatter.write_str("Tree-sitter parsing was cancelled"),
58            Self::InvalidEdit => formatter.write_str("source edit is outside the current buffer"),
59            Self::InvalidSyntax(span) if span.line_column_range().is_some() => {
60                write!(formatter, "invalid Macaulay2 syntax at {span}")
61            }
62            Self::InvalidSyntax(_) => formatter.write_str("invalid Macaulay2 syntax"),
63            Self::Migrate(error) => error.fmt(formatter),
64            Self::UnsupportedNode { kind, .. } => {
65                write!(
66                    formatter,
67                    "Tree-sitter node `{kind}` has no typed representation"
68                )
69            }
70        }
71    }
72}
73
74impl Error for ParseError {
75    fn source(&self) -> Option<&(dyn Error + 'static)> {
76        match self {
77            Self::Lex(error) => Some(error),
78            Self::Tokenize(error) => Some(error),
79            Self::Language(error) => Some(error),
80            Self::Migrate(error) => Some(error),
81            Self::Cancelled
82            | Self::InvalidEdit
83            | Self::InvalidSyntax(_)
84            | Self::UnsupportedNode { .. } => None,
85        }
86    }
87}
88
89impl From<MigrateError> for ParseError {
90    fn from(error: MigrateError) -> Self {
91        Self::Migrate(error)
92    }
93}
94
95impl From<LexError> for ParseError {
96    fn from(error: LexError) -> Self {
97        Self::Lex(error)
98    }
99}
100
101impl From<CellStreamError> for ParseError {
102    fn from(error: CellStreamError) -> Self {
103        Self::Tokenize(error)
104    }
105}
106
107/// A reusable Tree-sitter parser and direct typed-CST lowerer.
108pub struct TreeSitterParser {
109    parser: tree_sitter::Parser,
110}
111
112/// An incrementally updated Tree-sitter parse for editor-style source changes.
113///
114/// The parser retains its previous Tree-sitter tree, applies each [`TextEdit`]
115/// to that tree, and supplies it to the next parse. Typed syntax is lowered
116/// afresh from the incrementally produced tree, so every public node and span
117/// describes the current source snapshot. Missing group closers are recoverable
118/// and remain available through [`Self::diagnostics`].
119pub struct RealtimeParser {
120    parser: tree_sitter::Parser,
121    source: Arc<Source>,
122    parse_view: String,
123    tree: tree_sitter::Tree,
124    syntax: SourceFile,
125    diagnostics: Vec<LexError>,
126    changed_ranges: Vec<Span>,
127}
128
129impl RealtimeParser {
130    /// Creates a retained parse of the initial source snapshot.
131    ///
132    /// # Errors
133    ///
134    /// Returns [`ParseError`] when the grammar cannot parse and lower the
135    /// source, apart from recoverable missing group closers.
136    pub fn new(source: impl Into<String>) -> Result<Self, ParseError> {
137        let source = Source::new(source.into());
138        let mut parser = TreeSitterParser::new()?.parser;
139        let ParsedTree {
140            parse_view,
141            tree,
142            syntax,
143            diagnostics,
144        } = parse_recovered_tree(&mut parser, Arc::clone(&source), None)?;
145        Ok(Self {
146            parser,
147            source,
148            parse_view,
149            tree,
150            syntax,
151            diagnostics,
152            changed_ranges: Vec::new(),
153        })
154    }
155
156    /// Applies one source edit and incrementally refreshes the typed syntax.
157    ///
158    /// The update is transactional: a failed edit or parse leaves the previous
159    /// source, tree, syntax, and diagnostics unchanged.
160    ///
161    /// # Errors
162    ///
163    /// Returns [`ParseError::InvalidEdit`] when the edit is outside the current
164    /// UTF-8 buffer, or another [`ParseError`] when the edited source cannot be
165    /// recovered and lowered.
166    pub fn apply_edit(&mut self, edit: &TextEdit) -> Result<(), ParseError> {
167        let source_text = edit
168            .apply(self.source.text())
169            .ok_or(ParseError::InvalidEdit)?;
170        let source = Source::with_file(self.source.file(), source_text);
171        let (view, aliases, diagnostics) = renamed_source_recovering(source.text())?;
172        let parse_view = view.into_owned();
173
174        let mut edited_tree = self.tree.clone();
175        edited_tree.edit(&input_edit_between(&self.parse_view, &parse_view));
176        let tree = self
177            .parser
178            .parse(parse_view.as_bytes(), Some(&edited_tree))
179            .ok_or(ParseError::Cancelled)?;
180        if let Some(error) = first_error(tree.root_node()) {
181            return Err(ParseError::InvalidSyntax(Span::ranged(
182                Arc::clone(&source),
183                error.start_byte().min(source.text().len())
184                    ..error.end_byte().min(source.text().len()),
185            )));
186        }
187        let syntax = Lowerer::new(Arc::clone(&source), source.text(), aliases)
188            .source_file(tree.root_node())?;
189        let changed_ranges = edited_tree
190            .changed_ranges(&tree)
191            .map(|range| {
192                Span::ranged(
193                    Arc::clone(&source),
194                    range.start_byte.min(source.text().len())
195                        ..range.end_byte.min(source.text().len()),
196                )
197            })
198            .collect();
199
200        self.source = source;
201        self.parse_view = parse_view;
202        self.tree = tree;
203        self.syntax = syntax;
204        self.diagnostics = diagnostics;
205        self.changed_ranges = changed_ranges;
206        Ok(())
207    }
208
209    /// Returns the current source snapshot.
210    pub fn source(&self) -> &str {
211        self.source.text()
212    }
213
214    /// Returns the typed syntax for the current snapshot.
215    pub fn syntax(&self) -> &SourceFile {
216        &self.syntax
217    }
218
219    /// Returns the recoverable diagnostics for the current snapshot.
220    pub fn diagnostics(&self) -> &[LexError] {
221        &self.diagnostics
222    }
223
224    /// Returns structural ranges changed by the most recent incremental parse.
225    pub fn changed_ranges(&self) -> &[Span] {
226        &self.changed_ranges
227    }
228
229    /// Consumes the retained parser and returns its current typed syntax.
230    pub fn into_syntax(self) -> SourceFile {
231        self.syntax
232    }
233}
234
235struct ParsedTree {
236    parse_view: String,
237    tree: tree_sitter::Tree,
238    syntax: SourceFile,
239    diagnostics: Vec<LexError>,
240}
241
242fn parse_recovered_tree(
243    parser: &mut tree_sitter::Parser,
244    source: Arc<Source>,
245    old_tree: Option<&tree_sitter::Tree>,
246) -> Result<ParsedTree, ParseError> {
247    let source_text = source.text();
248    let (view, aliases, diagnostics) = renamed_source_recovering(source_text)?;
249    let parse_view = view.into_owned();
250    let tree = parser
251        .parse(parse_view.as_bytes(), old_tree)
252        .ok_or(ParseError::Cancelled)?;
253    if let Some(error) = first_error(tree.root_node()) {
254        return Err(ParseError::InvalidSyntax(Span::ranged(
255            Arc::clone(&source),
256            error.start_byte().min(source_text.len())..error.end_byte().min(source_text.len()),
257        )));
258    }
259    let syntax =
260        Lowerer::new(Arc::clone(&source), source_text, aliases).source_file(tree.root_node())?;
261    Ok(ParsedTree {
262        parse_view,
263        tree,
264        syntax,
265        diagnostics,
266    })
267}
268
269fn input_edit_between(old: &str, new: &str) -> tree_sitter::InputEdit {
270    let mut start = old
271        .as_bytes()
272        .iter()
273        .zip(new.as_bytes())
274        .take_while(|(old, new)| old == new)
275        .count();
276    while !old.is_char_boundary(start) || !new.is_char_boundary(start) {
277        start -= 1;
278    }
279
280    let available_suffix = old.len().min(new.len()).saturating_sub(start);
281    let mut suffix = old
282        .as_bytes()
283        .iter()
284        .rev()
285        .zip(new.as_bytes().iter().rev())
286        .take(available_suffix)
287        .take_while(|(old, new)| old == new)
288        .count();
289    while !old.is_char_boundary(old.len() - suffix) || !new.is_char_boundary(new.len() - suffix) {
290        suffix -= 1;
291    }
292
293    let old_end = old.len() - suffix;
294    let new_end = new.len() - suffix;
295    tree_sitter::InputEdit {
296        start_byte: start,
297        old_end_byte: old_end,
298        new_end_byte: new_end,
299        start_position: point_at(old, start),
300        old_end_position: point_at(old, old_end),
301        new_end_position: point_at(new, new_end),
302    }
303}
304
305fn point_at(source: &str, offset: usize) -> tree_sitter::Point {
306    let before = &source[..offset];
307    let row = before.bytes().filter(|byte| *byte == b'\n').count();
308    let column = before
309        .as_bytes()
310        .iter()
311        .rposition(|byte| *byte == b'\n')
312        .map_or(before.len(), |newline| before.len() - newline - 1);
313    tree_sitter::Point { row, column }
314}
315
316impl TreeSitterParser {
317    /// Creates a parser loaded with the bundled Macaulay2 grammar.
318    ///
319    /// # Errors
320    ///
321    /// Returns [`ParseError::Language`] if Tree-sitter rejects the bundled
322    /// language definition.
323    pub fn new() -> Result<Self, ParseError> {
324        let mut parser = tree_sitter::Parser::new();
325        parser
326            .set_language(&tree_sitter_macaulay2::language())
327            .map_err(ParseError::Language)?;
328        Ok(Self { parser })
329    }
330
331    fn parse_source_in(&mut self, source: Arc<Source>) -> Result<SourceFile, ParseError> {
332        let source_text = source.text();
333        let (renamed, aliases) = renamed_source(source_text)?;
334        let tree = self
335            .parser
336            .parse(renamed.as_bytes(), None)
337            .ok_or(ParseError::Cancelled)?;
338        if let Some(error) = first_error(tree.root_node()) {
339            return Err(ParseError::InvalidSyntax(Span::ranged(
340                Arc::clone(&source),
341                error.start_byte()..error.end_byte(),
342            )));
343        }
344        Lowerer::new(Arc::clone(&source), source_text, aliases).source_file(tree.root_node())
345    }
346
347    /// Parses incomplete source while retaining syntax inside unclosed groups.
348    ///
349    /// The parsing view is completed only for Tree-sitter; migrated nodes
350    /// retain the original source spans and zero-width missing closers.
351    ///
352    /// # Errors
353    ///
354    /// Returns [`ParseError`] when source has a non-recoverable lexical or
355    /// grammatical failure, parsing is cancelled, or lowering fails.
356    pub fn parse_recovering(
357        &mut self,
358        source: &str,
359    ) -> Result<Recovered<SourceFile, LexError>, ParseError> {
360        let source = Source::new(source);
361        let source_text = source.text();
362        let (renamed, aliases, diagnostics) = renamed_source_recovering(source_text)?;
363        let tree = self
364            .parser
365            .parse(renamed.as_bytes(), None)
366            .ok_or(ParseError::Cancelled)?;
367        if let Some(error) = first_error(tree.root_node()) {
368            return Err(ParseError::InvalidSyntax(Span::ranged(
369                Arc::clone(&source),
370                error.start_byte().min(source_text.len())..error.end_byte().min(source_text.len()),
371            )));
372        }
373        let syntax = Lowerer::new(Arc::clone(&source), source_text, aliases)
374            .source_file(tree.root_node())?;
375        Ok(Recovered::new(syntax, diagnostics))
376    }
377}
378
379impl Parser for TreeSitterParser {
380    type Error = ParseError;
381
382    fn parse_cells(&mut self, cells: CellStream) -> Result<SourceFile, Self::Error> {
383        let (cell_comments, comments) = cells.comment_ownership();
384        let mut source_file = match cells.complete_source() {
385            Some(source) => self.parse_source_in(source),
386            None => self.parse_source_in(Source::new(cells.to_string())),
387        }?;
388        if source_file.cells.len() == cell_comments.len() {
389            for (cell, comments) in source_file.cells.iter_mut().zip(cell_comments) {
390                cell.comments = comments;
391            }
392            source_file.comments = comments;
393        } else {
394            source_file.comments = comments;
395            for comments in cell_comments {
396                source_file.comments.append(comments);
397            }
398        }
399        Ok(source_file)
400    }
401}
402
403/// Parses source with Tree-sitter and lowers its CST into the typed syntax tree.
404///
405/// # Errors
406///
407/// Returns [`ParseError`] when parsing or typed migration fails.
408pub fn parse_file(source: &str) -> Result<SourceFile, ParseError> {
409    let mut parser = TreeSitterParser::new()?;
410    let cells = lex_str(source)?.to_cell_stream()?;
411    parser.parse_cells(cells)
412}
413
414/// Parses incomplete source while retaining syntax inside unclosed groups.
415///
416/// # Errors
417///
418/// Returns [`ParseError`] for failures other than missing closing delimiters or
419/// when the recovered Tree-sitter CST cannot be lowered.
420pub fn parse_file_recovering(source: &str) -> Result<Recovered<SourceFile, LexError>, ParseError> {
421    TreeSitterParser::new()?.parse_recovering(source)
422}
423
424/// Parses an emitted M2 token stream into the complete typed source file.
425///
426/// # Errors
427///
428/// Returns [`ParseError`] when the emitted source is invalid or migration
429/// fails.
430pub fn parse_tokens(tokens: &TokenStream) -> Result<SourceFile, ParseError> {
431    let cells = tokens.to_cell_stream()?;
432    TreeSitterParser::new()?.parse_cells(cells)
433}
434
435fn first_error(root: tree_sitter::Node<'_>) -> Option<tree_sitter::Node<'_>> {
436    let mut pending = vec![root];
437    while let Some(node) = pending.pop() {
438        if node.is_error() || node.is_missing() {
439            return Some(node);
440        }
441        pending.extend((0..node.child_count()).rev().filter_map(|index| {
442            node.child(u32::try_from(index).expect("Tree-sitter child count fits u32"))
443        }));
444    }
445    None
446}
447
448struct Lowerer<'source> {
449    source: &'source [u8],
450    source_span: Span,
451    aliases: Vec<CoreAlias>,
452}
453
454impl<'source> Lowerer<'source> {
455    fn new(source_owner: Arc<Source>, source: &'source str, aliases: Vec<CoreAlias>) -> Self {
456        Self {
457            source: source.as_bytes(),
458            source_span: Span::ranged(source_owner, 0..source.len()),
459            aliases,
460        }
461    }
462
463    fn source_file(&self, root: tree_sitter::Node<'_>) -> Result<SourceFile, ParseError> {
464        let mut cells = Vec::new();
465        let raw_cells = self.semantic_children(root);
466        for (index, child) in raw_cells.iter().copied().enumerate() {
467            match child.kind() {
468                "cell" | "muted" => {
469                    let next = raw_cells.get(index + 1).copied();
470                    cells.push(self.cell(child, self.eoc_offset(child, next))?);
471                }
472                kind => return Err(self.unsupported(kind, child)),
473            }
474        }
475        let eof_offset = cells
476            .last()
477            .and_then(|cell| cell.eoc.span().start())
478            .unwrap_or(self.source.len());
479        Ok(SourceFile::new(
480            cells,
481            EOF::new("", self.source_span.at(eof_offset)),
482        ))
483    }
484
485    fn cell(&self, node: tree_sitter::Node<'_>, eoc_offset: usize) -> Result<Cell, ParseError> {
486        let (content, semicolon) = if node.kind() == "muted" {
487            let semicolon = self.required_kind(node, ";")?;
488            (
489                self.expr_pack(self.children(node))?,
490                Some(self.migrate(semicolon)?),
491            )
492        } else {
493            let child = self.only_semantic_child(node)?;
494            let pack = if child.kind() == "naked_sequence" {
495                self.expr_pack(self.children(child))?
496            } else {
497                ExprPack::new(Punctuated::from_single(Component::Expr(Box::new(
498                    self.expr(child)?,
499                ))))
500            };
501            (pack, None)
502        };
503        Ok(Cell::new(
504            content,
505            semicolon,
506            EOC::new("", self.source_span.at(eoc_offset)),
507        ))
508    }
509
510    fn eoc_offset(
511        &self,
512        _node: tree_sitter::Node<'_>,
513        next: Option<tree_sitter::Node<'_>>,
514    ) -> usize {
515        next.map_or(self.source.len(), |next| next.start_byte())
516            .min(self.source.len())
517    }
518
519    fn expr_pack(&self, nodes: Vec<tree_sitter::Node<'_>>) -> Result<ExprPack, ParseError> {
520        let pack_span = nodes
521            .iter()
522            .map(|node| self.span(*node))
523            .reduce(|left, right| {
524                left.join(right)
525                    .expect("Tree-sitter nodes share one source snapshot")
526            })
527            .unwrap_or_else(|| Span::unlocated(Arc::clone(self.source_span.source())));
528        let mut values = Vec::new();
529        let mut commas = Vec::new();
530        for node in nodes.into_iter().filter(|node| !node.is_extra()) {
531            match node.kind() {
532                "," => commas.push(self.migrate::<Token![,]>(node)?),
533                "empty_component" => values.push(Component::Empty(Empty::new("", self.span(node)))),
534                ";" | "(" | ")" | "[" | "]" | "{" | "}" | "<|" | "|>" | "muted" => {}
535                _ if node.is_named() => values.push(Component::Expr(Box::new(self.expr(node)?))),
536                _ => {}
537            }
538        }
539        let mut values = values.into_iter();
540        let Some(first) = values.next() else {
541            return Err(self.unsupported_span("empty expression pack", pack_span));
542        };
543        let value_count = values.len() + 1;
544        let comma_count = commas.len();
545        if value_count != comma_count + 1 {
546            return Err(self.unsupported_span("invalid expression pack", pack_span));
547        }
548        let rest = commas
549            .into_iter()
550            .zip(values)
551            .collect::<Vec<(Token![,], Component)>>();
552        Ok(ExprPack::new(Punctuated::new(first, rest)))
553    }
554
555    fn expr(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
556        match node.kind() {
557            "symbol" => Ok(self.migrate::<Symbol>(node)?.into()),
558            "integer_literal" if self.text(node).contains('p') => {
559                Ok(FloatLiteral::new(self.text(node), self.span(node)).into())
560            }
561            "integer_literal" => Ok(self.migrate::<IntegerLiteral>(node)?.into()),
562            "float_literal" => Ok(self.migrate::<FloatLiteral>(node)?.into()),
563            "string_literal" => self.string_literal(node),
564            "raw_string_literal" => self.raw_string_literal(node),
565            "array" | "list" | "angle_bar_list" | "sequence" | "parenthesized_expression" => {
566                self.collection(node)
567            }
568            "binary_expression" => self.binary_expr(node),
569            "prefix_expression" => self.prefix_expr(node),
570            "postfix_expression" => self.postfix_expr(node),
571            "lambda_expression" => self.lambda_expression(node),
572            "assignment"
573            | "local_assignment"
574            | "binary_assignment"
575            | "prefix_assignment"
576            | "postfix_assignment"
577            | "binary_installation"
578            | "prefix_installation"
579            | "postfix_installation"
580            | "structured_binding"
581            | "local_structured_binding" => self.assignment(node),
582            "evaluated_assignment" => Ok(EvaluatedAssignment::new(
583                self.expr(self.required_field(node, "left")?)?,
584                self.migrate(self.required_field(node, "operator")?)?,
585                self.expr(self.required_field(node, "right")?)?,
586            )
587            .into()),
588            "option" => Ok(OptionExpression::new(
589                self.expr(self.required_field(node, "left")?)?,
590                self.migrate(self.required_field(node, "operator")?)?,
591                self.expr(self.required_field(node, "right")?)?,
592            )
593            .into()),
594            "if_statement" => self.if_statement(node),
595            "for_loop" => self.for_loop(node),
596            "while_loop" => self.while_loop(node),
597            "try_statement" => self.try_statement(node),
598            "quote_expression" => self.quote_expression(node),
599            "new_statement" => self.new_statement(node),
600            "break_statement" => Ok(BreakExpr::new(
601                self.migrate(self.required_kind(node, "break")?)?,
602                self.first_expression_child(node)
603                    .map(|child| self.expr(child))
604                    .transpose()?,
605            )
606            .into()),
607            "continue_statement" => Ok(ContinueExpr::new(
608                self.migrate(self.required_kind(node, "continue")?)?,
609                self.first_expression_child(node)
610                    .map(|child| self.expr(child))
611                    .transpose()?,
612            )
613            .into()),
614            "return_statement" => Ok(ReturnExpr::new(
615                self.migrate(self.required_kind(node, "return")?)?,
616                self.first_expression_child(node)
617                    .map(|child| self.expr(child))
618                    .transpose()?,
619            )
620            .into()),
621            "catch_statement" => Ok(Catch::new(
622                self.migrate(self.required_kind(node, "catch")?)?,
623                self.expr(self.required_expression_child(node)?)?,
624            )
625            .into()),
626            "throw_statement" => Ok(Throw::new(
627                self.migrate(self.required_kind(node, "throw")?)?,
628                self.expr(self.required_expression_child(node)?)?,
629            )
630            .into()),
631            "trap_statement" => Ok(Trap::new(
632                self.migrate(self.required_kind(node, "trap")?)?,
633                self.expr(self.required_expression_child(node)?)?,
634            )
635            .into()),
636            "debug_clause" => self.debug_clause(node),
637            kind => Err(self.unsupported(kind, node)),
638        }
639    }
640
641    fn collection(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
642        let spans = self.delimiter_spans(node)?;
643        let statements = self
644            .semantic_children(node)
645            .into_iter()
646            .filter(|child| child.kind() == "muted")
647            .map(|child| self.statement(child))
648            .collect::<Result<Vec<_>, _>>()?;
649
650        if node.kind() == "parenthesized_expression" {
651            let value = self
652                .semantic_children(node)
653                .into_iter()
654                .find(|child| child.kind() != "muted")
655                .map(|child| self.expr(child))
656                .transpose()?;
657            let mut holder = Holder::new(statements, value);
658            holder.delimiter = <Delimiter![()] as DelimiterToken>::new(spans);
659            return Ok(holder.into());
660        }
661
662        let has_elements = self.children(node).into_iter().any(|child| {
663            !child.is_extra()
664                && (child.kind() == ","
665                    || child.kind() == "empty_component"
666                    || (child.is_named() && child.kind() != "muted"))
667        });
668        let elements = has_elements
669            .then(|| self.expr_pack(self.children(node)))
670            .transpose()?;
671        Ok(match node.kind() {
672            "array" => {
673                let mut value = Array::new(statements, elements);
674                value.delimiter = <Delimiter![[]] as DelimiterToken>::new(spans);
675                value.into()
676            }
677            "list" => {
678                let mut value = List::new(statements, elements);
679                value.delimiter = <Delimiter![{}] as DelimiterToken>::new(spans);
680                value.into()
681            }
682            "angle_bar_list" => {
683                let mut value = AngleBarList::new(statements, elements);
684                value.delimiter = <Delimiter![<| |>] as DelimiterToken>::new(spans);
685                value.into()
686            }
687            "sequence" => {
688                let mut value = Sequence::new(statements, elements);
689                value.delimiter = <Delimiter![()] as DelimiterToken>::new(spans);
690                value.into()
691            }
692            kind => return Err(self.unsupported(kind, node)),
693        })
694    }
695
696    fn statement(&self, node: tree_sitter::Node<'_>) -> Result<Statement, ParseError> {
697        Ok(Statement::new(
698            self.expr_pack(self.children(node))?,
699            self.migrate(self.required_kind(node, ";")?)?,
700        ))
701    }
702
703    fn string_literal(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
704        let elements = self
705            .children(node)
706            .into_iter()
707            .filter(|child| child.kind() != "\"")
708            .filter(|child| !child.is_extra())
709            .map(|child| match child.kind() {
710                "escape_sequence" => self.migrate(child).map(StringElement::EscapeSequence),
711                "string_content" => self.migrate(child).map(StringElement::StringContent),
712                _ => Ok(StringElement::StringContent(StringContent::new(
713                    self.text(child),
714                    self.span(child),
715                ))),
716            })
717            .collect::<Result<Vec<_>, ParseError>>()?;
718        Ok(StringLiteral::new(elements, self.span(node)).into())
719    }
720
721    fn raw_string_literal(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
722        let elements = self
723            .children(node)
724            .into_iter()
725            .filter(|child| child.kind() != "///")
726            .filter(|child| !child.is_extra())
727            .map(|child| match child.kind() {
728                "escape_sequence" => self.migrate(child).map(RawStringElement::EscapeSequence),
729                "raw_string_content" => self.migrate(child).map(RawStringElement::RawStringContent),
730                kind => Err(self.unsupported(kind, child)),
731            })
732            .collect::<Result<Vec<_>, ParseError>>()?;
733        Ok(RawStringLiteral::new(elements, self.span(node)).into())
734    }
735
736    fn binary_expr(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
737        let left = self.expr(self.required_field(node, "left")?)?;
738        let operator = self.required_field(node, "operator")?;
739        let right = self.expr(self.required_field(node, "right")?)?;
740        if operator.kind() == "SPACE" {
741            Ok(AdjacentExpr::new(left, Adj::new("", self.span(operator)), right).into())
742        } else {
743            Ok(BinaryExpr::new(left, self.migrate(operator)?, right).into())
744        }
745    }
746
747    fn prefix_expr(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
748        Ok(PrefixExpr::new(
749            self.migrate(self.required_field(node, "operator")?)?,
750            self.expr(self.required_field(node, "operand")?)?,
751        )
752        .into())
753    }
754
755    fn postfix_expr(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
756        Ok(PostfixExpr::new(
757            self.expr(self.required_field(node, "operand")?)?,
758            self.migrate(self.required_field(node, "operator")?)?,
759        )
760        .into())
761    }
762
763    fn lambda_expression(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
764        let parameter_expr = self.expr(self.required_field(node, "parameters")?)?;
765        let parameters = lambda_parameters(parameter_expr)
766            .ok_or_else(|| self.unsupported("lambda parameters", node))?;
767        Ok(LambdaExpression::new(
768            parameters,
769            self.migrate(self.required_field(node, "operator")?)?,
770            self.expr(self.required_field(node, "body")?)?,
771        )
772        .into())
773    }
774
775    fn assignment(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
776        let right = self.expr(self.required_field(node, "right")?)?;
777        Ok(match node.kind() {
778            "assignment" => GlobalBinding::new(
779                self.migrate(self.required_field(node, "left")?)?,
780                self.migrate(self.required_field(node, "operator")?)?,
781                right,
782            )
783            .into(),
784            "local_assignment" => LocalBinding::new(
785                self.migrate(self.required_field(node, "left")?)?,
786                self.migrate(self.required_field(node, "operator")?)?,
787                right,
788            )
789            .into(),
790            "binary_assignment" | "prefix_assignment" | "postfix_assignment" => {
791                let Expr::OperatorExpr(left) = self.expr(self.required_field(node, "left")?)?
792                else {
793                    return Err(self.unsupported("operator assignment target", node));
794                };
795                OperatorAssignment::new(
796                    left,
797                    self.migrate(self.required_field(node, "operator")?)?,
798                    right,
799                )
800                .into()
801            }
802            "binary_installation" | "prefix_installation" | "postfix_installation" => {
803                let Expr::OperatorExpr(left) = self.expr(self.required_field(node, "left")?)?
804                else {
805                    return Err(self.unsupported("operator installation target", node));
806                };
807                let (typical_value, function) = installation_value(right);
808                match left {
809                    OperatorExpr::AdjacentExpr(application) => MethodInstallation::new(
810                        *application.left_operand,
811                        *application.right_operand,
812                        self.migrate(self.required_field(node, "operator")?)?,
813                        typical_value,
814                        function,
815                    )
816                    .into(),
817                    domain => OperatorInstallation::new(
818                        domain,
819                        self.migrate(self.required_field(node, "operator")?)?,
820                        typical_value,
821                        function,
822                    )
823                    .into(),
824                }
825            }
826            "structured_binding" | "local_structured_binding" => {
827                let pack_expr = self.expr(self.required_field(node, "binding_pack")?)?;
828                let pack = assignment_pack(pack_expr)
829                    .ok_or_else(|| self.unsupported("assignment pack", node))?;
830                if node.kind() == "local_structured_binding" {
831                    LocalParallelAssignment::new(
832                        pack,
833                        self.migrate(self.required_field(node, "operator")?)?,
834                        right,
835                    )
836                    .into()
837                } else {
838                    GlobalParallelAssignment::new(
839                        pack,
840                        self.migrate(self.required_field(node, "operator")?)?,
841                        right,
842                    )
843                    .into()
844                }
845            }
846            kind => return Err(self.unsupported(kind, node)),
847        })
848    }
849
850    fn then_clause(&self, node: tree_sitter::Node<'_>) -> Result<ThenClause, ParseError> {
851        Ok(ThenClause::new(
852            self.migrate(self.required_kind(node, "then")?)?,
853            self.expr(self.required_expression_child(node)?)?,
854        ))
855    }
856
857    fn else_clause(&self, node: tree_sitter::Node<'_>) -> Result<ElseClause, ParseError> {
858        Ok(ElseClause::new(
859            self.migrate(self.required_kind(node, "else")?)?,
860            self.expr(self.required_expression_child(node)?)?,
861        ))
862    }
863
864    fn if_statement(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
865        Ok(IfStatement::new(
866            self.migrate(self.required_kind(node, "if")?)?,
867            self.expr(self.required_field(node, "condition")?)?,
868            self.then_clause(self.required_kind(node, "then_clause")?)?,
869            self.optional_kind(node, "else_clause")
870                .map(|child| self.else_clause(child))
871                .transpose()?,
872        )
873        .into())
874    }
875
876    fn loop_body(&self, node: tree_sitter::Node<'_>) -> Result<LoopBody, ParseError> {
877        let list_step = self
878            .optional_kind(node, "list")
879            .map(|token| {
880                Ok::<_, ParseError>(ListStep::new(
881                    self.migrate(token)?,
882                    self.expr(self.required_field(node, "listed_value")?)?,
883                ))
884            })
885            .transpose()?;
886        let do_step = self
887            .optional_kind(node, "do")
888            .map(|token| {
889                Ok::<_, ParseError>(DoStep::new(
890                    self.migrate(token)?,
891                    self.expr(self.required_field(node, "ignored_value")?)?,
892                ))
893            })
894            .transpose()?;
895        Ok(LoopBody::new(list_step, do_step))
896    }
897
898    fn for_loop(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
899        let iteration_domain = self
900            .optional_kind(node, "iteration_range")
901            .map(|range| self.iteration_domain(range))
902            .transpose()?;
903        let when_condition = self
904            .optional_kind(node, "when")
905            .map(|token| {
906                Ok::<_, ParseError>(WhenCondition::new(
907                    self.migrate(token)?,
908                    self.expr(self.required_field(node, "filter")?)?,
909                ))
910            })
911            .transpose()?;
912        Ok(ForLoop::new(
913            self.migrate(self.required_kind(node, "for")?)?,
914            self.migrate(self.required_field(node, "variable")?)?,
915            iteration_domain,
916            when_condition,
917            self.loop_body(self.required_kind(node, "loop_body")?)?,
918        )
919        .into())
920    }
921
922    fn iteration_domain(&self, node: tree_sitter::Node<'_>) -> Result<IterationDomain, ParseError> {
923        if let Some(token) = self.optional_kind(node, "in") {
924            return Ok(IterIn::new(
925                self.migrate(token)?,
926                self.expr(self.required_field(node, "iterated_collection")?)?,
927            )
928            .into());
929        }
930        let lower_bound = self
931            .optional_kind(node, "from")
932            .map(|token| {
933                Ok::<_, ParseError>(RangeBoundFrom::new(
934                    self.migrate(token)?,
935                    self.expr(self.required_field(node, "range_start")?)?,
936                ))
937            })
938            .transpose()?;
939        let upper_bound = self
940            .optional_kind(node, "to")
941            .map(|token| {
942                Ok::<_, ParseError>(RangeBoundTo::new(
943                    self.migrate(token)?,
944                    self.expr(self.required_field(node, "range_end")?)?,
945                ))
946            })
947            .transpose()?;
948        Ok(IterRange::new(lower_bound, upper_bound).into())
949    }
950
951    fn while_loop(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
952        Ok(WhileLoop::new(
953            self.migrate(self.required_kind(node, "while")?)?,
954            self.expr(self.required_field(node, "condition")?)?,
955            self.loop_body(self.required_kind(node, "loop_body")?)?,
956        )
957        .into())
958    }
959
960    fn new_statement(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
961        let mut installation = None;
962        let class =
963            self.new_statement_element(self.required_field(node, "class")?, &mut installation)?;
964        let parent_class = self
965            .optional_kind(node, "of")
966            .map(|token| {
967                Ok::<_, ParseError>(OfClass::new(
968                    self.migrate(token)?,
969                    self.new_statement_element(
970                        self.required_field(node, "parent")?,
971                        &mut installation,
972                    )?,
973                ))
974            })
975            .transpose()?;
976        let instance = self
977            .optional_kind(node, "from")
978            .map(|token| {
979                Ok::<_, ParseError>(FromInstance::new(
980                    self.migrate(token)?,
981                    self.new_statement_element(
982                        self.required_field(node, "instance")?,
983                        &mut installation,
984                    )?,
985                ))
986            })
987            .transpose()?;
988        let statement = NewStatement::new(
989            self.migrate(self.required_kind(node, "new")?)?,
990            class,
991            parent_class,
992            instance,
993        );
994        Ok(match installation {
995            Some((operator, function)) => {
996                NewInstallation::new(statement, operator, function).into()
997            }
998            None => statement.into(),
999        })
1000    }
1001
1002    fn new_statement_element(
1003        &self,
1004        node: tree_sitter::Node<'_>,
1005        installation: &mut Option<(Token![:=], Expr)>,
1006    ) -> Result<Expr, ParseError> {
1007        match node.kind() {
1008            "assignment" => return Err(self.unsupported("`new` assignment with `=`", node)),
1009            "local_assignment" => {}
1010            _ => return self.expr(node),
1011        }
1012        *installation = Some((
1013            self.migrate(self.required_field(node, "operator")?)?,
1014            self.expr(self.required_field(node, "right")?)?,
1015        ));
1016        self.expr(self.required_field(node, "left")?)
1017    }
1018
1019    fn try_statement(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
1020        let value = self
1021            .semantic_children(node)
1022            .into_iter()
1023            .find(|child| {
1024                child.kind() != "then_clause"
1025                    && child.kind() != "else_clause"
1026                    && child.kind() != "except_clause"
1027            })
1028            .ok_or_else(|| self.unsupported("try value", node))?;
1029        let on_success = self
1030            .optional_kind(node, "then_clause")
1031            .map(|child| self.then_clause(child))
1032            .transpose()?;
1033        let fallback = self
1034            .child_by_field(node, "fallback")
1035            .map(|child| match child.kind() {
1036                "else_clause" => self.else_clause(child).map(TryFallback::ElseClause),
1037                "except_clause" => self.except_do(child).map(TryFallback::ExceptDo),
1038                kind => Err(self.unsupported(kind, child)),
1039            })
1040            .transpose()?;
1041        Ok(TryStatement::new(
1042            self.migrate(self.required_kind(node, "try")?)?,
1043            self.expr(value)?,
1044            on_success,
1045            fallback,
1046        )
1047        .into())
1048    }
1049
1050    fn except_do(&self, node: tree_sitter::Node<'_>) -> Result<ExceptDo, ParseError> {
1051        Ok(ExceptDo::new(
1052            self.migrate(self.required_kind(node, "except")?)?,
1053            self.migrate(self.required_field(node, "exception")?)?,
1054            self.migrate(self.required_kind(node, "do")?)?,
1055            self.expr(self.required_expression_child(node)?)?,
1056        ))
1057    }
1058
1059    fn quote_expression(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
1060        let token = self
1061            .children(node)
1062            .into_iter()
1063            .find(|child| {
1064                matches!(
1065                    child.kind(),
1066                    "symbol" | "local" | "global" | "threadVariable" | "threadLocal"
1067                ) && self.child_by_field(node, "token") != Some(*child)
1068            })
1069            .ok_or_else(|| self.unsupported("quote specifier", node))?;
1070        let specifier = match token.kind() {
1071            "symbol" => QuoteSpecifier::Symbol(self.migrate(token)?),
1072            "local" => QuoteSpecifier::Local(self.migrate(token)?),
1073            "global" => QuoteSpecifier::Global(self.migrate(token)?),
1074            "threadVariable" => QuoteSpecifier::ThreadVariable(self.migrate(token)?),
1075            "threadLocal" => QuoteSpecifier::ThreadLocal(self.migrate(token)?),
1076            kind => return Err(self.unsupported(kind, token)),
1077        };
1078        let quoted = self.required_field(node, "token")?;
1079        Ok(
1080            QuoteExpression::new(specifier, Symbol::new(self.text(quoted), self.span(quoted)))
1081                .into(),
1082        )
1083    }
1084
1085    fn debug_clause(&self, node: tree_sitter::Node<'_>) -> Result<Expr, ParseError> {
1086        let keyword = self.required_field(node, "keyword")?;
1087        let value = self
1088            .first_expression_child(node)
1089            .map(|child| self.expr(child))
1090            .transpose()?;
1091        Ok(match keyword.kind() {
1092            "elapsedTime" => ProfilingExpr::new(
1093                ProfilingModifier::ElapsedTime(self.migrate(keyword)?),
1094                value.ok_or_else(|| self.unsupported("profiling operand", node))?,
1095            )
1096            .into(),
1097            "elapsedTiming" => ProfilingExpr::new(
1098                ProfilingModifier::ElapsedTiming(self.migrate(keyword)?),
1099                value.ok_or_else(|| self.unsupported("profiling operand", node))?,
1100            )
1101            .into(),
1102            "profile" => ProfilingExpr::new(
1103                ProfilingModifier::Profile(self.migrate(keyword)?),
1104                value.ok_or_else(|| self.unsupported("profiling operand", node))?,
1105            )
1106            .into(),
1107            "time" => ProfilingExpr::new(
1108                ProfilingModifier::Time(self.migrate(keyword)?),
1109                value.ok_or_else(|| self.unsupported("profiling operand", node))?,
1110            )
1111            .into(),
1112            "timing" => ProfilingExpr::new(
1113                ProfilingModifier::Timing(self.migrate(keyword)?),
1114                value.ok_or_else(|| self.unsupported("profiling operand", node))?,
1115            )
1116            .into(),
1117            "TEST" => DebugExpr::new(DebugKeyword::Test(self.migrate(keyword)?), value).into(),
1118            "step" => DebugExpr::new(DebugKeyword::Step(self.migrate(keyword)?), value).into(),
1119            "finish" => DebugExpr::new(DebugKeyword::Finish(self.migrate(keyword)?), value).into(),
1120            "shield" => DebugExpr::new(DebugKeyword::Shield(self.migrate(keyword)?), value).into(),
1121            "breakpoint" => {
1122                DebugExpr::new(DebugKeyword::Breakpoint(self.migrate(keyword)?), value).into()
1123            }
1124            kind => return Err(self.unsupported(kind, keyword)),
1125        })
1126    }
1127
1128    fn migrate<T>(&self, node: tree_sitter::Node<'_>) -> Result<T, ParseError>
1129    where
1130        for<'tree> T: Migrate<TreeSitterNode<'tree, 'source>>,
1131    {
1132        T::migrate(TreeSitterNode::with_span(
1133            node,
1134            self.source,
1135            self.span(node),
1136        ))
1137        .map_err(Into::into)
1138    }
1139
1140    fn delimiter_spans(&self, node: tree_sitter::Node<'_>) -> Result<DoubleSpan, ParseError> {
1141        let kind = match node.kind() {
1142            "parenthesized_expression" | "sequence" => DelimiterKind::Parenthesis,
1143            "array" => DelimiterKind::Bracket,
1144            "list" => DelimiterKind::Brace,
1145            "angle_bar_list" => DelimiterKind::AngleBar,
1146            other => return Err(self.unsupported(other, node)),
1147        };
1148        let opening = self.span(self.required_kind(node, kind.opening())?);
1149        let closing = self.required_kind(node, kind.closing())?;
1150        if closing.start_byte() >= self.source.len() {
1151            Ok(DoubleSpan::unclosed(opening))
1152        } else {
1153            Ok(DoubleSpan::new(opening, self.span(closing)))
1154        }
1155    }
1156
1157    fn children<'tree>(&self, node: tree_sitter::Node<'tree>) -> Vec<tree_sitter::Node<'tree>> {
1158        (0..node.child_count())
1159            .filter_map(|index| node.child(u32::try_from(index).expect("child count fits u32")))
1160            .collect()
1161    }
1162
1163    fn semantic_children<'tree>(
1164        &self,
1165        node: tree_sitter::Node<'tree>,
1166    ) -> Vec<tree_sitter::Node<'tree>> {
1167        self.children(node)
1168            .into_iter()
1169            .filter(|child| child.is_named() && !child.is_extra())
1170            .collect()
1171    }
1172
1173    fn only_semantic_child<'tree>(
1174        &self,
1175        node: tree_sitter::Node<'tree>,
1176    ) -> Result<tree_sitter::Node<'tree>, ParseError> {
1177        let children = self.semantic_children(node);
1178        match children.as_slice() {
1179            [child] => Ok(*child),
1180            _ => Err(self.unsupported("cell contents", node)),
1181        }
1182    }
1183
1184    fn first_expression_child<'tree>(
1185        &self,
1186        node: tree_sitter::Node<'tree>,
1187    ) -> Option<tree_sitter::Node<'tree>> {
1188        self.semantic_children(node).into_iter().find(|child| {
1189            !matches!(
1190                child.kind(),
1191                "then_clause" | "else_clause" | "except_clause" | "iteration_range" | "loop_body"
1192            )
1193        })
1194    }
1195
1196    fn required_expression_child<'tree>(
1197        &self,
1198        node: tree_sitter::Node<'tree>,
1199    ) -> Result<tree_sitter::Node<'tree>, ParseError> {
1200        self.first_expression_child(node)
1201            .ok_or_else(|| self.unsupported("expression child", node))
1202    }
1203
1204    fn child_by_field<'tree>(
1205        &self,
1206        node: tree_sitter::Node<'tree>,
1207        field: &str,
1208    ) -> Option<tree_sitter::Node<'tree>> {
1209        node.child_by_field_name(field)
1210    }
1211
1212    fn required_field<'tree>(
1213        &self,
1214        node: tree_sitter::Node<'tree>,
1215        field: &str,
1216    ) -> Result<tree_sitter::Node<'tree>, ParseError> {
1217        self.child_by_field(node, field)
1218            .ok_or_else(|| self.unsupported(field, node))
1219    }
1220
1221    fn optional_kind<'tree>(
1222        &self,
1223        node: tree_sitter::Node<'tree>,
1224        kind: &str,
1225    ) -> Option<tree_sitter::Node<'tree>> {
1226        self.children(node)
1227            .into_iter()
1228            .find(|child| !child.is_extra() && child.kind() == kind)
1229    }
1230
1231    fn required_kind<'tree>(
1232        &self,
1233        node: tree_sitter::Node<'tree>,
1234        kind: &str,
1235    ) -> Result<tree_sitter::Node<'tree>, ParseError> {
1236        self.optional_kind(node, kind)
1237            .ok_or_else(|| self.unsupported(kind, node))
1238    }
1239
1240    fn text(&self, node: tree_sitter::Node<'_>) -> Cow<'_, str> {
1241        let range = self
1242            .span(node)
1243            .bounds()
1244            .map_or_else(|| node.byte_range(), |(start, end)| start..end);
1245        String::from_utf8_lossy(&self.source[range])
1246    }
1247
1248    fn span(&self, node: tree_sitter::Node<'_>) -> Span {
1249        let range = node.byte_range();
1250        self.aliases
1251            .iter()
1252            .find(|alias| alias.bare == range)
1253            .map_or_else(
1254                || {
1255                    self.source_span.subspan(
1256                        node.start_byte().min(self.source.len()),
1257                        node.end_byte().min(self.source.len()),
1258                    )
1259                },
1260                |alias| self.source_span.subspan(alias.full.start, alias.full.end),
1261            )
1262    }
1263
1264    fn unsupported(&self, kind: impl Into<String>, node: tree_sitter::Node<'_>) -> ParseError {
1265        self.unsupported_span(kind, self.span(node))
1266    }
1267
1268    fn unsupported_span(&self, kind: impl Into<String>, span: Span) -> ParseError {
1269        ParseError::UnsupportedNode {
1270            kind: kind.into(),
1271            span,
1272        }
1273    }
1274}
1275
1276#[derive(Clone)]
1277struct CoreAlias {
1278    full: Range<usize>,
1279    bare: Range<usize>,
1280}
1281
1282fn renamed_source(source: &str) -> Result<(Cow<'_, str>, Vec<CoreAlias>), LexError> {
1283    let tokens = lex_str(source)?;
1284    let mut aliases = Vec::new();
1285    collect_core_aliases(&tokens, &mut aliases);
1286    if aliases.is_empty() {
1287        return Ok((Cow::Borrowed(source), aliases));
1288    }
1289
1290    let mut renamed = source.as_bytes().to_vec();
1291    for alias in &aliases {
1292        renamed[alias.full.start..alias.bare.start].fill(b' ');
1293    }
1294    Ok((
1295        Cow::Owned(String::from_utf8(renamed).expect("replacing ASCII bytes preserves UTF-8")),
1296        aliases,
1297    ))
1298}
1299
1300type RecoveredSource<'source> = (Cow<'source, str>, Vec<CoreAlias>, Vec<LexError>);
1301
1302fn renamed_source_recovering(source: &str) -> Result<RecoveredSource<'_>, LexError> {
1303    let recovered = lex_str_recovering(source)?;
1304    let (tokens, diagnostics) = recovered.into_parts();
1305    let mut aliases = Vec::new();
1306    collect_core_aliases(&tokens, &mut aliases);
1307    let mut missing = Vec::new();
1308    collect_missing_closers(&tokens, &mut missing);
1309
1310    if aliases.is_empty() && missing.is_empty() {
1311        return Ok((Cow::Borrowed(source), aliases, diagnostics));
1312    }
1313
1314    let mut renamed = source.as_bytes().to_vec();
1315    for alias in &aliases {
1316        renamed[alias.full.start..alias.bare.start].fill(b' ');
1317    }
1318    for kind in missing {
1319        renamed.extend_from_slice(kind.closing().as_bytes());
1320    }
1321    Ok((
1322        Cow::Owned(String::from_utf8(renamed).expect("ASCII recovery preserves UTF-8")),
1323        aliases,
1324        diagnostics,
1325    ))
1326}
1327
1328fn collect_missing_closers(tokens: &TokenStream, missing: &mut Vec<DelimiterKind>) {
1329    for token in tokens.iter() {
1330        let TokenTree::Group(group) = token else {
1331            continue;
1332        };
1333        collect_missing_closers(group.stream(), missing);
1334        if !group.delimiter().is_closed() {
1335            missing.push(group.delim_kind());
1336        }
1337    }
1338}
1339
1340fn collect_core_aliases(tokens: &TokenStream, aliases: &mut Vec<CoreAlias>) {
1341    for token in tokens.iter() {
1342        match token {
1343            TokenTree::Group(group) => collect_core_aliases(group.stream(), aliases),
1344            TokenTree::Ident(identifier) => {
1345                let spelling = identifier.text();
1346                let bare = crate::lexer::canonical_word_spelling(spelling);
1347                if bare == spelling {
1348                    continue;
1349                }
1350                let Some((start, end)) = identifier.expect_span().bounds() else {
1351                    continue;
1352                };
1353                aliases.push(CoreAlias {
1354                    full: start..end,
1355                    bare: end - bare.len()..end,
1356                });
1357            }
1358            TokenTree::Literal(_) | TokenTree::Punct(_) => {}
1359        }
1360    }
1361}
1362
1363#[derive(Clone)]
1364/// A borrowed Tree-sitter node paired with the source bytes it spans.
1365pub struct TreeSitterNode<'tree, 'source> {
1366    node: tree_sitter::Node<'tree>,
1367    source: &'source [u8],
1368    span: Option<Span>,
1369}
1370
1371impl<'tree, 'source> TreeSitterNode<'tree, 'source> {
1372    /// Creates an external migration node.
1373    pub fn new(node: tree_sitter::Node<'tree>, source: &'source [u8]) -> Self {
1374        Self {
1375            node,
1376            source,
1377            span: None,
1378        }
1379    }
1380
1381    fn with_span(node: tree_sitter::Node<'tree>, source: &'source [u8], span: Span) -> Self {
1382        Self {
1383            node,
1384            source,
1385            span: Some(span),
1386        }
1387    }
1388}
1389
1390impl ExternalCstNode for TreeSitterNode<'_, '_> {
1391    type Children<'syntax>
1392        = IntoIter<ExternalCstChild<Self>>
1393    where
1394        Self: 'syntax;
1395
1396    fn identity(&self) -> CSTNodeClassLabel<'_> {
1397        CSTNodeClassLabel::new(self.node.kind(), self.node.is_named())
1398    }
1399
1400    fn children(&self) -> Self::Children<'_> {
1401        let parent = self.node;
1402        (0..parent.child_count())
1403            .filter_map(|index| {
1404                let index = u32::try_from(index).expect("Tree-sitter child count fits u32");
1405                parent.child(index).map(|node| ExternalCstChild {
1406                    field: parent.field_name_for_child(index),
1407                    node: Self::new(node, self.source),
1408                })
1409            })
1410            .collect::<Vec<_>>()
1411            .into_iter()
1412    }
1413
1414    fn text(&self) -> Cow<'_, str> {
1415        let range = self
1416            .span
1417            .as_ref()
1418            .and_then(Span::bounds)
1419            .map_or_else(|| self.node.byte_range(), |(start, end)| start..end);
1420        String::from_utf8_lossy(&self.source[range])
1421    }
1422
1423    fn is_extra(&self) -> bool {
1424        self.node.is_extra()
1425    }
1426}
1427
1428impl Spanned for TreeSitterNode<'_, '_> {
1429    fn try_span(&self) -> Option<Span> {
1430        self.span.clone()
1431    }
1432}