@@ -185,3 +185,268 @@ pub fn lint(text: String) -> Result<JsValue, Error> {
185185fn into_error < E : std:: fmt:: Display > ( err : E ) -> Error {
186186 Error :: new ( & err. to_string ( ) )
187187}
188+
189+ #[ wasm_bindgen]
190+ pub fn goto_definition ( content : String , line : u32 , col : u32 ) -> Result < JsValue , Error > {
191+ let parse = squawk_syntax:: SourceFile :: parse ( & content) ;
192+ let line_index = LineIndex :: new ( & content) ;
193+ let offset = position_to_offset ( & line_index, line, col) ?;
194+ let result = squawk_ide:: goto_definition:: goto_definition ( parse. tree ( ) , offset) ;
195+
196+ let response = result. map ( |range| {
197+ let start = line_index. line_col ( range. start ( ) ) ;
198+ let end = line_index. line_col ( range. end ( ) ) ;
199+ let start_wide = line_index
200+ . to_wide ( line_index:: WideEncoding :: Utf16 , start)
201+ . unwrap ( ) ;
202+ let end_wide = line_index
203+ . to_wide ( line_index:: WideEncoding :: Utf16 , end)
204+ . unwrap ( ) ;
205+
206+ LocationRange {
207+ start_line : start_wide. line ,
208+ start_column : start_wide. col ,
209+ end_line : end_wide. line ,
210+ end_column : end_wide. col ,
211+ }
212+ } ) ;
213+
214+ serde_wasm_bindgen:: to_value ( & response) . map_err ( into_error)
215+ }
216+
217+ #[ wasm_bindgen]
218+ pub fn hover ( content : String , line : u32 , col : u32 ) -> Result < JsValue , Error > {
219+ let parse = squawk_syntax:: SourceFile :: parse ( & content) ;
220+ let line_index = LineIndex :: new ( & content) ;
221+ let offset = position_to_offset ( & line_index, line, col) ?;
222+ let result = squawk_ide:: hover:: hover ( & parse. tree ( ) , offset) ;
223+
224+ serde_wasm_bindgen:: to_value ( & result) . map_err ( into_error)
225+ }
226+
227+ #[ wasm_bindgen]
228+ pub fn find_references ( content : String , line : u32 , col : u32 ) -> Result < JsValue , Error > {
229+ let parse = squawk_syntax:: SourceFile :: parse ( & content) ;
230+ let line_index = LineIndex :: new ( & content) ;
231+ let offset = position_to_offset ( & line_index, line, col) ?;
232+ let references = squawk_ide:: find_references:: find_references ( & parse. tree ( ) , offset) ;
233+
234+ let locations: Vec < LocationRange > = references
235+ . iter ( )
236+ . map ( |range| {
237+ let start = line_index. line_col ( range. start ( ) ) ;
238+ let end = line_index. line_col ( range. end ( ) ) ;
239+ let start_wide = line_index
240+ . to_wide ( line_index:: WideEncoding :: Utf16 , start)
241+ . unwrap ( ) ;
242+ let end_wide = line_index
243+ . to_wide ( line_index:: WideEncoding :: Utf16 , end)
244+ . unwrap ( ) ;
245+
246+ LocationRange {
247+ start_line : start_wide. line ,
248+ start_column : start_wide. col ,
249+ end_line : end_wide. line ,
250+ end_column : end_wide. col ,
251+ }
252+ } )
253+ . collect ( ) ;
254+
255+ serde_wasm_bindgen:: to_value ( & locations) . map_err ( into_error)
256+ }
257+
258+ #[ wasm_bindgen]
259+ pub fn document_symbols ( content : String ) -> Result < JsValue , Error > {
260+ let parse = squawk_syntax:: SourceFile :: parse ( & content) ;
261+ let line_index = LineIndex :: new ( & content) ;
262+ let symbols = squawk_ide:: document_symbols:: document_symbols ( & parse. tree ( ) ) ;
263+
264+ let converted: Vec < WasmDocumentSymbol > = symbols
265+ . into_iter ( )
266+ . map ( |s| convert_document_symbol ( & line_index, s) )
267+ . collect ( ) ;
268+
269+ serde_wasm_bindgen:: to_value ( & converted) . map_err ( into_error)
270+ }
271+
272+ #[ wasm_bindgen]
273+ pub fn code_actions ( content : String , line : u32 , col : u32 ) -> Result < JsValue , Error > {
274+ let parse = squawk_syntax:: SourceFile :: parse ( & content) ;
275+ let line_index = LineIndex :: new ( & content) ;
276+ let offset = position_to_offset ( & line_index, line, col) ?;
277+ let actions = squawk_ide:: code_actions:: code_actions ( parse. tree ( ) , offset) ;
278+
279+ let converted = actions. map ( |actions| {
280+ actions
281+ . into_iter ( )
282+ . map ( |action| {
283+ let edits = action
284+ . edits
285+ . into_iter ( )
286+ . map ( |edit| {
287+ let start_pos = line_index. line_col ( edit. text_range . start ( ) ) ;
288+ let end_pos = line_index. line_col ( edit. text_range . end ( ) ) ;
289+ let start_wide = line_index
290+ . to_wide ( line_index:: WideEncoding :: Utf16 , start_pos)
291+ . unwrap ( ) ;
292+ let end_wide = line_index
293+ . to_wide ( line_index:: WideEncoding :: Utf16 , end_pos)
294+ . unwrap ( ) ;
295+
296+ TextEdit {
297+ start_line_number : start_wide. line ,
298+ start_column : start_wide. col ,
299+ end_line_number : end_wide. line ,
300+ end_column : end_wide. col ,
301+ text : edit. text . unwrap_or_default ( ) ,
302+ }
303+ } )
304+ . collect ( ) ;
305+
306+ WasmCodeAction {
307+ title : action. title ,
308+ edits,
309+ kind : match action. kind {
310+ squawk_ide:: code_actions:: ActionKind :: QuickFix => "quickfix" ,
311+ squawk_ide:: code_actions:: ActionKind :: RefactorRewrite => "refactor.rewrite" ,
312+ }
313+ . to_string ( ) ,
314+ }
315+ } )
316+ . collect :: < Vec < _ > > ( )
317+ } ) ;
318+
319+ serde_wasm_bindgen:: to_value ( & converted) . map_err ( into_error)
320+ }
321+
322+ fn position_to_offset (
323+ line_index : & LineIndex ,
324+ line : u32 ,
325+ col : u32 ,
326+ ) -> Result < rowan:: TextSize , Error > {
327+ let wide_pos = line_index:: WideLineCol { line, col } ;
328+
329+ let pos = line_index
330+ . to_utf8 ( line_index:: WideEncoding :: Utf16 , wide_pos)
331+ . ok_or_else ( || Error :: new ( "Invalid position" ) ) ?;
332+
333+ line_index
334+ . offset ( pos)
335+ . ok_or_else ( || Error :: new ( "Invalid position offset" ) )
336+ }
337+
338+ #[ derive( Serialize ) ]
339+ struct LocationRange {
340+ start_line : u32 ,
341+ start_column : u32 ,
342+ end_line : u32 ,
343+ end_column : u32 ,
344+ }
345+
346+ #[ derive( Serialize ) ]
347+ struct WasmCodeAction {
348+ title : String ,
349+ edits : Vec < TextEdit > ,
350+ kind : String ,
351+ }
352+
353+ #[ derive( Serialize ) ]
354+ struct WasmDocumentSymbol {
355+ name : String ,
356+ detail : Option < String > ,
357+ kind : String ,
358+ start_line : u32 ,
359+ start_column : u32 ,
360+ end_line : u32 ,
361+ end_column : u32 ,
362+ selection_start_line : u32 ,
363+ selection_start_column : u32 ,
364+ selection_end_line : u32 ,
365+ selection_end_column : u32 ,
366+ children : Vec < WasmDocumentSymbol > ,
367+ }
368+
369+ fn convert_document_symbol (
370+ line_index : & LineIndex ,
371+ symbol : squawk_ide:: document_symbols:: DocumentSymbol ,
372+ ) -> WasmDocumentSymbol {
373+ let full_start = line_index. line_col ( symbol. full_range . start ( ) ) ;
374+ let full_end = line_index. line_col ( symbol. full_range . end ( ) ) ;
375+ let full_start_wide = line_index
376+ . to_wide ( line_index:: WideEncoding :: Utf16 , full_start)
377+ . unwrap ( ) ;
378+ let full_end_wide = line_index
379+ . to_wide ( line_index:: WideEncoding :: Utf16 , full_end)
380+ . unwrap ( ) ;
381+
382+ let focus_start = line_index. line_col ( symbol. focus_range . start ( ) ) ;
383+ let focus_end = line_index. line_col ( symbol. focus_range . end ( ) ) ;
384+ let focus_start_wide = line_index
385+ . to_wide ( line_index:: WideEncoding :: Utf16 , focus_start)
386+ . unwrap ( ) ;
387+ let focus_end_wide = line_index
388+ . to_wide ( line_index:: WideEncoding :: Utf16 , focus_end)
389+ . unwrap ( ) ;
390+
391+ WasmDocumentSymbol {
392+ name : symbol. name ,
393+ detail : symbol. detail ,
394+ kind : match symbol. kind {
395+ squawk_ide:: document_symbols:: DocumentSymbolKind :: Table => "table" ,
396+ squawk_ide:: document_symbols:: DocumentSymbolKind :: Function => "function" ,
397+ squawk_ide:: document_symbols:: DocumentSymbolKind :: Column => "column" ,
398+ }
399+ . to_string ( ) ,
400+ start_line : full_start_wide. line ,
401+ start_column : full_start_wide. col ,
402+ end_line : full_end_wide. line ,
403+ end_column : full_end_wide. col ,
404+ selection_start_line : focus_start_wide. line ,
405+ selection_start_column : focus_start_wide. col ,
406+ selection_end_line : focus_end_wide. line ,
407+ selection_end_column : focus_end_wide. col ,
408+ children : symbol
409+ . children
410+ . into_iter ( )
411+ . map ( |child| convert_document_symbol ( line_index, child) )
412+ . collect ( ) ,
413+ }
414+ }
415+
416+ #[ wasm_bindgen]
417+ pub fn inlay_hints ( content : String ) -> Result < JsValue , Error > {
418+ let parse = squawk_syntax:: SourceFile :: parse ( & content) ;
419+ let line_index = LineIndex :: new ( & content) ;
420+ let hints = squawk_ide:: inlay_hints:: inlay_hints ( & parse. tree ( ) ) ;
421+
422+ let converted: Vec < WasmInlayHint > = hints
423+ . into_iter ( )
424+ . map ( |hint| {
425+ let position = line_index. line_col ( hint. position ) ;
426+ let position_wide = line_index
427+ . to_wide ( line_index:: WideEncoding :: Utf16 , position)
428+ . unwrap ( ) ;
429+
430+ WasmInlayHint {
431+ line : position_wide. line ,
432+ column : position_wide. col ,
433+ label : hint. label ,
434+ kind : match hint. kind {
435+ squawk_ide:: inlay_hints:: InlayHintKind :: Type => "type" ,
436+ squawk_ide:: inlay_hints:: InlayHintKind :: Parameter => "parameter" ,
437+ }
438+ . to_string ( ) ,
439+ }
440+ } )
441+ . collect ( ) ;
442+
443+ serde_wasm_bindgen:: to_value ( & converted) . map_err ( into_error)
444+ }
445+
446+ #[ derive( Serialize ) ]
447+ struct WasmInlayHint {
448+ line : u32 ,
449+ column : u32 ,
450+ label : String ,
451+ kind : String ,
452+ }
0 commit comments