-
Notifications
You must be signed in to change notification settings - Fork 37
Implement "go to definition" for render calls in ERB templates
#659
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
base: main
Are you sure you want to change the base?
Conversation
It's common to want to traverse through several partials while updating HTML that a controller action renders. Rails.vim has a neat `gf` shortcut for this, though it probably doesn't have the precision that Prism would provide. This brings the same functionality to Ruby LSP Rails, by implementing "go to definition" support for render calls inside ERB templates. It supports partial name passed as positional argument, or via `:partial`, `:layout`, and `:spacer_template` keyword arguments. It even handles `:variants`, `:formats`, and `:handlers` options, as well as `:template` for rendering non-partial templates. Relative lookup will also check in view directories of controller ancestors. For the latter, I considered doing a call to the Rails process that will return `ActionController::Base._prefixes`. However, I couldn't think of a good enough interface, and that method ableit public is undocumented, so it seems like we shouldn't rely on it. Given that this ancestry lookup is non-configurable anyway, I chose to implement it in Ruby LSP land based on indexed controller files. To avoid the overhead of booting the Rails process too many times in tests, I updated the test helpers to allow sending multiple `textDocument/definition` requests to the same server.
rafaelfranca
left a comment
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.
Made a few comments. Typechecker is failing and new methods are missing typing information.
Also add missing type annotations.
While here, we undo changes in code lens to handle custom view paths. If this approach is accepted, we can always update the code lens later.
|
@rafaelfranca I believe I addressed all your feedback and fixed typechecking. |
rafaelfranca
left a comment
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.
Amazing work!
@Shopify/ruby-dx can someone do a second review?
|
I have signed the CLA! |
In our app, we have an `app/views/shared/components` directory that contains shared "component" partials. It doesn't have any matching controller, and components can render other components, you just need to specify the full path to the render call (we have a helper method for that). We should make go to definition work for these cases as well.
It's common to want to traverse through several partials while updating HTML that a controller action renders. Rails.vim has a neat
gfshortcut for this. This brings the same functionality to Ruby LSP Rails, by implementing "go to definition" support forrendercalls inside ERB templates.Screen.Recording.2025-10-28.at.21.08.51.mov
It supports partial name passed as positional argument, or via
:partial,:layout, and:spacer_templatekeyword arguments. It even handles:variants,:formats, and:handlersoptions, as well as:templatefor rendering non-partial templates.The initial implementation mimicked the template lookup logic inside the language server. However, that turned out to be more complex and didn't handle custom
view_paths. So, I ended up callingActionView::LookupContextto perform the actual template lookup on the server. I also needed to determine the controller from the template directory in a way that handles customview_paths, as well as handle controllerless template directories.To avoid the overhead of booting the Rails process too many times in tests, I updated the test helpers to allow sending multiple
textDocument/definitionrequests to the same server.