metricfu / metric_fu

A fist full of code metrics
http://metricfu.github.com/metric_fu
MIT License
627 stars 96 forks source link

undefined method `strip' for nil:NilClass on Rails 4, metric_fu 4.11.0 #229

Closed anselmbradford closed 10 years ago

anselmbradford commented 10 years ago

With metric_fu 4.11.0 installed (latest release), I get the following error when running metric_fu:

$ metric_fu
******* STARTING METRIC cane
******* ENDING METRIC cane
******* STARTING METRIC churn
******* ENDING METRIC churn
******* STARTING METRIC flay
/Users/anselmbradford/.rvm/gems/ruby-2.1.1@ohana-web-search/gems/metric_fu-4.11.0/lib/metric_fu/metrics/flay/generator.rb:25:in `block (2 levels) in to_h': undefined method `strip' for nil:NilClass (NoMethodError)
    from /Users/anselmbradford/.rvm/gems/ruby-2.1.1@ohana-web-search/gems/metric_fu-4.11.0/lib/metric_fu/metrics/flay/generator.rb:23:in `map'
    from /Users/anselmbradford/.rvm/gems/ruby-2.1.1@ohana-web-search/gems/metric_fu-4.11.0/lib/metric_fu/metrics/flay/generator.rb:23:in `block in to_h'
    from /Users/anselmbradford/.rvm/gems/ruby-2.1.1@ohana-web-search/gems/metric_fu-4.11.0/lib/metric_fu/metrics/flay/generator.rb:21:in `each'
    from /Users/anselmbradford/.rvm/gems/ruby-2.1.1@ohana-web-search/gems/metric_fu-4.11.0/lib/metric_fu/metrics/flay/generator.rb:21:in `to_h'
    from /Users/anselmbradford/.rvm/gems/ruby-2.1.1@ohana-web-search/gems/metric_fu-4.11.0/lib/metric_fu/generator.rb:108:in `generate_result'
    from /Users/anselmbradford/.rvm/gems/ruby-2.1.1@ohana-web-search/gems/metric_fu-4.11.0/lib/metric_fu/reporting/result.rb:50:in `add'
    from /Users/anselmbradford/.rvm/gems/ruby-2.1.1@ohana-web-search/gems/metric_fu-4.11.0/lib/metric_fu/run.rb:19:in `block in measure'
    from /Users/anselmbradford/.rvm/gems/ruby-2.1.1@ohana-web-search/gems/metric_fu-4.11.0/lib/metric_fu/run.rb:17:in `each'
    from /Users/anselmbradford/.rvm/gems/ruby-2.1.1@ohana-web-search/gems/metric_fu-4.11.0/lib/metric_fu/run.rb:17:in `measure'
    from /Users/anselmbradford/.rvm/gems/ruby-2.1.1@ohana-web-search/gems/metric_fu-4.11.0/lib/metric_fu/run.rb:8:in `run'
    from /Users/anselmbradford/.rvm/gems/ruby-2.1.1@ohana-web-search/gems/metric_fu-4.11.0/lib/metric_fu/cli/helper.rb:18:in `run'
    from /Users/anselmbradford/.rvm/gems/ruby-2.1.1@ohana-web-search/gems/metric_fu-4.11.0/lib/metric_fu/cli/client.rb:18:in `run'
    from /Users/anselmbradford/.rvm/gems/ruby-2.1.1@ohana-web-search/gems/metric_fu-4.11.0/bin/metric_fu:9:in `<top (required)>'
    from /Users/anselmbradford/.rvm/gems/ruby-2.1.1@ohana-web-search/bin/metric_fu:23:in `load'
    from /Users/anselmbradford/.rvm/gems/ruby-2.1.1@ohana-web-search/bin/metric_fu:23:in `<main>'
    from /Users/anselmbradford/.rvm/gems/ruby-2.1.1@ohana-web-search/bin/ruby_executable_hooks:15:in `eval'
    from /Users/anselmbradford/.rvm/gems/ruby-2.1.1@ohana-web-search/bin/ruby_executable_hooks:15:in `<main>'

Here's my debug output:

$ metric_fu --debug
{"Ruby"=>
  {"Engine"=>"ruby",
   "Version"=>"2.1.1",
   "Patchlevel"=>76,
   "Ripper Support"=>true,
   "Rubygems Version"=>"2.2.2",
   "Long Description"=>
    "ruby 2.1.1p76 (2014-02-24 revision 45161) [x86_64-darwin12.0]"},
 "Environment"=>
  {"VERBOSE"=>"false",
   "External Encoding"=>"UTF-8",
   "Internal Encoding"=>"",
   "Host Architecture"=>"x86_64-apple-darwin12.5.0",
   "Ruby Prefix"=>"/Users/anselmbradford/.rvm/rubies/ruby-2.1.1",
   "Ruby Options"=>""},
 "MetricFu"=>
  {"Version"=>"4.11.0",
   "Verbose Mode"=>false,
   "Enabled Metrics"=>
    [:cane,
     :churn,
     :flay,
     :flog,
     :stats,
     :saikuro,
     :reek,
     :roodi,
     :rails_best_practices,
     :hotspots],
   "Dependencies"=>
    [{"name"=>"flay", "version"=>"2.4.0"},
     {"name"=>"churn", "version"=>"0.0.35"},
     {"name"=>"flog", "version"=>"4.2.0"},
     {"name"=>"reek", "version"=>"1.3.7"},
     {"name"=>"cane", "version"=>"2.6.2"},
     {"name"=>"rails_best_practices", "version"=>"1.15.4"},
     {"name"=>"saikuro", "version"=>[">= 1.1.3", "~> 1.1"]},
     {"name"=>"roodi", "version"=>"3.3.1"},
     {"name"=>"code_metrics", "version"=>"0.1.3"},
     {"name"=>"redcard", "version"=>"1.1.0"},
     {"name"=>"coderay", "version"=>"1.1.0"},
     {"name"=>"multi_json", "version"=>"1.10.0"},
     {"name"=>"launchy", "version"=>"2.4.2"},
     {"name"=>"rcov", "version"=>["~> 0.8"]}]}}

My Gemfile.lock looks like:

GEM
  remote: https://rubygems.org/
  specs:
    actionmailer (4.0.5)
      actionpack (= 4.0.5)
      mail (~> 2.5.4)
    actionpack (4.0.5)
      activesupport (= 4.0.5)
      builder (~> 3.1.0)
      erubis (~> 2.7.0)
      rack (~> 1.5.2)
      rack-test (~> 0.6.2)
    activemodel (4.0.5)
      activesupport (= 4.0.5)
      builder (~> 3.1.0)
    activerecord (4.0.5)
      activemodel (= 4.0.5)
      activerecord-deprecated_finders (~> 1.0.2)
      activesupport (= 4.0.5)
      arel (~> 4.0.0)
    activerecord-deprecated_finders (1.0.3)
    activesupport (4.0.5)
      i18n (~> 0.6, >= 0.6.9)
      minitest (~> 4.2)
      multi_json (~> 1.3)
      thread_safe (~> 0.1)
      tzinfo (~> 0.3.37)
    addressable (2.3.6)
    arel (4.0.2)
    arrayfields (4.9.2)
    autoparse (0.3.3)
      addressable (>= 2.3.1)
      extlib (>= 0.9.15)
      multi_json (>= 1.0.0)
    awesome_print (1.2.0)
    better_errors (1.1.0)
      coderay (>= 1.0.0)
      erubis (>= 2.6.6)
    binding_of_caller (0.7.2)
      debug_inspector (>= 0.0.1)
    builder (3.1.4)
    cane (2.6.2)
      parallel
    capybara (2.2.1)
      mime-types (>= 1.16)
      nokogiri (>= 1.3.3)
      rack (>= 1.0.0)
      rack-test (>= 0.5.4)
      xpath (~> 2.0)
    capybara-webkit (1.1.0)
      capybara (~> 2.0, >= 2.0.2)
      json
    chronic (0.10.2)
    chunky_png (1.3.1)
    churn (0.0.35)
      chronic (>= 0.2.3)
      hirb
      json_pure
      main
      rest-client (>= 1.6.0)
      ruby_parser (~> 3.0)
      sexp_processor (~> 4.1)
    code_analyzer (0.4.5)
      sexp_processor
    code_metrics (0.1.3)
    coderay (1.1.0)
    colored (1.2)
    compass (0.12.6)
      chunky_png (~> 1.2)
      fssm (>= 0.2.7)
      sass (~> 3.2.19)
    compass-rails (1.1.7)
      compass (>= 0.12.2)
      sprockets (<= 2.11.0)
    coveralls (0.7.0)
      multi_json (~> 1.3)
      rest-client
      simplecov (>= 0.7)
      term-ansicolor
      thor
    crack (0.4.2)
      safe_yaml (~> 1.0.0)
    dalli (2.7.1)
    debug_inspector (0.0.2)
    diff-lcs (1.2.5)
    docile (1.1.3)
    email_spec (1.5.0)
      launchy (~> 2.1)
      mail (~> 2.2)
    erubis (2.7.0)
    execjs (2.0.2)
    extlib (0.9.16)
    faraday (0.9.0)
      multipart-post (>= 1.2, < 3)
    faraday-http-cache (0.4.0)
      faraday (~> 0.8)
    fattr (2.2.2)
    figaro (0.7.0)
      bundler (~> 1.0)
      rails (>= 3, < 5)
    flay (2.4.0)
      ruby_parser (~> 3.0)
      sexp_processor (~> 4.0)
    flog (4.2.0)
      ruby_parser (~> 3.1, > 3.1.0)
      sexp_processor (~> 4.4)
    font-awesome-sass (4.0.3.1)
      sass (~> 3.2)
    fssm (0.2.10)
    google-api-client (0.7.1)
      addressable (>= 2.3.2)
      autoparse (>= 0.3.3)
      extlib (>= 0.9.15)
      faraday (>= 0.9.0)
      jwt (>= 0.1.5)
      launchy (>= 2.1.1)
      multi_json (>= 1.0.0)
      retriable (>= 1.4)
      signet (>= 0.5.0)
      uuidtools (>= 2.1.0)
    haml (4.0.5)
      tilt
    haml-rails (0.5.3)
      actionpack (>= 4.0.1)
      activesupport (>= 4.0.1)
      haml (>= 3.1, < 5.0)
      railties (>= 4.0.1)
    hike (1.2.3)
    hirb (0.7.1)
    html5shiv-rails (0.0.2)
      railties (>= 3.2.0, < 5.0)
    i18n (0.6.9)
    jshintrb (0.2.4)
      execjs
      multi_json (>= 1.3)
      rake
    json (1.8.1)
    json_pure (1.8.1)
    jwt (1.0.0)
    kgio (2.9.2)
    launchy (2.4.2)
      addressable (~> 2.3)
    letter_opener (1.2.0)
      launchy (~> 2.2)
    mail (2.5.4)
      mime-types (~> 1.16)
      treetop (~> 1.4.8)
    main (6.0.0)
      arrayfields (>= 4.7.4)
      chronic (>= 0.6.2)
      fattr (>= 2.2.0)
      map (>= 5.1.0)
    map (6.5.3)
    memcachier (0.0.2)
    metric_fu (4.11.0)
      cane (~> 2.5, >= 2.5.2)
      churn (~> 0.0.35)
      code_metrics (~> 0.1)
      coderay
      flay (~> 2.1, >= 2.0.1)
      flog (~> 4.1, >= 4.1.1)
      launchy (~> 2.0)
      metric_fu-Saikuro (~> 1.1, >= 1.1.3)
      multi_json
      rails_best_practices (~> 1.14, >= 1.14.3)
      redcard
      reek (~> 1.3, >= 1.3.4)
      roodi (~> 3.1)
    metric_fu-Saikuro (1.1.3)
    mime-types (1.25.1)
    mini_portile (0.6.0)
    minitest (4.7.5)
    multi_json (1.10.0)
    multipart-post (2.0.0)
    newrelic_rpm (3.8.0.218)
    nokogiri (1.6.2.1)
      mini_portile (= 0.6.0)
    ohanakapa (1.0.0)
      sawyer (~> 0.3.0)
    parallel (1.0.0)
    polyglot (0.3.4)
    quiet_assets (1.0.2)
      railties (>= 3.1, < 5.0)
    rack (1.5.2)
    rack-cache (1.2)
      rack (>= 0.4)
    rack-rewrite (1.5.0)
    rack-test (0.6.2)
      rack (>= 1.0)
    rack_session_access (0.1.1)
      builder (>= 2.0.0)
      rack (>= 1.0.0)
    rails (4.0.5)
      actionmailer (= 4.0.5)
      actionpack (= 4.0.5)
      activerecord (= 4.0.5)
      activesupport (= 4.0.5)
      bundler (>= 1.3.0, < 2.0)
      railties (= 4.0.5)
      sprockets-rails (~> 2.0.0)
    rails_12factor (0.0.2)
      rails_serve_static_assets
      rails_stdout_logging
    rails_best_practices (1.15.4)
      activesupport
      awesome_print
      code_analyzer (>= 0.4.3)
      colored
      erubis
      i18n
      json
      require_all
      ruby-progressbar
    rails_serve_static_assets (0.0.2)
    rails_stdout_logging (0.0.3)
    railties (4.0.5)
      actionpack (= 4.0.5)
      activesupport (= 4.0.5)
      rake (>= 0.8.7)
      thor (>= 0.18.1, < 2.0)
    rainbow (2.0.0)
    raindrops (0.13.0)
    rake (10.3.1)
    redcard (1.1.0)
    reek (1.3.7)
      rainbow
      ruby2ruby (~> 2.0.8)
      ruby_parser (~> 3.3)
      sexp_processor
    require_all (1.3.2)
    requirejs-rails (0.9.2)
      railties (>= 3.1.1, < 4.1)
    rest-client (1.6.7)
      mime-types (>= 1.16)
    retriable (1.4.1)
    roodi (3.3.1)
      ruby_parser (~> 3.2, >= 3.2.2)
    rspec-core (2.14.8)
    rspec-expectations (2.14.5)
      diff-lcs (>= 1.1.3, < 2.0)
    rspec-mocks (2.14.6)
    rspec-rails (2.14.2)
      actionpack (>= 3.0)
      activemodel (>= 3.0)
      activesupport (>= 3.0)
      railties (>= 3.0)
      rspec-core (~> 2.14.0)
      rspec-expectations (~> 2.14.0)
      rspec-mocks (~> 2.14.0)
    ruby-progressbar (1.5.0)
    ruby2ruby (2.0.8)
      ruby_parser (~> 3.1)
      sexp_processor (~> 4.0)
    ruby_parser (3.6.1)
      sexp_processor (~> 4.1)
    safe_yaml (1.0.3)
    sass (3.2.19)
    sass-rails (4.0.3)
      railties (>= 4.0.0, < 5.0)
      sass (~> 3.2.0)
      sprockets (~> 2.8, <= 2.11.0)
      sprockets-rails (~> 2.0)
    sawyer (0.3.0)
      faraday (~> 0.8, < 0.10)
      uri_template (~> 0.5.0)
    selectivizr-rails (1.1.2)
    sexp_processor (4.4.3)
    signet (0.5.0)
      addressable (>= 2.2.3)
      faraday (>= 0.9.0.rc5)
      jwt (>= 0.1.5)
      multi_json (>= 1.0.0)
    simplecov (0.8.2)
      docile (~> 1.1.0)
      multi_json
      simplecov-html (~> 0.8.0)
    simplecov-html (0.8.0)
    sprockets (2.11.0)
      hike (~> 1.2)
      multi_json (~> 1.0)
      rack (~> 1.0)
      tilt (~> 1.1, != 1.3.0)
    sprockets-rails (2.0.1)
      actionpack (>= 3.0)
      activesupport (>= 3.0)
      sprockets (~> 2.8)
    term-ansicolor (1.3.0)
      tins (~> 1.0)
    thor (0.19.1)
    thread_safe (0.3.3)
    tilt (1.4.1)
    tins (1.3.0)
    treetop (1.4.15)
      polyglot
      polyglot (>= 0.3.1)
    tzinfo (0.3.39)
    uglifier (2.5.0)
      execjs (>= 0.3.0)
      json (>= 1.8.0)
    unicorn (4.8.3)
      kgio (~> 2.6)
      rack
      raindrops (~> 0.7)
    uri_template (0.5.3)
    uuidtools (2.1.4)
    vcr (2.9.0)
    webmock (1.18.0)
      addressable (>= 2.3.6)
      crack (>= 0.3.2)
    xpath (2.0.0)
      nokogiri (~> 1.3)
    yard (0.8.7.4)

PLATFORMS
  ruby

DEPENDENCIES
  better_errors (>= 1.1.0)
  binding_of_caller (>= 0.7.2)
  capybara (>= 2.2.1)
  capybara-webkit
  compass-rails (>= 1.1.7)
  coveralls (>= 0.7.0)
  dalli (~> 2.7.1)
  email_spec (>= 1.5.0)
  faraday-http-cache (>= 0.4.0)
  figaro (>= 0.7.0)
  font-awesome-sass (>= 4.0.3.1)
  google-api-client (>= 0.7.1)
  haml-rails (>= 0.5.3)
  html5shiv-rails (>= 0.0.2)
  jshintrb (>= 0.2.4)
  json (>= 1.8.1)
  kgio
  letter_opener (>= 1.2.0)
  memcachier
  metric_fu (= 4.11.0)
  newrelic_rpm (>= 3.8.0.218)
  ohanakapa (~> 1.0)
  quiet_assets (>= 1.0.2)
  rack-cache (>= 1.2)
  rack-rewrite (>= 1.5.0)
  rack_session_access
  rails (~> 4.0.4)
  rails_12factor
  requirejs-rails (>= 0.9.2)
  rspec-rails (>= 2.14.2)
  sass-rails (~> 4.0.2)
  selectivizr-rails (>= 1.1.2)
  uglifier (>= 2.5.0)
  unicorn (>= 4.8.3)
  vcr (>= 2.9.0)
  webmock (>= 1.17.4)
  yard
anselmbradford commented 10 years ago

This is the type of file (line 6 it appears) that the error is being thrown at

<%%= simple_form_for(@<%= singular_table_name %>) do |f| %>
  <%%= f.error_notification %>

  <div class="form-inputs">
  <%- attributes.each do |attribute| -%>
    <%%= f.<%= attribute.reference? ? :association : :input %> :<%= attribute.name %> %>
  <%- end -%>
  </div>

  <div class="form-actions">
    <%%= f.button :submit %>
  </div>
<%% end %>

See an example here: https://github.com/dockyard/igata/blob/master/lib/templates/erb/scaffold/_form.html.erb

bf4 commented 10 years ago

Hmm, will look at a quick fix for that later today.

bf4 commented 10 years ago

So, the issue is the braindead way metric_fu is parsing the flay output.

Given

******* STARTING METRIC flay
Total score (lower is better) = 494

1) IDENTICAL code found in :defn (mass*2 = 196)
  app/models/template_demo.rb:61
  app/models/template_purchase.rb:58

2) IDENTICAL code found in :defn (mass*2 = 144)
  app/models/template_demo.rb:16
  app/models/template_purchase.rb:25

3) Similar code found in :resbody (mass = 58)
  app/models/template.rb:80
  app/models/template.rb:125

4) Similar code found in :defn (mass = 50)
  app/controllers/my_templates_git_controller.rb:4
  app/controllers/my_templates_git_controller.rb:10

5) Similar code found in :call (mass = 46)
  app/inputs/checkbox_list_input.rb:25
  app/inputs/screenshots_input.rb:22
ERRORS:
  lib/templates/erb/scaffold/_form.html.erb:6 :: parse error on value ";" (tSEMI)
  skipping lib/templates/erb/scaffold/_form.html.erb

metric_fu 'parses' it with @output.chomp.split("\n\n").map{|m| m.split("\n ") } and then each element with

       reason = problem.shift.strip
       lines_info = problem.map do |full_line|                                                                                             
          name, line = full_line.split(":")
          {:name => name.strip, :line => line.strip}

which results in reason 5) Similar code found in :call (mass = 46) being 'parsed' as

[
  "app/inputs/checkbox_list_input.rb:25", 
  "app/inputs/screenshots_input.rb:22\nERRORS:", 
  "lib/templates/erb/scaffold/_form.html.erb:6 :: parse error on value \";\" (tSEMI)", 
  "skipping lib/templates/erb/scaffold/_form.html.erb"
]

Due to the lack of \n between the last 'reason' and the 'ERRORS', the split on '\n\n' lumps them together. The 'problem' should be

[
  "app/inputs/checkbox_list_input.rb:25", 
  "app/inputs/screenshots_input.rb:22", 
]

A quick fix would be to change full_line.split(":") to full_line.split(":").map(&:strip), though that would erroneously include the error text in the report

bf4 commented 10 years ago

And the ERRORS line comes from capturing stderr in the gem_run... so... that's on me, it appears

anselmbradford commented 10 years ago

Thanks for the quick fix!