reek 1.2.7.1 → 1.2.7.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. data/History.txt +13 -1
  2. data/config/defaults.reek +4 -1
  3. data/features/masking_smells.feature +7 -7
  4. data/features/rake_task.feature +2 -2
  5. data/features/reports.feature +3 -3
  6. data/features/samples.feature +5 -2
  7. data/features/yaml.feature +0 -39
  8. data/lib/reek.rb +1 -1
  9. data/lib/reek/cli/command_line.rb +3 -3
  10. data/lib/reek/cli/reek_command.rb +5 -6
  11. data/lib/reek/cli/report.rb +9 -20
  12. data/lib/reek/cli/yaml_command.rb +1 -1
  13. data/lib/reek/core/class_context.rb +1 -2
  14. data/lib/reek/core/code_context.rb +10 -27
  15. data/lib/reek/core/code_parser.rb +1 -18
  16. data/lib/reek/core/detector_stack.rb +4 -0
  17. data/lib/reek/core/masking_collection.rb +6 -0
  18. data/lib/reek/core/method_context.rb +8 -56
  19. data/lib/reek/core/module_context.rb +6 -32
  20. data/lib/reek/core/object_refs.rb +36 -36
  21. data/lib/reek/core/singleton_method_context.rb +10 -21
  22. data/lib/reek/core/sniffer.rb +3 -2
  23. data/lib/reek/examiner.rb +39 -31
  24. data/lib/reek/smell_warning.rb +8 -0
  25. data/lib/reek/smells/attribute.rb +4 -2
  26. data/lib/reek/smells/class_variable.rb +3 -3
  27. data/lib/reek/smells/control_couple.rb +1 -2
  28. data/lib/reek/smells/data_clump.rb +86 -9
  29. data/lib/reek/smells/duplication.rb +2 -3
  30. data/lib/reek/smells/feature_envy.rb +9 -4
  31. data/lib/reek/smells/simulated_polymorphism.rb +1 -2
  32. data/lib/reek/smells/smell_detector.rb +0 -6
  33. data/lib/reek/smells/uncommunicative_method_name.rb +8 -2
  34. data/lib/reek/smells/uncommunicative_parameter_name.rb +1 -1
  35. data/lib/reek/smells/uncommunicative_variable_name.rb +1 -1
  36. data/lib/reek/smells/utility_function.rb +17 -5
  37. data/lib/reek/source/reference_collector.rb +21 -0
  38. data/lib/reek/source/sexp_formatter.rb +1 -0
  39. data/lib/reek/source/tree_dresser.rb +67 -9
  40. data/lib/reek/spec/should_reek.rb +1 -1
  41. data/lib/reek/spec/should_reek_of.rb +1 -1
  42. data/lib/reek/spec/should_reek_only_of.rb +1 -1
  43. data/reek.gemspec +3 -3
  44. data/spec/reek/cli/reek_command_spec.rb +3 -2
  45. data/spec/reek/cli/report_spec.rb +2 -2
  46. data/spec/reek/cli/yaml_command_spec.rb +2 -2
  47. data/spec/reek/core/code_context_spec.rb +39 -54
  48. data/spec/reek/core/method_context_spec.rb +7 -26
  49. data/spec/reek/core/module_context_spec.rb +0 -15
  50. data/spec/reek/core/singleton_method_context_spec.rb +0 -6
  51. data/spec/reek/examiner_spec.rb +6 -6
  52. data/spec/reek/smells/attribute_spec.rb +30 -32
  53. data/spec/reek/smells/class_variable_spec.rb +15 -18
  54. data/spec/reek/smells/data_clump_spec.rb +22 -6
  55. data/spec/reek/smells/duplication_spec.rb +33 -19
  56. data/spec/reek/smells/feature_envy_spec.rb +82 -88
  57. data/spec/reek/smells/large_class_spec.rb +1 -1
  58. data/spec/reek/smells/smell_detector_shared.rb +1 -1
  59. data/spec/reek/smells/uncommunicative_method_name_spec.rb +37 -35
  60. data/spec/reek/smells/utility_function_spec.rb +7 -0
  61. data/spec/reek/source/reference_collector_spec.rb +53 -0
  62. data/spec/reek/source/tree_dresser_spec.rb +10 -0
  63. data/spec/reek/spec/should_reek_only_of_spec.rb +1 -1
  64. data/spec/spec_helper.rb +7 -0
  65. metadata +4 -5
  66. data/features/profile.feature +0 -34
  67. data/lib/reek/core/block_context.rb +0 -18
  68. data/spec/reek/core/block_context_spec.rb +0 -26
@@ -21,7 +21,7 @@ shared_examples_for 'SmellDetector' do
21
21
 
22
22
  context 'configuration' do
23
23
  it 'becomes disabled when disabled' do
