1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
//! A generic library for lossless syntax trees.
//! See `examples/s_expressions.rs` for a tutorial.
#![forbid(
    missing_debug_implementations,
    unconditional_recursion,
    future_incompatible,
    // missing_docs
)]
#![deny(unsafe_code)]

#[allow(unsafe_code)]
mod swap_cell;
mod green;
#[allow(unsafe_code)]
mod imp;
mod syntax_token;
mod syntax_node;
mod syntax_element;
mod algo;

use std::fmt;
use crate::{green::GreenIndex, imp::SyntaxIndex};

// Reexport types for working with strings.
// We might be too opinionated about these,
// as a custom interner might work better,
// but `SmolStr` is a pretty good default.
pub use smol_str::SmolStr;
pub use text_unit::{TextRange, TextUnit};

pub use crate::{
    green::{GreenNode, GreenToken, GreenElement, GreenNodeBuilder},
    imp::SyntaxNode,
    syntax_token::SyntaxToken,
    syntax_element::SyntaxElement,
    algo::{WalkEvent, TokenAtOffset, SyntaxNodeChildren, SyntaxElementChildren},
};

/// `Types` customizes data, stored in the
/// syntax tree. All types in this crate are
/// parametrized over `T: Types`.
pub trait Types: Send + Sync + 'static {
    /// `Kind` is stored in each node and designates
    /// it's class. Typically it is a fieldless enum.
    type Kind: fmt::Debug + Copy + Eq + Send + Sync;
    /// `RootData` is stored in the root of the syntax trees.
    /// It can be just `()`, but you can use it to store,
    /// for example, syntax errors.
    type RootData: fmt::Debug + Send + Sync;
}

pub use crate::imp::{TransparentNewType, TreeArc};

// NB: borrow requires that Eq & Hash for `Owned` are consistent with thouse for
// `Borrowed`. This is true for `TreeArc`, but for a slightly peculiar reason:
// it forces "identity" (comparisons of pointers) semantics on the contents.
impl<T, N> std::borrow::Borrow<N> for TreeArc<T, N>
where
    T: Types,
    N: TransparentNewType<Repr = SyntaxNode<T>>,
{
    fn borrow(&self) -> &N {
        &*self
    }
}

impl<T, N> fmt::Debug for TreeArc<T, N>
where
    T: Types,
    N: TransparentNewType<Repr = SyntaxNode<T>> + fmt::Debug,
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let inner: &N = &*self;
        fmt::Debug::fmt(inner, fmt)
    }
}

// FIXME: replace with successors once it is stable
fn generate<'a, T: 'a, F: Fn(&T) -> Option<T> + 'a>(
    seed: Option<T>,
    step: F,
) -> impl Iterator<Item = T> + 'a {
    std::iter::repeat(()).scan(seed, move |state, ()| {
        state.take().map(|curr| {
            *state = step(&curr);
            curr
        })
    })
}

#[cfg(test)]
mod tests {
    use super::*;

    #[derive(Clone, Copy)]
    enum SillyTypes {}
    impl Types for SillyTypes {
        type Kind = u16;
        type RootData = ();
    }

    #[test]
    fn assert_send_sync() {
        fn f<T: Send + Sync>() {}
        f::<GreenNode<SillyTypes>>();
        f::<SyntaxNode<SillyTypes>>();
        f::<TreeArc<SillyTypes, SyntaxNode<SillyTypes>>>();
    }

    #[test]
    fn test_size_of() {
        use std::mem::size_of;

        eprintln!("GreenNode    {}", size_of::<GreenNode<SillyTypes>>());
        eprintln!("GreenToken   {}", size_of::<GreenToken<SillyTypes>>());
        eprintln!("GreenElement {}", size_of::<GreenElement<SillyTypes>>());
        eprintln!();
        eprintln!("SyntaxNode    {}", size_of::<SyntaxNode<SillyTypes>>());
        eprintln!("SyntaxToken   {}", size_of::<SyntaxToken<SillyTypes>>());
        eprintln!("SyntaxElement {}", size_of::<SyntaxElement<SillyTypes>>());
    }
}