Fix anonymous parameter modeling and merging#624
Conversation
833bfe5 to
4d0c0b0
Compare
| end | ||
|
|
||
| class Param | ||
| # @override |
There was a problem hiding this comment.
Override of what? This class has no subclass
There was a problem hiding this comment.
It's an override of Node#compatible_with?.
Param and the other nodes in this files are all subclasses of Node, though they are just reopenings so we didn't specify the superclass again.
There was a problem hiding this comment.
though they are just reopenings so we didn't specify the superclass again.
We should never do that. If you are reopening keep the inheritance correct.
Signed-off-by: Alexandre Terrasa <alexandre.terrasa@shopify.com>
Signed-off-by: Alexandre Terrasa <alexandre.terrasa@shopify.com>
4d0c0b0 to
be2225d
Compare
Signed-off-by: Alexandre Terrasa <alexandre.terrasa@shopify.com>
Signed-off-by: Alexandre Terrasa <alexandre.terrasa@shopify.com>
be2225d to
290fc6f
Compare
amomchilov
left a comment
There was a problem hiding this comment.
Forgot to submit my draft review. 🤦
Small comments.
| end | ||
| SigParam.new(name, sig_param.type) | ||
| end | ||
| sig.params.replace(sig_params) |
| def initialize(name, value, loc: nil, comments: nil, &block) | ||
| super(name, loc: loc, comments: comments) | ||
| super(loc: loc, comments: comments) | ||
| @name = name.to_s #: String |
There was a problem hiding this comment.
It's already a string, likewise below
| @name = name.to_s #: String | |
| @name = name |
| when Prism::SymbolNode | ||
| node.value.to_s | ||
| else | ||
| node_string!(node).delete_suffix(":") |
There was a problem hiding this comment.
BTW This breaks for unusual sigs, like params("a": Integer)
I have a wip to fix this across the repo
Summary
Fixes Shopify/spoom#928.
This updates RBI’s parameter model to represent Ruby anonymous parameters faithfully instead of approximating anonymity through parameter names.
Ruby supports anonymous rest, keyword rest, and block parameters:
Prism represents these with
name == nil. RBI now preserves that information in the model instead of assigning synthetic names.Previous behavior
Before this change, every
RBI::Paramhad a non-nilname, and anonymity was tracked through an@anonymousivar derived from the name:That meant names starting with
_were treated as anonymous, even though they are still real Ruby parameter names.However, this was name-based, not syntax-based. True Ruby anonymous parameters could not be represented directly because the model required a string name. The parser had to synthesize names instead:
Merge behavior was also somewhat surprising:
_-prefixed names acted as wildcards for parameters of the same kind.What changed
RBI::Paramis now more abstract and no longer stores a requiredname.ReqParamOptParamKwParamKwOptParamRestParamKwRestParamBlockParam@anonymousivar.nil.nilnames for anonymous Ruby params:***&"*""**""&"Merge behavior
Method merging now treats anonymous params as compatible with named params only when the parameter kind is compatible.
Anonymous params are not a wildcard for arbitrary parameter shapes. They only mean “this parameter has no name.”
For example:
RestParam(nil)is compatible withRestParam("args")KwRestParam(nil)is compatible withKwRestParam("kwargs")BlockParam(nil)is compatible withBlockParam("block")RestParam(nil)is not compatible withReqParam("arg")When one side has an anonymous parameter and the other side has a named parameter of the same kind, merge prefers the non-anonymous name.
Example:
merged with:
produces:
This also updates sig merging so anonymous sig projection names are renamed to match the final merged method parameters.
Breaking changes
This is a breaking API change for consumers of the RBI model.
Previously, callers could generally assume every parameter had a non-nil name-like value. That is no longer true:
RBI::Paramitself no longer stores a requiredname.RestParam#name,KwRestParam#name, andBlockParam#namecan now benil._-prefixed parameter names are no longer considered anonymous by default.nilnames or callanonymous?.Merge behavior changed as well:
_-prefixed named params no longer act as anonymous wildcardsThis makes the model more accurate, but downstream code assuming anonymous params have stable synthetic names, or assuming
_-prefixed names are anonymous, will need to be updated.