0

我在为以下 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处理程序中,范围完全不同(我不想添加一些新文档,我想扩展已经存在的方法。)

所以我决定在里面使用Proxy代码对象MyDSLHandler#process来标记延迟未来后处理所需的方法(这将发生在内置MethodHandleron 中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对象是从 plain 派生的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对象,以便它们在对象实际实例化期间可用?

4

1 回答 1

1

好吧,我能够解决它。

这里的使用Proxy是不应该的。s 有一个非常特殊的CodeObject特性:它们是“沉默的”单例。因此,当您通过 定义对象时,对同一对象(根据)的CodeObject.new所有即将调用都将重新映射到现有对象。newRegistry

因此,在我的情况下,我只是创建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

于 2013-03-13T14:00:21.077 回答