Add rewriter to transform attributes into methods#308
Conversation
| class AttrWriter | ||
| sig { returns(T::Array[Method]) } | ||
| def convert_to_methods | ||
| raise "How can there be multiple?" unless sigs.one? |
There was a problem hiding this comment.
Sig overloads are allowed in RBI files: sorbet/sorbet#7412
There was a problem hiding this comment.
In .rbi files only. With sorbet.run you're testing with a .rb file.
There was a problem hiding this comment.
Indeed, looks like it allows it, but the revealed type is whichever one you listed first. I think we should warn in that case, it likely wasn't intended.
There was a problem hiding this comment.
We currently do not do any linting / warning inside rbi, it's up to the client to make sure that what is produced is correct.
This could be a warning in Tapioca when pulling the gem's hand-written annotations. Or it could be done by Sorbet.
61d982d to
a425158
Compare
|
Here were the previously open questions. Spoke offline, decisions in-line. 1. Which
|
b8d34ae to
d321f86
Compare
| comments: T::Array[Comment], | ||
| ).returns(Method) | ||
| end | ||
| def create_setter_method(name, sig, attribute_type, visibility, loc, comments) # rubocop:disable Metrics/ParameterLists |
There was a problem hiding this comment.
6 params, but the upper limit is 5. Worth overriding?
e9b5a36 to
a501a77
Compare
866256c to
f1f606f
Compare
lib/rbi/rewriters/attr_to_methods.rb
Outdated
| def visit(node) | ||
| case node | ||
| when Tree | ||
| visit_all(node.nodes) |
There was a problem hiding this comment.
Curious, why does this work correctly without needing a .dup?
| visit_all(node.nodes) | |
| visit_all(node.nodes.dup) |
There seems to be a risk of concurrently modifying an array while it's being iterated by the visitor. Perhaps we just don't hit that edge case in our tests.
There was a problem hiding this comment.
I think you need a test iterating over multiple nodes:
class Foo
def foo; end
attr_accessor :bar
def baz; end
endThere was a problem hiding this comment.
Yeah I tried that, and a bunch of more complex cases, and they all work fine lol
There was a problem hiding this comment.
Ah, it's needed, so I added.
This case reproduces it:
rbi = Parser.parse_string(<<~RBI)
class Foo
sig { returns(Integer) }
attr_reader :i1
sig { returns(Integer) }
attr_reader :i2
end
RBII thought I by alternating def and attr I'd have the highest chance of hitting it, but in fact, that's the only safe configuration haha
lib/rbi/rewriters/attr_to_methods.rb
Outdated
| def visit(node) | ||
| case node | ||
| when Tree | ||
| visit_all(node.nodes) |
There was a problem hiding this comment.
I think you need a test iterating over multiple nodes:
class Foo
def foo; end
attr_accessor :bar
def baz; end
endf1f606f to
ae559a7
Compare
ae559a7 to
b1807ac
Compare
| case node | ||
| when Tree | ||
| visit_all(node.nodes.dup) | ||
|
|
|
|
||
| module RBI | ||
| class UnexpectedMultipleSigsError < Error | ||
| attr_reader :node |
There was a problem hiding this comment.
| attr_reader :node | |
| sig { returns(Node) } | |
| attr_reader :node |
b1807ac to
e572c2c
Compare
e572c2c to
c47cd74
Compare
Part of Shopify/tapioca#1918
This PR introduces a new rewriter which transforms
attr_reader/attr_writer/attr_accessorRBIs into methods with the corresponding sigs. This has two benefits: