cstree/syntax/mod.rs
1//! Implementation of the outer, "red" tree.
2//!
3//! Inner [`SyntaxNode`]s represent only structural information, but can hold additional, user-defined data.
4//! Leaf [`SyntaxToken`]s represent individual pieces of source text.
5//! Use [`SyntaxNode::new_root`] and [`SyntaxNode::new_root_with_resolver`] to construct a syntax
6//! tree on top of a green tree.
7
8mod element;
9pub use element::{SyntaxElement, SyntaxElementRef};
10mod node;
11pub use node::SyntaxNode;
12mod token;
13pub use token::SyntaxToken;
14mod resolved;
15pub use resolved::{ResolvedElement, ResolvedElementRef, ResolvedNode, ResolvedToken};
16mod iter;
17pub use iter::{SyntaxElementChildren, SyntaxNodeChildren};
18
19mod text;
20pub use text::SyntaxText;
21
22// A note on `#[inline]` usage in this module:
23// In `rowan`, there are two layers of `SyntaxXY`s: the `cursor` layer and the `api` layer.
24// The `cursor` layer handles all of the actual methods on the tree, while the `api` layer is
25// generic over the `Syntax` of the tree and otherwise forwards its implementation to the `cursor`
26// layer.
27// Here, we have unified the `cursor` and the `api` layer into the `syntax` layer.
28// This means that all of our types here are generic over a `Syntax`, including the
29// implementations which, in `rowan`, are part of the `cursor` layer.
30// Very apparently, this makes the compiler less willing to inline. Almost every "regular use"
31// method in this file has some kind of `#[inline]` annotation to counteract that. This is _NOT_
32// just for fun, not inlining decreases tree traversal speed by approx. 50% at the time of writing
33// this.
34//
35// - DQ 01/2021
36
37#[cfg(test)]
38mod tests {
39 use super::*;
40 use crate::testing::*;
41
42 #[test]
43 #[cfg_attr(miri, ignore)]
44 fn assert_send_sync() {
45 fn f<T: Send + Sync>() {}
46 f::<SyntaxNode<TestSyntaxKind>>();
47 f::<SyntaxToken<TestSyntaxKind>>();
48 f::<SyntaxElement<TestSyntaxKind>>();
49 f::<SyntaxElementRef<'static, TestSyntaxKind>>();
50
51 f::<ResolvedNode<TestSyntaxKind>>();
52 f::<ResolvedToken<TestSyntaxKind>>();
53 f::<ResolvedElement<TestSyntaxKind>>();
54 f::<ResolvedElementRef<'static, TestSyntaxKind>>();
55 }
56
57 #[test]
58 #[cfg_attr(miri, ignore)]
59 #[rustfmt::skip]
60 fn assert_syntax_sizes() {
61 use std::mem::size_of;
62
63 assert_eq!(size_of::<SyntaxNode<TestSyntaxKind>>(), size_of::<*const u8>());
64 // verify niche opt of `NonNull`
65 assert_eq!(size_of::<Option<SyntaxNode<TestSyntaxKind>>>(), size_of::<*const u8>());
66 // parent + child index + text len
67 assert_eq!(size_of::<SyntaxToken<TestSyntaxKind>>(), size_of::<SyntaxNode<TestSyntaxKind>>() + size_of::<u32>() * 2);
68 }
69}