reek 0.3.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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