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,25 @@
1
+ require 'simplabs/excellent/parsing/sexp_context'
2
+
3
+ module Simplabs
4
+
5
+ module Excellent
6
+
7
+ module Parsing
8
+
9
+ class ConditionalContext < SexpContext #:nodoc:
10
+
11
+ protected
12
+
13
+ def contains_parameter?
14
+ return false unless @parent.is_a?(MethodContext)
15
+ return @exp[1][1] if @exp[1][0] == :lvar and @parent.has_parameter?(@exp[1][1])
16
+ false
17
+ end
18
+
19
+ end
20
+
21
+ end
22
+
23
+ end
24
+
25
+ end
@@ -0,0 +1,28 @@
1
+ module Simplabs
2
+
3
+ module Excellent
4
+
5
+ module Parsing
6
+
7
+ class CvarContext < SexpContext #:nodoc:
8
+
9
+ def initialize(exp, parent)
10
+ super
11
+ @name = exp[1].to_s.sub(/^@+/, '')
12
+ end
13
+
14
+ def full_name
15
+ return @name if @parent.blank?
16
+ full_name = @name
17
+ parent = @parent
18
+ parent = parent.parent until parent.is_a?(ClassContext) || parent.is_a?(ModuleContext)
19
+ full_name = "#{parent.full_name}.#{full_name}"
20
+ end
21
+
22
+ end
23
+
24
+ end
25
+
26
+ end
27
+
28
+ end
@@ -0,0 +1,73 @@
1
+ module Simplabs
2
+
3
+ module Excellent
4
+
5
+ module Parsing
6
+
7
+ module CyclomaticComplexityMeasure #:nodoc:
8
+
9
+ COMPLEXITY_NODE_TYPES = [:if, :while, :until, :for, :rescue, :case, :when, :and, :or]
10
+
11
+ def process_if(exp)
12
+ add_complexity_score(1)
13
+ super
14
+ end
15
+
16
+ def process_while(exp)
17
+ add_complexity_score(1)
18
+ super
19
+ end
20
+
21
+ def process_until(exp)
22
+ add_complexity_score(1)
23
+ super
24
+ end
25
+
26
+ def process_for(exp)
27
+ add_complexity_score(1)
28
+ super
29
+ end
30
+
31
+ def process_rescue(exp)
32
+ add_complexity_score(1)
33
+ super
34
+ end
35
+
36
+ def process_case(exp)
37
+ add_complexity_score(1)
38
+ super
39
+ end
40
+
41
+ def process_when(exp)
42
+ add_complexity_score(1)
43
+ super
44
+ end
45
+
46
+ def process_and(exp)
47
+ add_complexity_score(1)
48
+ super
49
+ end
50
+
51
+ def process_or(exp)
52
+ add_complexity_score(1)
53
+ super
54
+ end
55
+
56
+ def cc_score
57
+ @cc_score + 1 rescue 1
58
+ end
59
+
60
+ private
61
+
62
+ def add_complexity_score(score)
63
+ @cc_score ||= 0
64
+ @cc_score += score
65
+ end
66
+
67
+ end
68
+
69
+ end
70
+
71
+ end
72
+
73
+ end
@@ -0,0 +1,192 @@
1
+ module Simplabs
2
+
3
+ module Excellent
4
+
5
+ module Parsing
6
+
7
+ module FlogMeasure #:nodoc:
8
+
9
+ SCORES = Hash.new(1)
10
+ SCORES.merge!(
11
+ :define_method => 5,
12
+ :eval => 5,
13
+ :module_eval => 5,
14
+ :class_eval => 5,
15
+ :instance_eval => 5,
16
+ :alias_method => 2,
17
+ :extend => 2,
18
+ :include => 2,
19
+ :instance_method => 2,
20
+ :instance_methods => 2,
21
+ :method_added => 2,
22
+ :method_defined? => 2,
23
+ :method_removed => 2,
24
+ :method_undefined => 2,
25
+ :private_class_method => 2,
26
+ :private_instance_methods => 2,
27
+ :private_method_defined? => 2,
28
+ :protected_instance_methods => 2,
29
+ :protected_method_defined? => 2,
30
+ :public_class_method => 2,
31
+ :public_instance_methods => 2,
32
+ :public_method_defined? => 2,
33
+ :remove_method => 2,
34
+ :send => 3,
35
+ :undef_method => 2
36
+ )
37
+ BRANCHES = [:and, :case, :else, :if, :or, :rescue, :until, :when, :while]
38
+
39
+ def process_alias(exp)
40
+ add_flog_score(2)
41
+ super
42
+ end
43
+
44
+ def process_and(exp)
45
+ add_flog_score(1)
46
+ super
47
+ end
48
+
49
+ def process_or(exp)
50
+ add_flog_score(1)
51
+ super
52
+ end
53
+
54
+ def process_attrasgn(exp)
55
+ add_flog_score(1)
56
+ super
57
+ end
58
+
59
+ def process_attrset(exp)
60
+ add_flog_score(1)
61
+ super
62
+ end
63
+
64
+ def process_block_pass(exp)
65
+ add_flog_score(1)
66
+ arg = exp.last
67
+ if arg.is_a?(Sexp)
68
+ case arg.first
69
+ when :lit, :call
70
+ add_flog_score(5)
71
+ when :iter, :dsym, :dstr, *BRANCHES
72
+ add_flog_score(10)
73
+ end
74
+ end
75
+ super
76
+ end
77
+
78
+ def process_call(exp)
79
+ add_flog_score(SCORES[exp[2]])
80
+ super
81
+ end
82
+
83
+ def process_case(exp)
84
+ add_flog_score(1)
85
+ super
86
+ end
87
+
88
+ def process_dasgn_curr(exp)
89
+ add_flog_score(1)
90
+ super
91
+ end
92
+
93
+ def process_iasgn(exp)
94
+ add_flog_score(1)
95
+ super
96
+ end
97
+
98
+ def process_lasgn(exp)
99
+ add_flog_score(1)
100
+ super
101
+ end
102
+
103
+ def process_else(exp)
104
+ add_flog_score(1)
105
+ super
106
+ end
107
+
108
+ def process_rescue(exp)
109
+ add_flog_score(1)
110
+ super
111
+ end
112
+
113
+ def process_when(exp)
114
+ add_flog_score(1)
115
+ super
116
+ end
117
+
118
+ def process_if(exp)
119
+ add_flog_score(1)
120
+ super
121
+ end
122
+
123
+ def process_iter(exp)
124
+ add_flog_score 1
125
+ super
126
+ end
127
+
128
+ def process_lit(exp)
129
+ value = exp.shift
130
+ case value
131
+ when 0, -1
132
+ # do nothing
133
+ when Integer
134
+ add_flog_score(0.25)
135
+ end
136
+ super
137
+ end
138
+
139
+ def process_masgn(exp)
140
+ add_flog_score(1)
141
+ super
142
+ end
143
+
144
+ def process_sclass(exp)
145
+ add_flog_score(5)
146
+ super
147
+ end
148
+
149
+ def process_super(exp)
150
+ add_flog_score(1)
151
+ super
152
+ end
153
+
154
+ def process_while(exp)
155
+ add_flog_score(1)
156
+ super
157
+ end
158
+
159
+ def process_until(exp)
160
+ add_flog_score(1)
161
+ super
162
+ end
163
+
164
+ def process_yield(exp)
165
+ add_flog_score(1)
166
+ super
167
+ end
168
+
169
+ def flog_score
170
+ initialize_values
171
+ @score
172
+ end
173
+
174
+ private
175
+
176
+ def add_flog_score(score)
177
+ initialize_values
178
+ @score += (score * @multiplier)
179
+ end
180
+
181
+ def initialize_values
182
+ @score ||= 0
183
+ @multiplier ||= 1
184
+ end
185
+
186
+ end
187
+
188
+ end
189
+
190
+ end
191
+
192
+ end
@@ -0,0 +1,15 @@
1
+ module Simplabs
2
+
3
+ module Excellent
4
+
5
+ module Parsing
6
+
7
+ class ForLoopContext < SexpContext #:nodoc:
8
+
9
+ end
10
+
11
+ end
12
+
13
+ end
14
+
15
+ end
@@ -0,0 +1,21 @@
1
+ module Simplabs
2
+
3
+ module Excellent
4
+
5
+ module Parsing
6
+
7
+ class GvarContext < SexpContext #:nodoc:
8
+
9
+ def initialize(exp, parent)
10
+ super
11
+ @name = exp[1].to_s.sub(/^\$/, '')
12
+ @full_name = @name
13
+ end
14
+
15
+ end
16
+
17
+ end
18
+
19
+ end
20
+
21
+ end
@@ -0,0 +1,38 @@
1
+ require 'simplabs/excellent/parsing/conditional_context'
2
+
3
+ module Simplabs
4
+
5
+ module Excellent
6
+
7
+ module Parsing
8
+
9
+ class IfContext < ConditionalContext #:nodoc:
10
+
11
+ def initialize(exp, parent)
12
+ super
13
+ @contains_assignment = has_assignment?
14
+ @tests_parameter = contains_parameter?
15
+ end
16
+
17
+ def tests_assignment?
18
+ @contains_assignment
19
+ end
20
+
21
+ def tests_parameter?
22
+ @tests_parameter
23
+ end
24
+
25
+ private
26
+
27
+ def has_assignment?(exp = @exp[1])
28
+ return false if exp.node_type == :iter
29
+ super
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+
36
+ end
37
+
38
+ end
@@ -0,0 +1,32 @@
1
+ module Simplabs
2
+
3
+ module Excellent
4
+
5
+ module Parsing
6
+
7
+ class IvarContext < SexpContext #:nodoc:
8
+
9
+ def initialize(exp, parent)
10
+ super
11
+ @name = exp[1].to_s.sub(/^@+/, '')
12
+ end
13
+
14
+ def full_name
15
+ return @name if @parent.nil?
16
+ full_name = @name
17
+ parent = @parent
18
+ parent = parent.parent until parent.is_a?(ClassContext) || parent.is_a?(ModuleContext) || parent.nil?
19
+ if parent
20
+ full_name = "#{parent.full_name}.#{full_name}"
21
+ else
22
+ @name
23
+ end
24
+ end
25
+
26
+ end
27
+
28
+ end
29
+
30
+ end
31
+
32
+ end
@@ -0,0 +1,50 @@
1
+ require 'simplabs/excellent/parsing/cyclomatic_complexity_measure'
2
+ require 'simplabs/excellent/parsing/abc_measure'
3
+ require 'simplabs/excellent/parsing/flog_measure'
4
+
5
+ module Simplabs
6
+
7
+ module Excellent
8
+
9
+ module Parsing
10
+
11
+ class MethodContext < SexpContext #:nodoc:
12
+
13
+ include CyclomaticComplexityMeasure
14
+ include AbcMeasure
15
+ include FlogMeasure
16
+
17
+ attr_reader :parameters
18
+ attr_reader :calls
19
+ attr_reader :line_count
20
+
21
+ def initialize(exp, parent)
22
+ super
23
+ @parameters = []
24
+ @name = exp[1].to_s
25
+ @parent.methods << self if @parent && (@parent.is_a?(ClassContext) || @parent.is_a?(ModuleContext))
26
+ @calls = Hash.new(0)
27
+ @line_count = count_lines
28
+ end
29
+
30
+ def has_parameter?(parameter)
31
+ @parameters.include?(parameter)
32
+ end
33
+
34
+ def full_name
35
+ parent = @parent.is_a?(BlockContext) ? @parent.parent : @parent
36
+ return @name if parent.blank?
37
+ "#{parent.full_name}##{@name}"
38
+ end
39
+
40
+ def record_call_to(context)
41
+ @calls[context] += 1
42
+ end
43
+
44
+ end
45
+
46
+ end
47
+
48
+ end
49
+
50
+ end