123456789_123456789_123456789_123456789_123456789_

Class: YARD::Handlers::Processor

Relationships & Source Files
Inherits: Object
Defined in: lib/yard/handlers/processor.rb

Overview

Iterates over all statements in a file and delegates them to the Base objects that are registered to handle the statement.

This class is passed to each handler and keeps overall processing state. For example, if the #visibility is set in a handler, all following statements will have access to this state. This allows "public", "protected" and "private" statements to be handled in classes and modules. In addition, the #namespace can be set during parsing to control where objects are being created from. You can also access extra stateful properties that any handler can set during the duration of the post processing of a file from #extra_state. If you need to access state across different files, look at #globals.

See Also:

Class Attribute Summary

Class Method Summary

Instance Attribute Summary

Instance Method Summary

Constructor Details

.new(parser) ⇒ Processor

Creates a new Processor for a #file.

Parameters:

[ GitHub ]

  
# File 'lib/yard/handlers/processor.rb', line 92

def initialize(parser)
  @file = parser.file || "(stdin)"
  @namespace = YARD::Registry.root
  @visibility = :public
  @scope = :instance
  @owner = @namespace
  @parser_type = parser.parser_type
  @handlers_loaded = {}
  @globals = parser.globals || OpenStruct.new
  @extra_state = OpenStruct.new
  load_handlers
end

Class Attribute Details

.namespace_for_handlerHash (readonly)

This method is for internal use only.

Returns:

  • (Hash)

    a list of registered parser type extensions

Since:

  • 0.6.0

[ GitHub ]

  
# File 'lib/yard/handlers/processor.rb', line 33

attr_reader :namespace_for_handler

Class Method Details

.register_handler_namespace(type, ns)

Registers a new namespace for handlers of the given type.

Since:

  • 0.6.0

[ GitHub ]

  
# File 'lib/yard/handlers/processor.rb', line 24

def register_handler_namespace(type, ns)
  namespace_for_handler[type] = ns
end

Instance Attribute Details

#extra_stateOpenStruct (rw)

Share state across different handlers inside of a file. This attribute is similar to #visibility, #scope, #namespace and #owner, in that they all maintain state across all handlers for the entire source file. Use this attribute to store any data your handler might need to save during the parsing of a file. If you need to save state across files, see #globals.

Returns:

  • (OpenStruct)

    an open structure that can store arbitrary data

See Also:

[ GitHub ]

  
# File 'lib/yard/handlers/processor.rb', line 88

attr_accessor :extra_state

#fileString (rw)

Returns:

[ GitHub ]

  
# File 'lib/yard/handlers/processor.rb', line 41

attr_accessor :file

#globalsOpenStruct (rw)

::YARD::Handlers can share state for the entire post processing stage through this attribute. Note that post processing stage spans multiple files. To share state only within a single file, use #extra_state

Examples:

Sharing state among two handlers

class Handler1 < YARD::Handlers::Ruby::Base
  handles :class
  process { globals.foo = :bar }
end

class Handler2 < YARD::Handlers::Ruby::Base
  handles :method
  process { puts globals.foo }
end

Returns:

  • (OpenStruct)

    global shared state for post-processing stage

See Also:

[ GitHub ]

  
# File 'lib/yard/handlers/processor.rb', line 77

attr_accessor :globals

#namespaceCodeObjects::NamespaceObject (rw)

Returns:

[ GitHub ]

  
# File 'lib/yard/handlers/processor.rb', line 44

attr_accessor :namespace

#ownerCodeObjects::Base? (rw)

Returns:

  • (CodeObjects::Base, nil)

    unlike the namespace, the owner is a non-namespace object that should be stored between statements. For instance, when parsing a method body, the ::YARD::CodeObjects::MethodObject is set as the owner, in case any extra method information is processed.

[ GitHub ]

  
# File 'lib/yard/handlers/processor.rb', line 56

attr_accessor :owner

#parser_typeSymbol (rw)

Returns:

  • (Symbol)

    the parser type (:ruby, :ruby18, :c)

[ GitHub ]

  
# File 'lib/yard/handlers/processor.rb', line 59

attr_accessor :parser_type

#scopeSymbol (rw)

Returns:

  • (Symbol)

    the current scope (class, instance)

