nitpick 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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