mirror of
https://github.com/Myriad-Dreamin/tinymist.git
synced 2025-07-24 13:13:43 +00:00
refactor: add compatibility for typst_syntax::LinkedNode.leaf_at
(#582)
* refactor: add compatibility for `typst_syntax::LinkedNode.leaf_at` * feat: `LinkedNodeExt` trait with `leaf_at_compat`
This commit is contained in:
parent
ffa12bc2c9
commit
ce107efc7e
23 changed files with 86 additions and 28 deletions
|
@ -97,6 +97,7 @@ mod post_type_check_tests {
|
|||
|
||||
use insta::with_settings;
|
||||
use typst::syntax::LinkedNode;
|
||||
use typst_shim::syntax::LinkedNodeExt;
|
||||
|
||||
use crate::analysis::ty;
|
||||
use crate::tests::*;
|
||||
|
@ -110,7 +111,7 @@ mod post_type_check_tests {
|
|||
.to_typst_pos(find_test_position(&source), &source)
|
||||
.unwrap();
|
||||
let root = LinkedNode::new(source.root());
|
||||
let node = root.leaf_at(pos + 1).unwrap();
|
||||
let node = root.leaf_at_compat(pos + 1).unwrap();
|
||||
let text = node.get().clone().into_text();
|
||||
|
||||
let result = ty::type_check(ctx, source.clone());
|
||||
|
@ -132,6 +133,7 @@ mod type_describe_tests {
|
|||
|
||||
use insta::with_settings;
|
||||
use typst::syntax::LinkedNode;
|
||||
use typst_shim::syntax::LinkedNodeExt;
|
||||
|
||||
use crate::analysis::ty;
|
||||
use crate::tests::*;
|
||||
|
@ -145,7 +147,7 @@ mod type_describe_tests {
|
|||
.to_typst_pos(find_test_position(&source), &source)
|
||||
.unwrap();
|
||||
let root = LinkedNode::new(source.root());
|
||||
let node = root.leaf_at(pos + 1).unwrap();
|
||||
let node = root.leaf_at_compat(pos + 1).unwrap();
|
||||
let text = node.get().clone().into_text();
|
||||
|
||||
let result = ty::type_check(ctx, source.clone());
|
||||
|
@ -220,6 +222,7 @@ mod module_tests {
|
|||
mod matcher_tests {
|
||||
|
||||
use typst::syntax::LinkedNode;
|
||||
use typst_shim::syntax::LinkedNodeExt;
|
||||
|
||||
use crate::{syntax::get_def_target, tests::*};
|
||||
|
||||
|
@ -233,7 +236,7 @@ mod matcher_tests {
|
|||
.unwrap();
|
||||
|
||||
let root = LinkedNode::new(source.root());
|
||||
let node = root.leaf_at(pos).unwrap();
|
||||
let node = root.leaf_at_compat(pos).unwrap();
|
||||
|
||||
let result = get_def_target(node).map(|e| format!("{:?}", e.node().range()));
|
||||
let result = result.as_deref().unwrap_or("<nil>");
|
||||
|
@ -382,6 +385,7 @@ mod signature_tests {
|
|||
|
||||
use typst::foundations::Repr;
|
||||
use typst::syntax::LinkedNode;
|
||||
use typst_shim::syntax::LinkedNodeExt;
|
||||
|
||||
use crate::analysis::{analyze_signature, Signature, SignatureTarget};
|
||||
use crate::syntax::get_deref_target;
|
||||
|
@ -397,7 +401,7 @@ mod signature_tests {
|
|||
.unwrap();
|
||||
|
||||
let root = LinkedNode::new(source.root());
|
||||
let callee_node = root.leaf_at(pos).unwrap();
|
||||
let callee_node = root.leaf_at_compat(pos).unwrap();
|
||||
let callee_node = get_deref_target(callee_node, pos).unwrap();
|
||||
let callee_node = callee_node.node();
|
||||
|
||||
|
@ -463,6 +467,7 @@ mod call_info_tests {
|
|||
use core::fmt;
|
||||
|
||||
use typst::syntax::{LinkedNode, SyntaxKind};
|
||||
use typst_shim::syntax::LinkedNodeExt;
|
||||
|
||||
use crate::analysis::analyze_call;
|
||||
use crate::tests::*;
|
||||
|
@ -479,7 +484,7 @@ mod call_info_tests {
|
|||
.unwrap();
|
||||
|
||||
let root = LinkedNode::new(source.root());
|
||||
let mut call_node = root.leaf_at(pos + 1).unwrap();
|
||||
let mut call_node = root.leaf_at_compat(pos + 1).unwrap();
|
||||
|
||||
while let Some(parent) = call_node.parent() {
|
||||
if call_node.kind() == SyntaxKind::FuncCall {
|
||||
|
|
|
@ -23,6 +23,7 @@ use typst::{
|
|||
};
|
||||
use typst::{foundations::Value, model::Document, syntax::ast, text::Font};
|
||||
use typst::{layout::Position, syntax::FileId as TypstFileId};
|
||||
use typst_shim::syntax::LinkedNodeExt;
|
||||
|
||||
use super::{
|
||||
analyze_bib, analyze_expr_, analyze_import_, post_type_check, BibInfo, DefUseInfo,
|
||||
|
@ -367,7 +368,7 @@ impl<'w> AnalysisContext<'w> {
|
|||
let offset = self.to_typst_pos(position, source)?;
|
||||
let cursor = ceil_char_boundary(source.text(), offset + shift);
|
||||
|
||||
let node = LinkedNode::new(source.root()).leaf_at(cursor)?;
|
||||
let node = LinkedNode::new(source.root()).leaf_at_compat(cursor)?;
|
||||
Some((cursor, get_deref_target(node, cursor)))
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ use typst::{
|
|||
syntax::{LinkedNode, SyntaxKind},
|
||||
World,
|
||||
};
|
||||
use typst_shim::syntax::LinkedNodeExt;
|
||||
|
||||
use crate::{analysis::analyze_import_, syntax::resolve_id_by_path};
|
||||
|
||||
|
@ -91,7 +92,7 @@ impl<'a, 'w> ImportCollector<'a, 'w> {
|
|||
LexicalKind::Mod(LexicalModKind::Module(p)) => {
|
||||
let id = match p {
|
||||
ModSrc::Expr(exp) => {
|
||||
let exp = find_import_expr(self.root.leaf_at(exp.range.end));
|
||||
let exp = find_import_expr(self.root.leaf_at_compat(exp.range.end));
|
||||
let val = exp
|
||||
.as_ref()
|
||||
.and_then(|exp| analyze_import_(self.ctx.deref(), exp));
|
||||
|
|
|
@ -8,6 +8,7 @@ use typst::foundations::{IntoValue, Label, Selector, Type};
|
|||
use typst::model::BibliographyElem;
|
||||
use typst::syntax::FileId as TypstFileId;
|
||||
use typst::{foundations::Value, syntax::Span};
|
||||
use typst_shim::syntax::LinkedNodeExt;
|
||||
|
||||
use super::{prelude::*, BibInfo};
|
||||
use crate::{
|
||||
|
@ -208,7 +209,7 @@ pub fn find_definition(
|
|||
LexicalKind::Var(LexicalVarKind::Function) => {
|
||||
let def_source = ctx.source_by_id(def_fid).ok()?;
|
||||
let root = LinkedNode::new(def_source.root());
|
||||
let def_name = root.leaf_at(def.range.start + 1)?;
|
||||
let def_name = root.leaf_at_compat(def.range.start + 1)?;
|
||||
log::info!("def_name for function: {def_name:?}", def_name = def_name);
|
||||
let values = ctx.analyze_expr(&def_name);
|
||||
let func = values.into_iter().find(|v| matches!(v.0, Value::Func(..)));
|
||||
|
|
|
@ -13,6 +13,7 @@ use typst::{
|
|||
LinkedNode, Span, SyntaxKind,
|
||||
},
|
||||
};
|
||||
use typst_shim::syntax::LinkedNodeExt;
|
||||
use typst_shim::utils::LazyHash;
|
||||
|
||||
use crate::adt::interner::Interned;
|
||||
|
@ -260,7 +261,7 @@ pub(crate) fn analyze_signature(
|
|||
// };
|
||||
|
||||
// let root = LinkedNode::new(def_source.root());
|
||||
// let def_node = root.leaf_at(def_at.1.start + 1)?;
|
||||
// let def_node = root.leaf_at_compat(def_at.1.start + 1)?;
|
||||
// let def_node = get_def_target(def_node)?;
|
||||
// let def_node = match def_node {
|
||||
// DefTarget::Let(node) => node,
|
||||
|
@ -304,7 +305,7 @@ fn resolve_callee_v2(
|
|||
let _t = ctx.type_check(source)?;
|
||||
|
||||
let root = LinkedNode::new(def_source.root());
|
||||
let def_node = root.leaf_at(def_at.1.start + 1)?;
|
||||
let def_node = root.leaf_at_compat(def_at.1.start + 1)?;
|
||||
let def_node = get_def_target(def_node)?;
|
||||
let _def_node = match def_node {
|
||||
DefTarget::Let(node) => node,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use lsp_types::TextEdit;
|
||||
use once_cell::sync::{Lazy, OnceCell};
|
||||
use regex::Regex;
|
||||
use typst_shim::syntax::LinkedNodeExt;
|
||||
|
||||
use crate::{prelude::*, SemanticRequest};
|
||||
|
||||
|
@ -269,7 +270,7 @@ impl<'a, 'w> CodeActionWorker<'a, 'w> {
|
|||
}
|
||||
|
||||
fn work(&mut self, root: LinkedNode, cursor: usize) -> Option<()> {
|
||||
let node = root.leaf_at(cursor)?;
|
||||
let node = root.leaf_at_compat(cursor)?;
|
||||
let mut node = &node;
|
||||
|
||||
let mut heading_resolved = false;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use typst_shim::syntax::LinkedNodeExt;
|
||||
|
||||
use crate::{
|
||||
prelude::*,
|
||||
|
@ -75,7 +76,7 @@ impl InteractCodeContextRequest {
|
|||
|
||||
// Get mode
|
||||
let root = LinkedNode::new(source.root());
|
||||
let leaf = root.leaf_at(pos);
|
||||
let leaf = root.leaf_at_compat(pos);
|
||||
let mut leaf = leaf.as_ref();
|
||||
Some(loop {
|
||||
log::debug!("leaf for context: {leaf:?}");
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use typst_shim::syntax::LinkedNodeExt;
|
||||
|
||||
use crate::{prelude::*, SemanticRequest};
|
||||
|
||||
/// The [`textDocument/documentHighlight`] request
|
||||
|
@ -19,7 +21,7 @@ impl SemanticRequest for DocumentHighlightRequest {
|
|||
let cursor = ctx.to_typst_pos(self.position, &source)?;
|
||||
|
||||
let root = LinkedNode::new(source.root());
|
||||
let mut node = &root.leaf_at(cursor)?;
|
||||
let mut node = &root.leaf_at_compat(cursor)?;
|
||||
|
||||
loop {
|
||||
match node.kind() {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use core::fmt;
|
||||
|
||||
use typst_shim::syntax::LinkedNodeExt;
|
||||
|
||||
use crate::{
|
||||
analysis::{analyze_dyn_signature, find_definition, DefinitionLink, Signature},
|
||||
jump_from_cursor,
|
||||
|
@ -48,7 +50,7 @@ impl StatefulRequest for HoverRequest {
|
|||
))
|
||||
})?;
|
||||
|
||||
let ast_node = LinkedNode::new(source.root()).leaf_at(cursor)?;
|
||||
let ast_node = LinkedNode::new(source.root()).leaf_at_compat(cursor)?;
|
||||
let range = ctx.to_lsp_range(ast_node.range(), &source);
|
||||
|
||||
// Neovim shows ugly hover if the hover content is in array, so we join them
|
||||
|
@ -120,7 +122,7 @@ fn star_tooltip(
|
|||
source: &Source,
|
||||
cursor: usize,
|
||||
) -> Option<HoverContents> {
|
||||
let leaf = LinkedNode::new(source.root()).leaf_at(cursor)?;
|
||||
let leaf = LinkedNode::new(source.root()).leaf_at_compat(cursor)?;
|
||||
|
||||
if !matches!(leaf.kind(), SyntaxKind::Star) {
|
||||
return None;
|
||||
|
@ -174,7 +176,7 @@ fn def_tooltip(
|
|||
document: Option<&VersionedDocument>,
|
||||
cursor: usize,
|
||||
) -> Option<LspHoverContents> {
|
||||
let leaf = LinkedNode::new(source.root()).leaf_at(cursor)?;
|
||||
let leaf = LinkedNode::new(source.root()).leaf_at_compat(cursor)?;
|
||||
|
||||
let deref_target = get_deref_target(leaf.clone(), cursor)?;
|
||||
|
||||
|
|
|
@ -9,10 +9,11 @@ use typst::{
|
|||
layout::{Frame, FrameItem, Point, Position},
|
||||
syntax::{LinkedNode, Source, Span, SyntaxKind},
|
||||
};
|
||||
use typst_shim::syntax::LinkedNodeExt;
|
||||
|
||||
/// Find the output location in the document for a cursor position.
|
||||
pub fn jump_from_cursor(document: &Document, source: &Source, cursor: usize) -> Option<Position> {
|
||||
let node = LinkedNode::new(source.root()).leaf_at(cursor)?;
|
||||
let node = LinkedNode::new(source.root()).leaf_at_compat(cursor)?;
|
||||
if node.kind() != SyntaxKind::Text {
|
||||
return None;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
//! <https://github.com/rust-lang/rust-analyzer/blob/master/docs/dev/lsp-extensions.md#on-enter>
|
||||
|
||||
use typst_shim::syntax::LinkedNodeExt;
|
||||
|
||||
use crate::{prelude::*, SyntaxRequest};
|
||||
|
||||
/// The [`experimental/onEnter`] request is sent from client to server to handle
|
||||
|
@ -32,7 +34,7 @@ impl SyntaxRequest for OnEnterRequest {
|
|||
) -> Option<Self::Response> {
|
||||
let root = LinkedNode::new(source.root());
|
||||
let cursor = lsp_to_typst::position(self.position, position_encoding, source)?;
|
||||
let leaf = root.leaf_at(cursor)?;
|
||||
let leaf = root.leaf_at_compat(cursor)?;
|
||||
|
||||
let worker = OnEnterWorker {
|
||||
source,
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use typst_shim::syntax::LinkedNodeExt;
|
||||
|
||||
use crate::{prelude::*, SyntaxRequest};
|
||||
|
||||
/// The [`textDocument/selectionRange`] request is sent from the client to the
|
||||
|
@ -34,7 +36,7 @@ impl SyntaxRequest for SelectionRangeRequest {
|
|||
for position in self.positions {
|
||||
let typst_offset = lsp_to_typst::position(position, position_encoding, source)?;
|
||||
let tree = LinkedNode::new(source.root());
|
||||
let leaf = tree.leaf_at(typst_offset + 1)?;
|
||||
let leaf = tree.leaf_at_compat(typst_offset + 1)?;
|
||||
ranges.push(range_for_node(source, position_encoding, &leaf));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use once_cell::sync::OnceCell;
|
||||
use typst_shim::syntax::LinkedNodeExt;
|
||||
|
||||
use crate::{
|
||||
adt::interner::Interned,
|
||||
|
@ -27,7 +28,7 @@ impl SemanticRequest for SignatureHelpRequest {
|
|||
let source = ctx.source_by_path(&self.path).ok()?;
|
||||
let cursor = ctx.to_typst_pos(self.position, &source)? + 1;
|
||||
|
||||
let ast_node = LinkedNode::new(source.root()).leaf_at(cursor)?;
|
||||
let ast_node = LinkedNode::new(source.root()).leaf_at_compat(cursor)?;
|
||||
let CheckTarget::Param {
|
||||
callee,
|
||||
target,
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use std::ops::Range;
|
||||
|
||||
use typst_shim::syntax::LinkedNodeExt;
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::syntax::get_def_target;
|
||||
|
||||
|
@ -89,7 +91,7 @@ pub fn find_docs_before(src: &Source, cursor: usize) -> Option<String> {
|
|||
log::debug!("finding docs at: {id:?}, {cursor}", id = src.id());
|
||||
|
||||
let root = LinkedNode::new(src.root());
|
||||
let leaf = root.leaf_at(cursor)?;
|
||||
let leaf = root.leaf_at_compat(cursor)?;
|
||||
let def_target = get_def_target(leaf.clone())?;
|
||||
log::debug!("found docs target: {:?}", def_target.node().kind());
|
||||
// todo: import node
|
||||
|
|
|
@ -590,6 +590,7 @@ mod tests {
|
|||
use super::*;
|
||||
use insta::assert_snapshot;
|
||||
use typst::syntax::{is_newline, Source};
|
||||
use typst_shim::syntax::LinkedNodeExt;
|
||||
|
||||
fn map_base(source: &str, mapper: impl Fn(&LinkedNode, usize) -> char) -> String {
|
||||
let source = Source::detached(source.to_owned());
|
||||
|
@ -617,7 +618,7 @@ mod tests {
|
|||
|
||||
fn map_deref(source: &str) -> String {
|
||||
map_base(source, |root, cursor| {
|
||||
let node = root.leaf_at(cursor);
|
||||
let node = root.leaf_at_compat(cursor);
|
||||
let kind = node.and_then(|node| get_deref_target(node, cursor));
|
||||
match kind {
|
||||
Some(DerefTarget::VarAccess(..)) => 'v',
|
||||
|
@ -634,7 +635,7 @@ mod tests {
|
|||
|
||||
fn map_check(source: &str) -> String {
|
||||
map_base(source, |root, cursor| {
|
||||
let node = root.leaf_at(cursor);
|
||||
let node = root.leaf_at_compat(cursor);
|
||||
let kind = node.and_then(|node| get_check_target(node));
|
||||
match kind {
|
||||
Some(CheckTarget::Param { .. }) => 'p',
|
||||
|
|
|
@ -24,6 +24,7 @@ pub use insta::assert_snapshot;
|
|||
pub use reflexo_typst::TypstSystemWorld;
|
||||
pub use serde::Serialize;
|
||||
pub use serde_json::json;
|
||||
use typst_shim::syntax::LinkedNodeExt;
|
||||
|
||||
use crate::{
|
||||
analysis::{Analysis, AnalysisResources},
|
||||
|
@ -245,7 +246,7 @@ pub fn find_test_position_(s: &Source, offset: usize) -> LspPosition {
|
|||
.unwrap();
|
||||
|
||||
let n = LinkedNode::new(s.root());
|
||||
let mut n = n.leaf_at(re + 1).unwrap();
|
||||
let mut n = n.leaf_at_compat(re + 1).unwrap();
|
||||
|
||||
let match_prev = match &m {
|
||||
MatchAny { prev } => *prev,
|
||||
|
|
|
@ -11,6 +11,7 @@ use typst::syntax::ast::AstNode;
|
|||
use typst::syntax::package::PackageSpec;
|
||||
use typst::syntax::{ast, is_id_continue, is_id_start, is_ident, LinkedNode, Source, SyntaxKind};
|
||||
use typst::text::RawElem;
|
||||
use typst_shim::syntax::LinkedNodeExt;
|
||||
use unscanny::Scanner;
|
||||
|
||||
use super::{plain_docs_sentence, summarize_font_family};
|
||||
|
@ -969,7 +970,7 @@ impl<'a, 'w> CompletionContext<'a, 'w> {
|
|||
) -> Option<Self> {
|
||||
let text = source.text();
|
||||
let root = LinkedNode::new(source.root());
|
||||
let leaf = root.leaf_at(cursor)?;
|
||||
let leaf = root.leaf_at_compat(cursor)?;
|
||||
Some(Self {
|
||||
ctx,
|
||||
document,
|
||||
|
|
|
@ -8,6 +8,7 @@ use typst::layout::Length;
|
|||
use typst::model::Document;
|
||||
use typst::syntax::{ast, LinkedNode, Source, SyntaxKind};
|
||||
use typst::World;
|
||||
use typst_shim::syntax::LinkedNodeExt;
|
||||
use typst_shim::utils::{round_2, Numeric};
|
||||
|
||||
use super::{plain_docs_sentence, summarize_font_family, truncated_repr};
|
||||
|
@ -24,7 +25,7 @@ pub fn tooltip_(
|
|||
source: &Source,
|
||||
cursor: usize,
|
||||
) -> Option<Tooltip> {
|
||||
let leaf = LinkedNode::new(source.root()).leaf_at(cursor)?;
|
||||
let leaf = LinkedNode::new(source.root()).leaf_at_compat(cursor)?;
|
||||
if leaf.kind().is_trivia() {
|
||||
return None;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ use typst_preview::{
|
|||
ControlPlaneTx, DocToSrcJumpInfo, EditorServer, Location, MemoryFiles, MemoryFilesShort,
|
||||
PreviewArgs, PreviewBuilder, PreviewMode, Previewer, SourceFileServer, WsMessage,
|
||||
};
|
||||
use typst_shim::syntax::LinkedNodeExt;
|
||||
|
||||
use crate::world::{LspCompilerFeat, LspWorld};
|
||||
use crate::*;
|
||||
|
@ -47,7 +48,7 @@ impl CompileHandler {
|
|||
let source = world.source(source_id).ok()?;
|
||||
let cursor = source.line_column_to_byte(loc.pos.line, loc.pos.column)?;
|
||||
|
||||
let node = LinkedNode::new(source.root()).leaf_at(cursor)?;
|
||||
let node = LinkedNode::new(source.root()).leaf_at_compat(cursor)?;
|
||||
if node.kind() != SyntaxKind::Text {
|
||||
return None;
|
||||
}
|
||||
|
@ -676,7 +677,7 @@ impl Notification for NotifDocumentOutline {
|
|||
|
||||
/// Find the output location in the document for a cursor position.
|
||||
fn jump_from_cursor(document: &TypstDocument, source: &Source, cursor: usize) -> Option<Position> {
|
||||
let node = LinkedNode::new(source.root()).leaf_at(cursor)?;
|
||||
let node = LinkedNode::new(source.root()).leaf_at_compat(cursor)?;
|
||||
if node.kind() != SyntaxKind::Text {
|
||||
return None;
|
||||
}
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
pub mod syntax;
|
||||
pub mod utils;
|
||||
|
|
14
crates/typst-shim/src/nightly/syntax.rs
Normal file
14
crates/typst-shim/src/nightly/syntax.rs
Normal file
|
@ -0,0 +1,14 @@
|
|||
//! Typst Syntax
|
||||
use typst::syntax::LinkedNode;
|
||||
use typst::syntax::Side;
|
||||
|
||||
/// The `LinkedNodeExt` trait is designed for compatibility between new and old versions of `typst`.
|
||||
pub trait LinkedNodeExt: Sized {
|
||||
fn leaf_at_compat(&self, cursor: usize) -> Option<Self>;
|
||||
}
|
||||
|
||||
impl LinkedNodeExt for LinkedNode {
|
||||
fn leaf_at_compat(&self, cursor: usize) -> Option<Self> {
|
||||
self.leaf_at(cursor, Side::Before)
|
||||
}
|
||||
}
|
|
@ -1 +1,2 @@
|
|||
pub mod syntax;
|
||||
pub mod utils;
|
||||
|
|
14
crates/typst-shim/src/stable/syntax.rs
Normal file
14
crates/typst-shim/src/stable/syntax.rs
Normal file
|
@ -0,0 +1,14 @@
|
|||
//! Typst Syntax
|
||||
use typst_syntax::LinkedNode;
|
||||
|
||||
/// The `LinkedNodeExt` trait is designed for compatibility between new and old versions of `typst`.
|
||||
pub trait LinkedNodeExt: Sized {
|
||||
/// Get the leaf at the specified byte offset.
|
||||
fn leaf_at_compat(&self, cursor: usize) -> Option<Self>;
|
||||
}
|
||||
|
||||
impl<'a> LinkedNodeExt for LinkedNode<'a> {
|
||||
fn leaf_at_compat(&self, cursor: usize) -> Option<Self> {
|
||||
self.leaf_at(cursor)
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue