reek 1.2.7.3 → 1.2.8

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 (76) hide show
  1. data/History.txt +17 -0
  2. data/README.md +32 -48
  3. data/config/defaults.reek +7 -1
  4. data/features/api.feature +20 -0
  5. data/features/masking_smells.feature +41 -0
  6. data/features/options.feature +4 -0
  7. data/features/rake_task.feature +14 -0
  8. data/features/yaml.feature +8 -8
  9. data/lib/reek.rb +1 -1
  10. data/lib/reek/cli/command_line.rb +9 -2
  11. data/lib/reek/cli/reek_command.rb +5 -4
  12. data/lib/reek/cli/yaml_command.rb +2 -2
  13. data/lib/reek/core/code_context.rb +10 -1
  14. data/lib/reek/core/method_context.rb +2 -2
  15. data/lib/reek/core/sniffer.rb +3 -1
  16. data/lib/reek/core/stop_context.rb +4 -0
  17. data/lib/reek/examiner.rb +2 -2
  18. data/lib/reek/rake/task.rb +16 -0
  19. data/lib/reek/smell_warning.rb +3 -2
  20. data/lib/reek/smells/attribute.rb +13 -9
  21. data/lib/reek/smells/boolean_parameter.rb +14 -9
  22. data/lib/reek/smells/class_variable.rb +16 -5
  23. data/lib/reek/smells/control_couple.rb +11 -6
  24. data/lib/reek/smells/data_clump.rb +33 -30
  25. data/lib/reek/smells/duplication.rb +39 -8
  26. data/lib/reek/smells/feature_envy.rb +7 -8
  27. data/lib/reek/smells/irresponsible_module.rb +12 -3
  28. data/lib/reek/smells/large_class.rb +31 -15
  29. data/lib/reek/smells/long_method.rb +15 -5
  30. data/lib/reek/smells/long_parameter_list.rb +14 -7
  31. data/lib/reek/smells/long_yield_list.rb +12 -9
  32. data/lib/reek/smells/nested_iterators.rb +46 -11
  33. data/lib/reek/smells/simulated_polymorphism.rb +16 -8
  34. data/lib/reek/smells/smell_detector.rb +13 -13
  35. data/lib/reek/smells/uncommunicative_method_name.rb +12 -20
  36. data/lib/reek/smells/uncommunicative_module_name.rb +17 -19
  37. data/lib/reek/smells/uncommunicative_parameter_name.rb +22 -15
  38. data/lib/reek/smells/uncommunicative_variable_name.rb +24 -18
  39. data/lib/reek/smells/utility_function.rb +6 -6
  40. data/lib/reek/source/code_comment.rb +19 -1
  41. data/lib/reek/source/tree_dresser.rb +40 -22
  42. data/reek.gemspec +6 -4
  43. data/spec/matchers/smell_of_matcher.rb +58 -0
  44. data/spec/reek/core/code_context_spec.rb +4 -2
  45. data/spec/reek/core/code_parser_spec.rb +2 -1
  46. data/spec/reek/core/method_context_spec.rb +5 -5
  47. data/spec/reek/smells/attribute_spec.rb +2 -4
  48. data/spec/reek/smells/boolean_parameter_spec.rb +32 -42
  49. data/spec/reek/smells/class_variable_spec.rb +22 -6
  50. data/spec/reek/smells/control_couple_spec.rb +15 -14
  51. data/spec/reek/smells/data_clump_spec.rb +29 -111
  52. data/spec/reek/smells/duplication_spec.rb +79 -49
  53. data/spec/reek/smells/feature_envy_spec.rb +1 -2
  54. data/spec/reek/smells/irresponsible_module_spec.rb +43 -22
  55. data/spec/reek/smells/large_class_spec.rb +34 -59
  56. data/spec/reek/smells/long_method_spec.rb +15 -10
  57. data/spec/reek/smells/long_parameter_list_spec.rb +24 -24
  58. data/spec/reek/smells/long_yield_list_spec.rb +13 -14
  59. data/spec/reek/smells/nested_iterators_spec.rb +93 -76
  60. data/spec/reek/smells/smell_detector_shared.rb +4 -2
  61. data/spec/reek/smells/uncommunicative_method_name_spec.rb +10 -27
  62. data/spec/reek/smells/uncommunicative_module_name_spec.rb +22 -23
  63. data/spec/reek/smells/uncommunicative_parameter_name_spec.rb +36 -26
  64. data/spec/reek/smells/uncommunicative_variable_name_spec.rb +45 -48
  65. data/spec/reek/smells/utility_function_spec.rb +14 -13
  66. data/spec/reek/source/code_comment_spec.rb +61 -3
  67. data/spec/reek/source/tree_dresser_spec.rb +96 -1
  68. data/spec/samples/config/allow_duplication.reek +3 -0
  69. data/spec/samples/config/deeper_nested_iterators.reek +3 -0
  70. data/spec/samples/demo/demo.rb +8 -0
  71. data/spec/samples/inline_config/dirty.rb +16 -0
  72. data/spec/samples/inline_config/masked.reek +7 -0
  73. data/spec/samples/mask_some/dirty.rb +8 -0
  74. data/spec/samples/mask_some/some.reek +8 -0
  75. data/spec/spec_helper.rb +2 -0
  76. metadata +15 -5
