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:
ParaN3xus 2024-09-08 22:10:01 +08:00 committed by GitHub
parent ffa12bc2c9
commit ce107efc7e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
23 changed files with 86 additions and 28 deletions

View file

@ -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 {

View file

@ -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)))
}

View file

@ -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));

View file

@ -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(..)));

View file

@ -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,

View file

@ -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;

View file

@ -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:?}");

View file

@ -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() {

View file

@ -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)?;

View file

@ -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;
}

View file

@ -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,

View file

@ -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));
}

View file

@ -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,

View file

@ -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

View file

@ -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',

View file

@ -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,

View file

@ -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,

View file

@ -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;
}

View file

@ -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;
}

View file

@ -1 +1,2 @@
pub mod syntax;
pub mod utils;

View 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)
}
}

View file

@ -1 +1,2 @@
pub mod syntax;
pub mod utils;

View 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)
}
}