class Flog

Constants

BRANCHING

Names of nodes that branch.

DEFAULT_THRESHOLD

Cut off point where the report should stop unless –all given.

OTHER_SCORES

Various non-call constructs

SCORES

The scoring system hash. Maps node type to score.

Public Class Methods

new(option = {}) click to toggle source

Creates a new Flog instance with options.

Calls superclass method
# File lib/flog.rb, line 233
def initialize option = {}
  super()
  @option              = option
  @mass                = {}
  @parser              = nil
  @threshold           = option[:threshold] || DEFAULT_THRESHOLD
  self.auto_shift_type = true
  self.reset
end

Public Instance Methods

add_to_score(name, score = OTHER_SCORES[name]) click to toggle source

Add a score to the tally. Score can be predetermined or looked up automatically. Uses multiplier for additional spankings. Spankings!

# File lib/flog.rb, line 112
def add_to_score name, score = OTHER_SCORES[name]
  return if option[:methods] and method_stack.empty?
  @calls[signature][name] += score * @multiplier
end
average() click to toggle source

really?

# File lib/flog.rb, line 120
def average
  return 0 if calls.size == 0
  total_score / calls.size
end
calculate() click to toggle source

Calculates classes and methods scores.

# File lib/flog.rb, line 128
def calculate
  each_by_score threshold do |class_method, score, call_list|
    klass = class_method.scan(/.+(?=#|::)/).first

    method_scores[klass] << [class_method, score]
    scores[klass] += score
  end
end
calculate_total_scores() click to toggle source

Calculates the total score and populates @totals.

# File lib/flog.rb, line 306
def calculate_total_scores
  return if @totals

  @total_score = 0
  @totals = Hash.new(0)

  calls.each do |meth, tally|
    score = score_method(tally)

    @totals[meth] = score
    @total_score += score
  end
end
dsl_name?(args) click to toggle source

Returns true if the form looks like a “DSL” construct.

task :blah do ... end
=> s(:iter, s(:call, nil, :task, s(:lit, :blah)), ...)
# File lib/flog.rb, line 143
def dsl_name? args
  return false unless args and not args.empty?

  first_arg = args.first
  first_arg = first_arg[1] if first_arg[0] == :hash

  [:lit, :str].include? first_arg[0] and first_arg[1]
end
each_by_score(max = nil) { |class_method, score, call_list| ... } click to toggle source

Iterate over the calls sorted (descending) by score.

# File lib/flog.rb, line 155
def each_by_score max = nil
  current = 0

  calls.sort_by { |k,v| -totals[k] }.each do |class_method, call_list|
    score = totals[class_method]

    yield class_method, score, call_list

    current += score
    break if max and current >= max
  end
end
flog(*files) click to toggle source

Flog the given files. Deals with “-”, and syntax errors.

Not as smart as FlogCLI's flog method as it doesn't traverse dirs. Use PathExpander to expand dirs into files.

# File lib/flog.rb, line 174
def flog(*files)
  files.each do |file|
    next unless file == '-' or File.readable? file

    ruby = file == '-' ? $stdin.read : File.binread(file)

    flog_ruby ruby, file
  end

  calculate_total_scores
end
flog_ruby(ruby, file="-", timeout = 10) click to toggle source

Flog the given ruby source, optionally using file to provide paths for methods. Smart. Handles syntax errors and timeouts so you don't have to.

# File lib/flog.rb, line 191
def flog_ruby ruby, file="-", timeout = 10
  flog_ruby! ruby, file, timeout
rescue Timeout::Error
  warn "TIMEOUT parsing #{file}. Skipping."
rescue RubyParser::SyntaxError, Racc::ParseError => e
  q = option[:quiet]
  if e.inspect =~ /<\%|%\>/ or ruby =~ /<\%|%\>/ then
    return if q
    warn "#{e.inspect} at #{e.backtrace.first(5).join(', ')}"
    warn "\n...stupid lemmings and their bad erb templates... skipping"
  else
    warn "ERROR: parsing ruby file #{file}" unless q
    unless option[:continue] then
      warn "ERROR! Aborting. You may want to run with --continue."
      raise e
    end
    return if q
    warn "%s: %s at:\n  %s" % [e.class, e.message.strip,
                               e.backtrace.first(5).join("\n  ")]
  end
end
flog_ruby!(ruby, file="-", timeout = 10) click to toggle source

Flog the given ruby source, optionally using file to provide paths for methods. Does not handle timeouts or syntax errors. See flog_ruby.

# File lib/flog.rb, line 217
def flog_ruby! ruby, file="-", timeout = 10
  @parser = (option[:parser] || RubyParser).new

  warn "** flogging #{file}" if option[:verbose]

  ast = @parser.process ruby, file, timeout

  return unless ast

  mass[file] = ast.mass
  process ast
end
max_method() click to toggle source

Returns the method/score pair of the maximum score.

# File lib/flog.rb, line 246
def max_method
  totals.max_by { |_, score| score }
end
max_score() click to toggle source

Returns the maximum score for a single method. Used for FlogTask.

# File lib/flog.rb, line 253
def max_score
  max_method.last
end
penalize_by(bonus) { || ... } click to toggle source

For the duration of the block the complexity factor is increased by bonus This allows the complexity of sub-expressions to be influenced by the expressions in which they are found. Yields 42 to the supplied block.

# File lib/flog.rb, line 263
def penalize_by bonus
  @multiplier += bonus
  yield
  @multiplier -= bonus
end
reset() click to toggle source

Reset score data

# File lib/flog.rb, line 272
def reset
  @totals           = @total_score = nil
  @multiplier       = 1.0
  @calls            = Hash.new { |h,k| h[k] = Hash.new 0 }
  @method_scores    = Hash.new { |h,k| h[k] = [] }
  @scores           = Hash.new 0
  method_locations.clear
end
score_method(tally) click to toggle source

Compute the distance formula for a given tally

# File lib/flog.rb, line 284
def score_method(tally)
  a, b, c = 0, 0, 0
  tally.each do |cat, score|
    case cat
    when :assignment then a += score
    when :branch     then b += score
    else                  c += score
    end
  end
  Math.sqrt(a*a + b*b + c*c)
end
threshold() click to toggle source

Final threshold that is used for report

# File lib/flog.rb, line 299
def threshold
  option[:all] ? nil : total_score * @threshold
end