class RubyLint::DefinitionGenerator
The DefinitionGenerator
class is used for generating definitions based on the data that is available in the current Ruby runtime. Using this generator the otherwise painful and time consuming task of adding definitions for large projects (e.g. Ruby itself or Rails) becomes very easy up to the point where it will only take a minute or two.
Note that this generator works best on Ruby implementations that provide accurate parameter information using `UnboundMethod#parameters`. Currently the only implementation where this is the case is Rubinius HEAD. Both MRI and Jruby provide inaccurate information.
@!attribute [r] directory
@return [String] The directory to store the generated definitions in.
@!attribute [r] options
@return [Hash]
@!attribute [r] template
@return [String] The ERB template to use.
@!attribute [r] inspector
@return [RubyLint::Inspector]
Attributes
Public Class Methods
@param [Class] constant @param [String] directory @param [Hash] options
# File lib/ruby-lint/definition_generator.rb, line 40 def initialize(constant, directory, options = {}) @options = default_options.merge(options) @inspector = Inspector.new(constant) @directory = directory @template = File.read( File.expand_path('../template/definition.erb', __FILE__) ) end
Public Instance Methods
Generates the definitions for every constant.
# File lib/ruby-lint/definition_generator.rb, line 52 def generate constants = inspector.inspect_constants( inspector.constant, options[:ignore].dup ) constants = constants.sort group_constants(constants).each do |root, names| filepath = File.join(directory, "#{root.snake_case}.rb") constants = [] if File.file?(filepath) and !options[:overwrite] next end names.each do |name| current_inspector = Inspector.new(name) inspected_methods = inspect_methods(current_inspector) superclass = nil if current_inspector.inspect_superclass superclass = current_inspector.inspect_superclass.to_s end constant = GeneratedConstant.new( :name => current_inspector.constant_name, :constant => current_inspector.constant, :methods => method_information(inspected_methods), :superclass => superclass, # Kernel is ignored since its included already in core/object.rb :modules => current_inspector.inspect_modules - [Kernel] ) constants << constant end render_template(filepath, template, constants) end end
Private Instance Methods
@return [Hash]
# File lib/ruby-lint/definition_generator.rb, line 174 def argument_mapping return { :req => :argument, :opt => :optional_argument, :rest => :rest_argument, :block => :block_argument } end
@return [Hash]
# File lib/ruby-lint/definition_generator.rb, line 129 def default_options return {:ignore => [], :overwrite => false} end
Groups constants together based on the top level namespace segment.
@param [Array] constants @return [Hash]
# File lib/ruby-lint/definition_generator.rb, line 115 def group_constants(constants) grouped = Hash.new { |hash, key| hash[key] = [] } constants.each do |name| root = name.split('::')[0] grouped[root] << name end return grouped end
@param [RubyLint::Inspector] inspector @return [Hash]
# File lib/ruby-lint/definition_generator.rb, line 137 def inspect_methods(inspector) return { :method => inspector.inspect_methods, :instance_method => inspector.inspect_instance_methods } end
Returns a Hash containing all the instance and class methods and their arguments.
@param [Hash] inspected @return [Hash]
# File lib/ruby-lint/definition_generator.rb, line 151 def method_information(inspected) arg_mapping = argument_mapping info = {:method => {}, :instance_method => {}} inspected.each do |type, methods| methods.each do |method| args = [] method.parameters.each_with_index do |arg, index| name = arg[1] || "arg#{index + 1}" args << {:type => arg_mapping[arg[0]], :name => name} end info[type][method.name] = args end end return info end
@param [String] template @param [Hash] variables
# File lib/ruby-lint/definition_generator.rb, line 187 def render_erb(template, variables = {}) scope = Template::Scope.new(variables) erb = ERB.new(template, nil, '-').result(scope.get_binding) # Trim excessive newlines. erb.gsub!(/\n{3,}/, "\n\n") # Get rid of the occasional empty newline before `end` tokens. erb.gsub!(/\n{2,}end/, "\nend") return erb end
@param [String] path @param [String] template @param [Array] constants
# File lib/ruby-lint/definition_generator.rb, line 101 def render_template(path, template, constants) erb = render_erb(template, :constants => constants) File.open(path, 'w') do |handle| handle.write(erb) end end