-
Notifications
You must be signed in to change notification settings - Fork 86
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
Typechecking DSL files: top-level context and block context #974
Comments
Hey @lloeki I believe there is a way in RBS to define what self should be in a block (eg if it is instance_eval'd) https://github.com/ruby/rbs/blob/master/docs/syntax.md#self-type-binding Not sure about everything in this ticket but for the
|
Not sure if this is the right issue for this, but it is especially relevant I think for |
Confirmed that the top-level def test_self_type_annotation
run_type_check_test(
signatures: {},
code: {
"a.rb" => <<~RUBY
# @type self: String
self + ""
RUBY
},
expectations: <<~YAML
---
- file: a.rb
diagnostics: []
YAML
)
end
|
DSLs are great. Typed DSLs are even better: from the usual type checking of values to leveraging the LSP for autocompletion it would be fantastic that Steep could do a better job. Especially as a ton of DSLs are out there for many purposes and Ruby devs by and large love that, so I feel RBS/Steep would be incomplete without proper support of DSLs.
Here's the situation.
Steep DSL
Steep has a DSL... so I tried to typecheck
Steepfile
withsteep
!Unfortunately, despite the annotation
steep check Steepfile
gives:Note that for the last one it tried to look things up in
::Object
I tried adding more annotation to the block:
But it failed as well, in exactly the same way:
Note that it still references:
::Object
instead of::Steep::Project::DSL
for the last one::Steep::Project::DSL
instead of::Steep::Project::DSL::Target
for the last oneMaybe I'm misunderstanding the usage of the
@type: self
annotation?I also believe that once
target
is identified, Steep should be able to recognise that the block is to be evaluated in a::Steep::Project::DSL::Target
context as it isinstance_eval
'd, and thus ultimately findcheck
,library
, and whatnot.Maybe Steep can figure it out all by itself which would be ideal, or it needs the help of a Steep annotation, or RBS needs to provide that information in some way?
Rake DSL
Another popular DSL, I also tried to typecheck Rakefiles:
In spite of the
@type self: Rake::TaskLib
annotation,steep check Rakefile
gives:Again it failed in two areas:
::Object
instead ofRake::TaskLib
at the top level::Object
instead ofRake::TaskLib
on the nested blockI also believe that once top-level
namespace
is identified, Steep should be able to recognise that the block is still to be evaluated in aRake::TaskLib
context as it is merely yielded, and thus ultimately find nestednamespace
,task
, and whatnot.Again, maybe Steep can figure it out all by itself which would be ideal, or it needs the help of a Steep annotation, or RBS needs to provide that information in some way?
Gemfile
I tried type checking Gemfile too. It's a bit trickier as Bundler/Rubygems has no RBS signatures but a quick hack shows that it suffers from the same class of issues with
source
,gem
,group :foo do .. end
, etc... e.g:Minitest::Spec
Let's say I have something trivial:
And the corresponding spec:
steep check foo_spec.rb
gives:IIUC it works better because
Minitest::Spec
definesdescribe
onObject
, but you can see how it fails to pick up the block evaluation context, as with Steep and Rake.If I change it to add an annotation:
It then passes.
Still, I believe it should be really nice of Steep to find the evaluation context out, as the block is called with
class_eval
.Sure there's a bit of dancing with finding that dynamic
cls
but in terms of type I think it's all trackable in the code. Basically each class inherits from its parent in the stack, up toMinitest::Spec
(and its DSL).In addition, Steep might be able to figure out that in the following example
bar
is available for the second and third describe block but not the first:While currently it yells at all of them:
Similar examples could probably be produced by defining
bar
in a module and including it or extending with it at the seconddescribe
level.Again, maybe Steep can figure it out all by itself which would be ideal, or it needs the help of a Steep annotation, or RBS needs to provide that information in some way?
Rspec
I have not tried Rspec but the rationale should be similar as with Minitest::Spec.
Additional bits
Here's the RBS collection I used, checked out from
20e6e0f0685139dbd29df50e03367e222aa5d1b8
. I ignored a couple of inconsequential gems because they were yelling too loud, muddying the output.And for reference,
bundle show
:The text was updated successfully, but these errors were encountered: