kevinrutherford-reek 1.1.3.2 → 1.1.3.3

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,9 +1,11 @@
1
1
  == 1.1.4 (in git)
2
2
 
3
3
  === Minor Changes
4
- * LongMethod now counts statements deeper into each method (#25)
4
+ * LongMethod now counts statements deeper into each method (fixed #25)
5
5
  * LongMethod no longer counts control structures, only their contained stmts
6
- * LargeClass is disabled when checking in-memory classes
6
+ * LargeClass is disabled when checking in-memory classes (fixed #28)
7
+ * Output now reports on all files examined, even if they have no smells
8
+ * Smell warnings are indented in the report to distinguish them from file headers
7
9
 
8
10
  == 1.1.3 2009-05-19
9
11
 
@@ -11,7 +13,7 @@
11
13
  * No longer depends directly on the sexp_processor gem
12
14
 
13
15
  === Fixes
14
- * LargeClass now relies only on the given source code (#26)
16
+ * LargeClass now relies only on the given source code (fixed #26)
15
17
 
16
18
  == 1.1.2 2009-05-18
17
19
 
@@ -22,7 +24,7 @@
22
24
  == 1.1.1 2009-05-08
23
25
 
24
26
  === Minor enhancements
25
- * LargeClass now also warns about any class with > 9 instance variables (#6)
27
+ * LargeClass now also warns about any class with > 9 instance variables (fixed #6)
26
28
  * Now depends on ruby2ruby, to display code better
27
29
  * Duplication notices more repeated method calls
28
30
  * Smells within blocks are now reported better
@@ -30,7 +32,7 @@
30
32
  == 1.1.0 2009-04-10
31
33
 
32
34
  === Minor enhancements
33
- * Now possible to write 'MyClass.should_not reek' (#33)
35
+ * Now possible to write 'MyClass.should_not reek' (fixed #33)
34
36
 
35
37
  === Fixes
36
38
  * Now counts attr assignments ([]= etc) in feature envy calculations
@@ -39,7 +41,7 @@
39
41
  == 1.0.1 2009-04-06
40
42
 
41
43
  === Fixes
42
- * Dir[...].to_source now creates a Report that can be browsed (#36)
44
+ * Dir[...].to_source now creates a Report that can be browsed (fixed #36)
43
45
 
44
46
  == 1.0.0 2009-04-05
45
47
 
@@ -15,6 +15,11 @@ module Reek
15
15
  ClassContext.new(res[0], res[1], exp[2])
16
16
  end
17
17
 
18
+ def ClassContext.from_s(src)
19
+ source = Source.from_s(src)
20
+ CodeParser.new(Sniffer.new).process_class(source.generate_syntax_tree)
21
+ end
22
+
18
23
  def initialize(outer, name, superclass = nil)
19
24
  super(outer, nil)
20
25
  @name = name
@@ -27,11 +27,11 @@ module Reek
27
27
 
28
28
  class CodeParser
29
29
 
30
- # Creates a new Ruby code checker. Any smells discovered
31
- # will be stored in +report+.
32
- def initialize(report, smells, ctx = StopContext.new)
33
- @report = report
34
- @smells = smells
30
+ #
31
+ # Creates a new Ruby code checker.
32
+ #
33
+ def initialize(sniffer, ctx = StopContext.new)
34
+ @sniffer = sniffer
35
35
  @element = ctx
36
36
  end
37
37
 
@@ -127,9 +127,7 @@ module Reek
127
127
  end
128
128
 
129
129
  def process_while(exp)
130
- count_clause(exp[2])
131
- process_default(exp)
132
- @element.count_statements(-1)
130
+ process_until(exp)
133
131
  end
134
132
 
135
133
  def process_until(exp)
@@ -140,19 +138,16 @@ module Reek
140
138
 
141
139
  def process_for(exp)
142
140
  count_clause(exp[3])
143
- process_default(exp)
144
- @element.count_statements(-1)
141
+ process_case(exp)
145
142
  end
146
143
 
147
144
  def process_rescue(exp)
148
145
  count_clause(exp[1])
149
- process_default(exp)
150
- @element.count_statements(-1)
146
+ process_case(exp)
151
147
  end
152
148
 
153
149
  def process_resbody(exp)
154
- count_clause(exp[2])
155
- process_default(exp)
150
+ process_when(exp)
156
151
  end
157
152
 
158
153
  def process_case(exp)
@@ -209,8 +204,7 @@ module Reek
209
204
  end
210
205
 
211
206
  def check_smells(type)
212
- listeners = @smells[type]
213
- listeners.each {|smell| smell.examine(@element, @report) } if listeners
207
+ @sniffer.examine(@element, type)
214
208
  end
215
209
 
216
210
  def push(context)
@@ -22,7 +22,7 @@ module Reek
22
22
 
23
23
  def initialize(code, desc) # :nodoc:
24
24
  super
25
- @cf.disable('LargeClass')
25
+ @sniffer.disable('LargeClass')
26
26
  end
27
27
 
28
28
  def can_parse_objects?
data/lib/reek/report.rb CHANGED
@@ -1,12 +1,15 @@
1
1
  require 'set'
2
+ require 'reek/sniffer'
2
3
  require 'reek/smells/smell_detector'
3
4
 
4
5
  module Reek
5
6
  class Report
6
7
  include Enumerable
7
8
 
8
- def initialize # :nodoc:
9
+ def initialize(sniffer = nil) # :nodoc:
10
+ @masked_smells = SortedSet.new
9
11
  @report = SortedSet.new
12
+ sniffer.report_on(self) if sniffer
10
13
  end
11
14
 
12
15
  #
@@ -20,6 +23,14 @@ module Reek
20
23
  @report << smell
21
24
  true
22
25
  end
26
+
27
+ def record_masked_smell(smell)
28
+ @masked_smells << smell
29
+ end
30
+
31
+ def num_masked_smells
32
+ @masked_smells.length
33
+ end
23
34
 
24
35
  def empty?
25
36
  @report.empty?
@@ -38,13 +49,22 @@ module Reek
38
49
  # Creates a formatted report of all the +Smells::SmellWarning+ objects recorded in
39
50
  # this report, with a heading.
40
51
  def full_report(desc)
41
- "\"#{desc}\" -- #{length} warnings:\n#{to_s}\n"
52
+ result = header(desc, @report.length)
53
+ result += ":\n#{to_s}\n" if length > 0
54
+ result
55
+ end
56
+
57
+ def header(desc, num_smells)
58
+ result = "\"#{desc}\" -- #{num_smells} warning"
59
+ result += 's' unless num_smells == 1
60
+ result += " (+#{@masked_smells.length} masked)" unless @masked_smells.empty?
61
+ result
42
62
  end
43
63
 
44
64
  # Creates a formatted report of all the +Smells::SmellWarning+ objects recorded in
45
65
  # this report.
46
66
  def to_s
47
- @report.map {|smell| smell.report}.join("\n")
67
+ @report.map {|smell| " #{smell.report}"}.join("\n")
48
68
  end
49
69
  end
50
70
 
@@ -75,7 +95,7 @@ module Reek
75
95
  end
76
96
 
77
97
  def to_s
78
- smelly_sources.map { |src| src.full_report }.join("\n")
98
+ @sources.map { |src| src.full_report }.join("\n")
79
99
  end
80
100
  end
81
101
  end
@@ -49,12 +49,11 @@ module Reek
49
49
 
50
50
  #
51
51
  # Checks whether the given conditional statement relies on a control couple.
52
- # Any smells found are added to the +report+.
52
+ # Remembers any smells found.
53
53
  #
54
- def examine_context(cond, report)
54
+ def examine_context(cond)
55
55
  return unless cond.tests_a_parameter?
56
- report << SmellWarning.new(self, cond,
57
- "is controlled by argument #{SexpFormatter.format(cond.if_expr)}")
56
+ found(cond, "is controlled by argument #{SexpFormatter.format(cond.if_expr)}")
58
57
  end
59
58
  end
60
59
  end
@@ -33,10 +33,9 @@ module Reek
33
33
  @max_calls = config[MAX_ALLOWED_CALLS_KEY]
34
34
  end
35
35
 
36
- def examine_context(method, report)
36
+ def examine_context(method)
37
37
  smelly_calls(method).each do |call|
38
- report << SmellWarning.new(self, method,
39
- "calls #{SexpFormatter.format(call)} multiple times")
38
+ found(method, "calls #{SexpFormatter.format(call)} multiple times")
40
39
  end
41
40
  end
42
41
 
@@ -45,12 +45,11 @@ module Reek
45
45
  #
46
46
  # Checks whether the given +context+ includes any code fragment that
47
47
  # might "belong" on another class.
48
- # Any smells found are added to the +report+.
48
+ # Remembers any smells found.
49
49
  #
50
- def examine_context(context, report)
50
+ def examine_context(context)
51
51
  context.envious_receivers.each do |ref|
52
- report << SmellWarning.new(self, context,
53
- "refers to #{SexpFormatter.format(ref)} more than self")
52
+ found(context, "refers to #{SexpFormatter.format(ref)} more than self")
54
53
  end
55
54
  end
56
55
  end
@@ -42,27 +42,25 @@ module Reek
42
42
  @max_instance_variables = config[MAX_ALLOWED_IVARS_KEY]
43
43
  end
44
44
 
45
- def check_num_methods(klass, report) # :nodoc:
45
+ def check_num_methods(klass) # :nodoc:
46
46
  count = klass.num_methods
47
47
  return if count <= @max_methods
48
- report << SmellWarning.new(self, klass,
49
- "has at least #{count} methods")
48
+ found(klass, "has at least #{count} methods")
50
49
  end
51
50
 
52
- def check_num_ivars(klass, report) # :nodoc:
51
+ def check_num_ivars(klass) # :nodoc:
53
52
  count = klass.variable_names.length
54
53
  return if count <= @max_instance_variables
55
- report << SmellWarning.new(self, klass,
56
- "has at least #{count} instance variables")
54
+ found(klass, "has at least #{count} instance variables")
57
55
  end
58
56
 
59
57
  #
60
58
  # Checks +klass+ for too many methods or too many instance variables.
61
- # Any smells found are added to the +report+.
59
+ # Remembers any smells found.
62
60
  #
63
- def examine_context(klass, report)
64
- check_num_methods(klass, report)
65
- check_num_ivars(klass, report)
61
+ def examine_context(klass)
62
+ check_num_methods(klass)
63
+ check_num_ivars(klass)
66
64
  end
67
65
  end
68
66
  end
@@ -30,13 +30,12 @@ module Reek
30
30
 
31
31
  #
32
32
  # Checks the length of the given +method+.
33
- # Any smells found are added to the +report+.
33
+ # Remembers any smells found.
34
34
  #
35
- def examine_context(method, report)
35
+ def examine_context(method)
36
36
  num = method.num_statements
37
37
  return false if num <= @max_statements
38
- report << SmellWarning.new(self, method,
39
- "has approx #{num} statements")
38
+ found(method, "has approx #{num} statements")
40
39
  end
41
40
  end
42
41
  end
@@ -30,13 +30,12 @@ module Reek
30
30
 
31
31
  #
32
32
  # Checks the number of parameters in the given scope.
33
- # Any smells found are added to the +report+.
33
+ # Remembers any smells found.
34
34
  #
35
- def examine_context(ctx, report)
35
+ def examine_context(ctx)
36
36
  num_params = ctx.parameters.length
37
37
  return false if num_params <= @max_params
38
- report << SmellWarning.new(self, ctx,
39
- "#{@action} #{num_params} parameters")
38
+ found(ctx, "#{@action} #{num_params} parameters")
40
39
  end
41
40
  end
42
41
  end
@@ -17,11 +17,11 @@ module Reek
17
17
 
18
18
  #
19
19
  # Checks whether the given +block+ is inside another.
20
- # Any smells found are added to the +report+.
20
+ # Remembers any smells found.
21
21
  #
22
- def examine_context(block, report)
22
+ def examine_context(block)
23
23
  return false unless block.nested_block?
24
- report << SmellWarning.new(self, block, 'is nested')
24
+ found(block, 'is nested')
25
25
  end
26
26
  end
27
27
  end
@@ -37,20 +37,27 @@ module Reek
37
37
  def self.listen(hooks, config)
38
38
  detector = new(config[class_name])
39
39
  contexts.each { |ctx| hooks[ctx] << detector }
40
+ detector
40
41
  end
41
42
 
42
43
  def initialize(config)
43
44
  @enabled = config[ENABLED_KEY]
44
45
  @exceptions = config[EXCLUDE_KEY]
46
+ @smells_found = []
47
+ @masked = false
45
48
  end
46
49
 
47
- def examine(context, report)
48
- before = report.size
49
- examine_context(context, report) if @enabled and !exception?(context)
50
- report.length > before
50
+ def be_masked
51
+ @masked = true
51
52
  end
52
53
 
53
- def examine_context(context, report)
54
+ def examine(context)
55
+ before = @smells_found.size
56
+ examine_context(context) if @enabled and !exception?(context)
57
+ @smells_found.length > before
58
+ end
59
+
60
+ def examine_context(context)
54
61
  end
55
62
 
56
63
  def exception?(context)
@@ -58,6 +65,22 @@ module Reek
58
65
  context.matches?(@exceptions)
59
66
  end
60
67
 
68
+ def found(scope, warning)
69
+ smell = SmellWarning.new(self, scope, warning)
70
+ @smells_found << smell
71
+ smell
72
+ end
73
+
74
+ def report_on(report)
75
+ @smells_found.each do |smell|
76
+ if @masked
77
+ report.record_masked_smell(smell)
78
+ else
79
+ report << smell
80
+ end
81
+ end
82
+ end
83
+
61
84
  def smell_name
62
85
  self.class.name_words.join(' ')
63
86
  end
@@ -47,27 +47,25 @@ module Reek
47
47
 
48
48
  #
49
49
  # Checks the given +context+ for uncommunicative names.
50
- # Any smells found are added to the +report+.
50
+ # Remembers any smells found.
51
51
  #
52
- def examine_context(context, report)
53
- consider_name(context, report)
54
- consider_variables(context, report)
52
+ def examine_context(context)
53
+ consider_name(context)
54
+ consider_variables(context)
55
55
  end
56
56
 
57
- def consider_variables(context, report) # :nodoc:
57
+ def consider_variables(context) # :nodoc:
58
58
  context.variable_names.each do |name|
59
59
  next unless is_bad_name?(name)
60
- report << SmellWarning.new(self, context,
61
- "has the variable name '#{name}'")
60
+ found(context, "has the variable name '#{name}'")
62
61
  end
63
62
  end
64
63
 
65
- def consider_name(context, report) # :nodoc:
64
+ def consider_name(context) # :nodoc:
66
65
  name = context.name
67
66
  return false if @accept.include?(context.to_s) # TODO: fq_name() ?
68
67
  return false unless is_bad_name?(name)
69
- report << SmellWarning.new(self, context,
70
- "has the name '#{name}'")
68
+ found(context, "has the name '#{name}'")
71
69
  end
72
70
 
73
71
  def is_bad_name?(name) # :nodoc:
@@ -20,14 +20,13 @@ module Reek
20
20
 
21
21
  #
22
22
  # Checks whether the given +method+ is a utility function.
23
- # Any smells found are added to the +report+.
23
+ # Remembers any smells found.
24
24
  #
25
- def examine_context(method, report)
25
+ def examine_context(method)
26
26
  return false if method.calls.keys.length == 0 or
27
27
  method.num_statements == 0 or
28
28
  method.depends_on_instance?
29
- report << SmellWarning.new(self, method,
30
- "doesn't depend on instance state")
29
+ found(method, "doesn't depend on instance state")
31
30
  end
32
31
  end
33
32
  end
@@ -37,7 +37,7 @@ class Hash
37
37
  end
38
38
 
39
39
  module Reek
40
- class SmellConfig
40
+ class Sniffer
41
41
 
42
42
  SMELL_CLASSES = [
43
43
  Smells::ControlCouple,
@@ -53,22 +53,53 @@ module Reek
53
53
  ]
54
54
 
55
55
  def initialize
56
- defaults_file = File.join(File.dirname(__FILE__), '..', '..', '..', 'config', 'defaults.reek')
56
+ defaults_file = File.join(File.dirname(__FILE__), '..', '..', 'config', 'defaults.reek')
57
57
  @config = YAML.load_file(defaults_file)
58
+ @detectors = nil
59
+ @listeners = []
58
60
  end
59
61
 
60
- def smell_listeners()
61
- result = Hash.new {|hash,key| hash[key] = [] }
62
- SMELL_CLASSES.each { |smell| smell.listen(result, @config) }
63
- return result
62
+ #
63
+ # Configures this sniffer using any *.reek config files found
64
+ # on the path to the named file. Config files are applied in order,
65
+ # "root-first", so that config files closer to the named file override
66
+ # those further up the path.
67
+ #
68
+ def configure_along_path(filename)
69
+ path = File.expand_path(File.dirname(filename))
70
+ all_reekfiles(path).each { |rfile| configure_with(rfile) }
71
+ self
72
+ end
73
+
74
+ #
75
+ # Overrides this sniffer's current settings with those in the named
76
+ # +config_file+.
77
+ #
78
+ def configure_with(config_file)
79
+ YAML.load_file(config_file).push_keys(@config)
80
+ end
81
+
82
+ def disable(smell)
83
+ @config[smell].adopt!({Reek::Smells::SmellDetector::ENABLED_KEY => false})
84
+ end
85
+
86
+ def report_on(report)
87
+ @listeners.each {|smell| smell.report_on(report)}
64
88
  end
65
89
 
66
- def load_local(file)
67
- path = File.expand_path(file)
68
- all_reekfiles(path).each do |rfile|
69
- YAML.load_file(rfile).push_keys(@config)
90
+ def examine(scope, type)
91
+ listeners = smell_listeners[type]
92
+ listeners.each {|smell| smell.examine(scope) } if listeners
93
+ end
94
+
95
+ private
96
+
97
+ def smell_listeners()
98
+ unless @detectors
99
+ @detectors = Hash.new {|hash,key| hash[key] = [] }
100
+ SMELL_CLASSES.each { |smell| @listeners << smell.listen(@detectors, @config) }
70
101
  end
71
- self
102
+ @detectors
72
103
  end
73
104
 
74
105
  def all_reekfiles(path)
@@ -77,9 +108,5 @@ module Reek
77
108
  return [] if path == parent
78
109
  all_reekfiles(parent) + Dir["#{path}/*.reek"]
79
110
  end
80
-
81
- def disable(smell)
82
- @config[smell].adopt!({'enabled' => false})
83
- end
84
111
  end
85
112
  end
data/lib/reek/source.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  require 'reek/code_parser'
2
2
  require 'reek/report'
3
- require 'reek/smells/smells'
3
+ require 'reek/sniffer'
4
4
  require 'ruby_parser'
5
5
 
6
6
  module Reek
@@ -46,7 +46,8 @@ module Reek
46
46
  #
47
47
  def self.from_path(filename)
48
48
  code = IO.readlines(filename).join
49
- return new(code, filename, File.dirname(filename))
49
+ sniffer = Sniffer.new.configure_along_path(filename)
50
+ return new(code, filename, sniffer)
50
51
  end
51
52
 
52
53
  #
@@ -58,11 +59,10 @@ module Reek
58
59
  SourceList.new(sources)
59
60
  end
60
61
 
61
- def initialize(code, desc, dir = nil) # :nodoc:
62
+ def initialize(code, desc, sniffer = Sniffer.new) # :nodoc:
62
63
  @source = code
63
64
  @desc = desc
64
- @cf = SmellConfig.new
65
- @cf = @cf.load_local(dir) if dir
65
+ @sniffer = sniffer
66
66
  end
67
67
 
68
68
  def generate_syntax_tree
@@ -76,9 +76,9 @@ module Reek
76
76
  #
77
77
  def report
78
78
  unless @report
79
- @report = Report.new
80
- parser = CodeParser.new(@report, @cf.smell_listeners)
79
+ parser = CodeParser.new(@sniffer)
81
80
  parser.process(generate_syntax_tree)
81
+ @report = Report.new(@sniffer)
82
82
  end
83
83
  @report
84
84
  end
data/lib/reek.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  $:.unshift File.dirname(__FILE__)
2
2
 
3
3
  module Reek # :doc:
4
- VERSION = '1.1.3.2'
4
+ VERSION = '1.1.3.3'
5
5
  end
data/reek.gemspec CHANGED
@@ -2,17 +2,17 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{reek}
5
- s.version = "1.1.3.2"
5
+ s.version = "1.1.3.3"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Kevin Rutherford"]
9
- s.date = %q{2009-06-13}
9
+ s.date = %q{2009-06-17}
10
10
  s.default_executable = %q{reek}
11
11
  s.description = %q{Code smell detector for Ruby}
12
12
  s.email = ["kevin@rutherford-software.com"]
13
13
  s.executables = ["reek"]
14
14
  s.extra_rdoc_files = ["History.txt", "README.txt"]
15
- s.files = ["History.txt", "README.txt", "Rakefile", "bin/reek", "config/defaults.reek", "lib/reek.rb", "lib/reek/block_context.rb", "lib/reek/class_context.rb", "lib/reek/code_context.rb", "lib/reek/code_parser.rb", "lib/reek/exceptions.reek", "lib/reek/if_context.rb", "lib/reek/method_context.rb", "lib/reek/module_context.rb", "lib/reek/name.rb", "lib/reek/object_refs.rb", "lib/reek/object_source.rb", "lib/reek/options.rb", "lib/reek/rake_task.rb", "lib/reek/report.rb", "lib/reek/sexp_formatter.rb", "lib/reek/singleton_method_context.rb", "lib/reek/smell_warning.rb", "lib/reek/smells/control_couple.rb", "lib/reek/smells/duplication.rb", "lib/reek/smells/feature_envy.rb", "lib/reek/smells/large_class.rb", "lib/reek/smells/long_method.rb", "lib/reek/smells/long_parameter_list.rb", "lib/reek/smells/long_yield_list.rb", "lib/reek/smells/nested_iterators.rb", "lib/reek/smells/smell_detector.rb", "lib/reek/smells/smells.rb", "lib/reek/smells/uncommunicative_name.rb", "lib/reek/smells/utility_function.rb", "lib/reek/source.rb", "lib/reek/spec.rb", "lib/reek/stop_context.rb", "lib/reek/yield_call_context.rb", "reek.gemspec", "spec/reek/block_context_spec.rb", "spec/reek/class_context_spec.rb", "spec/reek/code_context_spec.rb", "spec/reek/code_parser_spec.rb", "spec/reek/config_spec.rb", "spec/reek/if_context_spec.rb", "spec/reek/method_context_spec.rb", "spec/reek/module_context_spec.rb", "spec/reek/name_spec.rb", "spec/reek/object_refs_spec.rb", "spec/reek/options_spec.rb", "spec/reek/report_spec.rb", "spec/reek/singleton_method_context_spec.rb", "spec/reek/smells/control_couple_spec.rb", "spec/reek/smells/duplication_spec.rb", "spec/reek/smells/feature_envy_spec.rb", "spec/reek/smells/large_class_spec.rb", "spec/reek/smells/long_method_spec.rb", "spec/reek/smells/long_parameter_list_spec.rb", "spec/reek/smells/nested_iterators_spec.rb", "spec/reek/smells/smell_spec.rb", "spec/reek/smells/uncommunicative_name_spec.rb", "spec/reek/smells/utility_function_spec.rb", "spec/slow/inline_spec.rb", "spec/slow/optparse_spec.rb", "spec/slow/redcloth_spec.rb", "spec/slow/reek_source_spec.rb", "spec/slow/samples/inline.rb", "spec/slow/samples/optparse.rb", "spec/slow/samples/redcloth.rb", "spec/slow/script_spec.rb", "spec/slow/source_list_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "tasks/reek.rake", "tasks/rspec.rake"]
15
+ s.files = ["History.txt", "README.txt", "Rakefile", "bin/reek", "config/defaults.reek", "lib/reek.rb", "lib/reek/block_context.rb", "lib/reek/class_context.rb", "lib/reek/code_context.rb", "lib/reek/code_parser.rb", "lib/reek/exceptions.reek", "lib/reek/if_context.rb", "lib/reek/method_context.rb", "lib/reek/module_context.rb", "lib/reek/name.rb", "lib/reek/object_refs.rb", "lib/reek/object_source.rb", "lib/reek/options.rb", "lib/reek/rake_task.rb", "lib/reek/report.rb", "lib/reek/sexp_formatter.rb", "lib/reek/singleton_method_context.rb", "lib/reek/smell_warning.rb", "lib/reek/smells/control_couple.rb", "lib/reek/smells/duplication.rb", "lib/reek/smells/feature_envy.rb", "lib/reek/smells/large_class.rb", "lib/reek/smells/long_method.rb", "lib/reek/smells/long_parameter_list.rb", "lib/reek/smells/long_yield_list.rb", "lib/reek/smells/nested_iterators.rb", "lib/reek/smells/smell_detector.rb", "lib/reek/smells/uncommunicative_name.rb", "lib/reek/smells/utility_function.rb", "lib/reek/sniffer.rb", "lib/reek/source.rb", "lib/reek/spec.rb", "lib/reek/stop_context.rb", "lib/reek/yield_call_context.rb", "reek.gemspec", "spec/reek/block_context_spec.rb", "spec/reek/class_context_spec.rb", "spec/reek/code_context_spec.rb", "spec/reek/code_parser_spec.rb", "spec/reek/config_spec.rb", "spec/reek/if_context_spec.rb", "spec/reek/method_context_spec.rb", "spec/reek/module_context_spec.rb", "spec/reek/name_spec.rb", "spec/reek/object_refs_spec.rb", "spec/reek/options_spec.rb", "spec/reek/report_spec.rb", "spec/reek/singleton_method_context_spec.rb", "spec/reek/smell_warning_spec.rb", "spec/reek/smells/control_couple_spec.rb", "spec/reek/smells/duplication_spec.rb", "spec/reek/smells/feature_envy_spec.rb", "spec/reek/smells/large_class_spec.rb", "spec/reek/smells/long_method_spec.rb", "spec/reek/smells/long_parameter_list_spec.rb", "spec/reek/smells/nested_iterators_spec.rb", "spec/reek/smells/smell_detector_spec.rb", "spec/reek/smells/uncommunicative_name_spec.rb", "spec/reek/smells/utility_function_spec.rb", "spec/slow/inline_spec.rb", "spec/slow/optparse_spec.rb", "spec/slow/redcloth_spec.rb", "spec/slow/reek_source_spec.rb", "spec/slow/samples/inline.rb", "spec/slow/samples/optparse.rb", "spec/slow/samples/redcloth.rb", "spec/slow/script_spec.rb", "spec/slow/source_list_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "tasks/reek.rake", "tasks/rspec.rake"]
16
16
  s.homepage = %q{http://wiki.github.com/kevinrutherford/reek}
17
17
  s.post_install_message = %q{
18
18
  For more information on reek, see http://wiki.github.com/kevinrutherford/reek
@@ -20,7 +20,7 @@ For more information on reek, see http://wiki.github.com/kevinrutherford/reek
20
20
  s.rdoc_options = ["--main", "README.txt"]
21
21
  s.require_paths = ["lib"]
22
22
  s.rubyforge_project = %q{reek}
23
- s.rubygems_version = %q{1.3.3}
23
+ s.rubygems_version = %q{1.3.4}
24
24
  s.summary = %q{Code smell detector for Ruby}
25
25
 
26
26
  if s.respond_to? :specification_version then
@@ -27,11 +27,8 @@ describe Report, "to_s" do
27
27
  @report = rpt.to_s.split("\n")
28
28
  end
29
29
 
30
- it 'should place each detailed report on a separate line' do
31
- @report.should have_at_least(2).lines
32
- end
33
-
34
30
  it 'should mention every smell name' do
31
+ @report.should have_at_least(2).lines
35
32
  @report[0].should match(/[Utility Function]/)
36
33
  @report[1].should match(/[Feature Envy]/)
37
34
  end
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/../../spec_helper.rb'
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
2
 
3
3
  require 'reek/smells/smells'
4
4
 
@@ -51,17 +51,17 @@ describe Duplication, '#examine' do
51
51
 
52
52
  it 'should return true when reporting a smell' do
53
53
  @mc.calls = {s(:call, nil, :other, s(:arglist)) => 47}
54
- @dup.examine(@mc, []).should == true
54
+ @dup.examine(@mc).should == true
55
55
  end
56
56
 
57
57
  it 'should return false when not reporting a smell' do
58
58
  @mc.calls = []
59
- @dup.examine(@mc, []).should == false
59
+ @dup.examine(@mc).should == false
60
60
  end
61
61
 
62
62
  it 'should return false when not reporting calls to new' do
63
63
  @mc.calls = {[:call, :Set, :new] => 4}
64
- @dup.examine(@mc, []).should == false
64
+ @dup.examine(@mc).should == false
65
65
  end
66
66
  end
67
67
 
@@ -69,13 +69,11 @@ describe Duplication, 'when disabled' do
69
69
  before :each do
70
70
  @ctx = MethodContext.new(StopContext.new, [0, :double_thing])
71
71
  @dup = Duplication.new({SmellDetector::ENABLED_KEY => false})
72
- @rpt = Report.new
73
72
  end
74
73
 
75
74
  it 'should not report repeated call' do
76
75
  @ctx.record_call_to([:fred])
77
76
  @ctx.record_call_to([:fred])
78
- @dup.examine(@ctx, @rpt).should == false
79
- @rpt.length.should == 0
77
+ @dup.examine(@ctx).should == false
80
78
  end
81
79
  end
@@ -133,22 +133,6 @@ describe FeatureEnvy do
133
133
  end'.should_not reek
134
134
  end
135
135
 
136
- it 'reports the most-used ivar' do
137
- pending('bug')
138
- 'def func
139
- @other.a
140
- @other.b
141
- @nother.c
142
- end'.should reek_of(:FeatureEnvy, /@other/)
143
- #
144
- # def other.func(me)
145
- # a
146
- # b
147
- # me.nother_c
148
- # end
149
- #
150
- end
151
-
152
136
  it 'ignores multiple ivars' do
153
137
  'def func
154
138
  @other.a
@@ -212,10 +196,10 @@ describe FeatureEnvy, '#examine' do
212
196
  it 'should return true when reporting a smell' do
213
197
  @context.refs.record_ref([:lvar, :thing])
214
198
  @context.refs.record_ref([:lvar, :thing])
215
- @fe.examine(@context, []).should == true
199
+ @fe.examine(@context).should == true
216
200
  end
217
201
 
218
202
  it 'should return false when not reporting a smell' do
219
- @fe.examine(@context, []).should == false
203
+ @fe.examine(@context).should == false
220
204
  end
221
205
  end
@@ -55,7 +55,6 @@ end
55
55
  describe LargeClass, 'when exceptions are listed' do
56
56
 
57
57
  before(:each) do
58
- @rpt = Report.new
59
58
  @ctx = ClassContext.create(StopContext.new, [0, :Humungous])
60
59
  30.times { |num| @ctx.record_method("method#{num}") }
61
60
  @config = LargeClass.default_config
@@ -64,43 +63,35 @@ describe LargeClass, 'when exceptions are listed' do
64
63
  it 'should ignore first excepted name' do
65
64
  @config[LargeClass::EXCLUDE_KEY] = ['Humungous']
66
65
  lc = LargeClass.new(@config)
67
- lc.examine(@ctx, @rpt).should == false
68
- @rpt.length.should == 0
66
+ lc.examine(@ctx).should == false
69
67
  end
70
68
 
71
69
  it 'should ignore second excepted name' do
72
70
  @config[LargeClass::EXCLUDE_KEY] = ['Oversized', 'Humungous']
73
71
  lc = LargeClass.new(@config)
74
- lc.examine(@ctx, @rpt).should == false
75
- @rpt.length.should == 0
72
+ lc.examine(@ctx).should == false
76
73
  end
77
74
 
78
75
  it 'should report non-excepted name' do
79
76
  @config[LargeClass::EXCLUDE_KEY] = ['SmellMe']
80
77
  lc = LargeClass.new(@config)
81
- lc.examine(@ctx, @rpt).should == true
82
- @rpt.length.should == 1
78
+ lc.examine(@ctx).should == true
83
79
  end
84
80
  end
85
81
 
86
82
  describe LargeClass, 'checking source code' do
87
83
 
88
- def process_class(src)
89
- source = Source.from_s(src)
90
- CodeParser.new(nil, {}).process_class(source.generate_syntax_tree)
91
- end
92
-
93
84
  describe 'counting instance variables' do
94
85
  it 'should not report empty class' do
95
- process_class('class Empty;end').variable_names.length.should == 0
86
+ ClassContext.from_s('class Empty;end').should have(0).variable_names
96
87
  end
97
88
 
98
89
  it 'should count ivars in one method' do
99
- process_class('class Empty;def ivars() @aa=@ab=@ac=@ad; end;end').variable_names.length.should == 4
90
+ ClassContext.from_s('class Empty;def ivars() @aa=@ab=@ac=@ad; end;end').should have(4).variable_names
100
91
  end
101
92
 
102
93
  it 'should count ivars in 2 methods' do
103
- process_class('class Empty;def iv1() @aa=@ab; end;def iv2() @aa=@ac; end;end').variable_names.length.should == 3
94
+ ClassContext.from_s('class Empty;def iv1() @aa=@ab; end;def iv2() @aa=@ac; end;end').should have(3).variable_names
104
95
  end
105
96
 
106
97
  it 'should not report 9 ivars' do
@@ -122,15 +113,15 @@ EOS
122
113
 
123
114
  describe 'counting methods' do
124
115
  it 'should not report empty class' do
125
- process_class('class Empty;end').num_methods.should == 0
116
+ ClassContext.from_s('class Empty;end').num_methods.should == 0
126
117
  end
127
118
 
128
119
  it 'should count 1 method' do
129
- process_class('class Empty;def ivars() @aa=@ab; end;end').num_methods.should == 1
120
+ ClassContext.from_s('class Empty;def ivars() @aa=@ab; end;end').num_methods.should == 1
130
121
  end
131
122
 
132
123
  it 'should count 2 methods' do
133
- process_class('class Empty;def meth1() @aa=@ab;end;def meth2() @aa=@ab;end;end').num_methods.should == 2
124
+ ClassContext.from_s('class Empty;def meth1() @aa=@ab;end;def meth2() @aa=@ab;end;end').num_methods.should == 2
134
125
  end
135
126
 
136
127
  it 'should not report 25 methods' do
@@ -9,7 +9,7 @@ include Reek::Smells
9
9
 
10
10
  def process_method(src)
11
11
  source = Source.from_s(src)
12
- CodeParser.new(nil, {}).process_defn(source.generate_syntax_tree)
12
+ CodeParser.new(Sniffer.new).process_defn(source.generate_syntax_tree)
13
13
  end
14
14
 
15
15
  describe LongMethod do
@@ -0,0 +1,23 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper.rb'
2
+
3
+ require 'reek/report'
4
+ require 'reek/smells/duplication'
5
+
6
+ include Reek
7
+ include Reek::Smells
8
+
9
+ describe SmellDetector, 'when masked' do
10
+ before(:each) do
11
+ @detector = Duplication.new
12
+ @detector.be_masked
13
+ @detector.found(nil, 'help')
14
+ end
15
+
16
+ it 'reports smells as masked' do
17
+ rpt = Report.new
18
+ @detector.report_on(rpt)
19
+ rpt.length.should == 0
20
+ rpt.num_masked_smells.should == 1
21
+ end
22
+ end
23
+
@@ -107,17 +107,16 @@ end
107
107
 
108
108
  describe UncommunicativeName, '#examine' do
109
109
  before :each do
110
- @report = Report.new
111
110
  @uc = UncommunicativeName.new
112
111
  end
113
112
 
114
113
  it 'should return true when reporting a smell' do
115
114
  mc = MethodContext.new(StopContext.new, [:defn, :x, nil])
116
- @uc.examine(mc, @report).should == true
115
+ @uc.examine(mc).should == true
117
116
  end
118
117
 
119
118
  it 'should return false when not reporting a smell' do
120
119
  mc = MethodContext.new(StopContext.new, [:defn, :not_bad, nil])
121
- @uc.examine(mc, @report).should == false
120
+ @uc.examine(mc).should == false
122
121
  end
123
122
  end
@@ -39,20 +39,6 @@ describe UtilityFunction do
39
39
  end
40
40
  Son.should_not reek
41
41
  end
42
-
43
- it 'should not report class method' do
44
- pending('bug')
45
- source = <<EOS
46
- class Cache
47
- class << self
48
- def create_unless_known(attributes)
49
- Cache.create(attributes) unless Cache.known?
50
- end
51
- end
52
- end
53
- EOS
54
- source.should_not reek
55
- end
56
42
 
57
43
  it 'should recognise a deep call' do
58
44
  src = <<EOS
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kevinrutherford-reek
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.3.2
4
+ version: 1.1.3.3
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: 2009-06-13 00:00:00 -07:00
12
+ date: 2009-06-17 00:00:00 -07:00
13
13
  default_executable: reek
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -85,9 +85,9 @@ files:
85
85
  - lib/reek/smells/long_yield_list.rb
86
86
  - lib/reek/smells/nested_iterators.rb
87
87
  - lib/reek/smells/smell_detector.rb
88
- - lib/reek/smells/smells.rb
89
88
  - lib/reek/smells/uncommunicative_name.rb
90
89
  - lib/reek/smells/utility_function.rb
90
+ - lib/reek/sniffer.rb
91
91
  - lib/reek/source.rb
92
92
  - lib/reek/spec.rb
93
93
  - lib/reek/stop_context.rb
@@ -106,6 +106,7 @@ files:
106
106
  - spec/reek/options_spec.rb
107
107
  - spec/reek/report_spec.rb
108
108
  - spec/reek/singleton_method_context_spec.rb
109
+ - spec/reek/smell_warning_spec.rb
109
110
  - spec/reek/smells/control_couple_spec.rb
110
111
  - spec/reek/smells/duplication_spec.rb
111
112
  - spec/reek/smells/feature_envy_spec.rb
@@ -113,7 +114,7 @@ files:
113
114
  - spec/reek/smells/long_method_spec.rb
114
115
  - spec/reek/smells/long_parameter_list_spec.rb
115
116
  - spec/reek/smells/nested_iterators_spec.rb
116
- - spec/reek/smells/smell_spec.rb
117
+ - spec/reek/smells/smell_detector_spec.rb
117
118
  - spec/reek/smells/uncommunicative_name_spec.rb
118
119
  - spec/reek/smells/utility_function_spec.rb
119
120
  - spec/slow/inline_spec.rb