-
Notifications
You must be signed in to change notification settings - Fork 7
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 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sig overloads are allowed in RBI files: sorbet/sorbet#7412
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.
Not for attributes, though. Sorbet.run
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.
In .rbi
files only. With sorbet.run you're testing with a .rb
file.
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.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you need a test iterating over multiple nodes:
class Foo
def foo; end
attr_accessor :bar
def baz; end
end
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.
Yeah I tried that, and a bunch of more complex cases, and they all work fine lol
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.
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
RBI
I 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you need a test iterating over multiple nodes:
class Foo
def foo; end
attr_accessor :bar
def baz; end
end
f1f606f
to
ae559a7
Compare
ae559a7
to
b1807ac
Compare
case node | ||
when Tree | ||
visit_all(node.nodes.dup) | ||
|
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.
|
||
module RBI | ||
class UnexpectedMultipleSigsError < Error | ||
attr_reader :node |
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.
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_accessor
RBIs into methods with the corresponding sigs. This has two benefits: