我在为以下DSL编写YARD插件时遇到问题:
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
现在我想为这些方法的文档片段添加注释,这些片段受DSL my_dsl
的“影响”。在my_dsl
处理程序中,范围完全不同(我不想添加一些新文档,我想扩展已存在的方法。)
所以我决定在MyDSLHandler#process
中使用Proxy代码对象来标记延迟的未来后期处理所需的方法(这将在MethodHandler
内置def do_it ; … ; end
内进行。)看起来像:
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
现在问题是Proxy
对象派生于普通Object
,而不是来自YARD::CodeObjects::Base
,因此没有定义[]=
方法:
[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'
我应该如何将当前上下文中的某些值存储到Proxy
对象,以便它们在对象真实实例化期间可用?
答案 0 :(得分:0)
好吧,我能够解决它。
不应该在这里使用Proxy
。 CodeObject
有一个非常独特的特点:他们是“沉默的”单身人士。因此,当您通过CodeObject.new
定义了一个对象时,所有即将对同一对象new
的调用(根据Registry
)将被重新映射到现有对象。
因此在我的情况下,我只需创建MethodObject
:
m = "#{astnode.jump(:string_content).source[1..-1]}";
obj = YARD::CodeObjects::MethodObject.new(namespace, "#{m}")
然后我在新创建的对象上执行我想要的操作:
obj.my_dsl_params = { :win => true, :mthd => "#{m}", … }
方法定义中的对象解析将merge
这些属性与它自己的属性。唯一的需要是使用register(obj)
注册一个对象,或者从process
方法返回它以进行系统注册。