diff --git a/lib/ruby_lsp/tapioca/addon.rb b/lib/ruby_lsp/tapioca/addon.rb index 663b0b0bb..2f061e654 100644 --- a/lib/ruby_lsp/tapioca/addon.rb +++ b/lib/ruby_lsp/tapioca/addon.rb @@ -209,16 +209,42 @@ def file_updated?(change, path) #: -> void def run_gem_rbi_check state = @global_state #: as !nil - gem_rbi_check = RunGemRbiCheck.new(state.workspace_path) + queue = @outgoing_queue #: as !nil + + gem_rbi_dir = gem_rbi_directory(state.workspace_path) + unless File.exist?(gem_rbi_dir) + queue << Notification.window_log_message("Did not find gem RBI directory", type: Constant::MessageType::WARNING) + return + end + + gem_rbi_check = RunGemRbiCheck.new(state.workspace_path, gem_rbi_dir) gem_rbi_check.run - queue = @outgoing_queue #: as !nil queue << Notification.window_log_message(gem_rbi_check.stdout) unless gem_rbi_check.stdout.empty? unless gem_rbi_check.stderr.empty? queue << Notification.window_log_message(gem_rbi_check.stderr, type: Constant::MessageType::WARNING) end end + + #: (String) -> String + def gem_rbi_directory(workspace_path) + config_file_path = File.join(workspace_path, ::Tapioca::TAPIOCA_CONFIG_FILE) + + if File.exist?(config_file_path) + begin + config = YAML.load_file(config_file_path, fallback: {}) + outdir = config.dig("gem", "outdir") || ::Tapioca::DEFAULT_GEM_DIR + + return File.expand_path(outdir, workspace_path) + rescue Errno::ENOENT + queue = @outgoing_queue #: as !nil + queue << Notification.window_log_message("Invalid YAML or file read error", type: Constant::MessageType::WARNING) + end + end + + File.expand_path(::Tapioca::DEFAULT_GEM_DIR, workspace_path) + end end end end diff --git a/lib/ruby_lsp/tapioca/run_gem_rbi_check.rb b/lib/ruby_lsp/tapioca/run_gem_rbi_check.rb index fbb14d5cb..9874471b9 100644 --- a/lib/ruby_lsp/tapioca/run_gem_rbi_check.rb +++ b/lib/ruby_lsp/tapioca/run_gem_rbi_check.rb @@ -13,9 +13,10 @@ class RunGemRbiCheck #: Process::Status? attr_reader :status - #: (String project_path) -> void - def initialize(project_path) + #: (String, ?String) -> void + def initialize(project_path, gem_rbi_dir = ::Tapioca::DEFAULT_GEM_DIR) @project_path = project_path + @gem_rbi_dir = gem_rbi_dir @stdout = "" #: String @stderr = "" #: String @status = nil #: Process::Status? @@ -79,16 +80,16 @@ def generate_gem_rbis #: (Array[String] gems) -> void def execute_tapioca_gem_command(gems) Bundler.with_unbundled_env do + cmd = ["bundle", "exec", "tapioca", "gem", "--lsp_addon"] + + if @gem_rbi_dir != ::Tapioca::DEFAULT_GEM_DIR + cmd.push("--outdir", @gem_rbi_dir) + end + + cmd.concat(gems) + stdout, stderr, status = Open3 #: as untyped - .capture3( - "bundle", - "exec", - "tapioca", - "gem", - "--lsp_addon", - *gems, - chdir: @project_path, - ) + .capture3(*cmd, chdir: @project_path) log_message(stdout) unless stdout.empty? @stderr = stderr unless stderr.empty? @@ -99,7 +100,7 @@ def execute_tapioca_gem_command(gems) #: (Array[String] gems) -> void def remove_rbis(gems) files = Dir.glob( - "sorbet/rbi/gems/{#{gems.join(",")}}@*.rbi", + "#{@gem_rbi_dir}/{#{gems.join(",")}}@*.rbi", base: @project_path, ) delete_files(files, "Removed RBIs for") @@ -117,7 +118,7 @@ def cleanup_orphaned_rbis #: (*untyped flags) -> Array[String] def git_ls_gem_rbis(*flags) self #: as untyped # rubocop:disable Style/RedundantSelf - .execute_in_project_path("git", "ls-files", *flags, "sorbet/rbi/gems/") + .execute_in_project_path("git", "ls-files", *flags, "#{@gem_rbi_dir}/") .lines .map(&:strip) end diff --git a/spec/tapioca/ruby_lsp/run_gem_rbi_check_spec.rb b/spec/tapioca/ruby_lsp/run_gem_rbi_check_spec.rb index 5d1a437f2..de3f6fc69 100644 --- a/spec/tapioca/ruby_lsp/run_gem_rbi_check_spec.rb +++ b/spec/tapioca/ruby_lsp/run_gem_rbi_check_spec.rb @@ -176,6 +176,26 @@ class RunGemRbiCheckSpec < SpecWithProject assert_project_file_exist("sorbet/rbi/gems/foo@0.0.1.rbi") end + + it "respects custom gem directory" do + FileUtils.mkdir_p("#{@project.absolute_path}/custom/gem/dir") + + foo = mock_gem("foo", "0.0.1") do + write!("lib/foo.rb", FOO_RB) + end + @project.require_mock_gem(foo) + @project.bundle_install! + + FileUtils.touch("#{@project.absolute_path}/custom/gem/dir/bar@0.0.1.rbi") + + check = ::RubyLsp::Tapioca::RunGemRbiCheck.new(@project.absolute_path, "custom/gem/dir") + check.run + + refute_project_file_exist("custom/gem/dir/bar@0.0.1.rbi") + assert_project_file_exist("custom/gem/dir/foo@0.0.1.rbi") + + @project.remove!("custom") + end end end end