Reputation: 121010
I have the problem writing YARD plugin for the following DSL:
class MyClass
my_dsl :do_it, :do_other
def do_it
# do it
end
def do_other
# do other
end
def do_unrelated
# do unrelated
end
end
Now I want to add notes to those methods’ documentation snippets, which are “influenced” by DSL my_dsl
. Within my_dsl
handler the scope is totally different (I don’t want to add some new docs, I want to extend already existing for methods.)
So I decided to use Proxy code object inside MyDSLHandler#process
to mark the needed methods for delayed future postprocessing (which is to occur within built-in MethodHandler
on def do_it ; … ; end
.) It looks like:
class MyDSLHandler < YARD::Handlers::Ruby::DSLHandler
handles method_call(:my_dsl)
namespace_only
def process
statement.parameters.each { |astnode|
mthd = astnode.jump(:string_content).source if astnode.respond_to? :jump
obj = YARD::CodeObjects::Proxy.new(namespace, "\##{mthd}", :method)
register(obj)
obj[:my_dsl_params] << {
name: mthd,
file: statement.file, line: statement.line # I need this!
}
}
end
end
Now the problem is that the Proxy
object is derived from plain Object
, not from YARD::CodeObjects::Base
and therefore has no []=
method defined:
[warn]: Load Order / Name Resolution Problem on MyClass#do_it:
[warn]: -
[warn]: Something is trying to call [] on object MyClass#do_it before it has been recognized.
[warn]: This error usually means that you need to modify the order in which you parse files
[warn]: so that MyClass#do_it is parsed before methods or other objects attempt to access it.
[warn]: -
[warn]: YARD will recover from this error and continue to parse but you *may* have problems
[warn]: with your generated documentation. You should probably fix this.
[warn]: -
[error]: Unhandled exception in Yard::Handlers::MyDSLHandler:
[error]: in `example_mydsl.rb`:5:
5: my_dsl :do_it, :do_other
[error]: ProxyMethodError: Proxy cannot call method #[] on object 'MyClass#do_it'
How am I supposed to store some values from current context to Proxy
object, so that they would be available during object real instantiation?
Upvotes: 0
Views: 418
Reputation: 121010
Well, I was able to resolve it.
The use of Proxy
here is not supposed. The CodeObject
s have a pretty peculiarity: they are “silent” singletons. Hence, as you have defined an object via CodeObject.new
, all the forthcoming calls to new
on the same object (according to Registry
) will be re-mapped to the existing one.
Therefore in my case I simply create the MethodObject
:
m = "#{astnode.jump(:string_content).source[1..-1]}";
obj = YARD::CodeObjects::MethodObject.new(namespace, "#{m}")
and then I do what I want on the newly created object:
obj.my_dsl_params = { :win => true, :mthd => "#{m}", … }
The object within method definition parse will merge
these properties with it’s own. The only need is either to register an object with register(obj)
or to return it from process
method for system registering.
Upvotes: 1