In Files

Parent

Included Modules

Files

ParseState

Main class and structure used to compute the cyclomatic complexity of Ruby programs.

Attributes

children[RW]
complexity[RW]
lines[RW]
name[RW]
parent[RW]

Public Class Methods

get_token_counter() click to toggle source
# File lib/saikuro.rb, line 118
def ParseState.get_token_counter
  @@token_counter
end
make_top_state() click to toggle source
# File lib/saikuro.rb, line 108
def ParseState.make_top_state()
  @@top_state = ParseState.new(nil)
  @@top_state.name = "__top__"
  @@top_state
end
new(lexer,parent=nil) click to toggle source
# File lib/saikuro.rb, line 122
def initialize(lexer,parent=nil)
  @name = ""
  @children = Array.new
  @complexity = 0
  @parent = parent
  @lexer = lexer
  @run = true
  # To catch one line def statements, We always have one line.
  @lines = 0
  @last_token_line_and_char = Array.new
end
set_token_counter(counter) click to toggle source
# File lib/saikuro.rb, line 115
def ParseState.set_token_counter(counter)
  @@token_counter = counter
end

Public Instance Methods

calc_complexity() click to toggle source
# File lib/saikuro.rb, line 149
def calc_complexity
  complexity = @complexity
  children.each do |child|
    complexity += child.calc_complexity
  end
  complexity
end
calc_lines() click to toggle source
# File lib/saikuro.rb, line 157
def calc_lines
  lines = @lines
  children.each do |child|
    lines += child.calc_lines
  end
  lines
end
compute_state(formater) click to toggle source
# File lib/saikuro.rb, line 165
def compute_state(formater)
  if top_state?
    compute_state_for_global(formater)
  end

  @children.each do |s|
    s.compute_state(formater)
  end
end
compute_state_for_global(formater) click to toggle source
# File lib/saikuro.rb, line 175
def compute_state_for_global(formater)
  global_def, @children = @children.partition do |s|
    !s.kind_of?(ParseClass)
  end
  return if global_def.empty?
  gx = global_def.inject(0) { |c,s| s.calc_complexity }
  gl = global_def.inject(0) { |c,s| s.calc_lines }
  formater.start_class_compute_state("Global", "", gx, gl)
  global_def.each do |s|
    s.compute_state(formater)
  end
  formater.end_class_compute_state("")
end
count_tokens?() click to toggle source

Count the tokens parsed if true else ignore them.

# File lib/saikuro.rb, line 190
def count_tokens?
  true
end
do_begin_token(token) click to toggle source
# File lib/saikuro.rb, line 235
def do_begin_token(token)
  make_state(EndableParseState, self)
end
do_block_token(token) click to toggle source
# File lib/saikuro.rb, line 272
def do_block_token(token)
  make_state(ParseBlock,self)
end
do_case_token(token) click to toggle source
# File lib/saikuro.rb, line 284
def do_case_token(token)
  make_state(EndableParseState, self)
end
do_class_token(token) click to toggle source
# File lib/saikuro.rb, line 239
def do_class_token(token)
  make_state(ParseClass,self)
end
do_comment_token(token) click to toggle source
# File lib/saikuro.rb, line 304
def do_comment_token(token)
  make_state(ParseComment, self)
end
do_conditional_do_control_token(token) click to toggle source
# File lib/saikuro.rb, line 280
def do_conditional_do_control_token(token)
  make_state(ParseDoCond,self)
end
do_conditional_token(token) click to toggle source
# File lib/saikuro.rb, line 276
def do_conditional_token(token)
  make_state(ParseCond,self)
end
do_constant_token(token) click to toggle source
# File lib/saikuro.rb, line 251
def do_constant_token(token)
  nil
end
do_def_token(token) click to toggle source
# File lib/saikuro.rb, line 247
def do_def_token(token)
  make_state(ParseDef,self)
end
do_else_token(token) click to toggle source
# File lib/saikuro.rb, line 299
def do_else_token(token)
  STDOUT.puts "Ignored/Unknown Token:#{token.class}" if $VERBOSE
  nil
end
do_end_token(token) click to toggle source
# File lib/saikuro.rb, line 267
def do_end_token(token)
  end_debug
  nil
end
do_identifier_token(token) click to toggle source
# File lib/saikuro.rb, line 255
def do_identifier_token(token)
  if (token.name == "__END__" && token.char_no.to_i == 0)
    # The Ruby code has stopped and the rest is data so cease parsing.
    @run = false
  end
  nil
end
do_module_token(token) click to toggle source
# File lib/saikuro.rb, line 243
def do_module_token(token)
  make_state(ParseModule,self)
end
do_one_line_conditional_token(token) click to toggle source
# File lib/saikuro.rb, line 288
def do_one_line_conditional_token(token)
  # This is an if with no end
  @complexity += 1
  #STDOUT.puts "got IF_MOD: #{self.to_yaml}" if $VERBOSE
  #if state.type != "class" && state.type != "def" && state.type != "cond"
  #STDOUT.puts "Changing IF_MOD Parent" if $VERBOSE
  #state = state.parent
  #@run = false
  nil
