Skip to content
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

Add hover functionality for dependencies in Gemfile #1279

Merged
merged 10 commits into from
Jan 10, 2024

Conversation

bravehager
Copy link
Contributor

Motivation

I've noticed that engineers are often inclined to litter their Gemfile with comments that summarize each and every gem dependency (often just pulling out the summary straight from the gemspec). This feels like a job for an LSP.

Implementation

Check for gem dependency definitions and add hover based on gem specification if applicable.

Overall, this PR could probably use some additional refactoring and test cases, but I wanted to present the concept for validation first.

Some open questions:

  • Do we display the summary, description or both?
  • Is there additional information in the spec worth displaying?
  • Should this feature be hidden behind a setting?
Screenshot 2024-01-04 at 2 51 11 PM

Automated Tests

Added a simple test case.

Manual Tests

  1. Open the branch
  2. Confirm the hover functionality for dependencies in Gemfile

@bravehager bravehager requested a review from a team as a code owner January 4, 2024 20:17
@KaanOzkan KaanOzkan requested review from vinistock and removed request for KaanOzkan January 4, 2024 21:26
Copy link
Member

@vinistock vinistock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really neat idea. Thanks for proposing this. I left some comments, but they are mostly details

lib/ruby_lsp/requests/hover.rb Outdated Show resolved Hide resolved
lib/ruby_lsp/requests/hover.rb Outdated Show resolved Hide resolved
lib/ruby_lsp/requests/hover.rb Show resolved Hide resolved
lib/ruby_lsp/requests/hover.rb Outdated Show resolved Hide resolved
test/requests/hover_expectations_test.rb Show resolved Hide resolved
@andyw8
Copy link
Contributor

andyw8 commented Jan 8, 2024

When testing this, I noticed problems with some gemspecs that use heredocs, e.g.:

https://github.com/lsegal/yard/blob/2d197a381c5d4cc5c55b2c60fff992b31c986361/yard.gemspec#L7-L12

Since the lines contain leading whitespace, the markdown treats that as code, so it renders like this:

Screenshot 2024-01-04 at 3 41 20 PM (1)

Really the gemspecs should be using <<~ rather than <<- but I think we should handle it by stripping the leading whitespace.

@andyw8
Copy link
Contributor

andyw8 commented Jan 8, 2024

Do we display the summary, description or both?

I think we should match rubygems.org:

https://github.com/rubygems/rubygems.org/blob/056a10c1634ae77a2dd418bf7303b06ccd1b9267/app/models/version.rb#L255

Comment on lines 163 to 165
info = [spec.description, spec.summary, "This rubygem does not have a description or summary."].find do |text|
!text.nil? && !text.empty?
end
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we can use #present? here since it's an Active Support extension—not the prettiest thing in the world but I think it's roughly the same in terms of functionality based on this guide.

@bravehager bravehager requested a review from vinistock January 8, 2024 21:42
@bravehager
Copy link
Contributor Author

@vinistock Thanks for the review! I think I incorporated all the feedback, let me know if there's anything else missing.

@bravehager
Copy link
Contributor Author

When testing this, I noticed problems with some gemspecs that use heredocs, e.g.:

https://github.com/lsegal/yard/blob/2d197a381c5d4cc5c55b2c60fff992b31c986361/yard.gemspec#L7-L12

Since the lines contain leading whitespace, the markdown treats that as code, so it renders like this:

I think this actually points out two issues, one being the incorrect use of heredocs and the other being that the content itself isn't actually markdown anyways.

I see a couple options:

  1. Truncate the leading whitespace on each line. Works for me, but AFAIK there's no way to distinguish between a string literal that uses a non-squiggly heredoc vs. has intentional leading whitespace (if there is, I think this is a great solution without many trade-offs).
  2. Use plaintext for the entire hover response.
  3. Keep using markdown but wrap only the summary/description so it doesn't get formatted. I tried using div and pre tags, but so far I could only get a text code fence to work:
Screenshot 2024-01-08 at 6 43 40 PM

Doesn't solve the original issue with heredocs but I think it might preserve the intentionality better in some cases, e.g. Minitest:

Screenshot 2024-01-08 at 6 46 46 PM

I'm fine w/ any solution (or something else entirely, or a combination of them).

@andyw8
Copy link
Contributor

andyw8 commented Jan 9, 2024

Option 1 makes sense to me. I can't think of a situation where there would be intentional leading whitespace in the description.

(Minitest is an odd one, I wouldn't worry too much about it since Rubygems.org doesn't render it well either: https://rubygems.org/gems/minitest/versions/5.20.0).

Copy link
Contributor

@andyw8 andyw8 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tried the latest update and YARD now displays correctly. Great work!

lib/ruby_lsp/requests/hover.rb Show resolved Hide resolved
Comment on lines +171 to +172
# Remove leading whitespace if a heredoc was used for the summary or description
info = info.gsub(/^ +/, "")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand the desire to make the presentation look good, but I wonder if we should instead create incentive for authors to fix their descriptions.

For example, YARD clearly wanted to use the ~ version of heredocs given that the entire description is indented at the same level. Feels like changing that in YARD would also ensure other tools display it correctly, rather than trying to account for that in the LSP.

Copy link
Contributor Author

@bravehager bravehager Jan 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it is kind of smoothing over an issue upstream. I can see the merits of either. We could also move the version into a Code Lens (or do away with it entirely), and keep the hover content restricted to the plaintext summary/description content.

Screenshot 2024-01-09 at 3 11 15 PM

Copy link
Contributor

@andyw8 andyw8 Jan 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, even the example in the Rubygems docs uses <<- with leading whitesapce:

https://guides.rubygems.org/specification-reference/#description

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can open a PR on https://github.com/rubygems/guides to use the squiggly heredoc. I would assume the docs pre-date the newer syntax itself?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that would be a helpful.

I still think we should strip the leading whitespace though, since some gems will never get around to updating, and it results in a disjointed experience for the user.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking about this more, even if it was supported in all non-EOL Ruby versions, it might actually restrict the gem from being installed on older versions due to invalid syntax, which might not be a reasonable trade-off.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Opened rubygems/guides#352 to address it in the RubyGems guides.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking about this more, even if it was supported in all non-EOL Ruby versions, it might actually restrict the gem from being installed on older versions due to invalid syntax, which might not be a reasonable trade-off.

The .gemspec file is not actually part of the distributed .gem package so I don't think it would be a problem.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TIL they're stored separately. It looks like the heredoc itself actually gets stripped out anyways and converted to a plain-old string literal (looking at my local copy of ~/.gem/ruby/3.3.0/specifications/yard-0.9.34.gemspec).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, let's ship this PR and we can always revisit the blank spaces thing later. No need to hold it back.

@@ -181,7 +181,6 @@ def test_hovering_over_gemfile_dependency

assert_includes(response.contents.value, spec.name)
assert_includes(response.contents.value, spec.version.to_s)
assert_includes(response.contents.value, spec.description)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think CI was failing on this line. Since we're stripping the description, I don't think we should assert on it anyways.

Copy link
Member

@vinistock vinistock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the contribution!

Comment on lines +171 to +172
# Remove leading whitespace if a heredoc was used for the summary or description
info = info.gsub(/^ +/, "")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, let's ship this PR and we can always revisit the blank spaces thing later. No need to hold it back.

@vinistock vinistock merged commit a68fceb into Shopify:main Jan 10, 2024
16 of 19 checks passed
@st0012 st0012 added the enhancement New feature or request label Jan 11, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants