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}