Skip to content

Commit 6b451aa

Browse files
feat(rust): replace parse_with with parse_with_options
Co-Authored-By: Jamee Kim <[email protected]>
1 parent a50e3d9 commit 6b451aa

File tree

2 files changed

+67
-6
lines changed

2 files changed

+67
-6
lines changed

bindings/rust/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ mod tests {
6969

7070
#[test]
7171
fn can_load_block_grammar() {
72+
tree_sitter::ParseOptions
7273
let mut parser = tree_sitter::Parser::new();
7374
parser
7475
.set_language(&LANGUAGE.into())

bindings/rust/parser.rs

Lines changed: 66 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
use std::collections::HashMap;
22
use std::num::NonZeroU16;
33

4-
use tree_sitter::{InputEdit, Language, Node, Parser, Point, Range, Tree, TreeCursor};
4+
use tree_sitter::{
5+
InputEdit, Language, Node, ParseOptions, Parser, Point, Range, Tree, TreeCursor,
6+
};
57

68
use crate::{INLINE_LANGUAGE, LANGUAGE};
79

@@ -14,9 +16,17 @@ pub struct MarkdownParser {
1416
inline_language: Language,
1517
}
1618

19+
/// The options used while parsing a [`MarkdownTree`].
20+
///
21+
/// This abstracts away the double block / inline structure of [`MarkdownParser`].
22+
pub struct MarkdownParseOptions<'a> {
23+
block_options: Option<ParseOptions<'a>>,
24+
inline_options: Option<ParseOptions<'a>>,
25+
}
26+
1727
/// A stateful object for walking a [`MarkdownTree`] efficiently.
1828
///
19-
/// This exposes the same methdos as [`TreeCursor`], but abstracts away the
29+
/// This exposes the same methods as [`TreeCursor`], but abstracts away the
2030
/// double block / inline structure of [`MarkdownTree`].
2131
pub struct MarkdownCursor<'a> {
2232
markdown_tree: &'a MarkdownTree,
@@ -244,6 +254,16 @@ impl Default for MarkdownParser {
244254
}
245255

246256
impl MarkdownParser {
257+
/// Parse a slice of UTF8 text.
258+
#[deprecated(since = "0.5.0", note = "Prefer `parse_with_options` instead")]
259+
pub fn parse_with<T: AsRef<[u8]>, F: FnMut(usize, Point) -> T>(
260+
&mut self,
261+
callback: &mut F,
262+
old_tree: Option<&MarkdownTree>,
263+
) -> Option<MarkdownTree> {
264+
self.parse_with_options(callback, old_tree, MarkdownParseOptions::default())
265+
}
266+
247267
/// Parse a slice of UTF8 text.
248268
///
249269
/// # Arguments:
@@ -252,14 +272,17 @@ impl MarkdownParser {
252272
/// If the text of the document has changed since `old_tree` was
253273
/// created, then you must edit `old_tree` to match the new text using
254274
/// [MarkdownTree::edit].
275+
/// * `options` The [options][MarkdownParseOptions] used for parsing.
276+
/// Use `MarkdownParseOptions::default()` if you don't need to pass any options.
255277
///
256278
/// Returns a [MarkdownTree] if parsing succeeded, or `None` if:
257279
/// * The timeout set with [tree_sitter::Parser::set_timeout_micros] expired
258280
/// * The cancellation flag set with [tree_sitter::Parser::set_cancellation_flag] was flipped
259-
pub fn parse_with<T: AsRef<[u8]>, F: FnMut(usize, Point) -> T>(
281+
pub fn parse_with_options<T: AsRef<[u8]>, F: FnMut(usize, Point) -> T>(
260282
&mut self,
261283
callback: &mut F,
262284
old_tree: Option<&MarkdownTree>,
285+
mut options: MarkdownParseOptions<'_>,
263286
) -> Option<MarkdownTree> {
264287
let MarkdownParser {
265288
parser,
@@ -272,7 +295,11 @@ impl MarkdownParser {
272295
parser
273296
.set_language(block_language)
274297
.expect("Could not load block grammar");
275-
let block_tree = parser.parse_with(callback, old_tree.map(|tree| &tree.block_tree))?;
298+
let block_tree = parser.parse_with_options(
299+
callback,
300+
old_tree.map(|tree| &tree.block_tree),
301+
options.block_options,
302+
)?;
276303
let (mut inline_trees, mut inline_indices) = if let Some(old_tree) = old_tree {
277304
let len = old_tree.inline_trees.len();
278305
(Vec::with_capacity(len), HashMap::with_capacity(len))
@@ -322,9 +349,10 @@ impl MarkdownParser {
322349
}
323350
ranges.push(range);
324351
parser.set_included_ranges(&ranges).ok()?;
325-
let inline_tree = parser.parse_with(
352+
let inline_tree = parser.parse_with_options(
326353
callback,
327354
old_tree.and_then(|old_tree| old_tree.inline_trees.get(i)),
355+
options.inline_options.as_mut().map(clone_parse_options),
328356
)?;
329357
inline_trees.push(inline_tree);
330358
inline_indices.insert(node.id(), i);
@@ -353,7 +381,39 @@ impl MarkdownParser {
353381
/// * The timeout set with [tree_sitter::Parser::set_timeout_micros] expired
354382
/// * The cancellation flag set with [tree_sitter::Parser::set_cancellation_flag] was flipped
355383
pub fn parse(&mut self, text: &[u8], old_tree: Option<&MarkdownTree>) -> Option<MarkdownTree> {
356-
self.parse_with(&mut |byte, _| &text[byte..], old_tree)
384+
self.parse_with_options(
385+
&mut |byte, _| &text[byte..],
386+
old_tree,
387+
MarkdownParseOptions::default(),
388+
)
389+
}
390+
}
391+
392+
impl Default for MarkdownParseOptions<'_> {
393+
fn default() -> Self {
394+
MarkdownParseOptions {
395+
block_options: None,
396+
inline_options: None,
397+
}
398+
}
399+
}
400+
401+
/// Creates a new [`ParseOptions`] that borrows all values while not consuming the original.
402+
fn clone_parse_options<'a>(options: &'a mut ParseOptions<'_>) -> ParseOptions<'a> {
403+
// This is needed because we need to pass in `ParseOptions` multiple times for the inline
404+
// language. Since the struct contains `&mut`, it cannot implement `Clone` or `Copy`. We get
405+
// around this by manually specifying that we mean to temporarily borrow all fields.
406+
// This is obviously somewhat hacky. If `tree-sitter` adds fields to `ParseOptions` that are
407+
// not `&mut`, this method might become implossible. Given this situation, the "proper" way to
408+
// solve this problem seems to be changing the param type to `&mut ParseOptions` for
409+
// `Parser::parse_with_options()` in upstream `tree-sitter` crate.
410+
let ParseOptions { progress_callback } = options;
411+
ParseOptions {
412+
// Cannot do `progress_callback.as_mut().map(..)` due to lifetime complications.
413+
progress_callback: match progress_callback {
414+
Some(cb) => Some(*cb),
415+
None => None,
416+
},
357417
}
358418
}
359419

0 commit comments

Comments
 (0)