nitpick 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/LICENSE +22 -0
  2. data/README +56 -0
  3. data/VERSION.yml +4 -0
  4. data/bin/nitpick +92 -0
  5. data/lib/nitpick.rb +32 -0
  6. data/lib/nitpick/argument_nitpicker.rb +21 -0
  7. data/lib/nitpick/block_nitpicker.rb +21 -0
  8. data/lib/nitpick/branch_nitpicker.rb +17 -0
  9. data/lib/nitpick/local_variable_counter.rb +81 -0
  10. data/lib/nitpick/local_variable_nitpicker.rb +26 -0
  11. data/lib/nitpick/method_nitpicker.rb +14 -0
  12. data/lib/nitpick/nitpicker.rb +46 -0
  13. data/lib/nitpick/rescue_nitpicker.rb +15 -0
  14. data/lib/nitpick/sexp_extension.rb +7 -0
  15. data/lib/nitpick/warnings/assignment_as_condition.rb +22 -0
  16. data/lib/nitpick/warnings/empty_method.rb +19 -0
  17. data/lib/nitpick/warnings/identical_branch.rb +18 -0
  18. data/lib/nitpick/warnings/rescue_everything.rb +20 -0
  19. data/lib/nitpick/warnings/rescue_value.rb +22 -0
  20. data/lib/nitpick/warnings/shadowed_variable.rb +51 -0
  21. data/lib/nitpick/warnings/simple_warning.rb +28 -0
  22. data/lib/nitpick/warnings/unprotected_block.rb +24 -0
  23. data/lib/nitpick/warnings/unused_argument.rb +19 -0
  24. data/lib/nitpick/warnings/unused_variable.rb +19 -0
  25. data/lib/nitpick/warnings/useless_branch.rb +20 -0
  26. data/spec/argument_nitpicker_spec.rb +79 -0
  27. data/spec/assignment_as_condition_spec.rb +41 -0
  28. data/spec/block_nitpicker_spec.rb +31 -0
  29. data/spec/branch_nitpicker_spec.rb +24 -0
  30. data/spec/fixtures/block_badness.rb +23 -0
  31. data/spec/fixtures/branch_badness.rb +27 -0
  32. data/spec/fixtures/local_variable_badness.rb +113 -0
  33. data/spec/fixtures/method_badness.rb +10 -0
  34. data/spec/fixtures/rescue_badness.rb +15 -0
  35. data/spec/local_variable_nitpicker_spec.rb +90 -0
  36. data/spec/method_nitpicker_spec.rb +18 -0
  37. data/spec/nitpicker_spec.rb +20 -0
  38. data/spec/rescue_nitpicker_spec.rb +25 -0
  39. data/spec/rescue_value_spec.rb +27 -0
  40. data/spec/shadowed_variable_spec.rb +60 -0
  41. data/spec/simple_warning_spec.rb +22 -0
  42. data/spec/spec_helper.rb +10 -0
  43. data/spec/useless_branch_spec.rb +11 -0
  44. metadata +109 -0
