-
Notifications
You must be signed in to change notification settings - Fork 139
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 support for RBS signature comments #2236
base: main
Are you sure you want to change the base?
Changes from all commits
c6f8239
7ca486e
c9591e8
4b11f0e
efda63e
8bed834
fa9f056
bd3f803
08d19f6
5995622
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -160,7 +160,7 @@ def with_rails_application(&blk) | |
Rails.app_class = Rails.application = rails_application | ||
end | ||
|
||
#: -> Array[singleton(Rails::Engine)] | ||
T::Sig::WithoutRuntime.sig { returns(T::Array[T.class_of(Rails::Engine)]) } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now that we re-execute the signatures, having a reference to |
||
def engines | ||
return [] unless defined?(Rails::Engine) | ||
|
||
|
@@ -216,7 +216,7 @@ def require_helper(file) | |
# The `eager_load_paths` method still exists, but doesn't return all paths anymore and causes Tapioca to miss some | ||
# engine paths. The following commit is the change: | ||
# https://github.com/rails/rails/commit/ebfca905db14020589c22e6937382e6f8f687664 | ||
#: (singleton(Rails::Engine) engine) -> Array[String] | ||
T::Sig::WithoutRuntime.sig { params(engine: T.class_of(Rails::Engine)).returns(T::Array[String]) } | ||
def eager_load_paths(engine) | ||
config = engine.config | ||
|
||
|
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,34 @@ | ||||||||
# typed: strict | ||||||||
# frozen_string_literal: true | ||||||||
|
||||||||
require "ruby-next/language/runtime" | ||||||||
|
||||||||
# This module rewrites RBS comments back into Sorbet's signatures as the files are being loaded. | ||||||||
# This will allow `sorbet-runtime` to wrap the methods as if they were originally written with the `sig{}` blocks. | ||||||||
# This will in turn allow Tapioca to use this signatures to generate typed RBI files. | ||||||||
|
||||||||
# We need to include `T::Sig` very early to make sure that the `sig` method is available since gems using RBS comments | ||||||||
# are unlikely to include `T::Sig` in their own classes. | ||||||||
Module.include(T::Sig) | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @KaanOzkan Is there any adverse effect to do this in the context of the LSP addon? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No it should be fine. Rewriting itself could be an issue with the addon, I'll test it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems okay on a first glance, not blocking. |
||||||||
|
||||||||
module Tapioca | ||||||||
module RBS | ||||||||
# Transpiles RBS comments back into Sorbet's `sig{}` blocks | ||||||||
class Rewriter < RubyNext::Language::Rewriters::Text | ||||||||
NAME = "rbs_rewriter" | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Out of curiosity, is this used by |
||||||||
|
||||||||
#: (String source) -> String | ||||||||
def rewrite(source) | ||||||||
# Do not try to parse files that don't have RBS comments | ||||||||
return source unless source =~ /^\s*#\s*typed: (ignore|false|true|strict|strong|__STDLIB_INTERNAL)/ | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Parsing all the files is a major slow down. We escape early if the file is not likely to contain Sorbet signatures. Note that I'd like for us to move away from having There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The more I'm thinking about it and the more I think it's a mistake. I already got confused while writing tests because I forgot the sigil. Matching on There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We would gain significant performance improvement for |
||||||||
|
||||||||
context.track!(self) | ||||||||
Spoom::Sorbet::Sigs.rbs_to_rbi(source) | ||||||||
end | ||||||||
end | ||||||||
end | ||||||||
end | ||||||||
|
||||||||
RubyNext::Language.include_patterns.clear | ||||||||
RubyNext::Language.include_patterns << "**/*.rb" | ||||||||
Comment on lines
+32
to
+33
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do these need to be cleared first? Does it include something other than Ruby files by default? We could do
Suggested change
or just append if it's already empty. |
||||||||
RubyNext::Language.rewriters = [Tapioca::RBS::Rewriter] | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note that we're replacing any list of rewriters that may have been set |
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.
Why are some comments now sigs? Is it so that tapioca's own RBIs are generated correctly?
Will it error in CI if someone wrote a RBS comment that was supposed to be a sig?
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.
It's only for the
checked(:never)
andSig::WithoutRuntime
because now that we re-inject them they get executed. This will only be required for the sigs in Tapioca we do not want to run at runtime.#2236 (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.
Thanks, I missed the
checked(:never)
calls. I think this is fine for now, we can look at speeding it up later.Locally I reverted some of these sigs to comments but I don't get any test failures. I'm wary that we'll forget to use sigs in this case and only encounter the issue after we release/merge. Is there a way we can run into this failure in CI and create a check?
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.
CI should fail if any of this method gets reverted to one checked at runtime. Try with the
BasicObject
test for example:bin/test -n "/can handle Basic/"
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.
Oh yeah. I tested it with RBI generation which strangely succeeds but CI fails. Thanks.