@@ -24,14 +24,14 @@ end
24
24
 
25
25
  describe MethodContext do
26
26
  it 'should record ivars as refs to self' do
27
- mctx = MethodContext.new(StopContext.new, [:defn, :feed])
27
+ mctx = MethodContext.new(StopContext.new, ast(:defn, :feed))
28
28
  mctx.envious_receivers.should == []
29
29
  mctx.record_call_to(ast(:call, s(:ivar, :@cow), :feed_to))
30
30
  mctx.envious_receivers.should == []
31
31
  end
32
32
 
33
33
  it 'should count calls to self' do
34
- mctx = MethodContext.new(StopContext.new, [:defn, :equals])
34
+ mctx = MethodContext.new(StopContext.new, ast(:defn, :equals))
35
35
  mctx.refs.record_ref([:lvar, :other])
36
36
  mctx.record_call_to(ast(:call, s(:self), :thing))
37
37
  mctx.envious_receivers.should be_empty
@@ -65,7 +65,7 @@ describe MethodParameters, 'default assignments' do
65
65
  @defaults = assignments_from(src)
66
66
  end
67
67
  it 'returns the param-value pair' do
68
- @defaults[:argb].should == s(:lit, 456)
68
+ @defaults[0].should == s(:argb, s(:lit, 456))
69
69
  end
70
70
  it 'returns the nothing else' do
71
71
  @defaults.length.should == 1
@@ -78,8 +78,8 @@ describe MethodParameters, 'default assignments' do
78
78
  @defaults = assignments_from(src)
79
79
  end
80
80
  it 'returns both param-value pairs' do
81
- @defaults[:arga].should == s(:lit, 123)
82
- @defaults[:argb].should == s(:lit, 456)
81
+ @defaults[0].should == s(:arga, s(:lit, 123))
82
+ @defaults[1].should == s(:argb, s(:lit, 456))
83
83
  end
84
84
  it 'returns nothing else' do
85
85
  @defaults.length.should == 2
@@ -18,8 +18,7 @@ describe Attribute do
18
18
  it 'records nothing in the module' do
19
19
  src = 'module Fred; end'
20
20
  ctx = CodeContext.new(nil, src.to_reek_source.syntax_tree)
21
- @detector.examine_context(ctx)
22
- @detector.smells_found.should be_empty
21
+ @detector.examine_context(ctx).should be_empty
23
22
  end
24
23
  end
25
24
 
@@ -31,8 +30,7 @@ describe Attribute do
31
30
  shared_examples_for 'one attribute found' do
