reek 0.3.1 → 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 (96) hide show
  1. data/History.txt +20 -0
  2. data/README.txt +4 -80
  3. data/Rakefile +15 -4
  4. data/bin/reek +10 -16
  5. data/config/defaults.reek +53 -0
  6. data/lib/reek.rb +1 -21
  7. data/lib/reek/block_context.rb +37 -0
  8. data/lib/reek/class_context.rb +73 -0
  9. data/lib/reek/code_context.rb +47 -0
  10. data/lib/reek/code_parser.rb +204 -0
  11. data/lib/reek/exceptions.reek +13 -0
  12. data/lib/reek/if_context.rb +25 -0
  13. data/lib/reek/method_context.rb +85 -0
  14. data/lib/reek/module_context.rb +34 -0
  15. data/lib/reek/name.rb +42 -0
  16. data/lib/reek/object_refs.rb +3 -6
  17. data/lib/reek/options.rb +60 -40
  18. data/lib/reek/rake_task.rb +20 -29
  19. data/lib/reek/report.rb +16 -27
  20. data/lib/reek/sexp_formatter.rb +52 -0
  21. data/lib/reek/singleton_method_context.rb +27 -0
  22. data/lib/reek/smell_warning.rb +49 -0
  23. data/lib/reek/smells/control_couple.rb +21 -13
  24. data/lib/reek/smells/duplication.rb +23 -27
  25. data/lib/reek/smells/feature_envy.rb +18 -25
  26. data/lib/reek/smells/large_class.rb +32 -17
  27. data/lib/reek/smells/long_method.rb +24 -16
  28. data/lib/reek/smells/long_parameter_list.rb +25 -18
  29. data/lib/reek/smells/long_yield_list.rb +7 -9
  30. data/lib/reek/smells/nested_iterators.rb +13 -9
  31. data/lib/reek/smells/smell_detector.rb +66 -0
  32. data/lib/reek/smells/smells.rb +71 -10
  33. data/lib/reek/smells/uncommunicative_name.rb +49 -41
  34. data/lib/reek/smells/utility_function.rb +18 -18
  35. data/lib/reek/source.rb +116 -0
  36. data/lib/reek/spec.rb +146 -0
  37. data/lib/reek/stop_context.rb +62 -0
  38. data/lib/reek/yield_call_context.rb +14 -0
  39. data/reek.gemspec +42 -0
  40. data/spec/integration/reek_source_spec.rb +20 -0
  41. data/spec/{script_spec.rb → integration/script_spec.rb} +11 -24
  42. data/spec/reek/class_context_spec.rb +198 -0
  43. data/spec/reek/code_context_spec.rb +92 -0
  44. data/spec/reek/code_parser_spec.rb +44 -0
  45. data/spec/reek/config_spec.rb +42 -0
  46. data/spec/reek/if_context_spec.rb +17 -0
  47. data/spec/reek/method_context_spec.rb +52 -0
  48. data/spec/reek/module_context_spec.rb +38 -0
  49. data/spec/reek/options_spec.rb +2 -28
  50. data/spec/reek/report_spec.rb +6 -40
  51. data/spec/reek/sexp_formatter_spec.rb +31 -0
  52. data/spec/reek/singleton_method_context_spec.rb +17 -0
  53. data/spec/reek/smells/control_couple_spec.rb +10 -18
  54. data/spec/reek/smells/duplication_spec.rb +53 -32
  55. data/spec/reek/smells/feature_envy_spec.rb +87 -49
  56. data/spec/reek/smells/large_class_spec.rb +45 -4
  57. data/spec/reek/smells/long_method_spec.rb +25 -41
  58. data/spec/reek/smells/long_parameter_list_spec.rb +30 -76
  59. data/spec/reek/smells/nested_iterators_spec.rb +19 -29
  60. data/spec/reek/smells/smell_spec.rb +9 -18
  61. data/spec/reek/smells/uncommunicative_name_spec.rb +88 -53
  62. data/spec/reek/smells/utility_function_spec.rb +45 -44
  63. data/spec/samples/inline_spec.rb +40 -0
  64. data/spec/samples/optparse_spec.rb +100 -0
  65. data/spec/samples/redcloth_spec.rb +93 -0
  66. data/spec/spec_helper.rb +3 -1
  67. data/tasks/reek.rake +1 -10
  68. data/tasks/rspec.rake +16 -35
  69. metadata +43 -46
  70. data/lib/reek/checker.rb +0 -66
  71. data/lib/reek/class_checker.rb +0 -25
  72. data/lib/reek/file_checker.rb +0 -20
  73. data/lib/reek/method_checker.rb +0 -198
  74. data/lib/reek/printer.rb +0 -154
  75. data/lib/reek/smells/smell.rb +0 -56
  76. data/lib/reek/version.rb +0 -9
  77. data/setup.rb +0 -1585
  78. data/spec/integration_spec.rb +0 -30
  79. data/spec/reek/class_checker_spec.rb +0 -48
  80. data/spec/reek/method_checker_spec.rb +0 -67
  81. data/spec/reek/printer_spec.rb +0 -30
  82. data/spec/reek_source_spec.rb +0 -12
  83. data/spec/samples/inline.reek +0 -27
  84. data/spec/samples/optparse.reek +0 -79
  85. data/spec/samples/optparse/date.rb +0 -17
  86. data/spec/samples/optparse/shellwords.rb +0 -6
  87. data/spec/samples/optparse/time.rb +0 -10
  88. data/spec/samples/optparse/uri.rb +0 -6
  89. data/spec/samples/optparse/version.rb +0 -70
  90. data/spec/samples/redcloth.reek +0 -65
  91. data/tasks/samples.rake +0 -17
  92. data/website/index.html +0 -71
  93. data/website/index.txt +0 -40
  94. data/website/javascripts/rounded_corners_lite.inc.js +0 -285
  95. data/website/stylesheets/screen.css +0 -138
  96. data/website/template.rhtml +0 -48
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reek
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin Rutherford
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-11-17 00:00:00 +00:00
12
+ date: 2009-04-05 00:00:00 +01:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -32,17 +32,7 @@ dependencies:
32
32
  - !ruby/object:Gem::Version
