class Rubycrap::Application

Public Class Methods

calcualte_crap_from_flog(file) click to toggle source
# File lib/application.rb, line 85
  def self.calcualte_crap_from_flog(file)
          begin
                  FlogCLI.load_plugins
                  options = FlogCLI.parse_options "-qma"
                  flogger = FlogCLI.new options

                  flogger.flog file["filename"]
logger.debug("flogger absolute_filename: #{file["filename"]}")
                  flogger.each_by_score nil do |class_method, score, call_list|
                          startline = flogger.method_locations[class_method].split(":")[1]
                          absolute_filename = flogger.method_locations[class_method].split(":")[0]
  logger.debug("flogger startline: #{startline}")
                          #match simplecov line with startine form floc
                          element = @simplecov_information.detect {|f| f[:startline] == startline.to_i }
                          if element.to_s == ""
    logger.debug("no match with simplecov for logger class_method: #{class_method} startline: #{startline} ")
                          else
    logger.debug("flogger class_method: #{class_method} simplecov: #{element}")
                                  test_coverage = element[:coverage]
                                  @crap_methods << {:methodname => class_method, :flog_score => score , :filepath => absolute_filename, :startline => startline, :method_coverage => test_coverage, :crap_score => crap(score,test_coverage)}
                          end
                  end
          rescue
                  # something went wrong with flog
          end
  end
calculate_method_coverage(file,startline,lastline) click to toggle source
# File lib/application.rb, line 33
    def self.calculate_method_coverage(file,startline,lastline)
      # first we get the coverage lines from simplecov
      # start position -1 and number of total lines (-1 if you dont want the end)
      total_lines = lastline-startline
logger.debug("startline #{startline}")
logger.debug("latline #{lastline}")
      coveragelinestotal = file["coverage"]
            
logger.debug( "total_lines #{total_lines}")
      coveragelines = coveragelinestotal.slice(startline-1,total_lines)
logger.debug("coveragelines: #{coveragelines}")
      covered_lines = 0
      coveragelines.each do |line|
        if !(line.to_s.eql? "0" or line.to_s.eql? "")
          covered_lines = covered_lines + 1
        end
      end
      method_coverage = covered_lines.to_f / total_lines.to_f
logger.debug("method_coverage: #{method_coverage}")
      return method_coverage
    end
crap(score,coverage) click to toggle source
# File lib/application.rb, line 78
def self.crap(score,coverage)
#    CRAP(m) = comp(m)^2 * (1 � cov(m)/100)^3 + comp(m)
  comp = score
  cov = coverage
  comp ** 2 * (1 - cov) ** 3 + comp
end
hasharray_to_html( hashArray ) click to toggle source
# File lib/application.rb, line 112
def self.hasharray_to_html( hashArray )
  # collect all hash keys, even if they don't appear in each hash:
  headers = hashArray.inject([]){|a,x| a |= x.keys ; a}  # use array union to find all unique headers/keys

  html = Builder::XmlMarkup.new(:indent => 2)
  html.table {
    html.tr { headers.each{|h| html.th(h)} }
    hashArray.each do |row|
      html.tr { row.values.each { |value| html.td(value) }}
    end
  }
  return html
end
minfo(object) click to toggle source
# File lib/application.rb, line 11
def self.minfo(object)
  puts ">supports: #{(object.methods  - Object.methods).inspect}\n"
end
new(filename,mode) click to toggle source
# File lib/rubycrap/application.rb, line 13
def initialize(filename,mode)
  Rubycrap::logger.level = mode
  coverage = JSON.parse(File.open(filename, "r").read)
  @coverage_files = coverage["files"]
end
parse_method_coverage(file,filename) click to toggle source
# File lib/application.rb, line 28
def self.parse_method_coverage(file,filename)
  ast = Parser::CurrentRuby.parse(File.open(filename, "r").read)
  recursive_search_ast(file,ast)
end
process_simplecov_file(file) click to toggle source

def self.logger

@logger ||= Logger.new(STDOUT)

end

> reads the sourcefile with an ast parser to get all the methods, then calculate the method coverage

# File lib/application.rb, line 21
    def self.process_simplecov_file(file)
      #get filename with its coverage information
      filename = file["filename"]
logger.debug(filename)
      parse_method_coverage(file,filename)
    end
recursive_search_ast(file,ast) click to toggle source
# File lib/application.rb, line 55
def self.recursive_search_ast(file,ast)
        begin
                ast.children.each do |child|
                        if child.class.to_s == "Parser::AST::Node"
                          if (child.type.to_s == "def" or child.type.to_s == "defs")

                            methodname = child.children[0].to_s
                            startline = child.loc.line
                            lastline = child.loc.last_line
                            logger.debug("\nmethodname: #{methodname}")
                            method_coverage = calculate_method_coverage(file,startline,lastline)

                            @simplecov_information << {:name => methodname, :coverage => method_coverage , :startline => startline, :lastline => lastline}
                          else
                            recursive_search_ast(file,child)
                          end
                        end
                end
        rescue
                # maybe empty source code
        end
end
run(coveragefile,mode) click to toggle source
# File lib/application.rb, line 126
    def self.run(coveragefile,mode)
logger.level = mode
coverage = JSON.parse(File.open(coveragefile, "r").read)

            # file = coverage["files"].first
            #
            # => get all the source filenames from the coverage file
            #
            puts "total files: #{coverage["files"].count}"
            coverage["files"].each.with_index(1) do |file, index|
  logger.debug("file nr. #{index}")
              process_simplecov_file(file)
              calcualte_crap_from_flog(file)
            end

            @sorted = @crap_methods.sort_by { |k| -k[:crap_score] }

            puts "\nRESULTS"
            @sorted.each do |element|
                    puts "#{element[:crap_score].round}".ljust(6) + "#{element[:methodname]}  ---> #{element[:filepath]}:#{element[:startline]}"
            end

            #
            # buidler sucks
            # it doesnt do thead and tbody
            # and th: isnt accepted in datatables


            # <script   src="https://code.jquery.com/jquery-2.2.2.min.js"   integrity="sha256-36cp2Co+/62rEAAYHLmRCPIych47CvdM+uTBJwSzWjI="   crossorigin="anonymous"></script>
            # <script   src="https://cdn.datatables.net/1.10.11/js/jquery.dataTables.js" crossorigin="anonymous"></script>
            # <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.11/css/jquery.dataTables.min.css">
            # <script type="text/javascript">
            #   $(document).ready(function(){
            #     $('#myTable').DataTable();
            #   });
            # </script>

            # <table id="myTable">

            File.open("CRAP.html", 'w') { |file| file.write(hasharray_to_html(@sorted)) }
            puts "THE END"
    end

Public Instance Methods

execute() click to toggle source
# File lib/rubycrap/application.rb, line 23
def execute
  @crap_methods = []
  puts "total files: #{@coverage_files.count}"
  @coverage_files.each.with_index(1) do |file, index|
    Rubycrap::logger.debug("file nr. #{index}")
    simplecov_information = Rubycrap::Coverage.new(file).process_simplecov_file
    @crap_methods.concat(Rubycrap::Crap.new(simplecov_information,file).calculate_with_flog)
  end
  show_results
end
show_results() click to toggle source
# File lib/rubycrap/application.rb, line 34
def show_results
  reporter = Rubycrap::Reporter.new(@crap_methods)
  puts "\nTOP 10 RESULTS"
  reporter.console
  reporter.html
  puts "THE END"
end