24
- @detector.configure({@detector.smell_type => {SmellConfiguration::ENABLED_KEY => false}})
24
+ @detector.configure_with({SmellConfiguration::ENABLED_KEY => false})
25
25
  @detector.should_not be_enabled
26
26
  end
27
27
  end
@@ -15,43 +15,45 @@ describe UncommunicativeMethodName do
15
15
 
16
16
  it_should_behave_like 'SmellDetector'
17
17
 
18
- it 'should not report one-word method name' do
19
- 'def help(fred) basics(17) end'.should_not reek
20
- end
21
- it 'should report one-letter method name' do
22
- 'def x(fred) basics(17) end'.should reek_only_of(:UncommunicativeMethodName, /x/)
23
- end
24
- it 'should report name of the form "x2"' do
25
- 'def x2(fred) basics(17) end'.should reek_only_of(:UncommunicativeMethodName, /x2/)
26
- end
27
- it 'should report long name ending in a number' do
28
- 'def method2(fred) basics(17) end'.should reek_only_of(:UncommunicativeMethodName, /method2/)
18
+ ['help', '+', '-', '/', '*'].each do |method_name|
19
+ it "accepts the method name '#{method_name}'" do
20
+ "def #{method_name}(fred) basics(17) end".should_not reek
21
+ end
29
22
  end
30
23
 
31
- context 'looking at the YAML' do
32
- before :each do
33
- src = 'def bad3() end'
34
- source = src.to_reek_source
35
- sniffer = Core::Sniffer.new(source)
36
- @mctx = Core::CodeParser.new(sniffer).process_defn(source.syntax_tree)
37
- @detector.examine(@mctx)
38
- warning = @detector.smells_found.to_a[0] # SMELL: too cumbersome!
39
- @yaml = warning.to_yaml
40
- end
41
- it 'reports the source' do
42
- @yaml.should match(/source:\s*#{@source_name}/)
43
- end
44
- it 'reports the class' do
45
- @yaml.should match(/\sclass:\s*UncommunicativeName/)
46
- end
47
- it 'reports the subclass' do
48
- @yaml.should match(/subclass:\s*UncommunicativeMethodName/)
49
- end
50
- it 'reports the variable name' do
51
- @yaml.should match(/method_name:\s*bad3/)
52
- end
53
- it 'reports the line number of the method def' do
54
- @yaml.should match(/lines:\s*- 1/)
24
+ ['x', 'x2', 'method2'].each do |method_name|
25
+ context 'with a bad name' do
26
+ before :each do
27
+ @full_name = 'anything you like'
28
+ ctx = mock('method', :null_object => true)
29
+ ctx.should_receive(:name).and_return(method_name)
30
+ ctx.should_receive(:full_name).at_least(:once).and_return(@full_name)
31
+ ctx.should_receive(:exp).and_return(ast(:defn))
32
+ @detector.examine_context(ctx)
33
+ @smells = @detector.smells_found.to_a
34
+ end
35
+
36
+ it 'records only that attribute' do
37
+ @smells.length.should == 1
38
+ end
39
+ it 'reports the attribute name' do
40
+ @smells[0].smell[UncommunicativeMethodName::METHOD_NAME_KEY].should == method_name
41
+ end
42
+ it 'reports the declaration line number' do
43
+ @smells[0].lines.should == [1]
44
+ end
45
+ it 'reports the correct smell class' do
46
+ @smells[0].smell_class.should == UncommunicativeMethodName::SMELL_CLASS
47
+ end
48
+ it 'reports the correct smell subclass' do
49
+ @smells[0].subclass.should == UncommunicativeMethodName::SMELL_SUBCLASS
50
+ end
51
+ it 'reports the context fq name' do
52
+ @smells[0].context.should == @full_name
53
+ end
54
+ it 'reports the source name' do
55
+ @smells[0].source.should == @source_name
56
+ end
55
57
  end
56
58
  end
57
59
  end
@@ -6,6 +6,13 @@ include Reek
6
6
  include Reek::Smells
7
7
 
8
8
  describe UtilityFunction do
9
+ context 'with a singleton method' do
10
+ ['self', 'local_call', '$global'].each do |receiver|
11
+ it 'ignores the receiver' do
12
+ "def #{receiver}.simple(arga) arga.to_s + arga.to_i end".should_not reek
13
+ end
14
+ end
15
+ end
9
16
  context 'with no calls' do
10
17
  it 'does not report empty method' do
11
18
  'def simple(arga) end'.should_not reek
@@ -0,0 +1,53 @@
1
+ require File.join(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__)))), 'spec_helper')
2
+ require File.join(File.dirname(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__))))), 'lib', 'reek', 'source', 'reference_collector')
3
+
4
+ include Reek::Source
5
+
6
+ describe ReferenceCollector do
7
+
8
+ context 'counting refs to self' do
9
+ def refs_to_self(src)
10
+ ReferenceCollector.new(src.to_reek_source.syntax_tree).num_refs_to_self
11
+ end
12
+ it 'with no refs to self' do
13
+ refs_to_self('def no_envy(arga) arga.barg end').should == 0
14
+ end
15
+ it 'counts a call to super' do
16
+ refs_to_self('def simple() super; end').should == 1
17
+ end
18
+ it 'counts a local call' do
19
+ refs_to_self('def simple() to_s; end').should == 1
20
+ end
21
+ it 'counts a use of self' do
22
+ refs_to_self('def simple() lv = self; end').should == 1
23
+ end
24
+ it 'counts a call with self as receiver' do
25
+ refs_to_self('def simple() self.to_s; end').should == 1
26
+ end
27
+ it 'counts uses of an ivar' do
28
+ refs_to_self('def no_envy() @item.to_a; @item = 4; @item end').should == 3
29
+ end
30
+ it 'counts an ivar passed to a method' do
31
+ refs_to_self('def no_envy(arga) arga.barg(@item); arga end').should == 1
32
+ end
33
+ it 'ignores global variables' do
34
+ refs_to_self('def no_envy(arga) $s2.to_a; $s2[arga] end').should == 0
35
+ end
36
+ it 'ignores global variables' do
37
+ src = <<EOS
38
+ def accept(t, pat = /.*/nm, &block)
39
+ if pat
40
+ pat.respond_to?(:match) or raise TypeError, "has no `match'"
41
+ else
42
+ pat = t if t.respond_to?(:match)
43
+ end
44
+ unless block
45
+ block = pat.method(:convert).to_proc if pat.respond_to?(:convert)
46
+ end
47
+ @atype[t] = [pat, block]
48
+ end
49
+ EOS
50
+ refs_to_self(src).should == 2
51
+ end
52
+ end
53
+ end
@@ -15,6 +15,16 @@ describe TreeDresser do
15
15
  end
