auto_lsp_core/ast/
node.rs1use crate::errors::PositionError;
20use downcast_rs::{impl_downcast, DowncastSync};
21use std::cmp::Ordering;
22use std::sync::Arc;
23use tree_sitter::Node;
24
25pub trait AstNode: std::fmt::Debug + Send + Sync + DowncastSync {
27 fn contains(node: &Node) -> bool
29 where
30 Self: Sized;
31
32 fn lower(&self) -> &dyn AstNode;
36
37 fn get_id(&self) -> usize;
41
42 fn get_parent_id(&self) -> Option<usize>;
44
45 fn get_range(&self) -> &tree_sitter::Range;
47
48 fn get_lsp_range(&self) -> lsp_types::Range {
50 let range = self.get_range();
51 lsp_types::Range {
52 start: lsp_types::Position {
53 line: range.start_point.row as u32,
54 character: range.start_point.column as u32,
55 },
56 end: lsp_types::Position {
57 line: range.end_point.row as u32,
58 character: range.end_point.column as u32,
59 },
60 }
61 }
62
63 fn get_start_position(&self) -> lsp_types::Position {
65 let range = self.get_range();
66 lsp_types::Position {
67 line: range.start_point.row as u32,
68 character: range.start_point.column as u32,
69 }
70 }
71
72 fn get_end_position(&self) -> lsp_types::Position {
74 let range = self.get_range();
75 lsp_types::Position {
76 line: range.end_point.row as u32,
77 character: range.end_point.column as u32,
78 }
79 }
80
81 fn get_text<'a>(&self, source_code: &'a [u8]) -> Result<&'a str, PositionError> {
88 let range = self.get_range();
89 let range = range.start_byte..range.end_byte;
90 match source_code.get(range.start..range.end) {
91 Some(text) => match std::str::from_utf8(text) {
92 Ok(text) => Ok(text),
93 Err(utf8_error) => Err(PositionError::UTF8Error { range, utf8_error }),
94 },
95 None => Err(PositionError::WrongTextRange { range }),
96 }
97 }
98
99 fn get_parent<'a>(&'a self, nodes: &'a [Arc<dyn AstNode>]) -> Option<&'a Arc<dyn AstNode>> {
103 match nodes.first() {
104 Some(first) => {
105 assert_eq!(
106 first.get_id(),
107 0,
108 "get_parent called on an unsorted node list"
109 );
110 nodes.get(self.get_parent_id()?)
111 }
112 None => None,
113 }
114 }
115}
116
117impl_downcast!(AstNode);
118
119impl PartialEq for dyn AstNode {
120 fn eq(&self, other: &Self) -> bool {
121 self.get_range().eq(other.get_range()) && self.get_id().eq(&other.get_id())
122 }
123}
124
125impl Eq for dyn AstNode {}
126
127impl PartialOrd for dyn AstNode {
128 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
129 Some(self.get_id().cmp(&other.get_id()))
130 }
131}
132
133impl Ord for dyn AstNode {
134 fn cmp(&self, other: &Self) -> Ordering {
135 self.get_id().cmp(&other.get_id())
136 }
137}