-
Notifications
You must be signed in to change notification settings - Fork 172
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Include non-development gemspec dependencies in DependencyDetector check #1031
Conversation
@@ -44,7 +44,7 @@ def typechecker? | |||
sig { params(gem_pattern: Regexp).returns(T::Boolean) } | |||
def direct_dependency?(gem_pattern) | |||
Bundler.with_original_env { Bundler.default_gemfile } && | |||
Bundler.locked_gems.dependencies.keys.grep(gem_pattern).any? | |||
Bundler.locked_gems.specs.map(&:name).grep(gem_pattern).any? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@vinistock what do you think of this approach? The other way might be to keep Bundler.locked_gems.dependencies
but separately read from .gemspec
, then aggregate them.
3bcd88b
to
6f43f53
Compare
6f43f53
to
a94279b
Compare
Dir.glob("{,*}.gemspec").flat_map do |path| | ||
Bundler.load_gemspec(path).dependencies.map(&:name) | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The gemspec
should have already been loaded by the gemfile, so I don't think finding it and loading it is the best way to do this.
I would instead recommend something like:
Bundler.locked_gems.sources.find { Bundler::Source::Gemspec === _1 }&.gemspec&.dependencies
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that seems cleaner. @vinistock, should we update the load_dependencies
method to do the same?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just for illustration, with
spec.add_dependency("minitest", "~> 5.0")
spec.add_dependency("minitest-reporters")
we get:
irb(main):005:0> Bundler.locked_gems.dependencies.keys
=> ["bundler", "debug", "rake", "rubocop-shopify", "rubocop-sorbet", "spoom", "tapioca"]
irb(main):006:0> Bundler.load_gemspec(gemspec_path).dependencies.map(&:name)
=> ["bundler", "minitest", "minitest-reporters", "rake", "erubi", "sorbet-static-and-runtime", "syntax_tree", "thor"]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's make sure it is really equivalent and that we get the same results. In case we do, are you talking about load_dependencies
in SetupBundler
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah SetupBundler#load_dependencies
. But on second thoughts, let's keep this PR focused on the DependencyDetector.
Co-authored-by: Ufuk Kayserilioglu <[email protected]>
|
||
sig { returns(T::Array[String]) } | ||
def gemspec_dependencies | ||
Array(Bundler.locked_gems.sources.find { Bundler::Source::Gemspec === _1 }&.gemspec&.dependencies).map(&:name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bundler supports more than one gemspec in the same project, so I think this needs to be something like
Bundler.locked_gems.sources.each_with_object([]) do |source, dependencies|
next unless Bundler::Source::Gemspec === source
dependencies.concat(source.gemspec&.dependencies.map(&:name))
end
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 Updated in 8af680d
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no need for each_with_object
here:
Bundler.locked_gems.sources.flat_map do |source|
next unless Bundler::Source::Gemspec === source
Array(source.gemspec&.dependencies).map(&:name)
end.compact
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, even better by doing the filtering first and then doing a flat map:
Bundler.locked_gems.sources.grep(Bundler::Source::Gemspec).flat_map { |source| Array(source.gemspec&.dependencies) }.map(&:name)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's almost what I had in 8af680d, but grepping by the class name is nice, I've updated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I honestly, don't think any of those options are more readable than using each_with_object
- in addition to them allocating more arrays. But whatever you all decide is fine.
Co-authored-by: Vinicius Stock <[email protected]>
083d5da
to
216877e
Compare
Motivation
Addresses the server side of #1635. We will need another change for the extension: Shopify/vscode-ruby-lsp#814
Note
We should aim to launch this alongside the extension update, to avoid inconsistent behaviour.
Implementation
Using the same approach as we already have in
SetupBunder#load_dependencies
.Automated Tests
Updated
Manual Tests
Start with the current (released version of Ruby LSP). We'll use Spoom verifiying.
In Spoom's gemspec, change
minitest
andminitest-reporters
to beadd_dependency
instead ofadd_development_dependency
. Open a test and confirm the code lens is not showing.Now, point
rubyLsp.branch
to this branch. Confirm the code lenses.