module RubyBreaker

RubyBreaker is a dynamic instrumentation and monitoring tool that generates type documentation automatically for Ruby programs.

-

This file contains utility functions that are useful for the Runtime
Library.

Constants

This constant contains the copyright information.

IO_EXTENSION

Extension used for files that contain type information in Ruby format

OPTIONS

Options for RubyBreaker

OPTION_PARSER

This option parser may be used for the command-line mode or for the library mode when used with Rakefile. See rubybreaker/task.rb for how this can be used in the latter.

TASK_EXTENSION

Extension used for files that contain RubyBreaker task information

YAML_EXTENSION

Extension used for files that contain type information in YAML format

Public Class Methods

break(*mods) click to toggle source

This method just redirects to Runtime’s method.

# File lib/rubybreaker/runtime.rb, line 93
def self.break(*mods)
  Runtime.break(*mods)
end
breakable(*mods) click to toggle source

This method just redirects to Runtime’s method. DEPRECATED: Use +RubyBreaker.break()+ to indicate the point of entry.

# File lib/rubybreaker/runtime.rb, line 88
def self.breakable(*mods)
  Runtime.breakable(*mods)
end
check(*mods) click to toggle source
# File lib/rubybreaker/runtime.rb, line 97
def self.check(*mods)
  Runtime.check(*mods)
end
defined_logger?() click to toggle source

This method returns true if the logger is already created and false otherwise.

# File lib/rubybreaker/debug/debug.rb, line 13
def self.defined_logger?()
  return defined?(LOGGER)
end
error(err, level=:error, &blk) click to toggle source

This method is for reporting an error to the user. It will immediately show the error message but also log it.

# File lib/rubybreaker/debug/debug.rb, line 44
def self.error(err, level=:error, &blk)
  msg = err.to_s
  msg = "#{msg} : #{yield}" if blk
  STDOUT.puts "[#{level.to_s.upcase}] #{msg}"
  LOGGER.send(level, msg) if defined?(OPTIONS) && OPTIONS[:debug]
end
log(str, level=:debug, context=nil, &blk) click to toggle source

This method logs a non-error (or error) message but with the provided context.

# File lib/rubybreaker/debug/debug.rb, line 53
def self.log(str, level=:debug, context=nil, &blk)
  return unless defined?(OPTIONS) && OPTIONS[:debug]
  msg = str.to_s
  msg = "#{msg} : #{yield}" if blk
  if context
    output = ""
    pp = PrettyPrint.new(output)
    context.format_with_msg(pp,msg)
    pp.flush
    msg = output
  end
  LOGGER.send(level, msg) 
end
monitor() click to toggle source

DEPRECATED: Use +RubyBreaker.run()+ to indicate the point of entry.

# File lib/rubybreaker/runtime.rb, line 83
def self.monitor()
end
run(*mods) click to toggle source

This method runs RubyBreaker for a particular test case (class). This is a bit different from running RubyBreaker as a shell program.

# File lib/rubybreaker.rb, line 175
def self.run(*mods)
  RubyBreaker.setup_logger() unless RubyBreaker.defined_logger?()

  # Task based run should use the rubybreaker options same as in shell
  # mode. So, parse the options first.
  if self.running_as_task?() # running in task mode
    RubyBreaker.verbose("Running RubyBreaker within a testcase")
    task = self.task
    OPTION_PARSER.parse(*task[:rubybreaker_opts])
    Runtime.break(*task[:break])
    Runtime.check(*task[:check])
    task_name = task[:name]
    RubyBreaker.verbose("Done reading task information")
    io_file = self.io_file(task_name)
  elsif OPTIONS[:prog] # running in shell mode
    Runtime.break(*mods) # should not happen but for backward-compatibility
    Runtime.break(*OPTIONS[:break])
    Runtime.check(*OPTIONS[:check])
    io_file = self.io_file(OPTIONS[:prog_file])
  else
    # Otherwise, assume there are no explicit IO files.
  end
  self.load_input(io_file)

  # The following is deprecated but doing this for backward compatibility
  Runtime.instrument()

  # At the end, we WILL generate an output of the type information.
  at_exit { self.output(io_file) }
end
verbose(str) { || ... } click to toggle source

This method will display verbose message. It is not for debugging but to inform users of each stage in the analysis.

# File lib/rubybreaker/debug/debug.rb, line 30
def self.verbose(str, &blk)
  return unless defined?(OPTIONS) && (OPTIONS[:verbose] || OPTIONS[:debug])
  if blk
    msg = yield
    msg = "#{str} : #{msg}" if str
  else
    msg = str
  end
  STDOUT.puts msg if OPTIONS[:verbose]
  LOGGER.info msg if OPTIONS[:debug]
end

Private Class Methods

io_file(prog_or_task) click to toggle source

This method finds the IO file for this run. It is either specified in io-file option or using the program name or the task name.

# File lib/rubybreaker.rb, line 160
def self.io_file(prog_or_task)
  if OPTIONS[:io_file]
    fname = OPTIONS[:io_file]
  elsif prog_or_task
    fname = "#{File.basename(prog_or_task.to_s, ".rb")}.#{IO_EXTENSION}"
  end
  return nil unless fname
  fname = File.absolute_path(fname) 
  return fname
end
load_input(fname) click to toggle source

This method loads the IO file by loading it.

# File lib/rubybreaker.rb, line 113
def self.load_input(fname)
  return fname
  eval "load \"#{fname}\"", TOPLEVEL_BINDING
  RubyBreaker.verbose("RubyBreaker input file #{fname} is loaded")
end
output(fname) click to toggle source

This method will generate the output to the given filename.

# File lib/rubybreaker.rb, line 120
def self.output(fname)

  RubyBreaker.verbose("Generating type documentation")

  code = ""

  # Document each module that was monitored.
  MONITOR_MAP.each_key { |mod| 
    str = Runtime::TypeSigUnparser.unparse(mod) 
    code << str
    print str if OPTIONS[:stdout] # display on the screen if requested
  }

  if fname && OPTIONS[:save_output]
    # Check if the file already exists--that is, if it was used for input
    io_exist = File.exists?(fname)
    if File.writable?(fname)
      RubyBreaker.verbose("Saving it to #{fname}")
      # Append the result to the input file (or create a new file)
      fmode = OPTIONS[:append] ? "a" : "w"
      open(fname, fmode) do |f|
        # When append, do not write the header
        unless OPTIONS[:append] 
          f.puts "# This file is auto-generated by RubyBreaker" 
        end
        # But time stamp always
        f.puts "# Last modified: #{Time.now}"
        f.puts "require \"rubybreaker\"" unless OPTIONS[:append] 
        f.print code
      end
    else
      RubyBreaker.verbose("Cannot write to #{fname}.")
    end
  end

  RubyBreaker.verbose("Done generating type documentation")
end
running_as_task?() click to toggle source

This method determines if RubyBreaker is running as a task.

# File lib/rubybreaker.rb, line 107
def self.running_as_task?(); return $__rubybreaker_task != nil end
task() click to toggle source

This method returns the task currently being run.

# File lib/rubybreaker.rb, line 110
def self.task(); return $__rubybreaker_task end