class Protocol::MethodParser
Parse protocol method definition to derive a Message
specification.
Attributes
__source_cache__[RW]
arg_kinds[R]
Returns the kinds of the arguments of the parsed method.
args[R]
Returns the names of the arguments of the parsed method.
arity[R]
Returns the arity of the parsed method.
Public Class Methods
flush_source_cache()
click to toggle source
Flushes the source cache.
# File lib/protocol/method_parser/ruby_parser.rb, line 10 def flush_source_cache __source_cache__.clear self end
new(modul, methodname, eigenclass = false)
click to toggle source
Create a new MethodParser
instance for method methodname
of module modul
. For eigenmethods set eigenclass
to true, otherwise bad things will happen.
# File lib/protocol/method_parser/ruby_parser.rb, line 20 def initialize(modul, methodname, eigenclass = false) @method = Module === modul ? modul.instance_method(methodname) : modul.method(methodname) compute_args parse_method end
Public Instance Methods
arg(i)
click to toggle source
Returns the i-th argument (beginning with 0).
# File lib/protocol/method_parser/ruby_parser.rb, line 32 def arg(i) @args[i] end
arg_kind(i)
click to toggle source
Returns the i-th kind of an argument (beginning with 0).
# File lib/protocol/method_parser/ruby_parser.rb, line 40 def arg_kind(i) @arg_kinds[i] end
block_arg?()
click to toggle source
Return true if a block argument was detected.
# File lib/protocol/method_parser/ruby_parser.rb, line 54 def block_arg? @arg_kinds.last == :block end
complex?()
click to toggle source
Return true if this protocol method is a complex method, which ought to be called for checking conformance to the protocol.
# File lib/protocol/method_parser/ruby_parser.rb, line 49 def complex? @complex end
Private Instance Methods
cached_source(filename)
click to toggle source
# File lib/protocol/method_parser/ruby_parser.rb, line 84 def cached_source(filename) cache = self.class.__source_cache__ unless source = cache[filename] begin source = IO.readlines(filename) cache[filename] = source $DEBUG and warn "#{self.class} just cached #{filename.inspect}." rescue SystemCallError => e $DEBUG and warn "Caught #{e.class}: #{e}" nil end end source end
compute_args()
click to toggle source
# File lib/protocol/method_parser/ruby_parser.rb, line 60 def compute_args @arity = @method.arity if @method.respond_to?(:parameters) parameters = @method.parameters @args, @arg_kinds = parameters.map do |kind, name| case kind when :req [ name, kind ] when :opt [ name, kind ] when :rest [ :"*#{name}", kind ] when :block [ :"&#{name}", kind ] end end.compact.transpose else raise NotImplementedError, "#{@method.class}#parameters as in ruby version >=1.9.2 is required" end @args ||= [] @arg_kinds ||= [] end
parse_method()
click to toggle source
# File lib/protocol/method_parser/ruby_parser.rb, line 99 def parse_method @complex = false filename, lineno = @method.source_location if filename source = cached_source(filename) or return source = source[(lineno - 1)..-1].join current = 0 tree = nil parser = RubyParser.new while current = source.index('end', current) current += 3 begin tree = parser.parse(source[0, current], filename) break rescue SyntaxError, Racc::ParseError end parser.reset end ary = tree.to_a.flatten @complex = ary.any? { |node| [ :call, :fcall, :vcall ].include?(node) } if ary.index(:yield) and @arg_kinds.last != :block @args.push :'&block' @arg_kinds.push :block end end end