39

Most of the code I write is in Ruby, and every once in a while, I make some typo which only gets caught after a while. This is irritating when I have my scripts running long tasks, and return to find I had a typo.

Is there an actively developed lint tool for Ruby that could help me overcome this? Would it be possible to use it across a system that works with a lot of source files, some of them loaded dynamically?

Take this snippet as an example:

a = 20
b = 30
puts c

To win bounty, show me a tool that will detect the c variable as not created/undefined.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Geo
  • 93,257
  • 117
  • 344
  • 520
  • You do realize that that program won't run? Ruby will issue `test.rb:1: undefined local variable or method `c' for main:Object (NameError)`. It seems like you should pick these errors up pretty quickly without a lint tool. – user229044 Oct 27 '10 at 20:49
  • 23
    You do realize this is an example? And that Ruby find this problem at RUNTIME? – Geo Oct 28 '10 at 04:55
  • 3
    You asked this 3 years ago. Nowadays with Ruby 2.0 you can do "ruby -wc" which gives you also warnings. In your case it'd warn you about "a" and "b" not having been used. But it won't warn you about using "c" (because it shouldn't). – Niccolo M. Nov 14 '13 at 12:17
  • 3
    ...and there's also 'ruby-lint', which seems quite good. – Niccolo M. Nov 14 '13 at 12:24
  • @NiccoloM. [ruby-lint](https://github.com/YorickPeterse/ruby-lint) seems like a good answer. Post as an answer and I'll +1. Or I can post it as community wiki if you like. – John McCarthy Feb 20 '14 at 16:49

9 Answers9

24
  • ruby -c myfile.rb will check for correct Ruby syntax.
  • Reek checks Ruby code for common code smells.
  • Roodi checks Ruby code for common object-oriented design issues.
  • Flog can warn you about unusually complex code.

[Plug] If your project is in a public Github repository, Caliper can run the latter three tools and others on your code every time you commit. (Disclaimer: I work on Caliper)

MCB
  • 2,021
  • 1
  • 18
  • 32
Avdi
  • 18,340
  • 6
  • 53
  • 62
  • Can either of them detect typos in variable names? – Geo Nov 27 '09 at 07:25
  • 2
    I ran Reek,Roodi and Flog on the snippet I provided, and neither of them said anything was wrong with the `c` variable. – Geo Nov 27 '09 at 17:49
  • 3
    Welcome to the world of dynamic languages. You gain a tremendous amount of flexibility, but you lose the ability to make static assertions about the code like "all the symbols I've referenced are valid at runtime". It's a tradeoff. That said, I think some of the recent IDEs attempt to identify mistakes like this. You might look into RubyMine or Netbeans. Personally, I agree with a previous commenter that your best bet is unit tests. If you want to be notified of mistakes quickly, use something like Autotest to run your tests constantly. – Avdi Nov 28 '09 at 04:38
  • 3
    To explain further, `c` at that point might refer to a local variable; a variable defined in an enclosing lexical scope; an instance method; a singleton method; a method defined in a superclass or module... etc. There is no way for a tool to know for a certainty that `c` is invalid and therefor a typo without actually running the code - and that brings us back to unit tests. – Avdi Nov 28 '09 at 04:44
  • In fact, 'c' in your initial example will be parsed as a call to a method. And in general Ruby (and any other Ruby tool) can't do enough static analysis when it reads the code to figure out that the method c() isn't defined in scope. – kevinrutherford Dec 02 '09 at 07:32
  • I wouldn't mind if the code gets evaled, in order to figure out that the variable is undefined. – Geo Dec 02 '09 at 09:21
  • 1
    In order to eval the code, you need something to call it. That's called a test. – Avdi Dec 02 '09 at 20:28
13

You could give Diamondback Ruby a try. It does a static typecheck of Ruby code, and will thus blame you for using an undefined variable.

While DRuby is an ongoing research project, it already works quite well for small, self-contained Ruby scripts. Currently, it is unable to analyze much of the Ruby standard library “out-of-the-box”. Currently they are working toward typing Ruby on Rails (see their most recent papers).

akuhn
  • 27,477
  • 2
  • 76
  • 91
11

RubyMine (http://www.jetbrains.com/ruby) does the trick:

alt text http://img707.imageshack.us/img707/5688/31911448.png

None of the below will do all the analysis that RubyMine does.

  • NetBeans Ruby pack
  • Aptana RadRails
  • gVIM (with syntastic plugin by scrooloose)

Each of these has the capacity to identify syntax errors such as wrong number of parentheses, too many defs, ends, braces, etc. But none will identify invalid method calls the way RubyMine does.

Here's why: it's difficult.

Since Ruby is extremely dynamic (and methods like 'c' could easily be generated on the fly), any editor that tries to identify non-existent variables/methods would need to have a large part of the entire evironment loaded and multiple program flow paths constantly tested in order to get accurate 'validity' results. This is much more difficult than in Java where almost all programming is static (at least it was when I dropped that hat).

This ability to easily generate methods on the fly is one of the reasons the community holds testing to such high esteem. I really do reccomend you try testing as well.

btelles
  • 5,390
  • 7
  • 46
  • 78
  • agreed. Even in this case, the code might be valid if you call ruby -rfoo a.rb, where foo defines a top level c method! – Jim Deville Dec 05 '09 at 17:20
  • I agree with your response, but RubyMine is an entire IDE. I only need one piece of it's functionality. – Geo Dec 05 '09 at 22:30
  • Cool cool...If you're really motivated, you could download the Ruby plugin for IntelliJ (which I understand is open source) and extract the part that does that processing. But it might be easier to just create your own parser using ParseTree :-) – btelles Dec 06 '09 at 06:17
  • 1
    Looks like you can also [run RubyMine's code inspection from the command line](http://www.jetbrains.com/ruby/webhelp/working-with-rubymine-features-from-command-line.html) – John McCarthy Feb 24 '14 at 16:47
7

Have a look at RuboCop. It is a Ruby code style checker based on the Ruby Style Guide. It's maintained pretty actively and supports all major Ruby implementations. It works well with Ruby 1.9 and 2.0 and has great Emacs integration.

Bozhidar Batsov
  • 55,802
  • 13
  • 100
  • 117
5

Yes. Test::Unit

Ok, I know you already know this and that in some sense this is a non-helpful answer, but you do bring up the negative consequence of duck typing, that there kind of is (at this time) no way around just writing more tests than something like Java might need.

So, for the record, see Test::Unit in the Ruby Standard Library or one of the other test frameworks.

Having unit tests that you can run and rerun is the best way to catch errors, and you do need more of them (tests, not errors :-) in dynamic languages like Ruby...

DigitalRoss
  • 143,651
  • 25
  • 248
  • 329
  • I know tests are a good thing :). I'd just like to have something readily available to just run, and tell me if I have typos, or unusually poor code. Something like `pylint` http://www.logilab.org/857 . – Geo Nov 26 '09 at 18:56
  • I guess I agree that it would be useful. The only thing is, often people deliberately pass different types to a method. Imagine `f x=nil;...;end; f(1);`. – DigitalRoss Nov 26 '09 at 19:30
  • I don't see a reason that you need more of them in dynamic languages. Compilers only solve one of an infinite number of possible errors that could happen. – Jim Deville Dec 05 '09 at 17:17
  • 5
    Imagine the life cycle of a complex software system. Eventually, something major will get refactored. With Java, this can be done with confidence. At the end of the process everyone is expecting the types they will actually be getting. In Ruby, there could be any number of unexpected types just waiting to be passed dynamically, even without any refactoring at all. That's the conventional wisdom and the usual argument in favor of static typing. – DigitalRoss Dec 07 '09 at 15:03
2

nitpick might be what you're lookng for.

With this code:

class MyString < String
  def awesome
    self.gsub("e", "3").gsub("l", "1").uppercase
  end
end

puts MyString.new("leet").awesome

... it outputs:

$ nitpick misspelling.rb 
*** Nitpick had trouble loading "misspelling.rb":
    NoMethodError undefined method `uppercase' for "133t":MyString
Nothing to report boss! He's clean!
phiggy
  • 898
  • 8
  • 9
0

Pelusa is nice, but is working in rubinius only. This shouln't be a proplem for people familar with RVM though.

phil pirozhkov
  • 4,740
  • 2
  • 33
  • 40
0

Have not used it yet, but sounds promising (will update when I've tested this).

https://github.com/michaeledgar/laser

Static analysis and style linter for Ruby code.

cvshepherd
  • 3,947
  • 3
  • 20
  • 14
-1
avdi@lazarus:~$ irb
>> a = 20
=> 20
>> b = 30
=> 30
>> puts c
NameError: undefined local variable or method `c' for main:Object
        from (irb):3
>>

There ya go, the tool is called "IRB". Do I get the bounty?

I'm only half joking. I wrote this second answer to hopefully drive home the point that in Ruby, if you want to know that something is defined or not, you have to run the code.

Avdi
  • 18,340
  • 6
  • 53
  • 62