ruby-lsp 0.7.5 → 0.7.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4825b35aef41194e36092d705d02735786950d140842c20d210ae79ece322a00
4
- data.tar.gz: 980bb51fca93844ec0e2bcf2ce57779441fd90a243bf8dab1c30d6dec683e438
3
+ metadata.gz: a645362acbfb8b0f819bd89fbaf1e53d0f7d9eda81974e62bc0f114aeefc221e
4
+ data.tar.gz: 861b5c68f9355f551ebfb519507ca1c0028f0e4e2edff70ae6ad62c652bdfd2c
5
5
  SHA512:
6
- metadata.gz: 5ce7d7401bf7a817a90b6cabeb3d2da7bcc7115d5cb2bf38d5866d4e30061eab615e1fc5366059e7c46630701e11345eb00ac8a09d171d17864ec7fae2ef5a58
7
- data.tar.gz: cb90d3684d0ea67aa35b53ff694821ecac2b30d43a878a6b24ac6bed873c8ed1eb284fb94a01f4295abda13a612dc0c757e233e0e6a96b2ab70e08c1ce2ddaf1
6
+ metadata.gz: 4283abdb1ce9865e6dbecd0827ddd88f07a63937a9f75ba8ca78142d3536624ac374b165e7a1277adee4197553c74615ed560dad3093eb346ae3e505e174dae5
7
+ data.tar.gz: 6084fd63d0d780c169b8f8766f347cdb699e2490a0c8de542a3fa969ad37d7f49e281ffa7f92a7ee15a764dccac9832e5e9a49265ba9077f9d204185d0c00e64
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.7.5
1
+ 0.7.6
data/exe/ruby-lsp CHANGED
@@ -1,32 +1,21 @@
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? && File.exist?("Gemfile.lock")
7
+ if ENV["BUNDLE_GEMFILE"].nil?
14
8
  require_relative "../lib/ruby_lsp/setup_bundler"
15
- RubyLsp::SetupBundler.new(Dir.pwd).setup!
16
-
17
- # In some cases, like when the `ruby-lsp` is already a part of the bundle, we don't generate `.ruby-lsp/Gemfile`.
18
- # However, we still want to run the server with `bundle exec`. We need to make sure we're pointing to the right
19
- # `Gemfile`
20
- bundle_gemfile = File.exist?(".ruby-lsp/Gemfile") ? ".ruby-lsp/Gemfile" : "Gemfile"
21
9
 
22
- # In addition to BUNDLE_GEMFILE, we also need to make sure that BUNDLE_PATH is absolute and not relative. For example,
23
- # if BUNDLE_PATH is `vendor/bundle`, we want the top level `vendor/bundle` and not `.ruby-lsp/vendor/bundle`.
24
- # Expanding to get the absolute path ensures we're pointing to the correct folder, which is the same one we use in
25
- # SetupBundler to install the gems
26
- path = Bundler.settings["path"]
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
27
16
 
28
17
  env = { "BUNDLE_GEMFILE" => bundle_gemfile }
29
- env["BUNDLE_PATH"] = File.expand_path(path, Dir.pwd) if path
18
+ env["BUNDLE_PATH"] = bundle_path if bundle_path
30
19
  exit exec(env, "bundle exec ruby-lsp #{ARGV.join(" ")}")
31
20
  end
32
21
 
@@ -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,107 +14,133 @@ 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
- @dependencies = T.let(load_dependencies, T::Hash[String, T.untyped])
20
- @custom_bundle_dependencies = T.let(
21
- if File.exist?(".ruby-lsp/Gemfile.lock")
22
- Bundler::LockfileParser.new(Bundler.read_file(".ruby-lsp/Gemfile.lock")).dependencies
23
- else
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::Hash[String, T.untyped],
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
- sig { void }
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
- # Do not setup a custom bundle if we're working on the Ruby LSP, since it's already included by default
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 the Gemfile")
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
- FileUtils.rm_r(".ruby-lsp") if Dir.exist?(".ruby-lsp")
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
- FileUtils.mkdir(".ruby-lsp") unless Dir.exist?(".ruby-lsp")
53
- File.write(".ruby-lsp/.gitignore", "*") unless File.exist?(".ruby-lsp/.gitignore")
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
- # Write the custom `.ruby-lsp/Gemfile` if it doesn't exist or if the content doesn't match
56
- content = custom_gemfile_content
65
+ write_custom_gemfile
57
66
 
58
- unless File.exist?(".ruby-lsp/Gemfile") && File.read(".ruby-lsp/Gemfile") == content
59
- File.write(".ruby-lsp/Gemfile", content)
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 File.exist?(".ruby-lsp/Gemfile.lock") &&
65
- File.stat(".ruby-lsp/Gemfile.lock").mtime > File.stat("Gemfile.lock").mtime
66
- warn("Ruby LSP> Skipping custom bundle setup since .ruby-lsp/Gemfile.lock already exists and is up to date")
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("Gemfile.lock", ".ruby-lsp/Gemfile.lock")
72
- run_bundle_install(".ruby-lsp/Gemfile")
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 custom_gemfile_content
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, source: "https://rubygems.org"'
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, source: "https://rubygems.org"'
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(Bundler.read_file("Gemfile.lock")).dependencies
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
- gemspec_path = Dir.glob("*.gemspec").first
107
- if gemspec_path
108
- gemspec_dependencies = Bundler.load_gemspec(gemspec_path).dependencies.to_h { |dep| [dep.name, dep] }
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.untyped).void }
116
- def run_bundle_install(bundle_gemfile = nil)
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
@@ -122,7 +149,7 @@ module RubyLsp
122
149
 
123
150
  # Use the absolute `BUNDLE_PATH` to prevent accidentally creating unwanted folders under `.ruby-lsp`
124
151
  env = {}
125
- env["BUNDLE_GEMFILE"] = bundle_gemfile if bundle_gemfile
152
+ env["BUNDLE_GEMFILE"] = bundle_gemfile.to_s
126
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
@@ -150,6 +177,7 @@ module RubyLsp
150
177
  # Add bundle update
151
178
  warn("Ruby LSP> Running bundle install for the custom bundle. This may take a while...")
152
179
  system(env, command)
180
+ [bundle_gemfile.to_s, path]
153
181
  end
154
182
  end
155
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.5
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-08-01 00:00:00.000000000 Z
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.16
143
+ rubygems_version: 3.4.17
144
144
  signing_key:
145
145
  specification_version: 4
146
146
  summary: An opinionated language server for Ruby