michaeledgar / laser

Static analysis and style linter for Ruby code.
http://carboni.ca/projects/p/laser
GNU Affero General Public License v3.0
387 stars 17 forks source link

"simulate_require" breaks when requiring standard libraries #7

Open rks opened 13 years ago

rks commented 13 years ago

laser is failing for me when my files require standard libraries, such as ostruct and pathname. It appears to assume that these libraries are part of my application. The error originates in Laser::Analysis::ControlFlow::Simulation#simulate_require: `simulate_require': No such file: ostruct (LoadError)

Example:

$ rvm info

ruby-1.9.2-p290@dev:

  system:
    uname:       "Linux rsouza 2.6.38-8-generic #42-Ubuntu SMP Mon Apr 11 03:31:24 UTC 2011 x86_64 x86_64 x86_64 GNU/Linux"
    bash:        "/usr/local/bin/bash => GNU bash, version 4.2.8(1)-release (x86_64-pc-linux-gnu)"
    zsh:         " => not installed"

  rvm:
    version:      "rvm 1.6.32 by Wayne E. Seguin (wayneeseguin@gmail.com) [https://rvm.beginrescueend.com/]"

  ruby:
    interpreter:  "ruby"
    version:      "1.9.2p290"
    date:         "2011-07-09"
    platform:     "x86_64-linux"
    patchlevel:   "2011-07-09 revision 32553"
    full_version: "ruby 1.9.2p290 (2011-07-09 revision 32553) [x86_64-linux]"

  homes:
    gem:          "/local/rvm/gems/ruby-1.9.2-p290@dev"
    ruby:         "/local/rvm/rubies/ruby-1.9.2-p290"

  binaries:
    ruby:         "/local/rvm/rubies/ruby-1.9.2-p290/bin/ruby"
    irb:          "/local/rvm/rubies/ruby-1.9.2-p290/bin/irb"
    gem:          "/local/rvm/rubies/ruby-1.9.2-p290/bin/gem"
    rake:         "/local/rvm/gems/ruby-1.9.2-p290@dev/bin/rake"

  environment:
    PATH:         "/local/rvm/gems/ruby-1.9.2-p290@dev/bin:/local/rvm/gems/ruby-1.9.2-p290@global/bin:/local/rvm/rubies/ruby-1.9.2-p290/bin:/local/rvm/bin:/home/rsouza/bin:/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games"
    GEM_HOME:     "/local/rvm/gems/ruby-1.9.2-p290@dev"
    GEM_PATH:     "/local/rvm/gems/ruby-1.9.2-p290@dev:/local/rvm/gems/ruby-1.9.2-p290@global"
    MY_RUBY_HOME: "/local/rvm/rubies/ruby-1.9.2-p290"
    IRBRC:        "/local/rvm/rubies/ruby-1.9.2-p290/.irbrc"
    RUBYOPT:      ""
    gemset:       "dev"

$ gem list laser

*** LOCAL GEMS ***

laser (0.7.0.pre1)

$ cat configuration.rb 
require 'ostruct'

class Configuration < OpenStruct
end

$ laser configuration.rb 
/local/rvm/gems/ruby-1.9.2-p290@dev/gems/laser-0.7.0.pre1/lib/laser/analysis/control_flow/simulation.rb:364:in `simulate_require': No such file: ostruct (LoadError)
    from /local/rvm/gems/ruby-1.9.2-p290@dev/gems/laser-0.7.0.pre1/lib/laser/analysis/control_flow/simulation.rb:279:in `simulate_special_method'
    from /local/rvm/gems/ruby-1.9.2-p290@dev/gems/laser-0.7.0.pre1/lib/laser/analysis/control_flow/simulation.rb:229:in `simulate_call_dispatch'
    from /local/rvm/gems/ruby-1.9.2-p290@dev/gems/laser-0.7.0.pre1/lib/laser/analysis/control_flow/simulation.rb:199:in `simulate_call'
    from /local/rvm/gems/ruby-1.9.2-p290@dev/gems/laser-0.7.0.pre1/lib/laser/analysis/control_flow/simulation.rb:190:in `simulate_call_instruction'
    from /local/rvm/gems/ruby-1.9.2-p290@dev/gems/laser-0.7.0.pre1/lib/laser/analysis/control_flow/simulation.rb:160:in `simulate_instruction'
    from /local/rvm/gems/ruby-1.9.2-p290@dev/gems/laser-0.7.0.pre1/lib/laser/analysis/control_flow/simulation.rb:112:in `simulate_exit_instruction'
    from /local/rvm/gems/ruby-1.9.2-p290@dev/gems/laser-0.7.0.pre1/lib/laser/analysis/control_flow/simulation.rb:96:in `simulate_block'
    from /local/rvm/gems/ruby-1.9.2-p290@dev/gems/laser-0.7.0.pre1/lib/laser/analysis/control_flow/simulation.rb:41:in `block in simulate'
    from /local/rvm/gems/ruby-1.9.2-p290@dev/gems/laser-0.7.0.pre1/lib/laser/analysis/control_flow/simulation.rb:39:in `loop'
    from /local/rvm/gems/ruby-1.9.2-p290@dev/gems/laser-0.7.0.pre1/lib/laser/analysis/control_flow/simulation.rb:39:in `simulate'
    from /local/rvm/gems/ruby-1.9.2-p290@dev/gems/laser-0.7.0.pre1/lib/laser/analysis/control_flow/control_flow_graph.rb:222:in `analyze'
    from /local/rvm/gems/ruby-1.9.2-p290@dev/gems/laser-0.7.0.pre1/lib/laser/analysis/control_flow.rb:23:in `perform_cfg_analysis'
    from /local/rvm/gems/ruby-1.9.2-p290@dev/gems/laser-0.7.0.pre1/lib/laser/analysis/annotations.rb:43:in `block in perform_load_time_analysis'
    from /local/rvm/gems/ruby-1.9.2-p290@dev/gems/laser-0.7.0.pre1/lib/laser/analysis/annotations.rb:38:in `each'
    from /local/rvm/gems/ruby-1.9.2-p290@dev/gems/laser-0.7.0.pre1/lib/laser/analysis/annotations.rb:38:in `perform_load_time_analysis'
    from /local/rvm/gems/ruby-1.9.2-p290@dev/gems/laser-0.7.0.pre1/lib/laser/analysis/annotations.rb:15:in `annotate_inputs'
    from /local/rvm/gems/ruby-1.9.2-p290@dev/gems/laser-0.7.0.pre1/lib/laser/analysis/sexp_analysis.rb:10:in `analyze_inputs'
    from /local/rvm/gems/ruby-1.9.2-p290@dev/gems/laser-0.7.0.pre1/lib/laser/analysis/sexp_analysis.rb:21:in `parse'
    from /local/rvm/gems/ruby-1.9.2-p290@dev/gems/laser-0.7.0.pre1/lib/laser/analysis/sexp_analysis.rb:32:in `find_sexps'
    from /local/rvm/gems/ruby-1.9.2-p290@dev/gems/laser-0.7.0.pre1/lib/laser/warnings/useless_double_quotes.rb:16:in `match?'
    from /local/rvm/gems/ruby-1.9.2-p290@dev/gems/laser-0.7.0.pre1/lib/laser/warning.rb:91:in `generated_warnings'
    from /local/rvm/gems/ruby-1.9.2-p290@dev/gems/laser-0.7.0.pre1/lib/laser/scanner.rb:166:in `block in scan_for_warnings'
    from /local/rvm/gems/ruby-1.9.2-p290@dev/gems/laser-0.7.0.pre1/lib/laser/scanner.rb:166:in `map'
    from /local/rvm/gems/ruby-1.9.2-p290@dev/gems/laser-0.7.0.pre1/lib/laser/scanner.rb:166:in `scan_for_warnings'
    from /local/rvm/gems/ruby-1.9.2-p290@dev/gems/laser-0.7.0.pre1/lib/laser/scanner.rb:138:in `scan_for_file_warnings'
    from /local/rvm/gems/ruby-1.9.2-p290@dev/gems/laser-0.7.0.pre1/lib/laser/scanner.rb:46:in `scan'
    from /local/rvm/gems/ruby-1.9.2-p290@dev/gems/laser-0.7.0.pre1/lib/laser/runner.rb:161:in `block in collect_warnings'
    from /local/rvm/gems/ruby-1.9.2-p290@dev/gems/laser-0.7.0.pre1/lib/laser/runner.rb:156:in `map'
    from /local/rvm/gems/ruby-1.9.2-p290@dev/gems/laser-0.7.0.pre1/lib/laser/runner.rb:156:in `collect_warnings'
    from /local/rvm/gems/ruby-1.9.2-p290@dev/gems/laser-0.7.0.pre1/lib/laser/runner.rb:18:in `run'
    from /local/rvm/gems/ruby-1.9.2-p290@dev/gems/laser-0.7.0.pre1/bin/laser:7:in `<top (required)>'
    from /local/rvm/gems/ruby-1.9.2-p290@dev/bin/laser:19:in `load'
    from /local/rvm/gems/ruby-1.9.2-p290@dev/bin/laser:19:in `<main>'
michaeledgar commented 13 years ago

Thanks for the report! This has been something I've been putting off for a while, but Laser should be able to handle something like ostruct. I'm thinking right now the best solution is to accept an environment variable and/or switch which sets the LOAD_PATH that Laser should use during simulation (in addition to its own stuff). LASER_LOAD_PATH and --load-path sound good to me.

michaeledgar commented 13 years ago

I've added some preliminary support for this feature in 1bcc99acb1854c884706c734c14138432f371880.

The -I option passable to Ruby is now supported, and by default, Laser will consider the environment variable LASER_RUBYPATH, then RUBYPATH, then the current $LOAD_PATH variable (before any modifications made by Laser itself).

You will, however, get "unused method" warnings from the standard library classes you've required. Still pondering how to approach that without hiding unused methods in user code.