33
33
  version: "3.0"
34
34
  version:
35
- - !ruby/object:Gem::Dependency
36
- name: hoe
37
- type: :development
38
- version_requirement:
39
- version_requirements: !ruby/object:Gem::Requirement
40
- requirements:
41
- - - ">="
42
- - !ruby/object:Gem::Version
43
- version: 1.8.2
44
- version:
45
- description: detects smells in Ruby code
35
+ description: Code smell detector for Ruby
46
36
  email:
47
37
  - kevin@rutherford-software.com
48
38
  executables:
@@ -52,22 +42,29 @@ extensions: []
52
42
  extra_rdoc_files:
53
43
  - History.txt
54
44
  - README.txt
55
- - website/index.txt
56
45
  files:
57
46
  - History.txt
58
47
  - README.txt
59
48
  - Rakefile
60
49
  - bin/reek
50
+ - config/defaults.reek
61
51
  - lib/reek.rb
62
- - lib/reek/checker.rb
63
- - lib/reek/class_checker.rb
64
- - lib/reek/file_checker.rb
65
- - lib/reek/method_checker.rb
52
+ - lib/reek/block_context.rb
53
+ - lib/reek/class_context.rb
54
+ - lib/reek/code_context.rb
55
+ - lib/reek/code_parser.rb
56
+ - lib/reek/exceptions.reek
57
+ - lib/reek/if_context.rb
58
+ - lib/reek/method_context.rb
59
+ - lib/reek/module_context.rb
60
+ - lib/reek/name.rb
66
61
  - lib/reek/object_refs.rb
67
62
  - lib/reek/options.rb
68
- - lib/reek/printer.rb
69
63
  - lib/reek/rake_task.rb
70
64
  - lib/reek/report.rb
65
+ - lib/reek/sexp_formatter.rb
66
+ - lib/reek/singleton_method_context.rb
67
+ - lib/reek/smell_warning.rb
71
68
  - lib/reek/smells/control_couple.rb
72
69
  - lib/reek/smells/duplication.rb
73
70
  - lib/reek/smells/feature_envy.rb
@@ -76,19 +73,29 @@ files:
76
73
  - lib/reek/smells/long_parameter_list.rb
77
74
  - lib/reek/smells/long_yield_list.rb
78
75
  - lib/reek/smells/nested_iterators.rb
79
- - lib/reek/smells/smell.rb
76
+ - lib/reek/smells/smell_detector.rb
80
77
  - lib/reek/smells/smells.rb
