class YARD::Parser::Ruby::TokenResolver
Supports {#each} enumeration over a source’s tokens, yielding the token and a possible {CodeObjects::Base} associated with the constant or identifier token.
Public Class Methods
new(source, namespace = Registry.root)
click to toggle source
Creates a token resolver for given source.
@param source [String] the source code to tokenize @param namespace [CodeObjects::Base] the object/namespace to resolve from
# File lib/yard/parser/ruby/token_resolver.rb, line 16 def initialize(source, namespace = Registry.root) @tokens = RubyParser.parse(source, '(tokenize)').tokens raise ParserSyntaxError if @tokens.empty? && !source.empty? @default_namespace = namespace end
state_attr(*attrs)
click to toggle source
# File lib/yard/parser/ruby/token_resolver.rb, line 92 def self.state_attr(*attrs) attrs.each do |attr| define_method(attr) { @states.last[attr.to_sym] } define_method("#{attr}=") {|v| @states.last[attr.to_sym] = v } protected attr, :"#{attr}=" end end
Public Instance Methods
each() { |token, nil| ... }
click to toggle source
Iterates over each token, yielding the token and a possible code object that is associated with the token.
@yieldparam token [Array(Symbol,String,Array(Integer,Integer))] the
current token object being iterated
@yieldparam object [CodeObjects::Base, nil] the fully qualified code
object associated with the current token, or nil if there is no object for the yielded token.
@example Yielding code objects
r = TokenResolver.new("A::B::C") r.each do |tok, obj| if obj puts "#{tok[0]} -> #{obj.path.inspect}" else puts "No object: #{tok.inspect}" end end # Prints: # :const -> "A" # No object: [:op, "::"] # :const -> "A::B" # No object: [:op, "::"] # :const -> "A::B::C"
# File lib/yard/parser/ruby/token_resolver.rb, line 46 def each @states = [] push_state @tokens.each do |token| yield_obj = false if skip_group && [:const, :ident, :op, :period].include?(token[0]) yield token, nil next else self.skip_group = false end case token[0] when :const lookup(token[0], token[1]) yield_obj = true self.last_sep = nil when :ident lookup(token[0], token[1]) yield_obj = true self.last_sep = nil when :op, :period self.last_sep = token[1] unless CodeObjects.types_for_separator(token[1]) self.object = nil self.last_sep = nil end when :lparen push_state when :rparen pop_state else self.object = nil end yield token, (yield_obj ? object : nil) if next_object self.object = next_object self.next_object = nil end self.skip_group = true if yield_obj && object.nil? end end
Private Instance Methods
lookup(toktype, name)
click to toggle source
# File lib/yard/parser/ruby/token_resolver.rb, line 112 def lookup(toktype, name) types = object_resolved_types return self.object = nil if types.empty? if toktype == :const types.any? do |type| prefix = type ? type.path : "" prefix += last_sep.to_s if separators.include?(last_sep.to_s) self.object = Registry.resolve(@default_namespace, "#{prefix}#{name}", true) end else # ident types.any? do |type| obj = Registry.resolve(type, name, true) if obj.nil? && name == "new" obj = Registry.resolve(object, "#initialize", true) self.next_object = object if obj.nil? end self.object = obj end end end
object_resolved_types(obj = object)
click to toggle source
# File lib/yard/parser/ruby/token_resolver.rb, line 134 def object_resolved_types(obj = object) return [obj] unless obj.is_a?(CodeObjects::MethodObject) resolved_types = [] tags = obj.tags(:return) tags += obj.tags(:overload).map {|o| o.tags(:return) }.flatten tags.each do |tag| next if tag.types.nil? tag.types.each do |type| type = type.sub(/<.+>/, '') if type == "self" resolved_types << obj.parent else type_obj = Registry.resolve(obj, type, true) resolved_types << type_obj if type_obj end end end resolved_types end
pop_state()
click to toggle source
# File lib/yard/parser/ruby/token_resolver.rb, line 106 def pop_state @states.pop end
push_state()
click to toggle source
# File lib/yard/parser/ruby/token_resolver.rb, line 102 def push_state @states.push :object => nil, :skip_group => false, :last_sep => nil end