16
16
  end
17
17
 
18
+ describe SexpNode do
19
+ context 'format' do
20
+ it 'formats self' do
21
+ @node = s(:self)
22
+ @node.extend(SexpNode)
23
+ @node.format.should == 'self'
24
+ end
25
+ end
26
+ end
27
+
18
28
  describe SexpExtensions::DefnNode do
19
29
  context 'with no parameters' do
20
30
  before :each do
@@ -10,7 +10,7 @@ describe ShouldReekOnlyOf do
10
10
  @expected_context_name = 'SmellyClass#big_method'
11
11
  @matcher = ShouldReekOnlyOf.new(@expected_smell_class, [/#{@expected_context_name}/])
12
12
  @examiner = mock('examiner', :null_object => true)
13
- @examiner.should_receive(:all_active_smells).and_return {smells}
13
+ @examiner.should_receive(:smells).and_return {smells}
14
14
  @match = @matcher.matches_examiner?(@examiner)
15
15
  end
16
16
 
data/spec/spec_helper.rb CHANGED
@@ -10,5 +10,12 @@ end
10
10
  require 'spec/autorun'
11
11
 
12
12
  require File.join((File.dirname(File.dirname(File.expand_path(__FILE__)))), 'lib', 'reek', 'spec')
13
+ require File.join((File.dirname(File.dirname(File.expand_path(__FILE__)))), 'lib', 'reek', 'source', 'tree_dresser')
13
14
 
14
15
  SAMPLES_DIR = 'spec/samples' unless Object.const_defined?('SAMPLES_DIR')
16
+
17
+ def ast(*args)
18
+ result = Reek::Source::TreeDresser.new.dress(s(*args))
19
+ result.line = 1
20
+ result
21
+ end
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: 1.2.7.1
4
+ version: 1.2.7.2
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: 2010-02-03 00:00:00 +00:00
12
+ date: 2010-03-05 00:00:00 +00:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -65,7 +65,6 @@ files:
65
65
  - config/defaults.reek
66
66
  - features/masking_smells.feature
67
67
  - features/options.feature
68
- - features/profile.feature
69
68
  - features/rake_task.feature
70
69
  - features/reports.feature
71
70
  - features/samples.feature
@@ -81,7 +80,6 @@ files:
81
80
  - lib/reek/cli/report.rb
82
81
  - lib/reek/cli/version_command.rb
83
82
  - lib/reek/cli/yaml_command.rb
84
- - lib/reek/core/block_context.rb
85
83
  - lib/reek/core/class_context.rb
86
84
  - lib/reek/core/code_context.rb
87
85
  - lib/reek/core/code_parser.rb
@@ -122,6 +120,7 @@ files:
122
120
  - lib/reek/source/code_comment.rb
123
121
  - lib/reek/source/config_file.rb
124
122
  - lib/reek/source/core_extras.rb
123
+ - lib/reek/source/reference_collector.rb
125
124
  - lib/reek/source/sexp_formatter.rb
126
125
  - lib/reek/source/source_code.rb
127
126
  - lib/reek/source/source_file.rb
@@ -137,7 +136,6 @@ files:
137
136
  - spec/reek/cli/report_spec.rb
138
137
  - spec/reek/cli/version_command_spec.rb
139
138
  - spec/reek/cli/yaml_command_spec.rb
140
- - spec/reek/core/block_context_spec.rb
141
139
  - spec/reek/core/class_context_spec.rb
142
140
  - spec/reek/core/code_context_spec.rb
143
141
  - spec/reek/core/code_parser_spec.rb
@@ -174,6 +172,7 @@ files:
174
172
  - spec/reek/smells/utility_function_spec.rb
175
173
  - spec/reek/source/code_comment_spec.rb
176
174
  - spec/reek/source/object_source_spec.rb
175
+ - spec/reek/source/reference_collector_spec.rb
177
176
  - spec/reek/source/source_code_spec.rb
178
177
  - spec/reek/source/tree_dresser_spec.rb
179
178
  - spec/reek/spec/should_reek_of_spec.rb
@@ -1,34 +0,0 @@
1
- @profile
2
- Feature: Reek's configuration can be based on any number of canned profiles
3
- The starting point for configuring the smell detectors can be
4
- selected from a list of supplied config files.
5
-
6
- # Scenario: XP profile reveals Attribute smells
7
- # When I run reek --profile xp spec/samples/not_quite_masked/dirty.rb
8
- # Then the exit status indicates smells
9
- # And it reports:
10
- # """
11
- # spec/samples/not_quite_masked/dirty.rb -- 5 warnings (+2 masked):
12
- # Dirty declares the attribute property (Attribute)
13
- # Dirty has the variable name '@s' (Uncommunicative Name)
14
- # Dirty#a calls @s.title twice (Duplication)
15
- # Dirty#a calls puts(@s.title) twice (Duplication)
16
- # Dirty#a has the name 'a' (Uncommunicative Name)
17
- #
18
- # """
19
- #
20
- # Scenario: XP profile works with unmasked smells
21
- # When I run reek --show-all --profile xp spec/samples/not_quite_masked/dirty.rb
22
- # Then the exit status indicates smells
23
- # And it reports:
24
- # """
25
- # spec/samples/not_quite_masked/dirty.rb -- 5 warnings (+2 masked):
26
- # Dirty declares the attribute property (Attribute)
27
- # Dirty has the variable name '@s' (Uncommunicative Name)
28
- # Dirty#a calls @s.title twice (Duplication)
29
- # Dirty#a calls puts(@s.title) twice (Duplication)
30
- # Dirty#a has the name 'a' (Uncommunicative Name)
31
- # (masked) Dirty#a/block has the variable name 'x' (Uncommunicative Name)
32
- # (masked) Dirty#a/block/block is nested (Nested Iterators)
33
- #
34
- # """
@@ -1,18 +0,0 @@
1
- require File.join(File.dirname(File.expand_path(__FILE__)), 'code_context')
2
-
3
- module Reek
4
- module Core
5
-
6
- #
7
- # A context wrapper for any block found in a syntax tree.
8
- #
9
- class BlockContext < CodeContext
10
-
11
- def initialize(outer, exp)
12
- super
13
- @name = 'block'
14
- @scope_connector = '/'
15
- end
16
- end
17
- end
18
- end
@@ -1,26 +0,0 @@
1
- require File.join(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__)))), 'spec_helper')
2
- require File.join(File.dirname(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__))))), 'lib', 'reek', 'core', 'block_context')
3
- require File.join(File.dirname(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__))))), 'lib', 'reek', 'core', 'method_context')
4
-
5
- include Reek::Core
6
-
7
- describe BlockContext do
8
- context 'full_name' do
9
- it "reports full context" do
10
- bctx = BlockContext.new(StopContext.new, s(nil, nil))
11
- bctx.full_name.should == 'block'
12
- end
13
- it 'uses / to connect to the class name' do
14
- element = StopContext.new
15
- element = ClassContext.new(element, :Fred, s(:class, :Fred))
16
- element = BlockContext.new(element, s(:iter, nil, s(:lasgn, :x), nil))
17
- element.full_name.should == 'Fred/block'
18
- end
19
- it 'uses / to connect to the module name' do
20
- element = StopContext.new
21
- element = ModuleContext.new(element, :Fred, s(:module, :Fred))
22
- element = BlockContext.new(element, s(:iter, nil, s(:lasgn, :x), nil))
23
- element.full_name.should == 'Fred/block'
24
- end
25
- end
26
- end