bend_language_server/core/
document.rs

1use ropey::Rope;
2use tower_lsp::lsp_types as lsp;
3use tree_sitter as ts;
4use tree_sitter_highlight::{self as hg, Highlighter};
5
6use crate::language::{bend, bend_parser};
7use crate::utils::rope::TextProviderRope;
8
9/// Represents a text document open in the client's text editor.
10pub struct Document {
11    pub url: lsp::Url,
12    pub text: Rope,
13    pub tree: Option<ts::Tree>,
14    pub parser: ts::Parser,
15    pub highlighter: hg::Highlighter,
16    // pub components: HashMap<String, ComponentInfo>
17}
18
19impl Document {
20    /// Create an empty document for `url`.
21    pub fn new(url: lsp::Url) -> Self {
22        Self {
23            url,
24            text: Rope::new(),
25            tree: None,
26            parser: bend_parser().unwrap(),
27            highlighter: Highlighter::new(),
28        }
29    }
30
31    /// Create a new document with text for `url`.
32    pub fn new_with_text(url: lsp::Url, text: &str) -> Self {
33        let mut doc = Self::new(url);
34        doc.update_whole_text(text);
35        doc
36    }
37
38    /// Update the document with entirely new text.
39    pub fn update_whole_text(&mut self, text: &str) {
40        self.text = Rope::from_str(text);
41        self.tree = self.parser.parse(text, None);
42    }
43
44    pub fn get_tree(&mut self) -> &ts::Tree {
45        if self.tree.is_none() {
46            self.do_parse();
47        }
48        self.tree.as_ref().expect("tried to get empty tree")
49    }
50
51    /// Find up to one node based on a tree-sitter query.
52    pub fn find_one(&self, query: &str) -> Option<ts::Node> {
53        let mut cursor = ts::QueryCursor::new();
54        let query = ts::Query::new(&bend(), query).unwrap();
55        let root = self.tree.as_ref()?.root_node();
56
57        cursor
58            .captures(&query, root, &TextProviderRope(&self.text))
59            .flat_map(|(m, _)| m.captures)
60            .next()
61            .map(|capture| capture.node)
62    }
63
64    fn do_parse(&mut self) -> Option<ts::Tree> {
65        self.parser.parse_with(
66            &mut |start_byte, _| {
67                self.text
68                    .byte_slice(start_byte..)
69                    .chunks()
70                    .next()
71                    .unwrap_or("")
72            },
73            self.tree.as_ref(),
74        )
75    }
76}