81
78
  - lib/reek/smells/uncommunicative_name.rb
82
79
  - lib/reek/smells/utility_function.rb
83
- - lib/reek/version.rb
84
- - setup.rb
85
- - spec/integration_spec.rb
86
- - spec/reek/class_checker_spec.rb
87
- - spec/reek/method_checker_spec.rb
80
+ - lib/reek/source.rb
81
+ - lib/reek/spec.rb
82
+ - lib/reek/stop_context.rb
83
+ - lib/reek/yield_call_context.rb
84
+ - reek.gemspec
85
+ - spec/integration/reek_source_spec.rb
86
+ - spec/integration/script_spec.rb
87
+ - spec/reek/class_context_spec.rb
88
+ - spec/reek/code_context_spec.rb
89
+ - spec/reek/code_parser_spec.rb
90
+ - spec/reek/config_spec.rb
91
+ - spec/reek/if_context_spec.rb
92
+ - spec/reek/method_context_spec.rb
93
+ - spec/reek/module_context_spec.rb
88
94
  - spec/reek/object_refs_spec.rb
89
95
  - spec/reek/options_spec.rb
90
- - spec/reek/printer_spec.rb
91
96
  - spec/reek/report_spec.rb
97
+ - spec/reek/sexp_formatter_spec.rb
98
+ - spec/reek/singleton_method_context_spec.rb
92
99
  - spec/reek/smells/control_couple_spec.rb
93
100
  - spec/reek/smells/duplication_spec.rb
94
101
  - spec/reek/smells/feature_envy_spec.rb
@@ -99,32 +106,22 @@ files:
99
106
  - spec/reek/smells/smell_spec.rb
100
107
  - spec/reek/smells/uncommunicative_name_spec.rb
101
108
  - spec/reek/smells/utility_function_spec.rb
102
- - spec/reek_source_spec.rb
103
109
  - spec/samples/inline.rb
104
- - spec/samples/inline.reek
110
+ - spec/samples/inline_spec.rb
105
111
  - spec/samples/optparse.rb
106
- - spec/samples/optparse.reek
107
- - spec/samples/optparse/date.rb
108
- - spec/samples/optparse/shellwords.rb
109
- - spec/samples/optparse/time.rb
110
- - spec/samples/optparse/uri.rb
111
- - spec/samples/optparse/version.rb
112
+ - spec/samples/optparse_spec.rb
112
113
  - spec/samples/redcloth.rb
113
- - spec/samples/redcloth.reek
114
- - spec/script_spec.rb
114
+ - spec/samples/redcloth_spec.rb
115
115
  - spec/spec.opts
116
116
  - spec/spec_helper.rb
117
117
  - tasks/reek.rake
118
118
  - tasks/rspec.rake
119
- - tasks/samples.rake
120
- - website/index.html
121
- - website/index.txt
122
- - website/javascripts/rounded_corners_lite.inc.js
123
- - website/stylesheets/screen.css
124
- - website/template.rhtml
125
119
  has_rdoc: true
126
- homepage: http://reek.rubyforge.org
127
- post_install_message:
120
+ homepage: http://wiki.github.com/kevinrutherford/reek
121
+ post_install_message: |
122
+
123
+ For more information on reek, see http://wiki.github.com/kevinrutherford/reek
124
+
128
125
  rdoc_options:
129
126
  - --main
130
127
  - README.txt
@@ -145,9 +142,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
145
142
  requirements: []
146
143
 
147
144
  rubyforge_project: reek
148
- rubygems_version: 1.2.0
145
+ rubygems_version: 1.3.1
149
146
  signing_key:
150
147
  specification_version: 2
151
- summary: detects smells in Ruby code
148
+ summary: Code smell detector for Ruby
152
149
  test_files: []
153
150
 
