1use zed::{
2 lsp::{Completion, CompletionKind, Symbol, SymbolKind},
3 CodeLabel, CodeLabelSpan,
4};
5use zed_extension_api::{self as zed, Result};
6
7pub struct RubyLsp {}
8
9impl RubyLsp {
10 pub const LANGUAGE_SERVER_ID: &'static str = "ruby-lsp";
11
12 pub fn new() -> Self {
13 Self {}
14 }
15
16 pub fn server_script_path(&mut self, worktree: &zed::Worktree) -> Result<String> {
17 let path = worktree.which("ruby-lsp").ok_or_else(|| {
18 "ruby-lsp must be installed manually. Install it with `gem install ruby-lsp`."
19 .to_string()
20 })?;
21
22 Ok(path)
23 }
24
25 pub fn label_for_completion(&self, completion: Completion) -> Option<CodeLabel> {
26 let highlight_name = match completion.kind? {
27 CompletionKind::Class | CompletionKind::Module => "type",
28 CompletionKind::Constant => "constant",
29 CompletionKind::Method => "function.method",
30 CompletionKind::Reference => "function.method",
31 CompletionKind::Keyword => "keyword",
32 _ => return None,
33 };
34
35 let len = completion.label.len();
36 let name_span = CodeLabelSpan::literal(completion.label, Some(highlight_name.to_string()));
37
38 Some(CodeLabel {
39 code: Default::default(),
40 spans: vec![name_span],
41 filter_range: (0..len).into(),
42 })
43 }
44
45 pub fn label_for_symbol(&self, symbol: Symbol) -> Option<CodeLabel> {
46 let name = &symbol.name;
47
48 return match symbol.kind {
49 SymbolKind::Method => {
50 let code = format!("def {name}; end");
51 let filter_range = 0..name.len();
52 let display_range = 4..4 + name.len();
53
54 Some(CodeLabel {
55 code,
56 spans: vec![CodeLabelSpan::code_range(display_range)],
57 filter_range: filter_range.into(),
58 })
59 }
60 SymbolKind::Class | SymbolKind::Module => {
61 let code = format!("class {name}; end");
62 let filter_range = 0..name.len();
63 let display_range = 6..6 + name.len();
64
65 Some(CodeLabel {
66 code,
67 spans: vec![CodeLabelSpan::code_range(display_range)],
68 filter_range: filter_range.into(),
69 })
70 }
71 SymbolKind::Constant => {
72 let code = name.to_uppercase().to_string();
73 let filter_range = 0..name.len();
74 let display_range = 0..name.len();
75
76 Some(CodeLabel {
77 code,
78 spans: vec![CodeLabelSpan::code_range(display_range)],
79 filter_range: filter_range.into(),
80 })
81 }
82 _ => None,
83 };
84 }
85}