ruby-lsp 0.7.4 → 0.7.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/exe/ruby-lsp +12 -23
- data/lib/ruby_lsp/requests/show_syntax_tree.rb +1 -1
- data/lib/ruby_lsp/requests/support/common.rb +1 -1
- data/lib/ruby_lsp/requests/support/dependency_detector.rb +4 -1
- data/lib/ruby_lsp/setup_bundler.rb +79 -49
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a645362acbfb8b0f819bd89fbaf1e53d0f7d9eda81974e62bc0f114aeefc221e
|
4
|
+
data.tar.gz: 861b5c68f9355f551ebfb519507ca1c0028f0e4e2edff70ae6ad62c652bdfd2c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4283abdb1ce9865e6dbecd0827ddd88f07a63937a9f75ba8ca78142d3536624ac374b165e7a1277adee4197553c74615ed560dad3093eb346ae3e505e174dae5
|
7
|
+
data.tar.gz: 6084fd63d0d780c169b8f8766f347cdb699e2490a0c8de542a3fa969ad37d7f49e281ffa7f92a7ee15a764dccac9832e5e9a49265ba9077f9d204185d0c00e64
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.7.
|
1
|
+
0.7.6
|
data/exe/ruby-lsp
CHANGED
@@ -1,33 +1,22 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
# We should make sure that, if we're running on a bundler project, that it has a Gemfile.lock
|
5
|
-
if File.exist?("Gemfile") && !File.exist?("Gemfile.lock")
|
6
|
-
warn("Project contains a Gemfile, but no Gemfile.lock. Run `bundle install` to lock gems and restart the server")
|
7
|
-
exit(78)
|
8
|
-
end
|
9
|
-
|
10
4
|
# When we're running without bundler, then we need to make sure the custom bundle is fully configured and re-execute
|
11
5
|
# using `BUNDLE_GEMFILE=.ruby-lsp/Gemfile bundle exec ruby-lsp` so that we have access to the gems that are a part of
|
12
6
|
# the application's bundle
|
13
|
-
if ENV["BUNDLE_GEMFILE"].nil?
|
7
|
+
if ENV["BUNDLE_GEMFILE"].nil?
|
14
8
|
require_relative "../lib/ruby_lsp/setup_bundler"
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
path = Bundler.settings["path"]
|
27
|
-
|
28
|
-
command = +"BUNDLE_GEMFILE=#{bundle_gemfile} bundle exec ruby-lsp #{ARGV.join(" ")}"
|
29
|
-
command.prepend("BUNDLE_PATH=#{File.expand_path(path, Dir.pwd)} ") if path
|
30
|
-
exit exec(command)
|
9
|
+
|
10
|
+
begin
|
11
|
+
bundle_gemfile, bundle_path = RubyLsp::SetupBundler.new(Dir.pwd).setup!
|
12
|
+
rescue RubyLsp::SetupBundler::BundleNotLocked
|
13
|
+
warn("Project contains a Gemfile, but no Gemfile.lock. Run `bundle install` to lock gems and restart the server")
|
14
|
+
exit(78)
|
15
|
+
end
|
16
|
+
|
17
|
+
env = { "BUNDLE_GEMFILE" => bundle_gemfile }
|
18
|
+
env["BUNDLE_PATH"] = bundle_path if bundle_path
|
19
|
+
exit exec(env, "bundle exec ruby-lsp #{ARGV.join(" ")}")
|
31
20
|
end
|
32
21
|
|
33
22
|
require "sorbet-runtime"
|
@@ -47,7 +47,7 @@ module RubyLsp
|
|
47
47
|
start_char = scanner.find_char_position(range[:start])
|
48
48
|
end_char = scanner.find_char_position(range[:end])
|
49
49
|
|
50
|
-
queue = T.cast(@document.tree, SyntaxTree::Program).statements.body
|
50
|
+
queue = T.cast(@document.tree, SyntaxTree::Program).statements.body.dup
|
51
51
|
found_nodes = []
|
52
52
|
|
53
53
|
until queue.empty?
|
@@ -26,7 +26,7 @@ module RubyLsp
|
|
26
26
|
params(node: T.any(SyntaxTree::ConstPathRef, SyntaxTree::ConstRef, SyntaxTree::TopConstRef)).returns(String)
|
27
27
|
end
|
28
28
|
def full_constant_name(node)
|
29
|
-
name =
|
29
|
+
name = node.constant.value.dup
|
30
30
|
constant = T.let(node, SyntaxTree::Node)
|
31
31
|
|
32
32
|
while constant.is_a?(SyntaxTree::ConstPathRef)
|
@@ -38,7 +38,10 @@ module RubyLsp
|
|
38
38
|
|
39
39
|
sig { params(gem_pattern: Regexp).returns(T::Boolean) }
|
40
40
|
def direct_dependency?(gem_pattern)
|
41
|
-
Bundler.
|
41
|
+
Bundler.with_original_env { Bundler.default_gemfile } &&
|
42
|
+
Bundler.locked_gems.dependencies.keys.grep(gem_pattern).any?
|
43
|
+
rescue Bundler::GemfileNotFound
|
44
|
+
false
|
42
45
|
end
|
43
46
|
end
|
44
47
|
end
|
@@ -4,6 +4,7 @@
|
|
4
4
|
require "sorbet-runtime"
|
5
5
|
require "bundler"
|
6
6
|
require "fileutils"
|
7
|
+
require "pathname"
|
7
8
|
|
8
9
|
# This file is a script that will configure a custom bundle for the Ruby LSP. The custom bundle allows developers to use
|
9
10
|
# the Ruby LSP without including the gem in their application's Gemfile while at the same time giving us access to the
|
@@ -13,123 +14,151 @@ module RubyLsp
|
|
13
14
|
class SetupBundler
|
14
15
|
extend T::Sig
|
15
16
|
|
17
|
+
class BundleNotLocked < StandardError; end
|
18
|
+
|
16
19
|
sig { params(project_path: String).void }
|
17
20
|
def initialize(project_path)
|
18
21
|
@project_path = project_path
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
22
|
+
|
23
|
+
# Custom bundle paths
|
24
|
+
@custom_dir = T.let(Pathname.new(".ruby-lsp").expand_path(Dir.pwd), Pathname)
|
25
|
+
@custom_gemfile = T.let(@custom_dir + "Gemfile", Pathname)
|
26
|
+
@custom_lockfile = T.let(@custom_dir + "Gemfile.lock", Pathname)
|
27
|
+
|
28
|
+
# Regular bundle paths
|
29
|
+
@gemfile = T.let(
|
30
|
+
begin
|
31
|
+
Bundler.default_gemfile
|
32
|
+
rescue Bundler::GemfileNotFound
|
33
|
+
nil
|
25
34
|
end,
|
26
|
-
T
|
35
|
+
T.nilable(Pathname),
|
27
36
|
)
|
37
|
+
@lockfile = T.let(@gemfile ? Bundler.default_lockfile : nil, T.nilable(Pathname))
|
38
|
+
|
39
|
+
@dependencies = T.let(load_dependencies, T::Hash[String, T.untyped])
|
40
|
+
@custom_bundle_dependencies = T.let(custom_bundle_dependencies, T::Hash[String, T.untyped])
|
28
41
|
end
|
29
42
|
|
30
|
-
|
43
|
+
# Setups up the custom bundle and returns the `BUNDLE_GEMFILE` and `BUNDLE_PATH` that should be used for running the
|
44
|
+
# server
|
45
|
+
sig { returns([String, T.nilable(String)]) }
|
31
46
|
def setup!
|
32
|
-
|
33
|
-
if File.basename(@project_path) == "ruby-lsp"
|
34
|
-
warn("Ruby LSP> Skipping custom bundle setup since we're working on the Ruby LSP itself")
|
35
|
-
run_bundle_install
|
36
|
-
return
|
37
|
-
end
|
47
|
+
raise BundleNotLocked if @gemfile&.exist? && !@lockfile&.exist?
|
38
48
|
|
39
49
|
# Do not setup a custom bundle if both `ruby-lsp` and `debug` are already in the Gemfile
|
40
50
|
if @dependencies["ruby-lsp"] && @dependencies["debug"]
|
41
|
-
warn("Ruby LSP> Skipping custom bundle setup since both `ruby-lsp` and `debug` are already in
|
51
|
+
warn("Ruby LSP> Skipping custom bundle setup since both `ruby-lsp` and `debug` are already in #{@gemfile}")
|
42
52
|
|
43
53
|
# If the user decided to add the `ruby-lsp` and `debug` to their Gemfile after having already run the Ruby LSP,
|
44
54
|
# then we need to remove the `.ruby-lsp` folder, otherwise we will run `bundle install` for the top level and
|
45
55
|
# try to execute the Ruby LSP using the custom bundle, which will fail since the gems are not installed there
|
46
|
-
|
47
|
-
run_bundle_install
|
48
|
-
return
|
56
|
+
@custom_dir.rmtree if @custom_dir.exist?
|
57
|
+
return run_bundle_install
|
49
58
|
end
|
50
59
|
|
51
60
|
# Automatically create and ignore the .ruby-lsp folder for users
|
52
|
-
|
53
|
-
|
61
|
+
@custom_dir.mkpath unless @custom_dir.exist?
|
62
|
+
ignore_file = @custom_dir + ".gitignore"
|
63
|
+
ignore_file.write("*") unless ignore_file.exist?
|
54
64
|
|
55
|
-
|
56
|
-
content = custom_gemfile_content
|
65
|
+
write_custom_gemfile
|
57
66
|
|
58
|
-
unless
|
59
|
-
|
67
|
+
unless @gemfile&.exist? && @lockfile&.exist?
|
68
|
+
warn("Ruby LSP> Skipping lockfile copies because there's no top level bundle")
|
69
|
+
return run_bundle_install(@custom_gemfile)
|
60
70
|
end
|
61
71
|
|
62
72
|
# If .ruby-lsp/Gemfile.lock already exists and the top level Gemfile.lock hasn't been modified since it was last
|
63
73
|
# updated, then we're ready to boot the server
|
64
|
-
if
|
65
|
-
|
66
|
-
|
67
|
-
run_bundle_install(".ruby-lsp/Gemfile")
|
68
|
-
return
|
74
|
+
if @custom_lockfile.exist? && @custom_lockfile.stat.mtime > @lockfile.stat.mtime
|
75
|
+
warn("Ruby LSP> Skipping custom bundle setup since #{@custom_lockfile} already exists and is up to date")
|
76
|
+
return run_bundle_install(@custom_gemfile)
|
69
77
|
end
|
70
78
|
|
71
|
-
FileUtils.cp(
|
72
|
-
run_bundle_install(
|
79
|
+
FileUtils.cp(@lockfile.to_s, @custom_lockfile.to_s)
|
80
|
+
run_bundle_install(@custom_gemfile)
|
73
81
|
end
|
74
82
|
|
75
83
|
private
|
76
84
|
|
77
|
-
sig { returns(String) }
|
78
|
-
def
|
85
|
+
sig { returns(T::Hash[String, T.untyped]) }
|
86
|
+
def custom_bundle_dependencies
|
87
|
+
return {} unless @custom_lockfile.exist?
|
88
|
+
|
89
|
+
ENV["BUNDLE_GEMFILE"] = @custom_gemfile.to_s
|
90
|
+
Bundler::LockfileParser.new(@custom_lockfile.read).dependencies
|
91
|
+
ensure
|
92
|
+
ENV.delete("BUNDLE_GEMFILE")
|
93
|
+
end
|
94
|
+
|
95
|
+
sig { void }
|
96
|
+
def write_custom_gemfile
|
79
97
|
parts = [
|
80
98
|
"# This custom gemfile is automatically generated by the Ruby LSP.",
|
81
99
|
"# It should be automatically git ignored, but in any case: do not commit it to your repository.",
|
82
100
|
"",
|
83
|
-
"eval_gemfile(File.expand_path(\"../Gemfile\", __dir__))",
|
84
101
|
]
|
85
102
|
|
103
|
+
# If there's a top level Gemfile, we want to evaluate from the custom bundle. We get the source from the top level
|
104
|
+
# Gemfile, so if there isn't one we need to add a default source
|
105
|
+
if @gemfile&.exist?
|
106
|
+
parts << "eval_gemfile(File.expand_path(\"../Gemfile\", __dir__))"
|
107
|
+
else
|
108
|
+
parts.unshift('source "https://rubygems.org"')
|
109
|
+
end
|
110
|
+
|
86
111
|
unless @dependencies["ruby-lsp"]
|
87
|
-
parts << 'gem "ruby-lsp", require: false, group: :development
|
112
|
+
parts << 'gem "ruby-lsp", require: false, group: :development'
|
88
113
|
end
|
89
114
|
|
90
115
|
unless @dependencies["debug"]
|
91
|
-
parts << 'gem "debug", require: false, group: :development, platforms: :mri
|
116
|
+
parts << 'gem "debug", require: false, group: :development, platforms: :mri'
|
92
117
|
end
|
93
118
|
|
94
|
-
parts.join("\n")
|
119
|
+
content = parts.join("\n")
|
120
|
+
@custom_gemfile.write(content) unless @custom_gemfile.exist? && @custom_gemfile.read == content
|
95
121
|
end
|
96
122
|
|
97
123
|
sig { returns(T::Hash[String, T.untyped]) }
|
98
124
|
def load_dependencies
|
125
|
+
return {} unless @lockfile&.exist?
|
126
|
+
|
99
127
|
# We need to parse the Gemfile.lock manually here. If we try to do `bundler/setup` to use something more
|
100
128
|
# convenient, we may end up with issues when the globally installed `ruby-lsp` version mismatches the one included
|
101
129
|
# in the `Gemfile`
|
102
|
-
dependencies = Bundler::LockfileParser.new(
|
130
|
+
dependencies = Bundler::LockfileParser.new(@lockfile.read).dependencies
|
103
131
|
|
104
132
|
# When working on a gem, the `ruby-lsp` might be listed as a dependency in the gemspec. We need to make sure we
|
105
|
-
# check those as well or else we may get version mismatch errors
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
dependencies.merge!(gemspec_dependencies)
|
133
|
+
# check those as well or else we may get version mismatch errors. Notice that bundler allows more than one
|
134
|
+
# gemspec, so we need to make sure we go through all of them
|
135
|
+
Dir.glob("{,*}.gemspec").each do |path|
|
136
|
+
dependencies.merge!(Bundler.load_gemspec(path).dependencies.to_h { |dep| [dep.name, dep] })
|
110
137
|
end
|
111
138
|
|
112
139
|
dependencies
|
113
140
|
end
|
114
141
|
|
115
|
-
sig { params(bundle_gemfile: T.
|
116
|
-
def run_bundle_install(bundle_gemfile =
|
142
|
+
sig { params(bundle_gemfile: T.nilable(Pathname)).returns([String, T.nilable(String)]) }
|
143
|
+
def run_bundle_install(bundle_gemfile = @gemfile)
|
117
144
|
# If the user has a custom bundle path configured, we need to ensure that we will use the absolute and not
|
118
145
|
# relative version of it when running `bundle install`. This is necessary to avoid installing the gems under the
|
119
146
|
# `.ruby-lsp` folder, which is not the user's intention. For example, if the path is configured as `vendor`, we
|
120
147
|
# want to install it in the top level `vendor` and not `.ruby-lsp/vendor`
|
121
148
|
path = Bundler.settings["path"]
|
122
149
|
|
123
|
-
command = +""
|
124
150
|
# Use the absolute `BUNDLE_PATH` to prevent accidentally creating unwanted folders under `.ruby-lsp`
|
125
|
-
|
126
|
-
|
151
|
+
env = {}
|
152
|
+
env["BUNDLE_GEMFILE"] = bundle_gemfile.to_s
|
153
|
+
env["BUNDLE_PATH"] = File.expand_path(path, Dir.pwd) if path
|
127
154
|
|
128
155
|
# If both `ruby-lsp` and `debug` are already in the Gemfile, then we shouldn't try to upgrade them or else we'll
|
129
156
|
# produce undesired source control changes. If the custom bundle was just created and either `ruby-lsp` or `debug`
|
130
157
|
# weren't a part of the Gemfile, then we need to run `bundle install` for the first time to generate the
|
131
158
|
# Gemfile.lock with them included or else Bundler will complain that they're missing. We can only update if the
|
132
159
|
# custom `.ruby-lsp/Gemfile.lock` already exists and includes both gems
|
160
|
+
command = +""
|
161
|
+
|
133
162
|
if (@dependencies["ruby-lsp"] && @dependencies["debug"]) ||
|
134
163
|
@custom_bundle_dependencies["ruby-lsp"].nil? || @custom_bundle_dependencies["debug"].nil?
|
135
164
|
# Install gems using the custom bundle
|
@@ -147,7 +176,8 @@ module RubyLsp
|
|
147
176
|
|
148
177
|
# Add bundle update
|
149
178
|
warn("Ruby LSP> Running bundle install for the custom bundle. This may take a while...")
|
150
|
-
system(command)
|
179
|
+
system(env, command)
|
180
|
+
[bundle_gemfile.to_s, path]
|
151
181
|
end
|
152
182
|
end
|
153
183
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-lsp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shopify
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-08-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: language_server-protocol
|
@@ -140,7 +140,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
140
140
|
- !ruby/object:Gem::Version
|
141
141
|
version: '0'
|
142
142
|
requirements: []
|
143
|
-
rubygems_version: 3.4.
|
143
|
+
rubygems_version: 3.4.17
|
144
144
|
signing_key:
|
145
145
|
specification_version: 4
|
146
146
|
summary: An opinionated language server for Ruby
|