@@ -28,21 +28,19 @@ use simplicityhl::{
2828 parse:: ParseFromStr ,
2929} ;
3030
31+ use crate :: completion:: builtin:: string_to_callname;
3132use crate :: completion:: { self , CompletionProvider } ;
3233use crate :: error:: LspError ;
3334use crate :: function:: Functions ;
34- use crate :: utils:: {
35- find_all_references, find_function_name_range, find_related_call, get_call_span,
36- get_comments_from_lines, position_to_span, span_contains, span_to_positions,
37- } ;
35+ use crate :: treesitter:: parser:: { self , AstContext } ;
36+ use crate :: utils:: { get_comments_from_lines, span_to_positions} ;
3837
39- #[ derive( Debug ) ]
4038struct Document {
4139 functions : Functions ,
40+ ast : AstContext ,
4241 text : Rope ,
4342}
4443
45- #[ derive( Debug ) ]
4644pub struct Backend {
4745 client : Client ,
4846
@@ -176,7 +174,11 @@ impl LanguageServer for Backend {
176174
177175 let completions = self
178176 . completion_provider
179- . process_completions ( prefix, & doc. functions . functions_and_docs ( ) )
177+ . process_completions (
178+ prefix,
179+ & doc. functions . functions_and_docs ( ) ,
180+ & doc. ast . scopes . get_visible_variables ( pos, false ) ,
181+ )
180182 . map ( CompletionResponse :: Array ) ;
181183
182184 Ok ( completions)
@@ -189,22 +191,20 @@ impl LanguageServer for Backend {
189191 let doc = documents
190192 . get ( uri)
191193 . ok_or ( LspError :: DocumentNotFound ( uri. to_owned ( ) ) ) ?;
192- let functions = doc. functions . functions ( ) ;
193194
194195 let token_pos = params. text_document_position_params . position ;
195-
196- let token_span = position_to_span ( token_pos) ?;
197- let Ok ( Some ( call) ) = find_related_call ( & functions, token_span) else {
196+ let Some ( token) = doc
197+ . ast
198+ . get_token_on_position ( & doc. text . to_string ( ) , token_pos)
199+ else {
198200 return Ok ( None ) ;
199201 } ;
200202
201- let call_span = get_call_span ( call) ?;
202- let ( start, end) = span_to_positions ( & call_span) ?;
203-
204- let description = match call. name ( ) {
205- parse:: CallName :: Jet ( jet) => {
203+ let token_text = token. text ;
204+ let description = match token. token {
205+ parser:: Token :: Jet => {
206206 let element =
207- simplicityhl:: simplicity:: jet:: Elements :: from_str ( format ! ( "{jet}" ) . as_str ( ) )
207+ simplicityhl:: simplicity:: jet:: Elements :: from_str ( token_text . as_str ( ) )
208208 . map_err ( |err| LspError :: ConversionFailed ( err. to_string ( ) ) ) ?;
209209
210210 let template = completion:: jet:: jet_to_template ( element) ;
@@ -216,12 +216,12 @@ impl LanguageServer for Backend {
216216 template. description
217217 )
218218 }
219- parse :: CallName :: Custom ( func ) => {
219+ parser :: Token :: Function => {
220220 let ( function, function_doc) =
221221 doc. functions
222- . get ( func . as_inner ( ) )
222+ . get ( & token_text )
223223 . ok_or ( LspError :: FunctionNotFound ( format ! (
224- "Function {func } is not found"
224+ "Function {token_text } is not found"
225225 ) ) ) ?;
226226
227227 let template = completion:: function_to_template ( function, function_doc) ;
@@ -233,8 +233,12 @@ impl LanguageServer for Backend {
233233 template. description
234234 )
235235 }
236- other => {
237- let Some ( template) = completion:: builtin:: match_callname ( other) else {
236+ parser:: Token :: BuiltinFunction => {
237+ let Some ( callname) = string_to_callname ( & token_text) else {
238+ return Ok ( None ) ;
239+ } ;
240+
241+ let Some ( template) = completion:: builtin:: match_callname ( & callname) else {
238242 return Ok ( None ) ;
239243 } ;
240244 format ! (
@@ -245,14 +249,37 @@ impl LanguageServer for Backend {
245249 template. description
246250 )
247251 }
252+ parser:: Token :: Identifier => {
253+ let vars = doc. ast . scopes . get_visible_variables ( token_pos, true ) ;
254+
255+ let Some ( definition) = vars. iter ( ) . find ( |& var| var. name == token_text) else {
256+ return Ok ( None ) ;
257+ } ;
258+
259+ format ! (
260+ "```simplicityhl\n let {}: {}\n ```" ,
261+ definition. name, definition. ty
262+ )
263+ }
264+ parser:: Token :: BuiltinAlias => {
265+ let Some ( info) = crate :: documentation:: alias:: type_info ( & token_text) else {
266+ return Ok ( None ) ;
267+ } ;
268+
269+ format ! (
270+ "```simplicityhl\n type {} = {}\n ```\n {}" ,
271+ token_text, info. 0 , info. 1
272+ )
273+ }
274+ parser:: Token :: Alias => return Ok ( None ) ,
248275 } ;
249276
250277 Ok ( Some ( Hover {
251278 contents : tower_lsp_server:: lsp_types:: HoverContents :: Markup ( MarkupContent {
252279 kind : MarkupKind :: Markdown ,
253280 value : description,
254281 } ) ,
255- range : Some ( Range { start , end } ) ,
282+ range : Some ( token . range ) ,
256283 } ) )
257284 }
258285
@@ -266,46 +293,35 @@ impl LanguageServer for Backend {
266293 let doc = documents
267294 . get ( uri)
268295 . ok_or ( LspError :: DocumentNotFound ( uri. to_owned ( ) ) ) ?;
269- let functions = doc. functions . functions ( ) ;
270296
271- let token_position = params. text_document_position_params . position ;
272- let token_span = position_to_span ( token_position) ?;
297+ let token_pos = params. text_document_position_params . position ;
273298
274- let Ok ( Some ( call) ) = find_related_call ( & functions, token_span) else {
275- let Some ( func) = functions
276- . iter ( )
277- . find ( |func| span_contains ( func. span ( ) , & token_span) )
278- else {
279- return Ok ( None ) ;
280- } ;
281- let range = find_function_name_range ( func, & doc. text ) ?;
282-
283- if token_position <= range. end && token_position >= range. start {
284- return Ok ( Some ( GotoDefinitionResponse :: from ( Location :: new (
285- uri. clone ( ) ,
286- range,
287- ) ) ) ) ;
288- }
299+ let Some ( token) = doc
300+ . ast
301+ . get_token_on_position ( & doc. text . to_string ( ) , token_pos)
302+ else {
289303 return Ok ( None ) ;
290304 } ;
291305
292- match call. name ( ) {
293- simplicityhl:: parse:: CallName :: Custom ( func) => {
294- let function =
295- doc. functions
296- . get_func ( func. as_inner ( ) )
297- . ok_or ( LspError :: FunctionNotFound ( format ! (
298- "Function {func} is not found"
299- ) ) ) ?;
300-
301- let ( start, end) = span_to_positions ( function. as_ref ( ) ) ?;
302- Ok ( Some ( GotoDefinitionResponse :: from ( Location :: new (
303- uri. clone ( ) ,
304- Range :: new ( start, end) ,
305- ) ) ) )
306+ let location = match token. token {
307+ parser:: Token :: Function => doc
308+ . ast
309+ . get_function_definition ( & doc. text . to_string ( ) , & token. text ) ?,
310+ parser:: Token :: Alias => doc
311+ . ast
312+ . get_alias_definition ( & doc. text . to_string ( ) , & token. text ) ?,
313+ parser:: Token :: Identifier => doc. ast . get_identifier_definition ( & token. text , token_pos) ,
314+ _ => {
315+ return Ok ( None ) ;
306316 }
307- _ => Ok ( None ) ,
308- }
317+ } ;
318+
319+ Ok ( Some ( GotoDefinitionResponse :: Array (
320+ location
321+ . iter ( )
322+ . map ( |& range| Location :: new ( uri. to_owned ( ) , range) )
323+ . collect ( ) ,
324+ ) ) )
309325 }
310326
311327 async fn references ( & self , params : ReferenceParams ) -> Result < Option < Vec < Location > > > {
@@ -315,53 +331,40 @@ impl LanguageServer for Backend {
315331 let doc = documents
316332 . get ( uri)
317333 . ok_or ( LspError :: DocumentNotFound ( uri. to_owned ( ) ) ) ?;
318- let functions = doc. functions . functions ( ) ;
319-
320- let token_position = params. text_document_position . position ;
321-
322- let token_span = position_to_span ( token_position) ?;
323-
324- let call_name =
325- find_related_call ( & functions, token_span) ?. map ( simplicityhl:: parse:: Call :: name) ;
326-
327- match call_name {
328- Some ( parse:: CallName :: Custom ( _) ) | None => { }
329- Some ( name) => {
330- return Ok ( Some (
331- find_all_references ( & functions, name) ?
332- . iter ( )
333- . map ( |range| Location {
334- range : * range,
335- uri : uri. clone ( ) ,
336- } )
337- . collect ( ) ,
338- ) ) ;
339- }
340- }
341334
342- let Some ( func) = functions. iter ( ) . find ( |func| match call_name {
343- Some ( parse:: CallName :: Custom ( name) ) => func. name ( ) == name,
344- _ => span_contains ( func. span ( ) , & token_span) ,
345- } ) else {
335+ let token_pos = params. text_document_position . position ;
336+
337+ let Some ( token) = doc
338+ . ast
339+ . get_token_on_position ( & doc. text . to_string ( ) , token_pos)
340+ else {
346341 return Ok ( None ) ;
347342 } ;
348343
349- let range = find_function_name_range ( func, & doc. text ) ?;
350-
351- if ( token_position <= range. end && token_position >= range. start ) || call_name. is_some ( ) {
352- Ok ( Some (
353- find_all_references ( & functions, & parse:: CallName :: Custom ( func. name ( ) . clone ( ) ) ) ?
354- . into_iter ( )
355- . chain ( std:: iter:: once ( range) )
356- . map ( |range| Location {
357- range,
358- uri : uri. clone ( ) ,
359- } )
360- . collect ( ) ,
361- ) )
362- } else {
363- Ok ( None )
364- }
344+ let token_text = token. text ;
345+
346+ let ranges = match token. token {
347+ parser:: Token :: Identifier => {
348+ doc. ast . get_identifier_reference ( & token_text, token_pos) ?
349+ }
350+ parser:: Token :: Function => doc
351+ . ast
352+ . get_function_reference ( & doc. text . to_string ( ) , & token_text) ?,
353+ parser:: Token :: Alias => doc
354+ . ast
355+ . get_alias_reference ( & doc. text . to_string ( ) , & token_text) ?,
356+
357+ _ => {
358+ return Ok ( None ) ;
359+ }
360+ } ;
361+
362+ Ok ( Some (
363+ ranges
364+ . iter ( )
365+ . map ( |& range| Location :: new ( uri. to_owned ( ) , range) )
366+ . collect ( ) ,
367+ ) )
365368 }
366369}
367370
@@ -421,10 +424,12 @@ impl Backend {
421424}
422425
423426/// Create [`Document`] using parsed program and code.
424- fn create_document ( program : & simplicityhl:: parse:: Program , text : & str ) -> Document {
427+ fn create_document ( program : & simplicityhl:: parse:: Program , text : & str ) -> Option < Document > {
425428 let mut document = Document {
426429 functions : Functions :: new ( ) ,
427430 text : Rope :: from_str ( text) ,
431+
432+ ast : AstContext :: new ( text) ?,
428433 } ;
429434
430435 program
@@ -447,7 +452,7 @@ fn create_document(program: &simplicityhl::parse::Program, text: &str) -> Docume
447452 ) ;
448453 } ) ;
449454
450- document
455+ Some ( document)
451456}
452457
453458/// Parse program using [`simplicityhl`] compiler and return [`RichError`],
@@ -460,7 +465,7 @@ fn parse_program(text: &str) -> (Option<RichError>, Option<Document>) {
460465
461466 (
462467 ast:: Program :: analyze ( & program) . with_file ( text) . err ( ) ,
463- Some ( create_document ( & program, text) ) ,
468+ create_document ( & program, text) ,
464469 )
465470}
466471
0 commit comments