From 6df95426ff1852f6a341d35a90c92ea2fcce0c5f Mon Sep 17 00:00:00 2001 From: Vinicius Stock Date: Wed, 25 Feb 2026 10:47:39 -0500 Subject: [PATCH] Add rubydex dependency --- .mcp.json | 7 + Gemfile.lock | 7 + lib/ruby_lsp/internal.rb | 1 + project-words | 1 + ruby-lsp.gemspec | 1 + sorbet/rbi/gems/rubydex@0.1.0.beta8.rbi | 450 ++++++++++++++++++++++++ sorbet/tapioca/require.rb | 1 + 7 files changed, 468 insertions(+) create mode 100644 .mcp.json create mode 100644 sorbet/rbi/gems/rubydex@0.1.0.beta8.rbi diff --git a/.mcp.json b/.mcp.json new file mode 100644 index 0000000000..2d80d3c1b6 --- /dev/null +++ b/.mcp.json @@ -0,0 +1,7 @@ +{ + "mcpServers": { + "rubydex": { + "command": "${HOME}/.cargo/bin/rubydex_mcp" + } + } +} diff --git a/Gemfile.lock b/Gemfile.lock index 1a05538583..220d118190 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -5,6 +5,7 @@ PATH language_server-protocol (~> 3.17.0) prism (>= 1.2, < 2.0) rbs (>= 3, < 5) + rubydex (~> 0.1.0.beta1) GEM remote: https://rubygems.org/ @@ -91,6 +92,9 @@ GEM rubocop (>= 1) ruby-progressbar (1.13.0) ruby2_keywords (0.0.5) + rubydex (0.1.0.beta8) + rubydex (0.1.0.beta8-arm64-darwin) + rubydex (0.1.0.beta8-x86_64-linux) sorbet (0.6.12913) sorbet-static (= 0.6.12913) sorbet-runtime (0.6.12913) @@ -200,6 +204,9 @@ CHECKSUMS ruby-lsp (0.26.7) ruby-progressbar (1.13.0) sha256=80fc9c47a9b640d6834e0dc7b3c94c9df37f08cb072b7761e4a71e22cff29b33 ruby2_keywords (0.0.5) sha256=ffd13740c573b7301cf7a2e61fc857b2a8e3d3aff32545d6f8300d8bae10e3ef + rubydex (0.1.0.beta8) sha256=6bba99fed4a334c32c9ea18e803e72335c7ac99a57fbfae552b0c902561eb0de + rubydex (0.1.0.beta8-arm64-darwin) sha256=ea09f759af9ec0986f6196faba505ac4e6618025bb9cc79af975c49acbef3ed3 + rubydex (0.1.0.beta8-x86_64-linux) sha256=49598b58d4be412f54164f6323c8e1d32cda883c25a0881f06c4c0b49d4af3dc sorbet (0.6.12913) sha256=259e28215af2b80bf530d3b6af1c509ddadcdef6fa34417a9afd315f76d4eaf4 sorbet-runtime (0.6.12913) sha256=b07b29c4070e7729fcda55f42ca2cf76ed369537be6680b36208e66c17934ff1 sorbet-static (0.6.12913-universal-darwin) sha256=bc064e1930f3736d7f7ded8ff7631c43d8d66681540be7103e1a3faaa08cc10f diff --git a/lib/ruby_lsp/internal.rb b/lib/ruby_lsp/internal.rb index 1083c51450..7b3a04a000 100644 --- a/lib/ruby_lsp/internal.rb +++ b/lib/ruby_lsp/internal.rb @@ -20,6 +20,7 @@ end require "set" require "strscan" +require "rubydex" require "prism" require "prism/visitor" require "language_server-protocol" diff --git a/project-words b/project-words index 331454d110..49679dbd25 100644 --- a/project-words +++ b/project-words @@ -88,6 +88,7 @@ rindex rjson rmtree rruby +rubydex rubyfmt rubylibdir rubylibprefix diff --git a/ruby-lsp.gemspec b/ruby-lsp.gemspec index e42cfafd47..328186e4a5 100644 --- a/ruby-lsp.gemspec +++ b/ruby-lsp.gemspec @@ -24,6 +24,7 @@ Gem::Specification.new do |s| s.add_dependency("language_server-protocol", "~> 3.17.0") s.add_dependency("prism", ">= 1.2", "< 2.0") s.add_dependency("rbs", ">= 3", "< 5") + s.add_dependency("rubydex", "~> 0.1.0.beta1") s.required_ruby_version = ">= 3.0" end diff --git a/sorbet/rbi/gems/rubydex@0.1.0.beta8.rbi b/sorbet/rbi/gems/rubydex@0.1.0.beta8.rbi new file mode 100644 index 0000000000..ffae66aa1c --- /dev/null +++ b/sorbet/rbi/gems/rubydex@0.1.0.beta8.rbi @@ -0,0 +1,450 @@ +# typed: true + +# DO NOT EDIT MANUALLY +# This is an autogenerated file for types exported from the `rubydex` gem. +# Please instead update this file by running `bin/tapioca gem rubydex`. + +# frozen_string_literal: true + +# source://rubydex//lib/rubydex/version.rb#3 +module Rubydex; end + +class Rubydex::AttrAccessorDefinition < ::Rubydex::Definition; end +class Rubydex::AttrReaderDefinition < ::Rubydex::Definition; end +class Rubydex::AttrWriterDefinition < ::Rubydex::Definition; end +class Rubydex::Class < ::Rubydex::Namespace; end +class Rubydex::ClassDefinition < ::Rubydex::Definition; end +class Rubydex::ClassVariable < ::Rubydex::Declaration; end +class Rubydex::ClassVariableDefinition < ::Rubydex::Definition; end + +# source://rubydex//lib/rubydex/comment.rb#4 +class Rubydex::Comment + # @return [Comment] a new instance of Comment + # + # source://rubydex//lib/rubydex/comment.rb#12 + sig { params(string: String, location: Rubydex::Location).void } + def initialize(string:, location:); end + + # source://rubydex//lib/rubydex/comment.rb#9 + sig { returns(Rubydex::Location) } + def location; end + + # source://rubydex//lib/rubydex/comment.rb#6 + sig { returns(String) } + def string; end +end + +class Rubydex::Constant < ::Rubydex::Declaration; end +class Rubydex::ConstantAlias < ::Rubydex::Declaration; end +class Rubydex::ConstantAliasDefinition < ::Rubydex::Definition; end +class Rubydex::ConstantDefinition < ::Rubydex::Definition; end + +class Rubydex::ConstantReference < ::Rubydex::Reference + # source://rubydex//lib/rubydex.rb#10 + def initialize(_arg0, _arg1); end + + # source://rubydex//lib/rubydex.rb#10 + sig { returns(Rubydex::Location) } + def location; end + + # source://rubydex//lib/rubydex.rb#10 + sig { returns(String) } + def name; end +end + +class Rubydex::Declaration + # source://rubydex//lib/rubydex.rb#10 + def initialize(_arg0, _arg1); end + + # source://rubydex//lib/rubydex.rb#10 + sig { returns(T::Enumerable[Rubydex::Definition]) } + def definitions; end + + # source://rubydex//lib/rubydex.rb#10 + sig { returns(String) } + def name; end + + # source://rubydex//lib/rubydex.rb#10 + sig { returns(Rubydex::Declaration) } + def owner; end + + # source://rubydex//lib/rubydex.rb#10 + sig { returns(T::Enumerable[Rubydex::Reference]) } + def references; end + + # source://rubydex//lib/rubydex.rb#10 + sig { returns(String) } + def unqualified_name; end + + class << self + private + + # source://rubydex//lib/rubydex.rb#10 + def new(*_arg0); end + end +end + +class Rubydex::Definition + # source://rubydex//lib/rubydex.rb#10 + def initialize(_arg0, _arg1); end + + # source://rubydex//lib/rubydex.rb#10 + sig { returns(T::Array[Rubydex::Comment]) } + def comments; end + + # source://rubydex//lib/rubydex.rb#10 + sig { returns(T::Boolean) } + def deprecated?; end + + # source://rubydex//lib/rubydex.rb#10 + sig { returns(Rubydex::Location) } + def location; end + + # source://rubydex//lib/rubydex.rb#10 + sig { returns(String) } + def name; end + + # source://rubydex//lib/rubydex.rb#10 + sig { returns(T.nilable(Rubydex::Location)) } + def name_location; end + + class << self + private + + # source://rubydex//lib/rubydex.rb#10 + def new(*_arg0); end + end +end + +# source://rubydex//lib/rubydex/diagnostic.rb#4 +class Rubydex::Diagnostic + # @return [Diagnostic] a new instance of Diagnostic + # + # source://rubydex//lib/rubydex/diagnostic.rb#15 + sig { params(rule: Symbol, message: String, location: Rubydex::Location).void } + def initialize(rule:, message:, location:); end + + # source://rubydex//lib/rubydex/diagnostic.rb#12 + sig { returns(Rubydex::Location) } + def location; end + + # source://rubydex//lib/rubydex/diagnostic.rb#9 + sig { returns(String) } + def message; end + + # source://rubydex//lib/rubydex/diagnostic.rb#6 + sig { returns(Symbol) } + def rule; end +end + +# A one based location intended for display purposes. This is what should be used when displaying a location to users, +# like in CLIs +# +# source://rubydex//lib/rubydex/location.rb#70 +class Rubydex::DisplayLocation < ::Rubydex::Location + # Normalize to zero-based for comparison with Location + # + # + # source://rubydex//lib/rubydex/location.rb#81 + sig { returns([String, Integer, Integer, Integer, Integer]) } + def comparable_values; end + + # Returns itself + # + # + # source://rubydex//lib/rubydex/location.rb#74 + sig { returns(Rubydex::DisplayLocation) } + def to_display; end + + # source://rubydex//lib/rubydex/location.rb#86 + sig { returns(String) } + def to_s; end +end + +class Rubydex::Document + # source://rubydex//lib/rubydex.rb#10 + def initialize(_arg0, _arg1); end + + # source://rubydex//lib/rubydex.rb#10 + sig { returns(T::Enumerable[Rubydex::Definition]) } + def definitions; end + + # source://rubydex//lib/rubydex.rb#10 + sig { returns(String) } + def uri; end + + class << self + private + + # source://rubydex//lib/rubydex.rb#10 + def new(*_arg0); end + end +end + +class Rubydex::Error < StandardError; end + +# source://rubydex//lib/rubydex/failures.rb#4 +class Rubydex::Failure + # @return [Failure] a new instance of Failure + # + # source://rubydex//lib/rubydex/failures.rb#9 + sig { params(message: String).void } + def initialize(message); end + + # source://rubydex//lib/rubydex/failures.rb#6 + sig { returns(String) } + def message; end +end + +class Rubydex::GlobalVariable < ::Rubydex::Declaration; end +class Rubydex::GlobalVariableAliasDefinition < ::Rubydex::Definition; end +class Rubydex::GlobalVariableDefinition < ::Rubydex::Definition; end + +# The global graph representing all declarations and their relationships for the workspace +# +# Note: this class is partially defined in C to integrate with the Rust backend +# +# source://rubydex//lib/rubydex/graph.rb#7 +class Rubydex::Graph + # @return [Graph] a new instance of Graph + # + # source://rubydex//lib/rubydex/graph.rb#20 + sig { params(workspace_path: T.nilable(String)).void } + def initialize(workspace_path: T.unsafe(nil)); end + + # source://rubydex//lib/rubydex.rb#10 + sig { params(fully_qualified_name: String).returns(T.nilable(Rubydex::Declaration)) } + def [](fully_qualified_name); end + + # source://rubydex//lib/rubydex.rb#10 + sig { returns(T::Array[Rubydex::Failure]) } + def check_integrity; end + + # source://rubydex//lib/rubydex.rb#10 + sig { returns(T::Enumerable[Rubydex::ConstantReference]) } + def constant_references; end + + # source://rubydex//lib/rubydex.rb#10 + sig { returns(T::Enumerable[Rubydex::Declaration]) } + def declarations; end + + # source://rubydex//lib/rubydex.rb#10 + sig { params(uri: String).returns(T.nilable(Rubydex::Document)) } + def delete_document(uri); end + + # source://rubydex//lib/rubydex.rb#10 + sig { returns(T::Array[Rubydex::Diagnostic]) } + def diagnostics; end + + # source://rubydex//lib/rubydex.rb#10 + sig { returns(T::Enumerable[Rubydex::Document]) } + def documents; end + + # source://rubydex//lib/rubydex.rb#10 + sig { params(encoding: String).void } + def encoding=(encoding); end + + # source://rubydex//lib/rubydex.rb#10 + sig { params(paths: T::Array[String]).returns(T::Array[String]) } + def index_all(paths); end + + # source://rubydex//lib/rubydex.rb#10 + sig { params(uri: String, source: String, language_id: String).void } + def index_source(uri, source, language_id); end + + # Index all files and dependencies of the workspace that exists in `@workspace_path` + # + # source://rubydex//lib/rubydex/graph.rb#26 + # Index all files and dependencies of the workspace that exists in `@workspace_path` + sig { returns(T::Array[String]) } + def index_workspace; end + + # source://rubydex//lib/rubydex.rb#10 + sig { returns(T::Enumerable[Rubydex::MethodReference]) } + def method_references; end + + # source://rubydex//lib/rubydex.rb#10 + sig { params(load_path: T::Array[String]).returns(T::Array[String]) } + def require_paths(load_path); end + + # source://rubydex//lib/rubydex.rb#10 + sig { returns(T.self_type) } + def resolve; end + + # source://rubydex//lib/rubydex.rb#10 + sig { params(name: String, nesting: T::Array[String]).returns(T.nilable(Rubydex::Declaration)) } + def resolve_constant(name, nesting); end + + # source://rubydex//lib/rubydex.rb#10 + sig { params(require_path: String, load_path: T::Array[String]).returns(T.nilable(Rubydex::Document)) } + def resolve_require_path(require_path, load_path); end + + # source://rubydex//lib/rubydex.rb#10 + sig { params(query: String).returns(T::Array[Rubydex::Declaration]) } + def search(query); end + + # source://rubydex//lib/rubydex/graph.rb#17 + sig { returns(String) } + def workspace_path; end + + # source://rubydex//lib/rubydex/graph.rb#17 + sig { params(workspace_path: String).void } + def workspace_path=(workspace_path); end + + # Returns all workspace paths that should be indexed, excluding directories that we don't need to descend into such + # as `.git`, `node_modules`. Also includes any top level Ruby files + # + # + # source://rubydex//lib/rubydex/graph.rb#34 + sig { returns(T::Array[String]) } + def workspace_paths; end + + private + + # Searches for the latest installation of the `rbs` gem and adds the paths for the core and stdlib RBS definitions + # to the list of paths. This method does not require `rbs` to be a part of the bundle. It searches for whatever + # latest installation of `rbs` exists in the system and fails silently if we can't find one + # + # + # source://rubydex//lib/rubydex/graph.rb#81 + sig { params(paths: T::Array[String]).void } + def add_core_rbs_definition_paths(paths); end + + # Gathers the paths we have to index for all workspace dependencies + # + # source://rubydex//lib/rubydex/graph.rb#57 + sig { params(paths: T::Array[String]).void } + def add_workspace_dependency_paths(paths); end +end + +# source://rubydex//lib/rubydex/graph.rb#8 +Rubydex::Graph::IGNORED_DIRECTORIES = T.let(T.unsafe(nil), Array) + +class Rubydex::InstanceVariable < ::Rubydex::Declaration; end +class Rubydex::InstanceVariableDefinition < ::Rubydex::Definition; end + +# source://rubydex//lib/rubydex/failures.rb#14 +class Rubydex::IntegrityFailure < ::Rubydex::Failure; end + +# A zero based internal location. Intended to be used for tool-to-tool communication, such as a language server +# communicating with an editor. +# +# source://rubydex//lib/rubydex/location.rb#6 +class Rubydex::Location + include ::Comparable + + # @return [Location] a new instance of Location + # + # source://rubydex//lib/rubydex/location.rb#18 + sig { params(uri: String, start_line: Integer, end_line: Integer, start_column: Integer, end_column: Integer).void } + def initialize(uri:, start_line:, end_line:, start_column:, end_column:); end + + # source://rubydex//lib/rubydex/location.rb#38 + sig { params(other: T.untyped).returns(T.nilable(Integer)) } + def <=>(other); end + + # source://rubydex//lib/rubydex/location.rb#45 + sig { returns([String, Integer, Integer, Integer, Integer]) } + def comparable_values; end + + # source://rubydex//lib/rubydex/location.rb#15 + sig { returns(Integer) } + def end_column; end + + # source://rubydex//lib/rubydex/location.rb#15 + sig { returns(Integer) } + def end_line; end + + # source://rubydex//lib/rubydex/location.rb#15 + sig { returns(Integer) } + def start_column; end + + # source://rubydex//lib/rubydex/location.rb#15 + sig { returns(Integer) } + def start_line; end + + # Turns this zero based location into a one based location for display purposes. + # + # + # source://rubydex//lib/rubydex/location.rb#52 + sig { returns(Rubydex::DisplayLocation) } + def to_display; end + + # @raise [NotFileUriError] + # + # source://rubydex//lib/rubydex/location.rb#27 + sig { returns(String) } + def to_file_path; end + + # source://rubydex//lib/rubydex/location.rb#63 + sig { returns(String) } + def to_s; end + + # source://rubydex//lib/rubydex/location.rb#12 + sig { returns(String) } + def uri; end +end + +# source://rubydex//lib/rubydex/location.rb#7 +class Rubydex::Location::NotFileUriError < ::StandardError; end + +class Rubydex::Method < ::Rubydex::Declaration; end +class Rubydex::MethodAliasDefinition < ::Rubydex::Definition; end +class Rubydex::MethodDefinition < ::Rubydex::Definition; end + +class Rubydex::MethodReference < ::Rubydex::Reference + # source://rubydex//lib/rubydex.rb#10 + def initialize(_arg0, _arg1); end + + # source://rubydex//lib/rubydex.rb#10 + sig { returns(Rubydex::Location) } + def location; end + + # source://rubydex//lib/rubydex.rb#10 + sig { returns(String) } + def name; end +end + +class Rubydex::Module < ::Rubydex::Namespace; end +class Rubydex::ModuleDefinition < ::Rubydex::Definition; end + +class Rubydex::Namespace < ::Rubydex::Declaration + # source://rubydex//lib/rubydex.rb#10 + sig { returns(T::Enumerable[Rubydex::Namespace]) } + def ancestors; end + + # source://rubydex//lib/rubydex.rb#10 + sig { returns(T::Enumerable[Rubydex::Namespace]) } + def descendants; end + + # source://rubydex//lib/rubydex.rb#10 + sig { params(name: String, only_inherited: T::Boolean).returns(T.nilable(Rubydex::Declaration)) } + def find_member(name, only_inherited: T.unsafe(nil)); end + + # source://rubydex//lib/rubydex.rb#10 + sig { params(name: String).returns(T.nilable(Rubydex::Declaration)) } + def member(name); end + + # source://rubydex//lib/rubydex.rb#10 + sig { returns(T.nilable(Rubydex::SingletonClass)) } + def singleton_class; end +end + +class Rubydex::Reference + # source://rubydex//lib/rubydex.rb#10 + def initialize(_arg0, _arg1); end + + class << self + private + + # source://rubydex//lib/rubydex.rb#10 + def new(*_arg0); end + end +end + +class Rubydex::SingletonClass < ::Rubydex::Namespace; end +class Rubydex::SingletonClassDefinition < ::Rubydex::Definition; end +class Rubydex::Todo < ::Rubydex::Namespace; end + +# source://rubydex//lib/rubydex/version.rb#4 +Rubydex::VERSION = T.let(T.unsafe(nil), String) diff --git a/sorbet/tapioca/require.rb b/sorbet/tapioca/require.rb index 36dd0a2df3..61f328097f 100644 --- a/sorbet/tapioca/require.rb +++ b/sorbet/tapioca/require.rb @@ -8,6 +8,7 @@ yarp_require_paths = Gem.loaded_specs["yarp"]&.full_require_paths $LOAD_PATH.delete_if { |path| yarp_require_paths.include?(path) } if yarp_require_paths +require "rubydex" require "language_server-protocol" require "prism" require "prism/visitor"