#!/usr/bin/env ruby # frozen_string_literal: true require "optparse" original_args = ARGV.dup options = {} parser = OptionParser.new do |opts| opts.banner = "Usage: ruby-lsp [options]" opts.on("--version", "Print ruby-lsp version") do require "ruby-lsp" puts RubyLsp::VERSION exit(0) end opts.on("--debug", "Launch the Ruby LSP with a debugger attached") do options[:debug] = true end opts.on("--time-index", "Measure the time it takes to index the project") do options[:time_index] = true end opts.on( "--branch [BRANCH]", "Launch the Ruby LSP using the specified branch rather than the release version", ) do |branch| options[:branch] = branch end opts.on( "--experimental", "Run pre-release versions of the Ruby LSP", ) do options[:experimental] = true end opts.on("--doctor", "Run troubleshooting steps") do options[:doctor] = true end opts.on("-h", "--help", "Print this help") do puts opts.help puts puts "See https://shopify.github.io/ruby-lsp/ for more information" exit(0) end end begin parser.parse! rescue OptionParser::InvalidOption => e warn(e) warn("") warn(parser.help) exit(1) end # When we're running without bundler, then we need to make sure the custom bundle is fully configured and re-execute # using `BUNDLE_GEMFILE=.ruby-lsp/Gemfile bundle exec ruby-lsp` so that we have access to the gems that are a part of # the application's bundle if ENV["BUNDLE_GEMFILE"].nil? require_relative "../lib/ruby_lsp/setup_bundler" begin bundle_gemfile, bundle_path, bundle_app_config = RubyLsp::SetupBundler.new(Dir.pwd, **options).setup! rescue RubyLsp::SetupBundler::BundleNotLocked warn("Project contains a Gemfile, but no Gemfile.lock. Run `bundle install` to lock gems and restart the server") exit(78) end env = { "BUNDLE_GEMFILE" => bundle_gemfile } env["BUNDLE_PATH"] = bundle_path if bundle_path env["BUNDLE_APP_CONFIG"] = bundle_app_config if bundle_app_config exit exec(env, "bundle exec ruby-lsp #{original_args.join(" ")}") end require "ruby_lsp/load_sorbet" $LOAD_PATH.unshift(File.expand_path("../lib", __dir__)) require "ruby_lsp/internal" if options[:debug] if ["x64-mingw-ucrt", "x64-mingw32"].include?(RUBY_PLATFORM) $stderr.puts "Debugging is not supported on Windows" exit 1 end begin ENV.delete("RUBY_DEBUG_IRB_CONSOLE") require "debug/open_nonstop" rescue LoadError $stderr.puts("You need to install the debug gem to use the --debug flag") end end if options[:time_index] require "benchmark" index = RubyIndexer::Index.new result = Benchmark.realtime { index.index_all } entries = index.instance_variable_get(:@entries) entries_by_entry_type = entries.values.flatten.group_by(&:class) puts <<~MSG Ruby LSP v#{RubyLsp::VERSION}: Indexing took #{result.round(5)} seconds and generated: - #{entries_by_entry_type.sort_by { |k, _| k.to_s }.map { |k, v| "#{k.name.split("::").last}: #{v.size}" }.join("\n- ")} MSG return end if options[:doctor] index = RubyIndexer::Index.new if File.exist?(".index.yml") begin config = YAML.parse_file(".index.yml").to_ruby rescue => e abort("Error parsing config: #{e.message}") end index.configuration.apply_config(config) end puts "Globbing for indexable files" index.configuration.indexables.each do |indexable| puts "indexing: #{indexable.full_path}" index.index_single(indexable) end return end RubyLsp::Server.new.start