2013-03-11 4 views
0

나는 다음과 같은 DSL에 대한 YARD 플러그인을 작성하는 문제가 있습니다YARD는 YARD 플러그인 하나 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 

가 지금은 그 방법에 메모를 추가 할을 '문서 스 니펫은 DSL my_dsl에 의해 영향을받습니다. my_dsl 내에서 (나는 방법에 대한 기존의 이미 확장 할, 나는 몇 가지 새로운 문서를 추가하지 않습니다.) 범위는 완전히 다른 핸들러

그래서 위해 필요한 방법을 표시 MyDSLHandler#process 내부 Proxy 코드 객체를 사용하기로 결정 (. 내 내장 MethodHandlerdef 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 개체가 YARD::CodeObjects::Base에서하지, 일반 Object에서 파생 된 것입니다 때문에 더 []=이 없습니다 정의 된 메소드 :

[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

글쎄, 해결할 수있었습니다.

여기서 Proxy의 사용을 가정하지 않습니다. CodeObject에는 매우 독특한 특징이 있습니다. "침묵하는"싱글 톤입니다. 따라서 CodeObject.new을 통해 개체를 정의하면 같은 개체 (Registry에 따라)의 new에 대한 모든 향후 호출이 기존 개체로 다시 매핑됩니다.

그러므로 내 경우에는 단순히 만드는 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 메서드를 반환해야합니다.