end
do_right_brace_token(token) click to toggle source
# File lib/saikuro.rb, line 263
def do_right_brace_token(token)
  nil
end
do_symbol_token(token) click to toggle source
# File lib/saikuro.rb, line 308
def do_symbol_token(token)
  make_state(ParseSymbol, self)
end
end_debug() click to toggle source
# File lib/saikuro.rb, line 372
def end_debug
  STDOUT.puts "got an end: #{@name} in #{self.class.name}" if $VERBOSE
  if @parent.nil?
    STDOUT.puts "DEBUG: Line #{@lexer.line_no}"
    STDOUT.puts "DEBUG: #{@name}; #{self.class}"
    # to_yaml can cause an infinite loop?
    #STDOUT.puts "TOP: #{@@top_state.to_yaml}"
    #STDOUT.puts "TOP: #{@@top_state.inspect}"

    # This may not be an error?
    #exit 1
  end
end
lexer=(lexer) click to toggle source
# File lib/saikuro.rb, line 138
def lexer=(lexer)
  @run = true
  @lexer = lexer
end
lexer_loop?(token) click to toggle source

Ruby-Lexer can go into a loop if the file does not end with a newline.

# File lib/saikuro.rb, line 212
def lexer_loop?(token)
  return false if @last_token_line_and_char.empty?
  loop_flag = false
  last = @last_token_line_and_char.last
  line = last[0]
  char = last[1]
  ltok = last[2]

  if ( (line == @lexer.line_no.to_i) &&
         (char == @lexer.char_no.to_i) &&
         (ltok.class == token.class) )
    # We are potentially in a loop
    if @last_token_line_and_char.size >= 3
      loop_flag = true
    end
  else
    # Not in a loop so clear stack
    @last_token_line_and_char = Array.new
  end

  loop_flag
end
make_state(type,parent = nil) click to toggle source
# File lib/saikuro.rb, line 143
def make_state(type,parent = nil)
  cstate = type.new(@lexer,self)
  parent.children<< cstate
  cstate
end
parse() click to toggle source
# File lib/saikuro.rb, line 194
def parse
  while @run do
    tok = @lexer.token
    @run = false if tok.nil?
    if lexer_loop?(tok)
      STDERR.puts "Lexer loop at line : #{@lexer.line_no} char #{@lexer.char_no}."
      @run = false
    end
    @last_token_line_and_char<< [@lexer.line_no.to_i, @lexer.char_no.to_i, tok]
    if $VERBOSE
      puts "DEBUG: #{@lexer.line_no} #{tok.class}:#{tok.name if tok.respond_to?(:name)}"
    end
    @@token_counter.count_token(@lexer.line_no, tok) if count_tokens?
    parse_token(tok)
  end
end
parse_token(token) click to toggle source
# File lib/saikuro.rb, line 312
def parse_token(token)
  state = nil
  case token
  when TkCLASS
    state = do_class_token(token)
  when TkMODULE
    state = do_module_token(token)
  when TkDEF
    state = do_def_token(token)
  when TkCONSTANT
    # Nothing to do with a constant at top level?
    state = do_constant_token(token)
  when TkIDENTIFIER,TkFID
    # Nothing to do at top level?
    state = do_identifier_token(token)
  when TkRBRACE
    # Nothing to do at top level
    state = do_right_brace_token(token)
  when TkEND
    state = do_end_token(token)
    # At top level this might be an error...
  when TkDO,TkfLBRACE
    state = do_block_token(token)
  when TkIF,TkUNLESS
    state = do_conditional_token(token)
  when TkWHILE,TkUNTIL,TkFOR
    state = do_conditional_do_control_token(token)
  when TkELSIF #,TkELSE
    @complexity += 1
  when TkELSE
    # Else does not increase complexity
  when TkCASE
    state = do_case_token(token)
  when TkWHEN
    @complexity += 1
  when TkBEGIN
    state = do_begin_token(token)
  when TkRESCUE
    # Maybe this should add complexity and not begin
    @complexity += 1
  when TkIF_MOD, TkUNLESS_MOD, TkUNTIL_MOD, TkWHILE_MOD, TkQUESTION
    state = do_one_line_conditional_token(token)
  when TkNL
    #
    @lines += 1
  when TkRETURN
    # Early returns do not increase complexity as the condition that
    # calls the return is the one that increases it.
  when TkCOMMENT
    state = do_comment_token(token)
  when TkSYMBEG
    state = do_symbol_token(token)
  when TkError
    STDOUT.puts "Lexer received an error for line #{@lexer.line_no} char #{@lexer.char_no}"
  else
    state = do_else_token(token)
  end
  state.parse if state
end
top_state?() click to toggle source
# File lib/saikuro.rb, line 134
def top_state?
  self == @@top_state
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.