summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2024-05-29 16:32:20 +0200
committerGitHub <noreply@github.com>2024-05-29 14:32:20 +0000
commit54604ccb6b96576c0495db48bd6a450dc69bc90b (patch)
tree374f74f647019dccec4c89a280c902e7bf1fdd52
parente6739ecc2f78f023b7b6b1729983af30f657e6dd (diff)
Fix `Default` impls for AST nodes (#4288)
-rw-r--r--crates/typst-ide/src/tooltip.rs38
-rw-r--r--crates/typst-syntax/src/ast.rs22
-rw-r--r--crates/typst-syntax/src/node.rs28
3 files changed, 67 insertions, 21 deletions
diff --git a/crates/typst-ide/src/tooltip.rs b/crates/typst-ide/src/tooltip.rs
index 3ecc4d8f..4864a266 100644
--- a/crates/typst-ide/src/tooltip.rs
+++ b/crates/typst-ide/src/tooltip.rs
@@ -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()"));
+ }
+}
diff --git a/crates/typst-syntax/src/ast.rs b/crates/typst-syntax/src/ast.rs
index a434e39a..01e0944d 100644
--- a/crates/typst-syntax/src/ast.rs
+++ b/crates/typst-syntax/src/ast.rs
@@ -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());
+ }
+}
diff --git a/crates/typst-syntax/src/node.rs b/crates/typst-syntax/src/node.rs
index b9efde6e..8e623d51 100644
--- a/crates/typst-syntax/src/node.rs
+++ b/crates/typst-syntax/src/node.rs
@@ -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())
}
}