-
Notifications
You must be signed in to change notification settings - Fork 194
/
Copy pathruby-lsp
executable file
·166 lines (134 loc) · 4.7 KB
/
ruby-lsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#!/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(
"--new-addon [NAME]",
"Create a new Ruby LSP add-on gem",
) do |name|
options[:new_addon] = name
end
opts.on("--doctor", "Run troubleshooting steps") do
options[:doctor] = true
end
opts.on("--use-launcher", "[EXPERIMENTAL] Use launcher mechanism to handle missing dependencies gracefully") do
options[:launcher] = 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 composed 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?
# Substitute the current process by the launcher. RubyGems activates all dependencies of a gem's executable eagerly,
# but we can't have that happen because we want to invoke Bundler.setup ourselves with the composed bundle and avoid
# duplicate spec activation errors. Replacing the process with the launcher executable will clear the activated specs,
# which gives us the opportunity to control which specs are activated and enter degraded mode if any gems failed to
# install rather than failing to boot the server completely
if options[:launcher]
flags = []
flags << "--debug" if options[:debug]
exit exec(Gem.ruby, File.expand_path("ruby-lsp-launcher", __dir__), *flags)
end
require_relative "../lib/ruby_lsp/setup_bundler"
begin
env = 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
bundler_path = File.join(Gem.default_bindir, "bundle")
base_command = (!Gem.win_platform? && File.exist?(bundler_path) ? "#{Gem.ruby} #{bundler_path}" : "bundle").dup
if env["BUNDLER_VERSION"]
base_command << " _#{env["BUNDLER_VERSION"]}_"
end
exit exec(env, "#{base_command} exec ruby-lsp #{original_args.join(" ")}".strip)
end
$LOAD_PATH.unshift(File.expand_path("../lib", __dir__))
require "ruby_lsp/load_sorbet"
require "ruby_lsp/internal"
T::Utils.run_all_sig_blocks
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]
index = RubyIndexer::Index.new
time_start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
index.index_all
elapsed_time = Process.clock_gettime(Process::CLOCK_MONOTONIC) - time_start
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 #{elapsed_time.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.indexable_uris.each do |uri|
puts "indexing: #{uri}"
index.index_file(uri)
end
return
end
if options[:new_addon]
require "ruby_lsp/generator"
RubyLsp::Generator.new(options[:new_addon]).run
exit(0)
end
# Ensure all output goes out stderr by default to allow puts/p/pp to work
# without specifying output device.
$> = $stderr
RubyLsp::Server.new.start