32
31
  before :each do
33
32
  ctx = CodeContext.new(nil, @src.to_reek_source.syntax_tree)
34
- @detector.examine_context(ctx)
35
- @smells = @detector.smells_found.to_a
33
+ @smells = @detector.examine_context(ctx)
36
34
  end
37
35
 
38
36
  it 'records only that attribute' do
@@ -8,69 +8,59 @@ describe BooleanParameter do
8
8
  context 'parameter defaulted with boolean' do
9
9
  context 'in a method' do
10
10
  it 'reports a parameter defaulted to true' do
11
- 'def cc(arga = true) end'.should reek_of(:BooleanParameter, /arga/)
11
+ src = 'def cc(arga = true) end'
12
+ src.should smell_of(BooleanParameter, BooleanParameter::PARAMETER_KEY => 'arga')
12
13
  end
13
14
  it 'reports a parameter defaulted to false' do
14
- 'def cc(arga = false) end'.should reek_of(:BooleanParameter, /arga/)
15
+ src = 'def cc(arga = false) end'
16
+ src.should smell_of(BooleanParameter, BooleanParameter::PARAMETER_KEY => 'arga')
15
17
  end
16
18
  it 'reports two parameters defaulted to booleans' do
17
19
  src = 'def cc(nowt, arga = true, argb = false, &blk) end'
18
- src.should reek_of(:BooleanParameter, /arga/)
19
- src.should reek_of(:BooleanParameter, /argb/)
20
+ src.should smell_of(BooleanParameter,
21
+ {BooleanParameter::PARAMETER_KEY => 'arga'},
22
+ {BooleanParameter::PARAMETER_KEY => 'argb'})
20
23
  end
21
24
  end
22
25
 
23
26
  context 'in a singleton method' do
24
27
  it 'reports a parameter defaulted to true' do
25
- 'def self.cc(arga = true) end'.should reek_of(:BooleanParameter, /arga/)
28
+ src = 'def self.cc(arga = true) end'
29
+ src.should smell_of(BooleanParameter, BooleanParameter::PARAMETER_KEY => 'arga')
26
30
  end
27
31
  it 'reports a parameter defaulted to false' do
28
- 'def fred.cc(arga = false) end'.should reek_of(:BooleanParameter, /arga/)
32
+ src = 'def fred.cc(arga = false) end'
33
+ src.should smell_of(BooleanParameter, BooleanParameter::PARAMETER_KEY => 'arga')
29
34
  end
30
35
  it 'reports two parameters defaulted to booleans' do
31
36
  src = 'def Module.cc(nowt, arga = true, argb = false, &blk) end'
32
- src.should reek_of(:BooleanParameter, /arga/)
33
- src.should reek_of(:BooleanParameter, /argb/)
37
+ src.should smell_of(BooleanParameter,
38
+ {BooleanParameter::PARAMETER_KEY => 'arga'},
39
+ {BooleanParameter::PARAMETER_KEY => 'argb'})
34
40
  end
35
41
  end
36
42
  end
37
- end
38
43
 
39
- describe BooleanParameter do
40
- before(:each) do
41
- @source_name = 'smokin'
42
- @detector = BooleanParameter.new(@source_name)
43
- end
44
+ context 'when a smell is reported' do
45
+ before(:each) do
46
+ @source_name = 'smokin'
47
+ @detector = BooleanParameter.new(@source_name)
48
+ end
44
49
 
45
- it_should_behave_like 'SmellDetector'
50
+ it_should_behave_like 'SmellDetector'
46
51
 
