Well, what does let
do? It creates a method whose name is given by the symbol argument and whose return value is given by the return value of the block.
So, if you wanted to write a type for that, you would have to
- take the symbol and turn it into a method name
- take the return type of the block and turn it into the return type of the method
I am pretty sure that is not possible with RDoc or YARD type notation.
So, the best thing you can do is a synthetic attribute reader:
# @!attribute [r] document
# @return [Document] a fake document
let(:document) { FactoryBot.create :document }
Note that YARD does support macros, but macros obviously only have access to what is in the source code, and the return type of the block is not part of the source code. In fact, the documentation block you showed looks like it was generated by a macro that looks somewhat like this:
# Defines a memoized method
# @param [Symbol] name the method name
# @param block how to compute the value
# @!macro [attach] let
# @!attribute [r] $1
# @return the value defined by the block
def let(name, &block) end
This will tell YARD that wherever it sees a call to let
, it should insert a synthetic documentation block for an attribute reader whose name is the first argument to let
.
However, it will not allow you to use the type of the block. These are the only interpolation variables that exist:
$0
- the method name being called
$1
, $2
, $3
, … - the Nth argument in the method call
$&
- the full source line
What would work, is if let
took a second argument that is the type, then you could write a macro like this:
# Defines a memoized method
# @param [Symbol] name the method name
# @param [Module] type the type of the memoized value
# @param block how to compute the value
# @!macro [attach] let
# @!attribute [r] $1
# @return [${-1}] the value defined by the block
def let(name, type, &block) end
And then you would call it like this:
let(:document, Document) { FactoryBot.create :document }
But, that is not how RSpec is designed, so the best you can do is the synthetic attribute reader from my first suggestion.