ruby: Move Ruby extension to zed-extensions/ruby repo (#19098)
This commit is contained in:
parent
56163b1e35
commit
5445f898e8
28 changed files with 2 additions and 1097 deletions
|
@ -1,16 +0,0 @@
|
|||
[package]
|
||||
name = "zed_ruby"
|
||||
version = "0.2.0"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
license = "Apache-2.0"
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[lib]
|
||||
path = "src/ruby.rs"
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
zed_extension_api = "0.1.0"
|
|
@ -1 +0,0 @@
|
|||
../../LICENSE-APACHE
|
|
@ -1,31 +0,0 @@
|
|||
id = "ruby"
|
||||
name = "Ruby"
|
||||
description = "Ruby support."
|
||||
version = "0.2.0"
|
||||
schema_version = 1
|
||||
authors = ["Vitaly Slobodin <vitaliy.slobodin@gmail.com>"]
|
||||
repository = "https://github.com/zed-industries/zed"
|
||||
|
||||
[language_servers.solargraph]
|
||||
name = "Solargraph"
|
||||
languages = ["Ruby"]
|
||||
|
||||
[language_servers.ruby-lsp]
|
||||
name = "Ruby LSP"
|
||||
languages = ["Ruby", "ERB"]
|
||||
|
||||
[language_servers.rubocop]
|
||||
name = "Rubocop"
|
||||
languages = ["Ruby"]
|
||||
|
||||
[grammars.ruby]
|
||||
repository = "https://github.com/tree-sitter/tree-sitter-ruby"
|
||||
commit = "7dbc1e2d0e2d752577655881f73b4573f3fe85d4"
|
||||
|
||||
[grammars.embedded_template]
|
||||
repository = "https://github.com/tree-sitter/tree-sitter-embedded-template"
|
||||
commit = "91fc5ae1140d5c9d922312431f7d251a48d7b8ce"
|
||||
|
||||
[grammars.rbs]
|
||||
repository = "https://github.com/joker1007/tree-sitter-rbs"
|
||||
commit = "8d8e65ac3f77fbc9e15b1cdb9f980a3e0ac3ab99"
|
|
@ -1,9 +0,0 @@
|
|||
name = "ERB"
|
||||
grammar = "embedded_template"
|
||||
path_suffixes = ["erb"]
|
||||
autoclose_before = ">})"
|
||||
brackets = [
|
||||
{ start = "<", end = ">", close = true, newline = true },
|
||||
]
|
||||
block_comment = ["<%#", "%>"]
|
||||
scope_opt_in_language_servers = ["tailwindcss-language-server"]
|
|
@ -1,12 +0,0 @@
|
|||
(comment_directive) @comment
|
||||
|
||||
[
|
||||
"<%#"
|
||||
"<%"
|
||||
"<%="
|
||||
"<%_"
|
||||
"<%-"
|
||||
"%>"
|
||||
"-%>"
|
||||
"_%>"
|
||||
] @keyword
|
|
@ -1,7 +0,0 @@
|
|||
((code) @content
|
||||
(#set! "language" "ruby")
|
||||
(#set! "combined"))
|
||||
|
||||
((content) @content
|
||||
(#set! "language" "html")
|
||||
(#set! "combined"))
|
|
@ -1,10 +0,0 @@
|
|||
name = "RBS"
|
||||
grammar = "rbs"
|
||||
path_suffixes = ["rbs"]
|
||||
autoclose_before = "]})"
|
||||
brackets = [
|
||||
{ start = "(", end = ")", close = true, newline = false },
|
||||
{ start = "{", end = "}", close = true, newline = false },
|
||||
{ start = "[", end = "]", close = true, newline = false },
|
||||
]
|
||||
line_comments = ["#"]
|
|
@ -1,144 +0,0 @@
|
|||
; Taken from https://github.com/nvim-treesitter/nvim-treesitter/blob/master/queries/rbs/highlights.scm
|
||||
; Use directive
|
||||
(use_clause
|
||||
[
|
||||
(type_name)
|
||||
(simple_type_name)
|
||||
] @type)
|
||||
|
||||
; Builtin constants and Keywords
|
||||
[
|
||||
"true"
|
||||
"false"
|
||||
] @boolean
|
||||
|
||||
"nil" @constant.builtin
|
||||
|
||||
[
|
||||
"use"
|
||||
"as"
|
||||
"module"
|
||||
"def"
|
||||
"attr_reader"
|
||||
"attr_writer"
|
||||
"attr_accessor"
|
||||
"end"
|
||||
"alias"
|
||||
] @keyword
|
||||
|
||||
[
|
||||
"interface"
|
||||
"type"
|
||||
"class"
|
||||
] @keyword.type
|
||||
|
||||
(class_decl
|
||||
"end" @keyword.type)
|
||||
|
||||
(interface_decl
|
||||
"end" @keyword.type)
|
||||
|
||||
"def" @keyword.function
|
||||
|
||||
; Members of declaration
|
||||
[
|
||||
"include"
|
||||
"extend"
|
||||
"prepend"
|
||||
] @function.method
|
||||
|
||||
(visibility) @keyword.modifier
|
||||
|
||||
(comment) @comment
|
||||
|
||||
(method_member
|
||||
(method_name
|
||||
[
|
||||
(identifier)
|
||||
(constant)
|
||||
(operator)
|
||||
(setter)
|
||||
] @function.method))
|
||||
|
||||
[
|
||||
(ivar_name)
|
||||
(cvar_name)
|
||||
] @variable.member
|
||||
|
||||
(alias_member
|
||||
(method_name) @function)
|
||||
|
||||
(class_name
|
||||
(constant) @type)
|
||||
|
||||
(module_name
|
||||
(constant) @type)
|
||||
|
||||
(interface_name
|
||||
(interface) @type)
|
||||
|
||||
(alias_name
|
||||
(identifier) @type)
|
||||
|
||||
(type_variable) @constant
|
||||
|
||||
(namespace
|
||||
(constant) @module)
|
||||
|
||||
(builtin_type) @type.builtin
|
||||
|
||||
(const_name
|
||||
(constant) @constant)
|
||||
|
||||
(global_name) @variable
|
||||
|
||||
; Standard Arguments
|
||||
(parameter
|
||||
(var_name) @variable.parameter)
|
||||
|
||||
; Keyword Arguments
|
||||
(keyword) @variable.parameter
|
||||
|
||||
; Self
|
||||
(self) @variable.builtin
|
||||
|
||||
; Literal
|
||||
(type
|
||||
(symbol_literal) @string.special.symbol)
|
||||
|
||||
(type
|
||||
(string_literal
|
||||
(escape_sequence) @string.escape))
|
||||
|
||||
(type
|
||||
(string_literal) @string)
|
||||
|
||||
(type
|
||||
(integer_literal) @number)
|
||||
|
||||
; Operators
|
||||
[
|
||||
"="
|
||||
"->"
|
||||
"<"
|
||||
"**"
|
||||
"*"
|
||||
"&"
|
||||
"|"
|
||||
"^"
|
||||
] @operator
|
||||
|
||||
; Punctuation
|
||||
[
|
||||
"("
|
||||
")"
|
||||
"["
|
||||
"]"
|
||||
"{"
|
||||
"}"
|
||||
] @punctuation.bracket
|
||||
|
||||
[
|
||||
","
|
||||
"."
|
||||
] @punctuation.delimiter
|
|
@ -1,14 +0,0 @@
|
|||
[
|
||||
(class_decl)
|
||||
(module_decl)
|
||||
(interface_decl)
|
||||
(parameters)
|
||||
(tuple_type)
|
||||
(record_type)
|
||||
] @indent.begin
|
||||
|
||||
(_ "[" "]" @end) @indent
|
||||
(_ "{" "}" @end) @indent
|
||||
(_ "(" ")" @end) @indent
|
||||
|
||||
(comment) @indent.ignore
|
|
@ -1,2 +0,0 @@
|
|||
((comment) @injection.content
|
||||
(#set! injection.language "comment"))
|
|
@ -1,14 +0,0 @@
|
|||
("[" @open "]" @close)
|
||||
("{" @open "}" @close)
|
||||
("\"" @open "\"" @close)
|
||||
("do" @open "end" @close)
|
||||
|
||||
(block_parameters "|" @open "|" @close)
|
||||
(interpolation "#{" @open "}" @close)
|
||||
|
||||
(if "if" @open "end" @close)
|
||||
(unless "unless" @open "end" @close)
|
||||
(begin "begin" @open "end" @close)
|
||||
(module "module" @open "end" @close)
|
||||
(_ . "def" @open "end" @close)
|
||||
(_ . "class" @open "end" @close)
|
|
@ -1,51 +0,0 @@
|
|||
name = "Ruby"
|
||||
grammar = "ruby"
|
||||
path_suffixes = [
|
||||
"rb",
|
||||
"Gemfile",
|
||||
"Guardfile",
|
||||
"rake",
|
||||
"Rakefile",
|
||||
"ru",
|
||||
"thor",
|
||||
"cap",
|
||||
"capfile",
|
||||
"Capfile",
|
||||
"jbuilder",
|
||||
"rabl",
|
||||
"rxml",
|
||||
"builder",
|
||||
"gemspec",
|
||||
"rdoc",
|
||||
"thor",
|
||||
"pryrc",
|
||||
"simplecov",
|
||||
"Steepfile",
|
||||
"Podfile",
|
||||
"Brewfile",
|
||||
"Vagrantfile",
|
||||
"Puppetfile",
|
||||
]
|
||||
first_line_pattern = '^#!.*\bruby\b'
|
||||
line_comments = ["# "]
|
||||
autoclose_before = ";:.,=}])>"
|
||||
brackets = [
|
||||
{ start = "{", end = "}", close = true, newline = true },
|
||||
{ start = "[", end = "]", close = true, newline = true },
|
||||
{ start = "(", end = ")", close = true, newline = true },
|
||||
{ start = "\"", end = "\"", close = true, newline = false, not_in = [
|
||||
"comment",
|
||||
"string",
|
||||
] },
|
||||
{ start = "'", end = "'", close = true, newline = false, not_in = [
|
||||
"comment",
|
||||
"string",
|
||||
] },
|
||||
]
|
||||
collapsed_placeholder = "# ..."
|
||||
tab_size = 2
|
||||
scope_opt_in_language_servers = ["tailwindcss-language-server"]
|
||||
|
||||
[overrides.string]
|
||||
word_characters = ["-"]
|
||||
opt_into_language_servers = ["tailwindcss-language-server"]
|
|
@ -1,22 +0,0 @@
|
|||
(
|
||||
(comment)* @context
|
||||
.
|
||||
[
|
||||
(module
|
||||
"module" @name
|
||||
name: (_) @name)
|
||||
(method
|
||||
"def" @name
|
||||
name: (_) @name
|
||||
body: (body_statement) @collapse)
|
||||
(class
|
||||
"class" @name
|
||||
name: (_) @name)
|
||||
(singleton_method
|
||||
"def" @name
|
||||
object: (_) @name
|
||||
"." @name
|
||||
name: (_) @name
|
||||
body: (body_statement) @collapse)
|
||||
] @item
|
||||
)
|
|
@ -1,202 +0,0 @@
|
|||
; Keywords
|
||||
|
||||
[
|
||||
"alias"
|
||||
"and"
|
||||
"begin"
|
||||
"break"
|
||||
"case"
|
||||
"class"
|
||||
"def"
|
||||
"do"
|
||||
"else"
|
||||
"elsif"
|
||||
"end"
|
||||
"ensure"
|
||||
"for"
|
||||
"if"
|
||||
"in"
|
||||
"module"
|
||||
"next"
|
||||
"or"
|
||||
"rescue"
|
||||
"retry"
|
||||
"return"
|
||||
"then"
|
||||
"unless"
|
||||
"until"
|
||||
"when"
|
||||
"while"
|
||||
"yield"
|
||||
] @keyword
|
||||
|
||||
((identifier) @keyword
|
||||
(#match? @keyword "^(private|protected|public)$"))
|
||||
|
||||
; Function calls
|
||||
|
||||
((identifier) @function.method.builtin
|
||||
(#eq? @function.method.builtin "require"))
|
||||
|
||||
"defined?" @function.method.builtin
|
||||
|
||||
(call
|
||||
method: [(identifier) (constant)] @function.method)
|
||||
|
||||
; Function definitions
|
||||
|
||||
(alias (identifier) @function.method)
|
||||
(setter (identifier) @function.method)
|
||||
(method name: [(identifier) (constant)] @function.method)
|
||||
(singleton_method name: [(identifier) (constant)] @function.method)
|
||||
(method_parameters [
|
||||
(identifier) @variable.parameter
|
||||
(optional_parameter name: (identifier) @variable.parameter)
|
||||
(keyword_parameter [name: (identifier) (":")] @variable.parameter)
|
||||
])
|
||||
|
||||
(block_parameters (identifier) @variable.parameter)
|
||||
|
||||
; Identifiers
|
||||
|
||||
((identifier) @constant.builtin
|
||||
(#match? @constant.builtin "^__(FILE|LINE|ENCODING)__$"))
|
||||
|
||||
(file) @constant.builtin
|
||||
(line) @constant.builtin
|
||||
(encoding) @constant.builtin
|
||||
|
||||
(hash_splat_nil
|
||||
"**" @operator
|
||||
) @constant.builtin
|
||||
|
||||
(global_variable) @constant
|
||||
|
||||
(constant) @type
|
||||
|
||||
((constant) @constant
|
||||
(#match? @constant "^[A-Z\\d_]+$"))
|
||||
|
||||
(superclass
|
||||
(constant) @type.super)
|
||||
|
||||
(superclass
|
||||
(scope_resolution
|
||||
(constant) @type.super))
|
||||
|
||||
(superclass
|
||||
(scope_resolution
|
||||
(scope_resolution
|
||||
(constant) @type.super)))
|
||||
|
||||
(self) @variable.special
|
||||
(super) @variable.special
|
||||
|
||||
[
|
||||
(class_variable)
|
||||
(instance_variable)
|
||||
] @variable.member
|
||||
|
||||
|
||||
; Literals
|
||||
|
||||
[
|
||||
(string)
|
||||
(bare_string)
|
||||
(subshell)
|
||||
(heredoc_body)
|
||||
(heredoc_beginning)
|
||||
] @string
|
||||
|
||||
[
|
||||
(simple_symbol)
|
||||
(delimited_symbol)
|
||||
(hash_key_symbol)
|
||||
(bare_symbol)
|
||||
] @string.special.symbol
|
||||
|
||||
(regex) @string.regex
|
||||
(escape_sequence) @string.escape
|
||||
|
||||
[
|
||||
(integer)
|
||||
(float)
|
||||
] @number
|
||||
|
||||
[
|
||||
(nil)
|
||||
(true)
|
||||
(false)
|
||||
] @constant.builtin
|
||||
|
||||
(comment) @comment
|
||||
|
||||
; Operators
|
||||
|
||||
[
|
||||
"!"
|
||||
"~"
|
||||
"+"
|
||||
"-"
|
||||
"**"
|
||||
"*"
|
||||
"/"
|
||||
"%"
|
||||
"<<"
|
||||
">>"
|
||||
"&"
|
||||
"|"
|
||||
"^"
|
||||
">"
|
||||
"<"
|
||||
"<="
|
||||
">="
|
||||
"=="
|
||||
"!="
|
||||
"=~"
|
||||
"!~"
|
||||
"<=>"
|
||||
"||"
|
||||
"&&"
|
||||
".."
|
||||
"..."
|
||||
"="
|
||||
"**="
|
||||
"*="
|
||||
"/="
|
||||
"%="
|
||||
"+="
|
||||
"-="
|
||||
"<<="
|
||||
">>="
|
||||
"&&="
|
||||
"&="
|
||||
"||="
|
||||
"|="
|
||||
"^="
|
||||
"=>"
|
||||
"->"
|
||||
(operator)
|
||||
] @operator
|
||||
|
||||
[
|
||||
","
|
||||
";"
|
||||
"."
|
||||
"::"
|
||||
] @punctuation.delimiter
|
||||
|
||||
[
|
||||
"("
|
||||
")"
|
||||
"["
|
||||
"]"
|
||||
"{"
|
||||
"}"
|
||||
"%w("
|
||||
"%i("
|
||||
] @punctuation.bracket
|
||||
|
||||
(interpolation
|
||||
"#{" @punctuation.special
|
||||
"}" @punctuation.special) @embedded
|
|
@ -1,18 +0,0 @@
|
|||
(method "end" @end) @indent
|
||||
(class "end" @end) @indent
|
||||
(module "end" @end) @indent
|
||||
(begin "end" @end) @indent
|
||||
(singleton_method "end" @end) @indent
|
||||
(do_block "end" @end) @indent
|
||||
|
||||
(then) @indent
|
||||
(call) @indent
|
||||
|
||||
(ensure) @outdent
|
||||
(rescue) @outdent
|
||||
(else) @outdent
|
||||
|
||||
|
||||
(_ "[" "]" @end) @indent
|
||||
(_ "{" "}" @end) @indent
|
||||
(_ "(" ")" @end) @indent
|
|
@ -1,8 +0,0 @@
|
|||
(heredoc_body
|
||||
(heredoc_content) @content
|
||||
(heredoc_end) @language
|
||||
(#downcase! @language))
|
||||
|
||||
((regex
|
||||
(string_content) @content)
|
||||
(#set! "language" "regex"))
|
|
@ -1,20 +0,0 @@
|
|||
(class
|
||||
"class" @context
|
||||
name: (_) @name) @item
|
||||
|
||||
((identifier) @context
|
||||
(#match? @context "^(private|protected|public)$")) @item
|
||||
|
||||
(method
|
||||
"def" @context
|
||||
name: (_) @name) @item
|
||||
|
||||
(singleton_method
|
||||
"def" @context
|
||||
object: (_) @context
|
||||
"." @context
|
||||
name: (_) @name) @item
|
||||
|
||||
(module
|
||||
"module" @context
|
||||
name: (_) @name) @item
|
|
@ -1,3 +0,0 @@
|
|||
(comment) @comment
|
||||
(string) @string
|
||||
[(simple_symbol) (delimited_symbol)] @simple_symbol
|
|
@ -1,58 +0,0 @@
|
|||
; Adapted from the following sources:
|
||||
; Minitest: https://github.com/zidhuss/neotest-minitest/blob/main/lua/neotest-minitest/init.lua
|
||||
; RSpec: https://github.com/olimorris/neotest-rspec/blob/main/lua/neotest-rspec/init.lua
|
||||
|
||||
; Tests that inherit from a specific class
|
||||
(
|
||||
(class
|
||||
name: [
|
||||
(constant) @run
|
||||
(scope_resolution scope: (constant) name: (constant) @run)
|
||||
]
|
||||
(superclass (scope_resolution) @superclass (#match? @superclass "(::IntegrationTest|::TestCase|::SystemTestCase|Minitest::Test|TLDR)$"))
|
||||
) @_ruby-test
|
||||
(#set! tag ruby-test)
|
||||
)
|
||||
|
||||
(
|
||||
(call
|
||||
method: (identifier) @run (#eq? @run "test")
|
||||
arguments: (argument_list (string (string_content) @_name))
|
||||
) @_ruby-test
|
||||
(#set! tag ruby-test)
|
||||
)
|
||||
|
||||
; Methods that begin with test_
|
||||
(
|
||||
(method
|
||||
name: (identifier) @run (#match? @run "^test_")
|
||||
) @_ruby-test
|
||||
(#set! tag ruby-test)
|
||||
)
|
||||
|
||||
; System tests that inherit from ApplicationSystemTestCase
|
||||
(
|
||||
(class
|
||||
name: (constant) @run (superclass) @superclass (#match? @superclass "(ApplicationSystemTestCase)$")
|
||||
) @_ruby-test
|
||||
(#set! tag ruby-test)
|
||||
)
|
||||
|
||||
; Examples
|
||||
(
|
||||
(call
|
||||
method: (identifier) @run (#any-of? @run "describe" "context" "it" "its" "specify")
|
||||
arguments: (argument_list . (_) @_name)
|
||||
) @_ruby-test
|
||||
(#set! tag ruby-test)
|
||||
)
|
||||
|
||||
; Examples (one-liner syntax)
|
||||
(
|
||||
(call
|
||||
method: (identifier) @run (#any-of? @run "it" "its" "specify")
|
||||
block: (_) @_name
|
||||
!arguments
|
||||
) @_ruby-test
|
||||
(#set! tag ruby-test)
|
||||
)
|
|
@ -1,7 +0,0 @@
|
|||
[
|
||||
{
|
||||
"label": "test $ZED_RELATIVE_FILE:$ZED_ROW",
|
||||
"command": "echo 'To run tests, configure tasks in your \".zed/tasks.json\" file as described in the Ruby extension documentation.'",
|
||||
"tags": ["ruby-test"]
|
||||
}
|
||||
]
|
|
@ -1,7 +0,0 @@
|
|||
mod rubocop;
|
||||
mod ruby_lsp;
|
||||
mod solargraph;
|
||||
|
||||
pub use rubocop::*;
|
||||
pub use ruby_lsp::*;
|
||||
pub use solargraph::*;
|
|
@ -1,59 +0,0 @@
|
|||
use zed_extension_api::{self as zed, settings::LspSettings, LanguageServerId, Result};
|
||||
|
||||
pub struct RubocopBinary {
|
||||
pub path: String,
|
||||
pub args: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
pub struct Rubocop {}
|
||||
|
||||
impl Rubocop {
|
||||
pub const LANGUAGE_SERVER_ID: &'static str = "rubocop";
|
||||
|
||||
pub fn new() -> Self {
|
||||
Self {}
|
||||
}
|
||||
|
||||
pub fn language_server_command(
|
||||
&mut self,
|
||||
language_server_id: &LanguageServerId,
|
||||
worktree: &zed::Worktree,
|
||||
) -> Result<zed::Command> {
|
||||
let binary = self.language_server_binary(language_server_id, worktree)?;
|
||||
|
||||
Ok(zed::Command {
|
||||
command: binary.path,
|
||||
args: binary.args.unwrap_or_else(|| vec!["--lsp".to_string()]),
|
||||
env: worktree.shell_env(),
|
||||
})
|
||||
}
|
||||
|
||||
fn language_server_binary(
|
||||
&self,
|
||||
_language_server_id: &LanguageServerId,
|
||||
worktree: &zed::Worktree,
|
||||
) -> Result<RubocopBinary> {
|
||||
let binary_settings = LspSettings::for_worktree("rubocop", worktree)
|
||||
.ok()
|
||||
.and_then(|lsp_settings| lsp_settings.binary);
|
||||
let binary_args = binary_settings
|
||||
.as_ref()
|
||||
.and_then(|binary_settings| binary_settings.arguments.clone());
|
||||
|
||||
if let Some(path) = binary_settings.and_then(|binary_settings| binary_settings.path) {
|
||||
return Ok(RubocopBinary {
|
||||
path,
|
||||
args: binary_args,
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(path) = worktree.which("rubocop") {
|
||||
return Ok(RubocopBinary {
|
||||
path,
|
||||
args: binary_args,
|
||||
});
|
||||
}
|
||||
|
||||
Err("rubocop must be installed manually. Install it with `gem install rubocop` or specify the 'binary' path to it via local settings.".to_string())
|
||||
}
|
||||
}
|
|
@ -1,128 +0,0 @@
|
|||
use zed_extension_api::{
|
||||
self as zed,
|
||||
lsp::{Completion, CompletionKind, Symbol, SymbolKind},
|
||||
settings::LspSettings,
|
||||
CodeLabel, CodeLabelSpan, LanguageServerId, Result,
|
||||
};
|
||||
|
||||
pub struct RubyLspBinary {
|
||||
pub path: String,
|
||||
pub args: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
pub struct RubyLsp {}
|
||||
|
||||
impl RubyLsp {
|
||||
pub const LANGUAGE_SERVER_ID: &'static str = "ruby-lsp";
|
||||
|
||||
pub fn new() -> Self {
|
||||
Self {}
|
||||
}
|
||||
|
||||
pub fn language_server_command(
|
||||
&mut self,
|
||||
language_server_id: &LanguageServerId,
|
||||
worktree: &zed::Worktree,
|
||||
) -> Result<zed::Command> {
|
||||
let binary = self.language_server_binary(language_server_id, worktree)?;
|
||||
|
||||
Ok(zed::Command {
|
||||
command: binary.path,
|
||||
args: binary.args.unwrap_or_default(),
|
||||
env: worktree.shell_env(),
|
||||
})
|
||||
}
|
||||
|
||||
fn language_server_binary(
|
||||
&self,
|
||||
_language_server_id: &LanguageServerId,
|
||||
worktree: &zed::Worktree,
|
||||
) -> Result<RubyLspBinary> {
|
||||
let binary_settings = LspSettings::for_worktree("ruby-lsp", worktree)
|
||||
.ok()
|
||||
.and_then(|lsp_settings| lsp_settings.binary);
|
||||
let binary_args = binary_settings
|
||||
.as_ref()
|
||||
.and_then(|binary_settings| binary_settings.arguments.clone());
|
||||
|
||||
if let Some(path) = binary_settings.and_then(|binary_settings| binary_settings.path) {
|
||||
return Ok(RubyLspBinary {
|
||||
path,
|
||||
args: binary_args,
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(path) = worktree.which("ruby-lsp") {
|
||||
return Ok(RubyLspBinary {
|
||||
path,
|
||||
args: binary_args,
|
||||
});
|
||||
}
|
||||
|
||||
Err(
|
||||
"ruby-lsp must be installed manually. Install it with `gem install ruby-lsp`."
|
||||
.to_string(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn label_for_completion(&self, completion: Completion) -> Option<CodeLabel> {
|
||||
let highlight_name = match completion.kind? {
|
||||
CompletionKind::Class | CompletionKind::Module => "type",
|
||||
CompletionKind::Constant => "constant",
|
||||
CompletionKind::Method => "function.method",
|
||||
CompletionKind::Reference => "function.method",
|
||||
CompletionKind::Keyword => "keyword",
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
let len = completion.label.len();
|
||||
let name_span = CodeLabelSpan::literal(completion.label, Some(highlight_name.to_string()));
|
||||
|
||||
Some(CodeLabel {
|
||||
code: Default::default(),
|
||||
spans: vec![name_span],
|
||||
filter_range: (0..len).into(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn label_for_symbol(&self, symbol: Symbol) -> Option<CodeLabel> {
|
||||
let name = &symbol.name;
|
||||
|
||||
match symbol.kind {
|
||||
SymbolKind::Method => {
|
||||
let code = format!("def {name}; end");
|
||||
let filter_range = 0..name.len();
|
||||
let display_range = 4..4 + name.len();
|
||||
|
||||
Some(CodeLabel {
|
||||
code,
|
||||
spans: vec![CodeLabelSpan::code_range(display_range)],
|
||||
filter_range: filter_range.into(),
|
||||
})
|
||||
}
|
||||
SymbolKind::Class | SymbolKind::Module => {
|
||||
let code = format!("class {name}; end");
|
||||
let filter_range = 0..name.len();
|
||||
let display_range = 6..6 + name.len();
|
||||
|
||||
Some(CodeLabel {
|
||||
code,
|
||||
spans: vec![CodeLabelSpan::code_range(display_range)],
|
||||
filter_range: filter_range.into(),
|
||||
})
|
||||
}
|
||||
SymbolKind::Constant => {
|
||||
let code = name.to_uppercase().to_string();
|
||||
let filter_range = 0..name.len();
|
||||
let display_range = 0..name.len();
|
||||
|
||||
Some(CodeLabel {
|
||||
code,
|
||||
spans: vec![CodeLabelSpan::code_range(display_range)],
|
||||
filter_range: filter_range.into(),
|
||||
})
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,156 +0,0 @@
|
|||
use zed::lsp::{Completion, CompletionKind, Symbol, SymbolKind};
|
||||
use zed::{CodeLabel, CodeLabelSpan};
|
||||
use zed_extension_api::settings::LspSettings;
|
||||
use zed_extension_api::{self as zed, LanguageServerId, Result};
|
||||
|
||||
pub struct SolargraphBinary {
|
||||
pub path: String,
|
||||
pub args: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
pub struct Solargraph {}
|
||||
|
||||
impl Solargraph {
|
||||
pub const LANGUAGE_SERVER_ID: &'static str = "solargraph";
|
||||
|
||||
pub fn new() -> Self {
|
||||
Self {}
|
||||
}
|
||||
|
||||
pub fn language_server_command(
|
||||
&mut self,
|
||||
language_server_id: &LanguageServerId,
|
||||
worktree: &zed::Worktree,
|
||||
) -> Result<zed::Command> {
|
||||
let binary = self.language_server_binary(language_server_id, worktree)?;
|
||||
|
||||
Ok(zed::Command {
|
||||
command: binary.path,
|
||||
args: binary.args.unwrap_or_else(|| vec!["stdio".to_string()]),
|
||||
env: worktree.shell_env(),
|
||||
})
|
||||
}
|
||||
|
||||
fn language_server_binary(
|
||||
&self,
|
||||
_language_server_id: &LanguageServerId,
|
||||
worktree: &zed::Worktree,
|
||||
) -> Result<SolargraphBinary> {
|
||||
let binary_settings = LspSettings::for_worktree("solargraph", worktree)
|
||||
.ok()
|
||||
.and_then(|lsp_settings| lsp_settings.binary);
|
||||
let binary_args = binary_settings
|
||||
.as_ref()
|
||||
.and_then(|binary_settings| binary_settings.arguments.clone());
|
||||
|
||||
if let Some(path) = binary_settings.and_then(|binary_settings| binary_settings.path) {
|
||||
return Ok(SolargraphBinary {
|
||||
path,
|
||||
args: binary_args,
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(path) = worktree.which("solargraph") {
|
||||
return Ok(SolargraphBinary {
|
||||
path,
|
||||
args: binary_args,
|
||||
});
|
||||
}
|
||||
|
||||
Err("solargraph must be installed manually".to_string())
|
||||
}
|
||||
|
||||
pub fn label_for_completion(&self, completion: Completion) -> Option<CodeLabel> {
|
||||
let highlight_name = match completion.kind? {
|
||||
CompletionKind::Class | CompletionKind::Module => "type",
|
||||
CompletionKind::Constant => "constant",
|
||||
CompletionKind::Method => "function.method",
|
||||
CompletionKind::Keyword => {
|
||||
if completion.label.starts_with(':') {
|
||||
"string.special.symbol"
|
||||
} else {
|
||||
"keyword"
|
||||
}
|
||||
}
|
||||
CompletionKind::Variable => {
|
||||
if completion.label.starts_with('@') {
|
||||
"property"
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
let len = completion.label.len();
|
||||
let name_span = CodeLabelSpan::literal(completion.label, Some(highlight_name.to_string()));
|
||||
|
||||
Some(CodeLabel {
|
||||
code: Default::default(),
|
||||
spans: if let Some(detail) = completion.detail {
|
||||
vec![
|
||||
name_span,
|
||||
CodeLabelSpan::literal(" ", None),
|
||||
CodeLabelSpan::literal(detail, None),
|
||||
]
|
||||
} else {
|
||||
vec![name_span]
|
||||
},
|
||||
filter_range: (0..len).into(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn label_for_symbol(&self, symbol: Symbol) -> Option<CodeLabel> {
|
||||
let name = &symbol.name;
|
||||
|
||||
return match symbol.kind {
|
||||
SymbolKind::Method => {
|
||||
let mut parts = name.split('#');
|
||||
let container_name = parts.next()?;
|
||||
let method_name = parts.next()?;
|
||||
|
||||
if parts.next().is_some() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let filter_range = 0..name.len();
|
||||
|
||||
let spans = vec![
|
||||
CodeLabelSpan::literal(container_name, Some("type".to_string())),
|
||||
CodeLabelSpan::literal("#", None),
|
||||
CodeLabelSpan::literal(method_name, Some("function.method".to_string())),
|
||||
];
|
||||
|
||||
Some(CodeLabel {
|
||||
code: name.to_string(),
|
||||
spans,
|
||||
filter_range: filter_range.into(),
|
||||
})
|
||||
}
|
||||
SymbolKind::Class | SymbolKind::Module => {
|
||||
let class = "class ";
|
||||
let code = format!("{class}{name}");
|
||||
let filter_range = 0..name.len();
|
||||
let display_range = class.len()..class.len() + name.len();
|
||||
|
||||
Some(CodeLabel {
|
||||
code,
|
||||
spans: vec![CodeLabelSpan::code_range(display_range)],
|
||||
filter_range: filter_range.into(),
|
||||
})
|
||||
}
|
||||
SymbolKind::Constant => {
|
||||
let code = name.to_uppercase().to_string();
|
||||
let filter_range = 0..name.len();
|
||||
let display_range = 0..name.len();
|
||||
|
||||
Some(CodeLabel {
|
||||
code,
|
||||
spans: vec![CodeLabelSpan::code_range(display_range)],
|
||||
filter_range: filter_range.into(),
|
||||
})
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,88 +0,0 @@
|
|||
mod language_servers;
|
||||
|
||||
use zed::lsp::{Completion, Symbol};
|
||||
use zed::settings::LspSettings;
|
||||
use zed::{serde_json, CodeLabel, LanguageServerId};
|
||||
use zed_extension_api::{self as zed, Result};
|
||||
|
||||
use crate::language_servers::{Rubocop, RubyLsp, Solargraph};
|
||||
|
||||
struct RubyExtension {
|
||||
solargraph: Option<Solargraph>,
|
||||
ruby_lsp: Option<RubyLsp>,
|
||||
rubocop: Option<Rubocop>,
|
||||
}
|
||||
|
||||
impl zed::Extension for RubyExtension {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
solargraph: None,
|
||||
ruby_lsp: None,
|
||||
rubocop: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn language_server_command(
|
||||
&mut self,
|
||||
language_server_id: &LanguageServerId,
|
||||
worktree: &zed::Worktree,
|
||||
) -> Result<zed::Command> {
|
||||
match language_server_id.as_ref() {
|
||||
Solargraph::LANGUAGE_SERVER_ID => {
|
||||
let solargraph = self.solargraph.get_or_insert_with(Solargraph::new);
|
||||
solargraph.language_server_command(language_server_id, worktree)
|
||||
}
|
||||
RubyLsp::LANGUAGE_SERVER_ID => {
|
||||
let ruby_lsp = self.ruby_lsp.get_or_insert_with(RubyLsp::new);
|
||||
ruby_lsp.language_server_command(language_server_id, worktree)
|
||||
}
|
||||
Rubocop::LANGUAGE_SERVER_ID => {
|
||||
let rubocop = self.rubocop.get_or_insert_with(Rubocop::new);
|
||||
rubocop.language_server_command(language_server_id, worktree)
|
||||
}
|
||||
language_server_id => Err(format!("unknown language server: {language_server_id}")),
|
||||
}
|
||||
}
|
||||
|
||||
fn label_for_symbol(
|
||||
&self,
|
||||
language_server_id: &LanguageServerId,
|
||||
symbol: Symbol,
|
||||
) -> Option<CodeLabel> {
|
||||
match language_server_id.as_ref() {
|
||||
Solargraph::LANGUAGE_SERVER_ID => self.solargraph.as_ref()?.label_for_symbol(symbol),
|
||||
RubyLsp::LANGUAGE_SERVER_ID => self.ruby_lsp.as_ref()?.label_for_symbol(symbol),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn label_for_completion(
|
||||
&self,
|
||||
language_server_id: &LanguageServerId,
|
||||
completion: Completion,
|
||||
) -> Option<CodeLabel> {
|
||||
match language_server_id.as_ref() {
|
||||
Solargraph::LANGUAGE_SERVER_ID => {
|
||||
self.solargraph.as_ref()?.label_for_completion(completion)
|
||||
}
|
||||
RubyLsp::LANGUAGE_SERVER_ID => self.ruby_lsp.as_ref()?.label_for_completion(completion),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn language_server_initialization_options(
|
||||
&mut self,
|
||||
language_server_id: &LanguageServerId,
|
||||
worktree: &zed::Worktree,
|
||||
) -> Result<Option<serde_json::Value>> {
|
||||
let initialization_options =
|
||||
LspSettings::for_worktree(language_server_id.as_ref(), worktree)
|
||||
.ok()
|
||||
.and_then(|lsp_settings| lsp_settings.initialization_options.clone())
|
||||
.unwrap_or_default();
|
||||
|
||||
Ok(Some(serde_json::json!(initialization_options)))
|
||||
}
|
||||
}
|
||||
|
||||
zed::register_extension!(RubyExtension);
|
Loading…
Add table
Add a link
Reference in a new issue