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
123
124
125
126
127
128
129
130
131
132
133
134
|
//! The syntax model.
use std::any::Any;
use std::fmt::Debug;
use async_trait::async_trait;
use crate::{Pass, Feedback};
use crate::layout::{LayoutContext, Commands, Command};
use super::span::{Spanned, SpanVec};
/// Represents a parsed piece of source that can be layouted and in the future
/// also be queried for information used for refactorings, autocomplete, etc.
#[async_trait(?Send)]
pub trait Model: Debug + ModelBounds {
/// Layout the model into a sequence of commands processed by a
/// [`ModelLayouter`](crate::layout::ModelLayouter).
async fn layout<'a>(&'a self, ctx: LayoutContext<'_>) -> Pass<Commands<'a>>;
}
/// A tree representation of source code.
#[derive(Debug, Default, Clone, PartialEq)]
pub struct SyntaxModel {
/// The syntactical elements making up this model.
pub nodes: SpanVec<Node>,
}
impl SyntaxModel {
/// Create an empty syntax model.
pub fn new() -> SyntaxModel {
SyntaxModel { nodes: vec![] }
}
/// Add a node to the model.
pub fn add(&mut self, node: Spanned<Node>) {
self.nodes.push(node);
}
}
#[async_trait(?Send)]
impl Model for SyntaxModel {
async fn layout<'a>(&'a self, _: LayoutContext<'_>) -> Pass<Commands<'a>> {
Pass::new(vec![Command::LayoutSyntaxModel(self)], Feedback::new())
}
}
/// A node in the [syntax model](SyntaxModel).
#[derive(Debug, Clone)]
pub enum Node {
/// Whitespace containing less than two newlines.
Space,
/// Whitespace with more than two newlines.
Parbreak,
/// A forced line break.
Linebreak,
/// Plain text.
Text(String),
/// Lines of raw text.
Raw(Vec<String>),
/// Italics were enabled / disabled.
ToggleItalic,
/// Bolder was enabled / disabled.
ToggleBolder,
/// A submodel, typically a function invocation.
Model(Box<dyn Model>),
}
impl PartialEq for Node {
fn eq(&self, other: &Node) -> bool {
use Node::*;
match (self, other) {
(Space, Space) => true,
(Parbreak, Parbreak) => true,
(Linebreak, Linebreak) => true,
(Text(a), Text(b)) => a == b,
(Raw(a), Raw(b)) => a == b,
(ToggleItalic, ToggleItalic) => true,
(ToggleBolder, ToggleBolder) => true,
(Model(a), Model(b)) => a == b,
_ => false,
}
}
}
impl dyn Model {
/// Downcast this model to a concrete type implementing [`Model`].
pub fn downcast<T>(&self) -> Option<&T> where T: Model + 'static {
self.as_any().downcast_ref::<T>()
}
}
impl PartialEq for dyn Model {
fn eq(&self, other: &dyn Model) -> bool {
self.bound_eq(other)
}
}
impl Clone for Box<dyn Model> {
fn clone(&self) -> Self {
self.bound_clone()
}
}
/// This trait describes bounds necessary for types implementing [`Model`]. It is
/// automatically implemented for all types that are [`Model`], [`PartialEq`],
/// [`Clone`] and `'static`.
///
/// It is necessary to make models comparable and clonable.
pub trait ModelBounds {
/// Convert into a `dyn Any`.
fn as_any(&self) -> &dyn Any;
/// Check for equality with another model.
fn bound_eq(&self, other: &dyn Model) -> bool;
/// Clone into a boxed model trait object.
fn bound_clone(&self) -> Box<dyn Model>;
}
impl<T> ModelBounds for T where T: Model + PartialEq + Clone + 'static {
fn as_any(&self) -> &dyn Any {
self
}
fn bound_eq(&self, other: &dyn Model) -> bool {
match other.as_any().downcast_ref::<Self>() {
Some(other) => self == other,
None => false,
}
}
fn bound_clone(&self) -> Box<dyn Model> {
Box::new(self.clone())
}
}
|