data/lib/reek/checker.rb DELETED
@@ -1,66 +0,0 @@
1
- $:.unshift File.dirname(__FILE__)
2
-
3
- require 'rubygems'
4
- require 'parse_tree'
5
- require 'sexp_processor'
6
-
7
- module Reek
8
-
9
- class Checker < SexpProcessor
10
-
11
- def self.parse_tree_for(code) # :nodoc:
12
- ParseTree.new.parse_tree_for_string(code)
13
- end
14
-
15
- # Creates a new Ruby code checker. Any smells discovered by
16
- # +check_source+ or +check_object+ will be stored in +report+.
17
- def initialize(report)
18
- super()
19
- @smells = report
20
- @unsupported -= [:cfunc]
21
- @default_method = :process_default
22
- @require_empty = @warn_on_default = false
23
- end
24
-
25
- def process_default(exp)
26
- exp[1..-1].each { |e| process(e) if Array === e}
27
- s(exp)
28
- end
29
-
30
- def process_defn(exp) # :nodoc:
31
- Reek::MethodChecker.new(@smells, @description).process(exp)
32
- s(exp)
33
- end
34
-
35
- def report(smell) # :nodoc:
36
- @smells << smell
37
- end
38
-
39
- # Analyses the given Ruby source +code+ looking for smells.
40
- # Any smells found are saved in the +Report+ object that
41
- # was passed to this object's constructor.
42
- def check_source(code)
43
- check_parse_tree(Checker.parse_tree_for(code))
44
- end
45
-
46
- # Analyses the given Ruby object +obj+ looking for smells.
47
- # Any smells found are saved in the +Report+ object that
48
- # was passed to this object's constructor.
49
- def check_object(obj)
50
- check_parse_tree ParseTree.new.parse_tree(obj)
51
- end
52
-
53
- def to_s # :nodoc:
54
- description
55
- end
56
-
57
- def check_parse_tree(sexp) # :nodoc:
58
- sexp.each { |exp| process(exp) }
59
- end
60
- end
61
- end
62
-
63
- # SMELL:
64
- # This is here to resolve a circular dependency -- MethodChecker inherits
65
- # Checker, which calls MethodChecker. Yuk!
66
- require 'reek/method_checker'
@@ -1,25 +0,0 @@
1
- $:.unshift File.dirname(__FILE__)
2
-
3
- require 'reek/checker'
4
- require 'reek/smells/large_class'
5
-
6
- module Reek
7
-
8
- class ClassChecker < Checker
9
-
10
- attr_accessor :description
11
-
12
- def initialize(report)
13
- super(report)
14
- @description = ''
15
- end
16
-
17
- def process_class(exp) # :nodoc:
18
- @description = exp[1].to_s
19
- superclass = exp[2]
20
- Smells::LargeClass.check(@description, self)
21
- exp[3..-1].each { |defn| process(defn) } unless superclass == [:const, :Struct]
22
- s(exp)
23
- end
24
- end
25
- end
@@ -1,20 +0,0 @@
1
- $:.unshift File.dirname(__FILE__)
2
-
3
- require 'reek/checker'
4
- require 'reek/class_checker'
5
-
6
- module Reek
7
-
8
- class FileChecker < Checker
9
-
10
- def initialize(report)
11
- super(report)
12
- @description = ''
13
- end
14
-
15
- def process_class(exp) # :nodoc:
16
- Reek::ClassChecker.new(@smells).process(exp)
17
- s(exp)
18
- end
19
- end
20
- end
@@ -1,198 +0,0 @@
1
- $:.unshift File.dirname(__FILE__)
2
-
3
- require 'reek/checker'
4
- require 'reek/smells/control_couple'
5
- require 'reek/smells/feature_envy'
6
- require 'reek/smells/long_parameter_list'
7
- require 'reek/smells/long_yield_list'
8
- require 'reek/smells/nested_iterators'
9
- require 'reek/smells/utility_function'
10
- require 'reek/smells/smells'
11
- require 'reek/object_refs'
12
- require 'set'
13
-
14
- module Reek
15
-
16
- class MethodChecker < Checker
17
-
18
- attr_reader :local_variables, :name, :parameters, :num_statements
19
- attr_reader :instance_variables # TODO: should be on the class
20
- attr_reader :calls, :depends_on_self, :refs
21
-
22
- def initialize(smells, klass_name)
23
- super(smells)
24
- @class_name = klass_name
25
- @refs = ObjectRefs.new
26
- @local_variables = Set.new
27
- @instance_variables = Set.new
28
- @parameters = []
29
- @calls = Hash.new(0)
30
- @num_statements = 0
31
- @depends_on_self = false
32
- end
33
-
34
- def description
35
- "#{@class_name}##{@name}"
36
- end
37
-
38
- def process_defn(exp)
39
- name, args = exp[1..2]
40
- @name = name.to_s
41
- process(args)
42
- check_method_properties
43
- s(exp)
44
- end
45
-
46
- def process_args(exp)
47
- Smells::LongParameterList.check(exp, self)
48
- @parameters = exp[1..-1]
49
- s(exp)
50
- end
51
-
52
- def process_attrset(exp)
53
- @depends_on_self = true if /^@/ === exp[1].to_s
54
- s(exp)
55
- end
56
-
57
- def process_lit(exp)
58
- val = exp[1]
59
- @depends_on_self = true if val == :self
60
- s(exp)
61
- end
62
-
63
- def process_lvar(exp)
64
- s(exp)
65
- end
66
-
67
- def process_iter(exp)
68
- Smells::NestedIterators.check(@inside_an_iter, self)
69
- cascade_iter(exp)
70
- s(exp)
71
- end
72
-
73
- def process_block(exp)
74
- @num_statements += MethodChecker.count_statements(exp)
75
- exp[1..-1].each { |s| process(s) }
76
- s(exp)
77
- end
78
-
79
- def process_yield(exp)
80
- args = exp[1]
81
- if args
82
- Smells::LongYieldList.check(args, self)
83
- process(args)
84
- end
85
- s(exp)
86
- end
87
-
88
- def process_call(exp)
89
- @calls[exp] += 1
90
- receiver, meth, args = exp[1..3]
91
- deal_with_receiver(receiver, meth)
92
- process(args) if args
93
- s(exp)
94
- end
95
-
96
- def process_fcall(exp)
97
- @depends_on_self = true
98
- @refs.record_reference_to_self
99
- process(exp[2]) if exp.length >= 3
100
- s(exp)
101
- end
102
-
103
- def process_cfunc(exp)
104
- @depends_on_self = true
105
- s(exp)
106
- end
107
-
108
- def process_vcall(exp)
109
- @depends_on_self = true
110
- s(exp)
111
- end
112
-
113
- def process_if(exp)
114
- cond, then_part, else_part = exp[1..3]
115
- deal_with_conditional(cond, then_part)
116
- process(else_part) if else_part
117
- Smells::ControlCouple.check(cond, self, @parameters)
118
- s(exp)
119
- end
120
-
121
- def process_ivar(exp)
122
- @instance_variables << exp[1]
123
- @depends_on_self = true
124
- s(exp)
125
- end
126
-
127
- def process_gvar(exp)
128
- s(exp)
129
- end
130
-
131
- def process_lasgn(exp)
132
- @local_variables << exp[1]
133
- process(exp[2])
134
- s(exp)
135
- end
136
-
137
- def process_iasgn(exp)
138
- @instance_variables << exp[1]
139
- @depends_on_self = true
140
- process(exp[2])
141
- s(exp)
142
- end
143
-
144
- def process_self(exp)
145
- @depends_on_self = true
146
- s(exp)
147
- end
148
-
149
- private
150
-
151
- def self.count_statements(exp)
152
- result = exp.length - 1
153
- result -= 1 if Array === exp[1] and exp[1][0] == :args
154
- result -= 1 if exp[2] == s(:nil)
155
- result
156
- end
157
-
158
- def self.is_global_variable?(exp)
159
- Array === exp and exp[0] == :gvar
160
- end
161
-
162
- def self.is_override?(class_name, method_name)
163
- begin
164
- klass = Object.const_get(class_name)
165
- rescue
166
- return false
167
- end
168
- return false unless klass.superclass
169
- klass.superclass.instance_methods.include?(method_name)
170
- end
171
-
172
- def is_override?
173
- MethodChecker.is_override?(@class_name, @name)
174
- end
175
-
176
- def check_method_properties
177
- @depends_on_self = true if is_override?
178
- SMELLS[:defn].each {|smell| smell.examine(self, @smells) }
179
- end
180
-
181
- def cascade_iter(exp)
182
- process(exp[1])
183
- @inside_an_iter = true
184
- exp[2..-1].each { |s| process(s) }
185
- @inside_an_iter = false
186
- end
187
-
188
- def deal_with_conditional(cond, then_part)
189
- process(cond)
190
- process(then_part)
191
- end
192
-
193
- def deal_with_receiver(receiver, meth)
194
- @refs.record_ref(receiver) if (receiver[0] == :lvar and meth != :new)
195
- process(receiver)
196
- end
197
- end
198
- end