[ GitHub ]

  
# File 'lib/yard/handlers/processor.rb', line 50

attr_accessor :scope

#visibilitySymbol (rw)

Returns:

  • (Symbol)

    the current visibility (public, private, protected)

[ GitHub ]

  
# File 'lib/yard/handlers/processor.rb', line 47

attr_accessor :visibility

Instance Method Details

#find_handlers(statement) ⇒ Array<Base>

Searches for all handlers in Base.subclasses that match the statement

Parameters:

  • statement

    the statement object to match.

Returns:

  • (Array<Base>)

    a list of handlers to process the statement with.

[ GitHub ]

  
# File 'lib/yard/handlers/processor.rb', line 151

def find_handlers(statement)
  Base.subclasses.find_all do |handler|
    handler_base_class > handler &&
      (handler.namespace_only? ? owner.is_a?(CodeObjects::NamespaceObject) : true) &&
      handles?(handler, statement)
  end
end

#handler_base_classBase (private)

Returns the handler base class

Returns:

  • (Base)

    the base class

[ GitHub ]

  
# File 'lib/yard/handlers/processor.rb', line 172

def handler_base_class
  handler_base_namespace.const_get(:Base)
end

#handler_base_namespaceModule (private)

The module holding the handlers to be loaded

Returns:

[ GitHub ]

  
# File 'lib/yard/handlers/processor.rb', line 180

def handler_base_namespace
  self.class.namespace_for_handler[parser_type]
end

#handles?(handler, statement) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/yard/handlers/processor.rb', line 161

def handles?(handler, statement)
  return false unless handler.matches_file?(file)
  if handler.method(:handles?).arity == 1
    handler.handles?(statement)
  elsif [-1, 2].include?(handler.method(:handles?).arity)
    handler.handles?(statement, self)
  end
end

#load_handlersvoid (private)

This method returns an undefined value.

Loads handlers from #handler_base_namespace. This ensures that Ruby1.9 handlers are never loaded into 1.8; also lowers the amount of modules that are loaded

[ GitHub ]

  
# File 'lib/yard/handlers/processor.rb', line 188

def load_handlers
  return if @handlers_loaded[parser_type]
  handler_base_namespace.constants.each do |c|
    const = handler_base_namespace.const_get(c)
    unless Handlers::Base.subclasses.include?(const)
      Handlers::Base.subclasses << const
    end
  end
  @handlers_loaded[parser_type] = true
end

#parse_remaining_filesvoid

This method returns an undefined value.

Continue parsing the remainder of the files in the globals.ordered_parser object. After the remainder of files are parsed, processing will continue on the current file.

[ GitHub ]

  
# File 'lib/yard/handlers/processor.rb', line 140

def parse_remaining_files
  if globals.ordered_parser
    globals.ordered_parser.parse
    log.debug("Re-processing #{@file}...")
  end
end

#process(statements) ⇒ void

This method returns an undefined value.

Processes a list of statements by finding handlers to process each one.

Parameters:

  • statements (Array)

    a list of statements

[ GitHub ]

  
# File 'lib/yard/handlers/processor.rb', line 110

def process(statements)
  statements.each_with_index do |stmt, _index|
    find_handlers(stmt).each do |handler|
      begin
        handler.new(self, stmt).process
      rescue HandlerAborted
        log.debug "#{handler} cancelled from #{caller.last}"
        log.debug "\tin file '#{file}':#{stmt.line}:\n\n" + stmt.show + "\n"
      rescue NamespaceMissingError => missingerr
        log.warn "The #{missingerr.object.type} #{missingerr.object.path} has not yet been recognized.\n" \
                 "If this class/method is part of your source tree, this will affect your documentation results.\n" \
                 "You can correct this issue by loading the source file for this object before `#{file}'\n"
      rescue Parser::UndocumentableError => undocerr
        log.warn "in #{handler}: Undocumentable #{undocerr.message}\n" \
                 "\tin file '#{file}':#{stmt.line}:\n\n" + stmt.show + "\n"
      rescue => e
        log.error "Unhandled exception in #{handler}:\n" \
                  "  in `#{file}`:#{stmt.line}:\n\n#{stmt.show}\n"
        log.backtrace(e)
      end
    end
  end
end