@@ -0,0 +1,24 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+ require 'fixtures/branch_badness'
3
+
4
+ include Fixtures
5
+
6
+ describe Nitpick::BranchNitpicker do
7
+ it "should warn for a branch simply returning true and false" do
8
+ nitpicker = Nitpick::BranchNitpicker.new(BranchBadness, :branch_returning_true_or_false)
9
+ nitpicker.nitpick!
10
+ nitpicker.warnings.should == [Nitpick::Warnings::UselessBranch.new]
11
+ end
12
+
13
+ it "should warn for identical branches" do
14
+ nitpicker = Nitpick::BranchNitpicker.new(BranchBadness, :branch_returning_identical_things)
15
+ nitpicker.nitpick!
16
+ nitpicker.warnings.should == [Nitpick::Warnings::IdenticalBranch.new]
17
+ end
18
+
19
+ it "should warn for assignments as conditions" do
20
+ nitpicker = Nitpick::BranchNitpicker.new(BranchBadness, :branch_with_assignment_as_condition)
21
+ nitpicker.nitpick!
22
+ nitpicker.warnings.should == [Nitpick::Warnings::AssignmentAsCondition.new]
23
+ end
24
+ end
@@ -0,0 +1,23 @@
1
+ module Fixtures
2
+ class BlockBadness
3
+ def no_conditional_for_block_given
4
+ yield
5
+ end
6
+
7
+ def simple_check_for_block_given
8
+ yield if block_given?
9
+ end
10
+
11
+ def simple_conditional_without_check
12
+ if true
13
+ yield
14
+ end
15
+ end
16
+
17
+ def complex_conditional_with_check(var)
18
+ if (1 + 2 == var) && block_given?
19
+ yield
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,27 @@
1
+ module Fixtures
2
+ class BranchBadness
3
+ def branch_returning_true_or_false
4
+ if 1 == 2
5
+ true
6
+ else
7
+ false
8
+ end
9
+ end
10
+
11
+ def branch_returning_identical_things
12
+ if true
13
+ 1 + 2
14
+ else
15
+ 1 + 2
16
+ end
17
+ end
18
+
19
+ def branch_with_assignment_as_condition
20
+ if a = 1
21
+ 1
22
+ else
23
+ 2
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,113 @@
1
+ module Fixtures
2
+ class LocalVariableBadness
3
+ def unused_lasgn
4
+ bar = 4
5
+ 1 + 2
6
+ end
7
+
8
+ def used_lvar
9
+ bar = 4
10
+ bar + 4
11
+ end
12
+
13
+ def unused_lvar
14
+ bar = 4
15
+ bar
16
+ 1 + 2
17
+ end
18
+
19
+ def lvar_with_call(foo)
20
+ foo.bar
21
+ end
22
+
23
+ def simple_unused_arg(other)
24
+ -1
25
+ end
26
+
27
+ def unused_arg(arg)
28
+ 1 + 2
29
+ end
30
+
31
+ def used_arg(arg)
32
+ arg + 4
33
+ end
34
+
35
+ def lvar_with_iasgn
36
+ foo = 1
37
+ @bar = foo
38
+ end
39
+
40
+ def arg_with_iasgn(arg)
41
+ @foo = arg
42
+ end
43
+
44
+ def lvar_shadowed
45
+ x = 1
46
+ yields_to do |x|
47
+ something_else_happens_here
48
+ end
49
+ x + 1
50
+ end
51
+
52
+ def lvar_shadowed_many_block_vars
53
+ x = 1
54
+ yields_to do |p,d,q,x|
55
+ something_else_happens_here
56
+ end
57
+ x + 1
58
+ end
59
+
60
+ def lvar_not_shadowed
61
+ x = 1
62
+ yields_to do |y|
63
+ something_else_happens_here
64
+ end
65
+ x + 1
66
+ end
67
+
68
+ def used_splat_arg(*args)
69
+ args + 4
70
+ end
71
+
72
+ def args_used_with_splats(args)
73
+ respond(*args)
74
+ end
75
+
76
+ def splat_args_used_with_splat(*args)
77
+ respond(*args)
78
+ end
79
+
80
+ def default_args(args=false)
81
+ args
82
+ end
83
+
84
+ def block_arg_unused(&block)
85
+ 1 + 2
86
+ end
87
+
88
+ def block_arg_called(&block)
89
+ block.call
90
+ end
91
+
92
+ def block_arg_curried(&block)
93
+ respond(&block)
94
+ end
95
+
96
+ def super_with_implicit_args(arg)
97
+ super
98
+ end
99
+
100
+ def super_with_explicit_args(arg)
101
+ super()
102
+ end
103
+
104
+ def rescue_to_variable
105
+ begin
106
+ rescue => e
107
+ end
108
+ end
109
+
110
+ def anonymous_args(*)
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,10 @@
1
+ module Fixtures
2
+ class MethodBadness
3
+ def empty_method
4
+ end
5
+
6
+ def non_empty_method
7
+ 1 + 2
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,15 @@
1
+ module Fixtures
2
+ class RescueBadness
3
+ def rescue_nil
4
+ raise rescue nil
5
+ end
6
+
7
+ def rescue_exception
8
+ rescue Exception
9
+ end
10
+
11
+ def rescue_object
12
+ rescue Object
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,90 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+ require 'fixtures/local_variable_badness'
3
+
4
+ include Fixtures
5
+
6
+ describe Nitpick::LocalVariableNitpicker do
7
+ it "should increment uses for an lasgn node" do
8
+ nitpicker = Nitpick::LocalVariableNitpicker.new(LocalVariableBadness, :unused_lasgn)
9
+ nitpicker.nitpick!
10
+ nitpicker.uses(:bar).should == 1
11
+ end
12
+
13
+ it "should increment uses for an lvar node" do
14
+ nitpicker = Nitpick::LocalVariableNitpicker.new(LocalVariableBadness, :used_lvar)
15
+ nitpicker.nitpick!
16
+ nitpicker.uses(:bar).should == 2 # lvar + lasgn
17
+ end
18
+
19
+ it "should create warnings for an an assigned but unused local variable" do
20
+ nitpicker = Nitpick::LocalVariableNitpicker.new(LocalVariableBadness, :unused_lasgn)
21
+ nitpicker.nitpick!
22
+ nitpicker.warnings.should == [Nitpick::Warnings::UnusedVariable.new(:bar)]
23
+ end
24
+
25
+ it "should not create warnings for used local variables" do
26
+ nitpicker = Nitpick::LocalVariableNitpicker.new(LocalVariableBadness, :used_lvar)
27
+ nitpicker.nitpick!
28
+ nitpicker.warnings.should == []
29
+ end
30
+
31
+ it "should not create warnings for local variables with calls" do
32
+ nitpicker = Nitpick::LocalVariableNitpicker.new(LocalVariableBadness, :lvar_with_call)
33
+ nitpicker.nitpick!
34
+ nitpicker.warnings.should == []
35
+ end
36
+
37
+ it "should not create warnings for local variables with iasgns" do
38
+ nitpicker = Nitpick::LocalVariableNitpicker.new(LocalVariableBadness, :lvar_with_iasgn)
39
+ nitpicker.nitpick!
40
+ nitpicker.warnings.should == []
41
+ end
42
+
43
+ it "should not create warnings for arguments with iasgns" do
44
+ nitpicker = Nitpick::LocalVariableNitpicker.new(LocalVariableBadness, :arg_with_iasgn)
45
+ nitpicker.nitpick!
46
+ nitpicker.warnings.should == []
47
+ end
48
+
49
+ it "should warn when a block variable shadows a local variable" do
50
+ nitpicker = Nitpick::LocalVariableNitpicker.new(LocalVariableBadness, :lvar_shadowed)
51
+ nitpicker.nitpick!
52
+ nitpicker.warnings.should == [Nitpick::Warnings::ShadowedVariable.new(:x)]
53
+ end
54
+
55
+ it "should warn when a block variable (among many) shadows a local variable" do
56
+ nitpicker = Nitpick::LocalVariableNitpicker.new(LocalVariableBadness, :lvar_shadowed_many_block_vars)
57
+ nitpicker.nitpick!
58
+ nitpicker.warnings.should == [Nitpick::Warnings::ShadowedVariable.new]
59
+ end
60
+
61
+ it "should not warn when a block variable does not shadow a local variable" do
62
+ nitpicker = Nitpick::LocalVariableNitpicker.new(LocalVariableBadness, :lvar_not_shadowed)
63
+ nitpicker.nitpick!
64
+ nitpicker.warnings.should == []
65
+ end
66
+
67
+ it "should not warn when a block arg is referenced" do
68
+ nitpicker = Nitpick::LocalVariableNitpicker.new(LocalVariableBadness, :block_arg_curried)
69
+ nitpicker.nitpick!
70
+ nitpicker.warnings.should == []
71
+ end
72
+
73
+ it "should not warn when splat args are used with splats" do
74
+ nitpicker = Nitpick::LocalVariableNitpicker.new(LocalVariableBadness, :splat_args_used_with_splat)
75
+ nitpicker.nitpick!
76
+ nitpicker.warnings.should == []
77
+ end
78
+
79
+ it "should not warn about unused args" do
80
+ nitpicker = Nitpick::LocalVariableNitpicker.new(LocalVariableBadness, :simple_unused_arg)
81
+ nitpicker.nitpick!
82
+ nitpicker.warnings.should == []
83
+ end
84
+
85
+ it "shouldn't barf on anonymous splat args" do
86
+ nitpicker = Nitpick::LocalVariableNitpicker.new(LocalVariableBadness, :anonymous_args)
87
+ nitpicker.nitpick!
88
+ nitpicker.warnings.should == []
89
+ end
90
+ end
@@ -0,0 +1,18 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+ require 'fixtures/method_badness'
3
+
4
+ include Fixtures
5
+
6
+ describe Nitpick::MethodNitpicker do
7
+ it "should create a warning for an empty method" do
8
+ nitpicker = Nitpick::MethodNitpicker.new(MethodBadness, :empty_method)
9
+ nitpicker.nitpick!
10
+ nitpicker.warnings.include?(Nitpick::Warnings::EmptyMethod.new(:empty_method)).should be_true
11
+ end
12
+
13
+ it "should not create a empty method warning for a non empty method" do
14
+ nitpicker = Nitpick::MethodNitpicker.new(MethodBadness, :non_empty_method)
15
+ nitpicker.nitpick!
16
+ nitpicker.warnings.any? {|w| w.is_a? Nitpick::Warnings::EmptyMethod }.should be_false
17
+ end
18
+ end
@@ -0,0 +1,20 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+ require 'fixtures/branch_badness'
3
+
4
+ include Fixtures
5
+
6
+ describe Nitpick::Nitpicker do
7
+ before do
8
+ @nitpicker = nitpicker = Nitpick::Nitpicker.new(BranchBadness, :branch_returning_true_or_false)
9
+ end
10
+
11
+ it "should discover each of the warning classes with the correct options" do
12
+ warnings = [Nitpick::Warnings::UselessBranch, Nitpick::Warnings::IdenticalBranch]
13
+ branches = [s(:true), s(:false)]
14
+ warnings.each do |warning|
15
+ warning.should_receive(:discover).with(branches)
16
+ end
17
+
18
+ @nitpicker.scan_for warnings, :with => branches
19
+ end
20
+ end
@@ -0,0 +1,25 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+ require 'fixtures/rescue_badness'
3
+
4
+ include Fixtures
5
+
6
+ describe Nitpick::RescueNitpicker do
7
+ it "should create a warning for rescuing to a value" do
8
+ nitpicker = Nitpick::RescueNitpicker.new(RescueBadness, :rescue_nil)
9
+ nitpicker.nitpick!
10
+ nitpicker.warnings.should == [Nitpick::Warnings::RescueValue.new]
11
+ end
12
+
13
+ it "should create a warning for rescuing Exception" do
14
+ nitpicker = Nitpick::RescueNitpicker.new(RescueBadness, :rescue_exception)
15
+ nitpicker.nitpick!
16
+ nitpicker.warnings.should == [Nitpick::Warnings::RescueEverything.new]
17
+ end
18
+
19
+ it "should create a warning for rescuing Object" do
20
+ nitpicker = Nitpick::RescueNitpicker.new(RescueBadness, :rescue_object)
21
+ nitpicker.nitpick!
22
+ nitpicker.warnings.should == [Nitpick::Warnings::RescueEverything.new]
23
+ end
24
+
25
+ end
@@ -0,0 +1,27 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+ require 'fixtures/rescue_badness'
3
+
4
+ include Fixtures
5
+
6
+ describe Nitpick::Warnings::RescueValue do
7
+
8
+ it "should match rescuing to a nil" do
9
+ warning = Nitpick::Warnings::RescueValue.new(nil, [:nil])
10
+ warning.matches?.should be_true
11
+ end
12
+
13
+ it "should match rescuing to a lit" do
14
+ warning = Nitpick::Warnings::RescueValue.new(nil, [:lit, 4])
15
+ warning.matches?.should be_true
16
+ end
17
+
18
+ it "should not match with a rescue body" do
19
+ exp = [nil,
20
+ [:block,
21
+ [:call, [:lit, 4], :+, [:array, [:lit, 5]]],
22
+ [:call, [:lit, 6], :+, [:array, [:lit, 7]]]]]
23
+
24
+ warning = Nitpick::Warnings::RescueValue.new(*exp)
25
+ warning.matches?.should be_false
26
+ end
27
+ end
@@ -0,0 +1,60 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+ require 'fixtures/local_variable_badness'
3
+
4
+ include Fixtures
5
+
6
+ describe Nitpick::Warnings::ShadowedVariable do
7
+
8
+ it "should match an lasgn" do
9
+ warning = Nitpick::Warnings::ShadowedVariable.new(s(:lasgn, :x, nil))
10
+ warning.matches?.should be_true
11
+ end
12
+
13
+ it "should not match when there are no assignments" do
14
+ warning = Nitpick::Warnings::ShadowedVariable.new(nil)
15
+ warning.matches?.should_not be_true
16
+ end
17
+
18
+ it "should not match a block variable assignment" do
19
+ warning = Nitpick::Warnings::ShadowedVariable.new(s(:dasgn_curr, :y))
20
+ warning.matches?.should_not be_true
21
+ end
22
+
23
+ it "should store the name of a shadowed variable" do
24
+ warning = Nitpick::Warnings::ShadowedVariable.new(s(:lasgn, :x, nil))
25
+ warning.matches?
26
+ warning.vars.should == Set.new([:x])
27
+ end
28
+
29
+ it "should match and store names in multiple assignment" do
30
+ exp = s(:masgn, s(:array, s(:dasgn_curr, :p), s(:dasgn_curr, :d),
31
+ s(:dasgn_curr, :q), s(:lasgn, :x, nil)), nil, nil)
32
+
33
+ warning = Nitpick::Warnings::ShadowedVariable.new(exp)
34
+ warning.matches?.should be_true
35
+ warning.vars.should == Set.new([:x])
36
+ end
37
+
38
+ it "should handle splat args in multiple assignment" do
39
+ exp = s(:masgn, s(:array, s(:dasgn_curr, :x), s(:dasgn_curr, :y)), s(:lasgn, :a), nil)
40
+ warning = Nitpick::Warnings::ShadowedVariable.new(exp)
41
+ warning.matches?.should be_true
42
+ warning.vars.should == Set.new([:a])
43
+ end
44
+
45
+ it "should handle one splat arg" do
46
+ exp = s(:masgn, nil, s(:lasgn, :a), nil)
47
+ warning = Nitpick::Warnings::ShadowedVariable.new(exp)
48
+ warning.matches?.should be_true
49
+ warning.vars.should == Set.new([:a])
50
+ end
51
+
52
+ it "should store the name of all shadowed variables" do
53
+ exp = s(:masgn, s(:array, s(:dasgn_curr, :p), s(:dasgn_curr, :d),
54
+ s(:lasgn, :q, nil), s(:lasgn, :x, nil)), nil, nil)
55
+ warning = Nitpick::Warnings::ShadowedVariable.new(exp)
56
+ warning.matches?
57
+ warning.vars.should == Set.new([:q, :x])
58
+ end
59
+
60
+ end