excellent 1.5.4

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 (106) hide show
  1. data/History.txt +69 -0
  2. data/README.rdoc +72 -0
  3. data/VERSION.yml +4 -0
  4. data/bin/excellent +34 -0
  5. data/lib/simplabs/excellent.rb +16 -0
  6. data/lib/simplabs/excellent/checks.rb +33 -0
  7. data/lib/simplabs/excellent/checks/abc_metric_method_check.rb +43 -0
  8. data/lib/simplabs/excellent/checks/assignment_in_conditional_check.rb +39 -0
  9. data/lib/simplabs/excellent/checks/base.rb +62 -0
  10. data/lib/simplabs/excellent/checks/case_missing_else_check.rb +34 -0
  11. data/lib/simplabs/excellent/checks/class_line_count_check.rb +36 -0
  12. data/lib/simplabs/excellent/checks/class_name_check.rb +38 -0
  13. data/lib/simplabs/excellent/checks/control_coupling_check.rb +35 -0
  14. data/lib/simplabs/excellent/checks/cyclomatic_complexity_block_check.rb +48 -0
  15. data/lib/simplabs/excellent/checks/cyclomatic_complexity_check.rb +23 -0
  16. data/lib/simplabs/excellent/checks/cyclomatic_complexity_method_check.rb +48 -0
  17. data/lib/simplabs/excellent/checks/empty_rescue_body_check.rb +31 -0
  18. data/lib/simplabs/excellent/checks/flog_block_check.rb +40 -0
  19. data/lib/simplabs/excellent/checks/flog_check.rb +27 -0
  20. data/lib/simplabs/excellent/checks/flog_class_check.rb +40 -0
  21. data/lib/simplabs/excellent/checks/flog_method_check.rb +40 -0
  22. data/lib/simplabs/excellent/checks/for_loop_check.rb +42 -0
  23. data/lib/simplabs/excellent/checks/global_variable_check.rb +33 -0
  24. data/lib/simplabs/excellent/checks/line_count_check.rb +27 -0
  25. data/lib/simplabs/excellent/checks/method_line_count_check.rb +36 -0
  26. data/lib/simplabs/excellent/checks/method_name_check.rb +38 -0
  27. data/lib/simplabs/excellent/checks/module_line_count_check.rb +36 -0
  28. data/lib/simplabs/excellent/checks/module_name_check.rb +38 -0
  29. data/lib/simplabs/excellent/checks/name_check.rb +27 -0
  30. data/lib/simplabs/excellent/checks/nested_iterators_check.rb +34 -0
  31. data/lib/simplabs/excellent/checks/parameter_number_check.rb +38 -0
  32. data/lib/simplabs/excellent/checks/rails.rb +22 -0
  33. data/lib/simplabs/excellent/checks/rails/attr_accessible_check.rb +38 -0
  34. data/lib/simplabs/excellent/checks/rails/attr_protected_check.rb +39 -0
  35. data/lib/simplabs/excellent/checks/rails/custom_initialize_method_check.rb +37 -0
  36. data/lib/simplabs/excellent/checks/rails/instance_var_in_partial_check.rb +37 -0
  37. data/lib/simplabs/excellent/checks/rails/params_hash_in_view_check.rb +38 -0
  38. data/lib/simplabs/excellent/checks/rails/session_hash_in_view_check.rb +38 -0
  39. data/lib/simplabs/excellent/checks/rails/validations_check.rb +36 -0
  40. data/lib/simplabs/excellent/checks/singleton_variable_check.rb +33 -0
  41. data/lib/simplabs/excellent/command_line_runner.rb +37 -0
  42. data/lib/simplabs/excellent/extensions/sexp.rb +21 -0
  43. data/lib/simplabs/excellent/extensions/string.rb +28 -0
  44. data/lib/simplabs/excellent/formatters.rb +13 -0
  45. data/lib/simplabs/excellent/formatters/base.rb +49 -0
  46. data/lib/simplabs/excellent/formatters/html.rb +153 -0
  47. data/lib/simplabs/excellent/formatters/text.rb +40 -0
  48. data/lib/simplabs/excellent/parsing.rb +10 -0
  49. data/lib/simplabs/excellent/parsing/abc_measure.rb +52 -0
  50. data/lib/simplabs/excellent/parsing/block_context.rb +43 -0
  51. data/lib/simplabs/excellent/parsing/call_context.rb +52 -0
  52. data/lib/simplabs/excellent/parsing/case_context.rb +31 -0
  53. data/lib/simplabs/excellent/parsing/class_context.rb +99 -0
  54. data/lib/simplabs/excellent/parsing/code_processor.rb +165 -0
  55. data/lib/simplabs/excellent/parsing/conditional_context.rb +25 -0
  56. data/lib/simplabs/excellent/parsing/cvar_context.rb +28 -0
  57. data/lib/simplabs/excellent/parsing/cyclomatic_complexity_measure.rb +73 -0
  58. data/lib/simplabs/excellent/parsing/flog_measure.rb +192 -0
  59. data/lib/simplabs/excellent/parsing/for_loop_context.rb +15 -0
  60. data/lib/simplabs/excellent/parsing/gvar_context.rb +21 -0
  61. data/lib/simplabs/excellent/parsing/if_context.rb +38 -0
  62. data/lib/simplabs/excellent/parsing/ivar_context.rb +32 -0
  63. data/lib/simplabs/excellent/parsing/method_context.rb +50 -0
  64. data/lib/simplabs/excellent/parsing/module_context.rb +29 -0
  65. data/lib/simplabs/excellent/parsing/parser.rb +35 -0
  66. data/lib/simplabs/excellent/parsing/resbody_context.rb +39 -0
  67. data/lib/simplabs/excellent/parsing/scopeable.rb +34 -0
  68. data/lib/simplabs/excellent/parsing/sexp_context.rb +125 -0
  69. data/lib/simplabs/excellent/parsing/singleton_method_context.rb +55 -0
  70. data/lib/simplabs/excellent/parsing/until_context.rb +24 -0
  71. data/lib/simplabs/excellent/parsing/while_context.rb +24 -0
  72. data/lib/simplabs/excellent/rake.rb +1 -0
  73. data/lib/simplabs/excellent/rake/excellent_task.rb +61 -0
  74. data/lib/simplabs/excellent/runner.rb +143 -0
  75. data/lib/simplabs/excellent/warning.rb +53 -0
  76. data/spec/checks/abc_metric_method_check_spec.rb +122 -0
  77. data/spec/checks/assignment_in_conditional_check_spec.rb +90 -0
  78. data/spec/checks/case_missing_else_check_spec.rb +42 -0
  79. data/spec/checks/class_line_count_check_spec.rb +62 -0
  80. data/spec/checks/class_name_check_spec.rb +48 -0
  81. data/spec/checks/control_coupling_check_spec.rb +103 -0
  82. data/spec/checks/cyclomatic_complexity_block_check_spec.rb +47 -0
  83. data/spec/checks/cyclomatic_complexity_method_check_spec.rb +210 -0
  84. data/spec/checks/empty_rescue_body_check_spec.rb +170 -0
  85. data/spec/checks/flog_block_check_spec.rb +28 -0
  86. data/spec/checks/flog_class_check_spec.rb +28 -0
  87. data/spec/checks/flog_method_check_spec.rb +46 -0
  88. data/spec/checks/for_loop_check_spec.rb +52 -0
  89. data/spec/checks/global_variable_check_spec.rb +66 -0
  90. data/spec/checks/method_line_count_check_spec.rb +49 -0
  91. data/spec/checks/method_name_check_spec.rb +112 -0
  92. data/spec/checks/module_line_count_check_spec.rb +48 -0
  93. data/spec/checks/module_name_check_spec.rb +61 -0
  94. data/spec/checks/nested_iterators_check_spec.rb +44 -0
  95. data/spec/checks/parameter_number_check_spec.rb +97 -0
  96. data/spec/checks/rails/attr_accessible_check_spec.rb +79 -0
  97. data/spec/checks/rails/attr_protected_check_spec.rb +77 -0
  98. data/spec/checks/rails/custom_initialize_method_check_spec.rb +58 -0
  99. data/spec/checks/rails/instance_var_in_partial_check_spec.rb +40 -0
  100. data/spec/checks/rails/params_hash_in_view_check_spec.rb +40 -0
  101. data/spec/checks/rails/session_hash_in_view_check_spec.rb +40 -0
  102. data/spec/checks/rails/validations_check_spec.rb +81 -0
  103. data/spec/checks/singleton_variable_check_spec.rb +66 -0
  104. data/spec/extensions/string_spec.rb +13 -0
  105. data/spec/spec_helper.rb +13 -0
  106. metadata +189 -0
@@ -0,0 +1,28 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Simplabs::Excellent::Checks::FlogClassCheck do
4
+
5
+ before do
6
+ @excellent = Simplabs::Excellent::Runner.new(Simplabs::Excellent::Checks::FlogClassCheck.new({ :threshold => 0 }))
7
+ end
8
+
9
+ describe '#evaluate' do
10
+
11
+ it 'should calculate the score correctly' do
12
+ code = <<-END
13
+ class User < ActiveRecord::Base
14
+ has_many :projects
15
+ end
16
+ END
17
+ @excellent.check_code(code)
18
+ warnings = @excellent.warnings
19
+
20
+ warnings.should_not be_empty
21
+ warnings[0].info.should == { :class => 'User', :score => 1 }
22
+ warnings[0].line_number.should == 1
23
+ warnings[0].message.should == "User has flog score of 1."
24
+ end
25
+
26
+ end
27
+
28
+ end
@@ -0,0 +1,46 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Simplabs::Excellent::Checks::FlogMethodCheck do
4
+
5
+ before do
6
+ @excellent = Simplabs::Excellent::Runner.new(Simplabs::Excellent::Checks::FlogMethodCheck.new({ :threshold => 0 }))
7
+ end
8
+
9
+ describe '#evaluate' do
10
+
11
+ it 'should calculate the score correctly' do
12
+ code = <<-END
13
+ def method_name
14
+ puts 'test'
15
+ end
16
+ END
17
+
18
+ verify_code_score(code, 1)
19
+ end
20
+
21
+ it 'should calculate the score that uses special metaprogramming methods correctly' do
22
+ code = <<-END
23
+ def method_name
24
+ @instance.instance_eval do
25
+ def some_method
26
+ end
27
+ end
28
+ end
29
+ END
30
+
31
+ verify_code_score(code, 6)
32
+ end
33
+
34
+ end
35
+
36
+ def verify_code_score(code, score)
37
+ @excellent.check_code(code)
38
+ warnings = @excellent.warnings
39
+
40
+ warnings.should_not be_empty
41
+ warnings[0].info.should == { :method => 'method_name', :score => score }
42
+ warnings[0].line_number.should == 1
43
+ warnings[0].message.should == "method_name has flog score of #{score}."
44
+ end
45
+
46
+ end
@@ -0,0 +1,52 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Simplabs::Excellent::Checks::ForLoopCheck do
4
+
5
+ before do
6
+ @excellent = Simplabs::Excellent::Runner.new(Simplabs::Excellent::Checks::ForLoopCheck.new)
7
+ end
8
+
9
+ describe '#evaluate' do
10
+
11
+ it 'should accept iterators' do
12
+ code = <<-END
13
+ [:sym1, :sym2].each do |sym|
14
+ end
15
+ END
16
+ @excellent.check_code(code)
17
+ warnings = @excellent.warnings
18
+
19
+ warnings.should be_empty
20
+ end
21
+
22
+ it 'should reject for loops on ranges' do
23
+ code = <<-END
24
+ for i in 1..2
25
+ end
26
+ END
27
+
28
+ verify_warning_found(code)
29
+ end
30
+
31
+ it 'should reject for loops on enumerations' do
32
+ code = <<-END
33
+ for symbol in [:sym1, :sym2]
34
+ end
35
+ END
36
+
37
+ verify_warning_found(code)
38
+ end
39
+
40
+ end
41
+
42
+ def verify_warning_found(code)
43
+ @excellent.check_code(code)
44
+ warnings = @excellent.warnings
45
+
46
+ warnings.should_not be_empty
47
+ warnings[0].info.should == {}
48
+ warnings[0].line_number.should == 1
49
+ warnings[0].message.should == 'For loop used.'
50
+ end
51
+
52
+ end
@@ -0,0 +1,66 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Simplabs::Excellent::Checks::GlobalVariableCheck do
4
+
5
+ before(:each) do
6
+ @excellent = Simplabs::Excellent::Runner.new(Simplabs::Excellent::Checks::GlobalVariableCheck.new)
7
+ end
8
+
9
+ describe '#evaluate' do
10
+
11
+ it 'should reject global variables' do
12
+ code = <<-END
13
+ $foo = 'bar'
14
+ END
15
+ @excellent.check_code(code)
16
+ warnings = @excellent.warnings
17
+
18
+ warnings.should_not be_empty
19
+ warnings[0].info.should == { :variable => 'foo' }
20
+ warnings[0].line_number.should == 1
21
+ warnings[0].message.should == 'Global variable foo used.'
22
+ end
23
+
24
+ it 'should also work in modules' do
25
+ code = <<-END
26
+ module Outer
27
+ module Inner
28
+ class Class
29
+ $foo = 'bar'
30
+ end
31
+ end
32
+ end
33
+ END
34
+ @excellent.check_code(code)
35
+ warnings = @excellent.warnings
36
+
37
+ warnings.should_not be_empty
38
+ warnings[0].info.should == { :variable => 'foo' }
39
+ warnings[0].line_number.should == 4
40
+ warnings[0].message.should == 'Global variable foo used.'
41
+ end
42
+
43
+ it 'should also work for global variables that occur within methods' do
44
+ code = <<-END
45
+ module Outer
46
+ module Inner
47
+ class Class
48
+ def method
49
+ $foo == 'bar'
50
+ end
51
+ end
52
+ end
53
+ end
54
+ END
55
+ @excellent.check_code(code)
56
+ warnings = @excellent.warnings
57
+
58
+ warnings.should_not be_empty
59
+ warnings[0].info.should == { :variable => 'foo' }
60
+ warnings[0].line_number.should == 5
61
+ warnings[0].message.should == 'Global variable foo used.'
62
+ end
63
+
64
+ end
65
+
66
+ end
@@ -0,0 +1,49 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Simplabs::Excellent::Checks::MethodLineCountCheck do
4
+
5
+ before do
6
+ @excellent = Simplabs::Excellent::Runner.new(Simplabs::Excellent::Checks::MethodLineCountCheck.new({ :threshold => 2 }))
7
+ end
8
+
9
+ describe '#evaluate' do
10
+
11
+ it 'should accept methods with less lines than the threshold' do
12
+ code = <<-END
13
+ def one_line_method
14
+ end
15
+ END
16
+ @excellent.check_code(code)
17
+
18
+ @excellent.warnings.should be_empty
19
+ end
20
+
21
+ it 'should accept methods with the same number of lines as the threshold' do
22
+ code = <<-END
23
+ def two_line_method
24
+ end
25
+ END
26
+ @excellent.check_code(code)
27
+
28
+ @excellent.warnings.should be_empty
29
+ end
30
+
31
+ it 'should reject methods with more lines than the threshold' do
32
+ code = <<-END
33
+ def four_line_method
34
+ puts 1
35
+ puts 2
36
+ end
37
+ END
38
+ @excellent.check_code(code)
39
+ warnings = @excellent.warnings
40
+
41
+ warnings.should_not be_empty
42
+ warnings[0].info.should == { :method => 'four_line_method', :count => 4 }
43
+ warnings[0].line_number.should == 1
44
+ warnings[0].message.should == 'four_line_method has 4 lines.'
45
+ end
46
+
47
+ end
48
+
49
+ end
@@ -0,0 +1,112 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Simplabs::Excellent::Checks::MethodNameCheck do
4
+
5
+ before do
6
+ @excellent = Simplabs::Excellent::Runner.new(Simplabs::Excellent::Checks::MethodNameCheck.new)
7
+ end
8
+
9
+ describe '#evaluate' do
10
+
11
+ it 'should accept method names with underscores' do
12
+ code = <<-END
13
+ def good_method_name
14
+ end
15
+ END
16
+ @excellent.check_code(code)
17
+
18
+ @excellent.warnings.should be_empty
19
+ end
20
+
21
+ it 'should accept method names with numbers' do
22
+ code = <<-END
23
+ def good_method_name_1
24
+ end
25
+ END
26
+ @excellent.check_code(code)
27
+
28
+ @excellent.warnings.should be_empty
29
+ end
30
+
31
+ it 'should accept method names ending with a question mark' do
32
+ code = <<-END
33
+ def good_method_name?
34
+ end
35
+ END
36
+ @excellent.check_code(code)
37
+
38
+ @excellent.warnings.should be_empty
39
+ end
40
+
41
+ it 'should accept method names ending with an exclamation mark' do
42
+ code = <<-END
43
+ def good_method_name!
44
+ end
45
+ END
46
+ @excellent.check_code(code)
47
+
48
+ @excellent.warnings.should be_empty
49
+ end
50
+
51
+ it 'should accept method names ending an equals sign' do
52
+ code = <<-END
53
+ def good_method_name=
54
+ end
55
+ END
56
+ @excellent.check_code(code)
57
+
58
+ @excellent.warnings.should be_empty
59
+ end
60
+
61
+ ['<<', '>>', '==', '<', '<=', '>', '>=', '[]', '[]=', '+', '-', '*', '~', '/', '%', '&', '^', '|'].each do |operator|
62
+
63
+ it "should accept #{operator} as a method name" do
64
+ code = <<-END
65
+ def #{operator}
66
+ end
67
+ END
68
+ @excellent.check_code(code)
69
+
70
+ @excellent.warnings.should be_empty
71
+ end
72
+
73
+ end
74
+
75
+ end
76
+
77
+ it 'should reject camel cased method names' do
78
+ code = <<-END
79
+ def badMethodName
80
+ end
81
+ END
82
+ @excellent.check_code(code)
83
+ warnings = @excellent.warnings
84
+
85
+ warnings.should_not be_empty
86
+ warnings[0].info.should == { :method => 'badMethodName' }
87
+ warnings[0].line_number.should == 1
88
+ warnings[0].message.should == 'Bad method name badMethodName.'
89
+ end
90
+
91
+ it "should correctly return the method's full name" do
92
+ code = <<-END
93
+ class Class
94
+ def badMethodName
95
+ end
96
+ def self.badMethodName2
97
+ end
98
+ end
99
+ END
100
+ @excellent.check_code(code)
101
+ warnings = @excellent.warnings
102
+
103
+ warnings.should_not be_empty
104
+ warnings[0].info.should == { :method => 'Class#badMethodName' }
105
+ warnings[0].line_number.should == 2
106
+ warnings[0].message.should == 'Bad method name Class#badMethodName.'
107
+ warnings[1].info.should == { :method => 'Class.badMethodName2' }
108
+ warnings[1].line_number.should == 4
109
+ warnings[1].message.should == 'Bad method name Class.badMethodName2.'
110
+ end
111
+
112
+ end
@@ -0,0 +1,48 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Simplabs::Excellent::Checks::ModuleLineCountCheck do
4
+
5
+ before do
6
+ @excellent = Simplabs::Excellent::Runner.new(Simplabs::Excellent::Checks::ModuleLineCountCheck.new({ :threshold => 2 }))
7
+ end
8
+
9
+ describe '#evaluate' do
10
+
11
+ it 'should accept modules with less lines than the threshold' do
12
+ code = <<-END
13
+ module OneLineModule; end
14
+ END
15
+ @excellent.check_code(code)
16
+
17
+ @excellent.warnings.should be_empty
18
+ end
19
+
20
+ it 'should accept modules with the same number of lines as the threshold' do
21
+ code = <<-END
22
+ module TwoLinesModule
23
+ end
24
+ END
25
+ @excellent.check_code(code)
26
+
27
+ @excellent.warnings.should be_empty
28
+ end
29
+
30
+ it 'should reject modules with more lines than the threshold' do
31
+ code = <<-END
32
+ module FourLinesModule
33
+ @foo = 1
34
+ @bar = 2
35
+ end
36
+ END
37
+ @excellent.check_code(code)
38
+ warnings = @excellent.warnings
39
+
40
+ warnings.should_not be_empty
41
+ warnings[0].info.should == { :module => 'FourLinesModule', :count => 4 }
42
+ warnings[0].line_number.should == 1
43
+ warnings[0].message.should == 'FourLinesModule has 4 lines.'
44
+ end
45
+
46
+ end
47
+
48
+ end
@@ -0,0 +1,61 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Simplabs::Excellent::Checks::ModuleNameCheck do
4
+
5
+ before do
6
+ @excellent = Simplabs::Excellent::Runner.new(Simplabs::Excellent::Checks::ModuleNameCheck.new)
7
+ end
8
+
9
+ describe '#evaluate' do
10
+
11
+ it 'should accept camel case module names starting in capitals' do
12
+ code = <<-END
13
+ module GoodModuleName
14
+ end
15
+ END
16
+ @excellent.check_code(code)
17
+
18
+ @excellent.warnings.should be_empty
19
+ end
20
+
21
+ it 'should accept namespaced modules' do
22
+ code = <<-END
23
+ module Outer::Inner::GoodModuleName
24
+ end
25
+ END
26
+ @excellent.check_code(code)
27
+
28
+ @excellent.warnings.should be_empty
29
+ end
30
+
31
+ it 'should reject module names with underscores' do
32
+ code = <<-END
33
+ module Bad_ModuleName
34
+ end
35
+ END
36
+ @excellent.check_code(code)
37
+ warnings = @excellent.warnings
38
+
39
+ warnings.should_not be_empty
40
+ warnings[0].info.should == { :module => 'Bad_ModuleName' }
41
+ warnings[0].line_number.should == 1
42
+ warnings[0].message.should == 'Bad module name Bad_ModuleName.'
43
+ end
44
+
45
+ it 'should correctly report bad names of namespaced modules' do
46
+ code = <<-END
47
+ module Outer::Inner::Bad_ModuleName
48
+ end
49
+ END
50
+ @excellent.check_code(code)
51
+ warnings = @excellent.warnings
52
+
53
+ warnings.should_not be_empty
54
+ warnings[0].info.should == { :module => 'Outer::Inner::Bad_ModuleName' }
55
+ warnings[0].line_number.should == 1
56
+ warnings[0].message.should == 'Bad module name Outer::Inner::Bad_ModuleName.'
57
+ end
58
+
59
+ end
60
+
61
+ end