47
- context 'looking at the YAML' do
48
- before :each do
49
- src = <<EOS
50
- def cc(arga = true)
51
- end
52
- EOS
53
- source = src.to_reek_source
54
- sniffer = Sniffer.new(source)
55
- @mctx = CodeParser.new(sniffer).process_defn(source.syntax_tree)
56
- @detector.examine(@mctx)
57
- warning = @detector.smells_found.to_a[0] # SMELL: too cumbersome!
58
- @yaml = warning.to_yaml
59
- end
60
- it 'reports the source' do
61
- @yaml.should match(/source:\s*#{@source_name}/)
62
- end
63
- it 'reports the class' do
64
- @yaml.should match(/\sclass:\s*ControlCouple/)
65
- end
66
- it 'reports the subclass' do
67
- @yaml.should match(/subclass:\s*BooleanParameter/)
68
- end
69
- it 'reports the parameter name' do
70
- @yaml.should match(/parameter:\s*arga/)
71
- end
72
- it 'reports the correct line' do
73
- @yaml.should match(/lines:\s*- 1/)
52
+ it 'reports the fields correctly' do
53
+ src = 'def cc(arga = true) end'
54
+ ctx = MethodContext.new(nil, src.to_reek_source.syntax_tree)
55
+ @detector.examine(ctx)
56
+ smells = @detector.smells_found.to_a
57
+ smells.length.should == 1
58
+ smells[0].smell_class.should == BooleanParameter::SMELL_CLASS
59
+ smells[0].smell[BooleanParameter::PARAMETER_KEY].should == 'arga'
60
+ smells[0].source.should == @source_name
61
+ smells[0].smell_class.should == BooleanParameter::SMELL_CLASS
62
+ smells[0].subclass.should == BooleanParameter::SMELL_SUBCLASS
63
+ smells[0].lines.should == [1]
74
64
  end
75
65
  end
76
66
  end
@@ -8,7 +8,8 @@ include Reek::Smells
8
8
 
9
9
  describe ClassVariable do
10
10
  before :each do
11
- @detector = ClassVariable.new('raffles')
11
+ @source_name = 'raffles'
12
+ @detector = ClassVariable.new(@source_name)
12
13
  @class_variable = '@@things'
13
14
  end
14
15
 
@@ -17,11 +18,11 @@ describe ClassVariable do
17
18
  context 'with no class variables' do
18
19
  it 'records nothing in the class' do
19
20
  exp = ast(:class, :Fred)
20
- @detector.class_variables_in(exp).should be_empty
21
+ @detector.examine_context(CodeContext.new(nil, exp)).should be_empty
21
22
  end
22
23
  it 'records nothing in the module' do
23
24
  exp = ast(:module, :Fred)
24
- @detector.class_variables_in(exp).should be_empty
25
+ @detector.examine_context(CodeContext.new(nil, exp)).should be_empty
25
26
  end
26
27
  end
27
28
 
@@ -29,13 +30,13 @@ describe ClassVariable do
29
30
  shared_examples_for 'one variable found' do
30
31
  before :each do
31
32
  ast = @src.to_reek_source.syntax_tree
32
- @cvars = @detector.class_variables_in(ast).to_a
33
+ @smells = @detector.examine_context(CodeContext.new(nil, ast))
33
34
  end
34
35
  it 'records only that class variable' do
35
- @cvars.length.should == 1
36
+ @smells.length.should == 1
36
37
  end
37
38
  it 'records the variable name' do
38
- @cvars[0].to_s.should == @class_variable
39
+ @smells[0].smell[ClassVariable::VARIABLE_KEY].should == @class_variable
39
40
  end
40
41
  end
41
42
 
@@ -81,4 +82,19 @@ describe ClassVariable do
81
82
  end
82
83
  end
83
84
  end
85
+
86
+ it 'reports the correct fields' do
87
+ src = <<EOS
88
+ module Fred
89
+ #{@class_variable} = {}
90
+ end
91
+ EOS
92
+ ctx = CodeContext.new(nil, src.to_reek_source.syntax_tree)
93
+ @warning = @detector.examine_context(ctx)[0]
94
+ @warning.source.should == @source_name
95
+ @warning.smell_class.should == ClassVariable::SMELL_CLASS
96
+ @warning.subclass.should == ClassVariable::SMELL_SUBCLASS
97
+ @warning.smell[ClassVariable::VARIABLE_KEY].should == @class_variable
98
+ @warning.lines.should == [2]
99
+ end
84
100
  end
@@ -14,20 +14,24 @@ describe ControlCouple do
14
14
 
15
15
  context 'conditional on a parameter' do
16
16
  it 'should report a ternary check on a parameter' do
17
- 'def simple(arga) arga ? @ivar : 3 end'.should reek_only_of(:ControlCouple, /arga/)
17
+ src = 'def simple(arga) arga ? @ivar : 3 end'
18
+ src.should smell_of(ControlCouple, ControlCouple::PARAMETER_KEY => 'arga')
18
19
  end
19
20
  it 'should not report a ternary check on an ivar' do
20
- 'def simple(arga) @ivar ? arga : 3 end'.should_not reek
21
+ src = 'def simple(arga) @ivar ? arga : 3 end'
22
+ src.should_not smell_of(ControlCouple)
21
23
  end
22
24
  it 'should not report a ternary check on a lvar' do
23
- 'def simple(arga) lvar = 27; lvar ? arga : @ivar end'.should_not reek
25
+ src = 'def simple(arga) lvar = 27; lvar ? arga : @ivar end'
26
+ src.should_not smell_of(ControlCouple)
24
27
  end
25
28
  it 'should spot a couple inside a block' do
26
- 'def blocks(arg) @text.map { |blk| arg ? blk : "#{blk}" } end'.should reek_of(:ControlCouple, /arg/)
29
+ src = 'def blocks(arg) @text.map { |blk| arg ? blk : "#{blk}" } end'
30
+ src.should smell_of(ControlCouple, ControlCouple::PARAMETER_KEY => 'arg')
27
31
  end
28
32
  end
29
33
 
30
- context 'looking at the YAML' do
34
+ context 'when a smell is reported' do
31
35
  before :each do
32
36
  src = <<EOS
33
37
  def things(arg)
@@ -37,19 +41,16 @@ def things(arg)
37
41
  puts "hello" if arg
38
42
  end
39
43
  EOS
40
- source = src.to_reek_source
41
- sniffer = Sniffer.new(source)
42
- mctx = CodeParser.new(sniffer).process_defn(source.syntax_tree)
43
- @detector.examine_context(mctx)
44
- @warning = @detector.smells_found.to_a[0] # SMELL: too cumbersome!
44
+ ctx = MethodContext.new(nil, src.to_reek_source.syntax_tree)
45
+ smells = @detector.examine(ctx)
46
+ smells.length.should == 1
47
+ @warning = smells[0]
45
48
  end
46
49
 
47
50
  it_should_behave_like 'common fields set correctly'
48
51
 
49
- it 'reports the control parameter' do
50
- @warning.smell['parameter'].should == 'arg'
51
- end
52
- it 'reports all conditional locations' do
52
+ it 'has the correct fields' do
53
+ @warning.smell[ControlCouple::PARAMETER_KEY].should == 'arg'
53
54
  @warning.lines.should == [3,6]
54
55
  end
55
56
  end
@@ -14,8 +14,7 @@ shared_examples_for 'a data clump detector' do
14
14
  def third(pa) pa - pb + @fred; end
15
15
  end
16
16
  EOS
17
-
18
- src.should_not reek
17
+ src.should_not smell_of(DataClump)
19
18
  end
20
19
 
21
20
  context 'with 3 identical pairs' do
@@ -30,8 +29,7 @@ end
30
29
  EOS
31
30
  ctx = CodeContext.new(nil, @src.to_reek_source.syntax_tree)
32
31
  detector = DataClump.new('newt')
33
- detector.examine(ctx)
34
- @smells = detector.smells_found.to_a
32
+ @smells = detector.examine_context(ctx)
35
33
  @warning = @smells[0] # SMELL: too cumbersome!
36
34
  @yaml = @warning.to_yaml
37
35
  end
@@ -42,7 +40,7 @@ EOS
42
40
  @smells[0].smell[DataClump::PARAMETERS_KEY].should == ['pa', 'pb']
43
41
  end
44
42
  it 'reports the number of occurrences' do
45
- @smells[0].smell['occurrences'].should == 3
43
+ @smells[0].smell[DataClump::OCCURRENCES_KEY].should == 3
46
44
  end
47
45
  it 'reports all parameters' do
48
46
  @smells[0].smell[DataClump::METHODS_KEY].should == ['first', 'second', 'third']
@@ -66,8 +64,8 @@ EOS
66
64
  def tri(pa, pb) pa - pb + @fred; end
67
65
  end
68
66
  EOS
69
-
70
- src.should reek_of(:DataClump, /\[pa, pb\]/, /3 methods/)
67
+ src.should smell_of(DataClump, {DataClump::OCCURRENCES_KEY => 3,
68
+ DataClump::PARAMETERS_KEY => ['pa', 'pb']})
71
69
  end
72
70
 
73
71
  it 'reports 3 identical parameter sets in a class' do
@@ -78,14 +76,11 @@ EOS
78
76
  def third(pa, pb, pc) pa - pb + @fred; end
79
77
  end
80
78
  EOS
81
-
82
- src.should reek_of(:DataClump, /\[pa, pb, pc\]/, /3 methods/)
83
- src.should_not reek_of(:DataClump, /\[pa, pb\]/, /3 methods/)
84
- src.should_not reek_of(:DataClump, /\[pa, pc\]/, /3 methods/)
85
- src.should_not reek_of(:DataClump, /\[pb, pc\]/, /3 methods/)
79
+ src.should smell_of(DataClump, {DataClump::OCCURRENCES_KEY => 3,
80
+ DataClump::PARAMETERS_KEY => ['pa', 'pb', 'pc']})
86
81
  end
87
82
 
88
- it 'recognises re-ordered identical parameter sets' do
83
+ it 'reports re-ordered identical parameter sets' do
89
84
  src = <<EOS
90
85
  #{@context} Scrunch
91
86
  def first(pb, pa, pc) @field == :sym ? 0 : 3; end
@@ -93,11 +88,8 @@ EOS
93
88
  def third(pa, pb, pc) pa - pb + @fred; end
94
89
  end
95
90
  EOS
96
-
97
- src.should reek_of(:DataClump, /\[pa, pb, pc\]/, /3 methods/)
98
- src.should_not reek_of(:DataClump, /\[pa, pb\]/, /3 methods/)
99
- src.should_not reek_of(:DataClump, /\[pa, pc\]/, /3 methods/)
100
- src.should_not reek_of(:DataClump, /\[pb, pc\]/, /3 methods/)
91
+ src.should smell_of(DataClump, {DataClump::OCCURRENCES_KEY => 3,
92
+ DataClump::PARAMETERS_KEY => ['pa', 'pb', 'pc']})
101
93
  end
102
94
 
103
95
  it 'counts only identical parameter sets' do
@@ -108,12 +100,30 @@ EOS
108
100
  def fc(name, windowW, windowH) end
109
101
  end
110
102
  EOS
103
+ src.should_not smell_of(DataClump)
104
+ end
111
105
 
112
- src.should_not reek_of(:DataClump)
106
+ it 'gets a real example right' do
107
+ src = <<EOS
108
+ #{@context} Inline
109
+ def generate(src, options) end
110
+ def c (src, options) end
111
+ def c_singleton (src, options) end
112
+ def c_raw (src, options) end
113
+ def c_raw_singleton (src, options) end
114
+ end
115
+ EOS
116
+ src.should smell_of(DataClump, DataClump::OCCURRENCES_KEY => 5)
113
117
  end
114
118
  end
115
119
 
116
120
  describe DataClump do
121
+ before(:each) do
122
+ @detector = DataClump.new('newt')
123
+ end
124
+
125
+ it_should_behave_like 'SmellDetector'
126
+
117
127
  context 'in a class' do
118
128
  before :each do
119
129
  @context = 'class'
@@ -132,95 +142,3 @@ describe DataClump do
132
142
 
133
143
  # TODO: include singleton methods in the calcs
134
144
  end
135
-
136
- describe DataClump do
137
- before(:each) do
138
- @detector = DataClump.new('newt')
139
- end
140
-
141
- it_should_behave_like 'SmellDetector'
142
-
143
- it 'get a real example right' do
144
- src = <<-EOS
145
- module Inline
146
- def generate(src, options) end
147
- def c (src, options) end
148
- def c_singleton (src, options) end
149
- def c_raw (src, options) end
150
- def c_raw_singleton (src, options) end
151
- end
152
- EOS
153
- ctx = CodeContext.new(nil, src.to_reek_source.syntax_tree)
154
- detector = DataClump.new('newt')
155
- detector.examine(ctx)
156
- smells = detector.smells_found.to_a
157
- smells.length.should == 1
158
- warning = smells[0]
159
- warning.smell[DataClump::OCCURRENCES_KEY].should == 5
160
- end
161
- end
162
-
163
- #---------------------------------------------------------------------------------
164
- #
165
- #def occurrences(potential_clump, all_methods)
166
- # all_methods.select do |method|
167
- # potential_clump - method == []
168
- # end.length
169
- #end
170
- #
171
- #describe 'occurrences' do
172
- # it 'counts correctly' do
173
- # params = [[:a1, :a2], [:a1, :a2]]
174
- # potential_clump = [:a1, :a2]
175
- # occurrences(potential_clump, params).should == 2
176
- # end
177
- #end
178
- #
179
- #def immediate_clumps(root, other_params, all_methods)
180
- # result = []
181
- # other_params.map do |param|
182
- # potential_clump = (root + [param])
183
- # if occurrences(potential_clump, all_methods) >= 2
184
- # result << potential_clump
185
- # result = result + immediate_clumps(potential_clump, other_params - [param], all_methods)
186
- # end
187
- # end.compact
188
- # result
189
- #end
190
- #
191
- #def clumps_containing(root, other_params, all_methods)
192
- # return [] unless other_params
193
- # immediate_clumps(root, other_params, all_methods) + clumps_containing([other_params[0]], other_params[1..-1], all_methods)
194
- #end
195
- #
196
- #def clumps_in(all_methods)
197
- # all_params = all_methods.flatten.sort {|a,b| a.to_s <=> b.to_s}.uniq
198
- # clumps_containing([all_params[0]], all_params[1..-1], all_methods)
199
- #end
200
- #
201
- #describe 'set of parameters' do
202
- # it 'finds the trivial clump' do
203
- # params = [[:a1, :a2], [:a1, :a2]]
204
- # clumps_in(params).should == [[:a1, :a2]]
205
- # end
206
- #
207
- # it 'finds the trivial size-3 clump' do
208
- # params = [[:a1, :a2, :a3], [:a1, :a2, :a3]]
209
- # clumps_in(params).should == [[:a1, :a2, :a3]]
210
- # end
211
- #
212
- # it 'doesnt find non clump' do
213
- # params = [[:a1, :a2], [:a1, :a3]]
214
- # clumps_in(params).should == []
215
- # end
216
- #
217
- # it 'finds the trivial sub-clump' do
218
- # params = [[:a1, :a2], [:a3, :a1, :a2]]
219
- # clumps_in(params).should == [[:a1, :a2]]
220
- # end
221
- #
222
- # it 'finds the non-a1 clump' do
223
- # params = [[:a1, :a3, :a2], [:a3, :a2]]
224
- # clumps_in(params).should == [[:a2, :a3]]
225
- # end
226
- #end