simplabs-excellent 1.0.1 → 1.2.1

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 (96) hide show
  1. data/History.txt +19 -0
  2. data/README.rdoc +34 -0
  3. data/VERSION.yml +1 -1
  4. data/bin/excellent +21 -6
  5. data/lib/simplabs/excellent.rb +7 -5
  6. data/lib/simplabs/excellent/checks.rb +18 -1
  7. data/lib/simplabs/excellent/checks/abc_metric_method_check.rb +19 -56
  8. data/lib/simplabs/excellent/checks/assignment_in_conditional_check.rb +16 -16
  9. data/lib/simplabs/excellent/checks/base.rb +30 -21
  10. data/lib/simplabs/excellent/checks/case_missing_else_check.rb +13 -5
  11. data/lib/simplabs/excellent/checks/class_line_count_check.rb +10 -8
  12. data/lib/simplabs/excellent/checks/class_name_check.rb +11 -10
  13. data/lib/simplabs/excellent/checks/control_coupling_check.rb +13 -10
  14. data/lib/simplabs/excellent/checks/cyclomatic_complexity_block_check.rb +25 -9
  15. data/lib/simplabs/excellent/checks/cyclomatic_complexity_check.rb +4 -20
  16. data/lib/simplabs/excellent/checks/cyclomatic_complexity_method_check.rb +25 -10
  17. data/lib/simplabs/excellent/checks/duplication_check.rb +50 -0
  18. data/lib/simplabs/excellent/checks/empty_rescue_body_check.rb +10 -18
  19. data/lib/simplabs/excellent/checks/flog_block_check.rb +40 -0
  20. data/lib/simplabs/excellent/checks/flog_check.rb +27 -0
  21. data/lib/simplabs/excellent/checks/flog_class_check.rb +40 -0
  22. data/lib/simplabs/excellent/checks/flog_method_check.rb +40 -0
  23. data/lib/simplabs/excellent/checks/for_loop_check.rb +20 -4
  24. data/lib/simplabs/excellent/checks/line_count_check.rb +3 -21
  25. data/lib/simplabs/excellent/checks/method_line_count_check.rb +9 -7
  26. data/lib/simplabs/excellent/checks/method_name_check.rb +13 -9
  27. data/lib/simplabs/excellent/checks/module_line_count_check.rb +9 -7
  28. data/lib/simplabs/excellent/checks/module_name_check.rb +11 -7
  29. data/lib/simplabs/excellent/checks/name_check.rb +3 -8
  30. data/lib/simplabs/excellent/checks/nested_iterators_check.rb +33 -0
  31. data/lib/simplabs/excellent/checks/parameter_number_check.rb +13 -12
  32. data/lib/simplabs/excellent/checks/rails.rb +17 -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/singleton_variable_check.rb +32 -0
  36. data/lib/simplabs/excellent/extensions/sexp.rb +21 -0
  37. data/lib/simplabs/excellent/extensions/string.rb +23 -0
  38. data/lib/simplabs/excellent/parsing.rb +12 -0
  39. data/lib/simplabs/excellent/parsing/abc_measure.rb +52 -0
  40. data/lib/simplabs/excellent/parsing/block_context.rb +43 -0
  41. data/lib/simplabs/excellent/parsing/call_context.rb +36 -0
  42. data/lib/simplabs/excellent/parsing/case_context.rb +31 -0
  43. data/lib/simplabs/excellent/parsing/class_context.rb +68 -0
  44. data/lib/simplabs/excellent/parsing/code_processor.rb +154 -0
  45. data/lib/simplabs/excellent/parsing/conditional_context.rb +25 -0
  46. data/lib/simplabs/excellent/parsing/cvar_context.rb +28 -0
  47. data/lib/simplabs/excellent/parsing/cyclomatic_complexity_measure.rb +73 -0
  48. data/lib/simplabs/excellent/parsing/flog_measure.rb +192 -0
  49. data/lib/simplabs/excellent/parsing/for_loop_context.rb +15 -0
  50. data/lib/simplabs/excellent/parsing/if_context.rb +38 -0
  51. data/lib/simplabs/excellent/parsing/method_context.rb +50 -0
  52. data/lib/simplabs/excellent/parsing/module_context.rb +29 -0
  53. data/lib/simplabs/excellent/{core → parsing}/parser.rb +4 -2
  54. data/lib/simplabs/excellent/parsing/resbody_context.rb +39 -0
  55. data/lib/simplabs/excellent/parsing/scopeable.rb +34 -0
  56. data/lib/simplabs/excellent/parsing/sexp_context.rb +125 -0
  57. data/lib/simplabs/excellent/parsing/singleton_method_context.rb +55 -0
  58. data/lib/simplabs/excellent/parsing/until_context.rb +24 -0
  59. data/lib/simplabs/excellent/parsing/while_context.rb +24 -0
  60. data/lib/simplabs/excellent/runner.rb +105 -0
  61. data/lib/simplabs/excellent/warning.rb +53 -0
  62. data/spec/checks/abc_metric_method_check_spec.rb +36 -8
  63. data/spec/checks/assignment_in_conditional_check_spec.rb +31 -14
  64. data/spec/checks/case_missing_else_check_spec.rb +8 -8
  65. data/spec/checks/class_line_count_check_spec.rb +24 -11
  66. data/spec/checks/class_name_check_spec.rb +9 -9
  67. data/spec/checks/control_coupling_check_spec.rb +84 -13
  68. data/spec/checks/cyclomatic_complexity_block_check_spec.rb +13 -17
  69. data/spec/checks/cyclomatic_complexity_method_check_spec.rb +32 -6
  70. data/spec/checks/duplication_check_spec.rb +139 -0
  71. data/spec/checks/empty_rescue_body_check_spec.rb +54 -16
  72. data/spec/checks/flog_block_check_spec.rb +28 -0
  73. data/spec/checks/flog_class_check_spec.rb +28 -0
  74. data/spec/checks/flog_method_check_spec.rb +46 -0
  75. data/spec/checks/for_loop_check_spec.rb +11 -11
  76. data/spec/checks/method_line_count_check_spec.rb +11 -12
  77. data/spec/checks/method_name_check_spec.rb +34 -13
  78. data/spec/checks/module_line_count_check_spec.rb +11 -12
  79. data/spec/checks/module_name_check_spec.rb +31 -7
  80. data/spec/checks/nested_iterators_check_spec.rb +44 -0
  81. data/spec/checks/parameter_number_check_spec.rb +48 -12
  82. data/spec/checks/rails/attr_accessible_check_spec.rb +79 -0
  83. data/spec/checks/rails/attr_protected_check_spec.rb +77 -0
  84. data/spec/checks/singleton_variable_check_spec.rb +66 -0
  85. data/spec/{core/extensions/underscore_spec.rb → extensions/string_spec.rb} +1 -1
  86. metadata +58 -15
  87. data/README.markdown +0 -30
  88. data/lib/simplabs/excellent/checks/class_variable_check.rb +0 -25
  89. data/lib/simplabs/excellent/core.rb +0 -2
  90. data/lib/simplabs/excellent/core/checking_visitor.rb +0 -34
  91. data/lib/simplabs/excellent/core/error.rb +0 -31
  92. data/lib/simplabs/excellent/core/extensions/underscore.rb +0 -27
  93. data/lib/simplabs/excellent/core/iterator_visitor.rb +0 -29
  94. data/lib/simplabs/excellent/core/parse_tree_runner.rb +0 -88
  95. data/lib/simplabs/excellent/core/visitable_sexp.rb +0 -31
  96. data/spec/checks/class_variable_check_spec.rb +0 -26
