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

Sanitize version from source location #1095

Conversation

vinistock
Copy link
Member

Motivation

Including the gem versions in source location comments causes a lot of churn in RBIs every time there are gem upgrades. We can use a special string VERSION and let the Ruby LSP figure out the versions itself.

Implementation

Just started sanitizing the version numbers for VERSION and re-generated the RBIs. This branch is based on #1094.

Tests

Adapted the existing tests.

@vinistock vinistock self-assigned this Aug 3, 2022
@vinistock vinistock requested a review from a team as a code owner August 3, 2022 19:31
@@ -66,6 +66,10 @@ def add_source_location_comment(node, file, line)
return
end

# Sanitize the gem version from the comment to avoid excessive churn in the RBI when upgrading gems. The
# version is always between a hyphen at the end of the gem name and the `/lib` folder
Copy link
Member

Choose a reason for hiding this comment

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

Maybe we can also mention that having -VERSION will make ruby-lsp easier to substitute it with the actual version for path restoration?
I think currently it's not clear on why we keep this if the reader doesn't know how we'll use the source comment.

@@ -66,6 +66,10 @@ def add_source_location_comment(node, file, line)
return
end

# Sanitize the gem version from the comment to avoid excessive churn in the RBI when upgrading gems. The
# version is always between a hyphen at the end of the gem name and the `/lib` folder
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
# version is always between a hyphen at the end of the gem name and the `/lib` folder
# version is always between a hyphen at the end of the gem name and the `/lib` folder.

@@ -52,7 +52,7 @@ def add_source_location_comment(node, file, line)
realpath = path.realpath.to_s

path = if realpath.start_with?(gem.full_gem_path)
"#{gem.name}-#{gem.version}/#{path.realpath.relative_path_from(gem.full_gem_path)}"
"#{gem.name}-VERSION/#{path.realpath.relative_path_from(gem.full_gem_path)}"
Copy link
Member

Choose a reason for hiding this comment

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

I really don't like the fact that we are adding a VERSION string to the source URI. I think the problem here is that we are not treating the source: protocol as a URI scheme and we have never defined it properly. So far, we've been approaching it adhoc and have been assembling and parsing it using string operations instead of URI operations, which is generally asking for trouble.

I would suggest the following:

source://[gem_name][@version]/<path>[#<line_number>]

as the URI scheme where [] sections are always optional, and <> sections are mandatory.

So, here are the different cases we can encode with this:

  1. Implicit gem name and version: source:///some/path/to/file.rb#42
  2. Explicit gem name and implicit gem version: source://my_popular_gem/some/path/to/file.rb#42
  3. Explicit gem name and version: source://[email protected]/some/path/to/file.rb#42
  4. Link to file with unknown line number: source://[email protected]/some/path/to/file.rb

Moreover, we should be able to write a URI::Generic subclass to do the building/parsing of these source URIs.

Copy link
Member Author

Choose a reason for hiding this comment

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

I love the idea. Do we then need another scheme for Ruby lib paths?

Copy link
Member

@paracycle paracycle Aug 5, 2022

Choose a reason for hiding this comment

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

Do we then need another scheme for Ruby lib paths?

I think not. IMO, we are confounding where the gem is installed with where inside the gem this code is coming from. We want to encode the latter and leave it up to the client to resolve where the specified gem/version should be found.

For example, it could be the case that on my system I have the gem [email protected] installed in the Ruby lib path, but on a colleague's machine [email protected] is installed by Bundler/Rubygems to the gem path (imagine the colleague is using an older Ruby that bundles with [email protected] and [email protected] was a dependency in the lockfile).

It should be the responsibility of the client to resolve [email protected] to a path on disk and to then resolve the path relative to that location.

Copy link
Member Author

Choose a reason for hiding this comment

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

Sorry, I wasn't clear. I'm not talking about where the gem is installed.

I mean when methods are defined not inside a gem, but inside the Ruby standard library. Like in this test, where Mutex_m method locations are in the Ruby path - not inside any gems.

Those files are inside RbConfig::CONFIG["rubylibdir"] and not Bundler.bundle_path, so we need some way of differentiating between gems and the stdlib.

Copy link
Member

Choose a reason for hiding this comment

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

yes, I know, and that is still a gem: https://github.com/ruby/mutex_m

$ gem list

*** LOCAL GEMS ***

aasm (5.2.0)
abbrev (default: 0.1.0)
actioncable (7.0.3, 7.0.2.4, 7.0.2.3, 6.1.5, 6.1.4.6)
...
mutex_m (default: 0.1.1)
...

Copy link
Member Author

Choose a reason for hiding this comment

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

So, is your suggestion to do source://mutex.rb#12 and let the client figure out where it is?

Copy link
Member

Choose a reason for hiding this comment

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

More like source://[email protected]/mutex_m.rb#12, but yeah. Since, like I said in my comment above, on another machine the 0.1.1 version of the mutex_m gem can be installed in the normal gem path.

@vinistock vinistock force-pushed the vs/fix_source_location_for_gems_installed_from_source branch 3 times, most recently from f8272bd to 0da60d8 Compare August 11, 2022 17:24
@vinistock
Copy link
Member Author

I'll combine the work of this PR into #1094.

@vinistock vinistock closed this Aug 11, 2022
@vinistock vinistock deleted the vs/sanitize_version_from_source_location branch August 11, 2022 17:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants