Fix Default impls for AST nodes (#4288)

This commit is contained in:
Laurenz 2024-05-29 16:32:20 +02:00 committed by GitHub
parent e6739ecc2f
commit 54604ccb6b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 67 additions and 21 deletions

View File

@ -38,7 +38,7 @@ pub fn tooltip(
}
/// A hover tooltip.
#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq)]
pub enum Tooltip {
/// A string of text.
Text(EcoString),
@ -250,3 +250,39 @@ fn font_tooltip(world: &dyn World, leaf: &LinkedNode) -> Option<Tooltip> {
None
}
#[cfg(test)]
mod tests {
use typst::eval::Tracer;
use typst::syntax::Side;
use super::{tooltip, Tooltip};
use crate::tests::TestWorld;
fn text(text: &str) -> Option<Tooltip> {
Some(Tooltip::Text(text.into()))
}
fn code(code: &str) -> Option<Tooltip> {
Some(Tooltip::Code(code.into()))
}
#[track_caller]
fn test(text: &str, cursor: usize, side: Side, expected: Option<Tooltip>) {
let world = TestWorld::new(text);
let doc = typst::compile(&world, &mut Tracer::new()).ok();
assert_eq!(tooltip(&world, doc.as_ref(), &world.main, cursor, side), expected);
}
#[test]
fn test_tooltip() {
test("#let x = 1 + 2", 5, Side::After, code("3"));
test("#let x = 1 + 2", 6, Side::Before, code("3"));
test("#let f(x) = x + y", 11, Side::Before, text("This closure captures `y`."));
}
#[test]
fn test_empty_contextual() {
test("#{context}", 10, Side::Before, code("context()"));
}
}

View File

@ -24,12 +24,6 @@ pub trait AstNode<'a>: Sized {
}
}
/// A static syntax node used as a fallback value. This is returned instead of
/// panicking when the syntactical structure isn't valid. In a normal
/// compilation, evaluation isn't attempted on a broken file, but for IDE
/// functionality, it is.
static ARBITRARY: SyntaxNode = SyntaxNode::arbitrary();
macro_rules! node {
($(#[$attr:meta])* $name:ident) => {
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
@ -56,7 +50,9 @@ macro_rules! node {
impl Default for $name<'_> {
#[inline]
fn default() -> Self {
Self(&ARBITRARY)
static PLACEHOLDER: SyntaxNode
= SyntaxNode::placeholder(SyntaxKind::$name);
Self(&PLACEHOLDER)
}
}
};
@ -392,7 +388,7 @@ impl Expr<'_> {
impl Default for Expr<'_> {
fn default() -> Self {
Expr::Space(Space::default())
Expr::None(None::default())
}
}
@ -2135,3 +2131,13 @@ impl<'a> FuncReturn<'a> {
self.0.cast_last_match()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_expr_default() {
assert!(Expr::default().to_untyped().cast::<Expr>().is_some());
}
}

View File

@ -39,6 +39,21 @@ impl SyntaxNode {
Self(Repr::Error(Arc::new(ErrorNode::new(message, text))))
}
/// Create a dummy node of the given kind.
///
/// Panics if `kind` is `SyntaxKind::Error`.
#[track_caller]
pub const fn placeholder(kind: SyntaxKind) -> Self {
if matches!(kind, SyntaxKind::Error) {
panic!("cannot create error placeholder");
}
Self(Repr::Leaf(LeafNode {
kind,
text: EcoString::new(),
span: Span::detached(),
}))
}
/// The type of the node.
pub fn kind(&self) -> SyntaxKind {
match &self.0 {
@ -297,17 +312,6 @@ impl SyntaxNode {
Repr::Error(node) => node.error.span.number() + 1,
}
}
/// An arbitrary node just for filling a slot in memory.
///
/// In contrast to `default()`, this is a const fn.
pub(super) const fn arbitrary() -> Self {
Self(Repr::Leaf(LeafNode {
kind: SyntaxKind::End,
text: EcoString::new(),
span: Span::detached(),
}))
}
}
impl Debug for SyntaxNode {
@ -322,7 +326,7 @@ impl Debug for SyntaxNode {
impl Default for SyntaxNode {
fn default() -> Self {
Self::arbitrary()
Self::leaf(SyntaxKind::End, EcoString::new())
}
}