@@ -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,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,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(exp)
41
+ @calls[exp] += 1
42
+ end
43
+
44
+ end
45
+
46
+ end
47
+
48
+ end
49
+
50
+ end
@@ -0,0 +1,29 @@
1
+ require 'simplabs/excellent/parsing/scopeable'
2
+
3
+ module Simplabs
4
+
5
+ module Excellent
6
+
7
+ module Parsing
8
+
9
+ class ModuleContext < SexpContext #:nodoc:
10
+
11
+ include Scopeable
12
+
13
+ attr_reader :methods
14
+ attr_reader :line_count
15
+
16
+ def initialize(exp, parent)
17
+ super
18
+ @name, @full_name = get_names
19
+ @methods = []
20
+ @line_count = count_lines
21
+ end
22
+
23
+ end
24
+
25
+ end
26
+
27
+ end
28
+
29
+ end
@@ -6,14 +6,16 @@ module Simplabs
6
6
 
7
7
  module Excellent
8
8
 
9
- module Core
9
+ module Parsing
10
10
 
11
- class Parser
11
+ class Parser #:nodoc:
12
12
 
13
13
  def parse(content, filename)
14
14
  silence_stream(STDERR) do
15
15
  return silent_parse(content, filename)
16
16
  end
17
+ rescue
18
+ #continue on errors
17
19
  end
18
20
 
19
21
  private
@@ -0,0 +1,39 @@
1
+ module Simplabs
2
+
3
+ module Excellent
4
+
5
+ module Parsing
6
+
7
+ class ResbodyContext < SexpContext #:nodoc:
8
+
9
+ STATEMENT_NODES = [:fcall, :return, :attrasgn, :vcall, :call, :str, :lit, :hash, :false, :true, :nil]
10
+
11
+ def initialize(exp, parent)
12
+ super
13
+ @contains_statements = contains_statements?
14
+ end
15
+
16
+ def has_statements?
17
+ @contains_statements
18
+ end
19
+
20
+ private
21
+
22
+ def contains_statements?(exp = @exp)
23
+ return true if STATEMENT_NODES.include?(exp.node_type)
24
+ return true if assigning_other_than_exception_to_local_variable?(exp)
25
+ return true if (exp[1][0] == :array && exp[2][0] == :array rescue false)
26
+ return true if exp.children.any? { |child| contains_statements?(child) }
27
+ end
28
+
29
+ def assigning_other_than_exception_to_local_variable?(exp)
30
+ exp.node_type == :lasgn && exp[2].to_a != [:gvar, :$!]
31
+ end
32
+
33
+ end
34
+
35
+ end
36
+
37
+ end
38
+
39
+ end