-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathview_node.mbt
More file actions
132 lines (123 loc) · 3.52 KB
/
view_node.mbt
File metadata and controls
132 lines (123 loc) · 3.52 KB
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
// ViewNode: Serializable view tree for the editor protocol.
// Flattens ProjNode[T] + SourceMap into a language-agnostic representation
// suitable for JSON transport to the UI layer.
///|
/// A coloured / labelled slice of a node's text. `role` is a CSS-class-style
/// tag (e.g. "keyword", "string", "identifier") and `start`/`end` index into
/// the document text in the same units as `ViewNode.text_range`.
pub(all) struct TokenSpan {
role : String
start : Int
end : Int
} derive(Debug, Eq)
///|
pub fn TokenSpan::TokenSpan(
role~ : String,
start~ : Int,
end~ : Int,
) -> TokenSpan {
{ role, start, end }
}
///|
pub(all) struct ViewAnnotation {
kind : String
label : String
severity : String
} derive(Debug, Eq)
///|
pub fn ViewAnnotation::ViewAnnotation(
kind~ : String,
label~ : String,
severity? : String = "info",
) -> ViewAnnotation {
{ kind, label, severity }
}
///|
pub impl ToJson for ViewAnnotation with fn to_json(self) {
let m : Map[String, Json] = {}
m["kind"] = self.kind.to_json()
m["label"] = self.label.to_json()
m["severity"] = self.severity.to_json()
Json::object(m)
}
///|
/// Language-agnostic view of one projection node, JSON-serialised for the
/// frontend.
///
/// `ViewNode` flattens a `core.ProjNode[T]` plus its slice of the source map
/// into a uniform representation:
///
/// - `id` is the stable `NodeId` used to address the node in patches and
/// intents; it survives reparses.
/// - `kind_tag` is the AST variant name (lowercase, used by the frontend as a
/// discriminator).
/// - `label` is the short human-readable name shown in tree views.
/// - `text` is the rendered source for this subtree, when applicable.
/// - `text_range` is the half-open `[start, end)` range in the source
/// document the node occupies; consistent with `TokenSpan` offsets.
pub(all) struct ViewNode {
id : @core.NodeId
kind_tag : String
label : String
text : String?
text_range : (Int, Int)
token_spans : Array[TokenSpan]
editable : Bool
css_class : String
children : Array[ViewNode]
annotations : Array[ViewAnnotation]
} derive(Debug, Eq)
///|
pub fn ViewNode::ViewNode(
id~ : @core.NodeId,
kind_tag~ : String,
label~ : String,
text? : String,
text_range~ : (Int, Int),
token_spans? : Array[TokenSpan] = [],
editable? : Bool = false,
css_class? : String = "",
children? : Array[ViewNode] = [],
annotations? : Array[ViewAnnotation] = [],
) -> ViewNode {
{
id,
kind_tag,
label,
text,
text_range,
token_spans,
editable,
css_class,
children,
annotations,
}
}
///|
pub impl ToJson for TokenSpan with fn to_json(self) {
let m : Map[String, Json] = {}
m["role"] = self.role.to_json()
m["start"] = self.start.to_json()
m["end"] = self.end.to_json()
Json::object(m)
}
///|
pub impl ToJson for ViewNode with fn to_json(self) {
let m : Map[String, Json] = {}
let NodeId(id_int) = self.id
m["id"] = id_int.to_json()
m["kind_tag"] = self.kind_tag.to_json()
m["label"] = self.label.to_json()
m["text"] = match self.text {
Some(t) => t.to_json()
None => Json::null()
}
let (range_start, range_end) = self.text_range
m["text_range"] = Json::array([range_start.to_json(), range_end.to_json()])
m["token_spans"] = Json::array(self.token_spans.map(fn(ts) { ts.to_json() }))
m["editable"] = self.editable.to_json()
m["css_class"] = self.css_class.to_json()
m["children"] = Json::array(self.children.map(fn(c) { c.to_json() }))
m["annotations"] = Json::array(self.annotations.map(fn(a) { a.to_json() }))
Json::object(m)
}