@@ -11,11 +11,63 @@ use mlua::Error;
11
11
use mlua:: FromLua ;
12
12
use mlua:: IntoLua ;
13
13
use mlua:: Lua ;
14
+ use mlua:: UserData ;
15
+ use mlua:: UserDataMethods ;
14
16
use mlua:: Value ;
17
+ use mlua_tree_sitter:: TSNode ;
18
+ use mlua_tree_sitter:: TreeWithSource ;
15
19
16
20
use crate :: Offset ;
17
21
use crate :: Position ;
18
22
use crate :: Span ;
23
+ use crate :: SpanCalculator ;
24
+
25
+ /// An extension trait that lets you load the `lsp_positions` module into a Lua environment.
26
+ pub trait Module {
27
+ /// Loads the `lsp_positions` module into a Lua environment.
28
+ fn open_lsp_positions ( & self ) -> Result < ( ) , mlua:: Error > ;
29
+ }
30
+
31
+ impl Module for Lua {
32
+ fn open_lsp_positions ( & self ) -> Result < ( ) , mlua:: Error > {
33
+ let exports = self . create_table ( ) ?;
34
+ let sc_type = self . create_table ( ) ?;
35
+
36
+ let function = self . create_function ( |lua, source_value : mlua:: String | {
37
+ // We are going to add the Lua string as a user value of the SpanCalculator's Lua
38
+ // wrapper. That will ensure that the string is not garbage collected before the
39
+ // SpanCalculator, which makes it safe to transmute into a 'static reference.
40
+ let source = source_value. to_str ( ) ?;
41
+ let source: & ' static str = unsafe { std:: mem:: transmute ( source) } ;
42
+ let sc = SpanCalculator :: new ( source) ;
43
+ let sc = lua. create_userdata ( sc) ?;
44
+ sc. set_user_value ( source_value) ?;
45
+ Ok ( sc)
46
+ } ) ?;
47
+ sc_type. set ( "new" , function) ?;
48
+
49
+ #[ cfg( feature = "tree-sitter" ) ]
50
+ {
51
+ let function = self . create_function ( |lua, tws_value : Value | {
52
+ // We are going to add the tree-sitter treee as a user value of the
53
+ // SpanCalculator's Lua wrapper. That will ensure that the tree is not garbage
54
+ // collected before the SpanCalculator, which makes it safe to transmute into a
55
+ // 'static reference.
56
+ let tws = TreeWithSource :: from_lua ( tws_value. clone ( ) , lua) ?;
57
+ let source: & ' static str = unsafe { std:: mem:: transmute ( tws. src ) } ;
58
+ let sc = SpanCalculator :: new ( source) ;
59
+ let sc = lua. create_userdata ( sc) ?;
60
+ sc. set_user_value ( tws_value) ?;
61
+ Ok ( sc)
62
+ } ) ?;
63
+ sc_type. set ( "new_from_tree" , function) ?;
64
+ }
65
+
66
+ exports. set ( "SpanCalculator" , sc_type) ?;
67
+ self . globals ( ) . set ( "lsp_positions" , exports) ?;
68
+ Ok ( ( ) )
69
+ }
70
+ }
19
71
20
72
impl < ' lua > FromLua < ' lua > for Offset {
21
73
fn from_lua ( value : Value < ' lua > , _: & ' lua Lua ) -> Result < Self , Error > {
@@ -142,3 +194,24 @@ impl<'lua> IntoLua<'lua> for Span {
142
194
Ok ( Value :: Table ( result) )
143
195
}
144
196
}
197
+
198
+ impl UserData for SpanCalculator < ' static > {
199
+ fn add_methods < ' lua , M : UserDataMethods < ' lua , Self > > ( methods : & mut M ) {
200
+ methods. add_method_mut (
201
+ "for_line_and_column" ,
202
+ |_, sc, ( line, line_utf8_offset, column_utf8_offset) | {
203
+ Ok ( sc. for_line_and_column ( line, line_utf8_offset, column_utf8_offset) )
204
+ } ,
205
+ ) ;
206
+
207
+ methods. add_method_mut (
208
+ "for_line_and_grapheme" ,
209
+ |_, sc, ( line, line_utf8_offset, column_grapheme_offset) | {
210
+ Ok ( sc. for_line_and_grapheme ( line, line_utf8_offset, column_grapheme_offset) )
211
+ } ,
212
+ ) ;
213
+
214
+ #[ cfg( feature = "tree-sitter" ) ]
215
+ methods. add_method_mut ( "for_node" , |_, sc, node : TSNode | Ok ( sc. for_node ( & node) ) ) ;
216
+ }
217
+ }
0 commit comments