diff --git a/docs/Smell-Suppression.md b/docs/Smell-Suppression.md index 893f23c90..bb65eb540 100644 --- a/docs/Smell-Suppression.md +++ b/docs/Smell-Suppression.md @@ -1,15 +1,18 @@ ## Introduction -In some cases, it might be necessary to suppress one or more of `reek`'s smell warnings for a particular method or class. +In some cases, it might be necessary to suppress one or more of `reek`'s smell +warnings for a particular method or class. Possible reasons for this could be: * The code is outside of your control and you can't fix it -* `reek` is not the police. You might have legit reasons why your source code is good as it is. +* `reek` is not the police. You might have legit reasons why your source code + is good as it is. ## How to disable smell detection -First and foremost, there are the [Basic Smell Options](Basic-Smell-Options.md) you can use. +First and foremost, there are the [Basic Smell Options](Basic-Smell-Options.md) +you can use. Besides from that, you can use special comments, like so: @@ -20,7 +23,9 @@ def smelly_method foo end ``` -The method `smelly_method` will not be reported. The general pattern is to put the string ':reek:', followed by the smell class, in a comment before the method or class. +The method `smelly_method` will not be reported. The general pattern is to put +the string ':reek:', followed by the smell class, in a comment before the +method or class. It is also possible to specify options for a particular smell detector, like so: @@ -30,3 +35,12 @@ def many_parameters_it_has foo, bar, baz, qux # ... end ``` + +Multiple smells may be configured for the same method or class: + +```ruby +# :reek:LongParameterList: { max_params: 4 } and :reek:NestedIterators +def many_parameters_it_has foo, bar, baz, qux + foo.each {|bar| bar.each {|baz| baz.qux(qux)}} +end +``` diff --git a/lib/reek/code_comment.rb b/lib/reek/code_comment.rb index 1e9a7b832..a333426a5 100644 --- a/lib/reek/code_comment.rb +++ b/lib/reek/code_comment.rb @@ -14,31 +14,26 @@ class CodeComment CONFIG_REGEX = /:reek:(\w+)(:\s*\{.*?\})?/ def initialize(text) + @config = Hash.new { |hash, key| hash[key] = {} } @text = text.gsub(CONFIG_REGEX) do - add_to_config($1, $2) + @config.merge! add_to_config($1, $2) '' end.gsub(/#/, '').gsub(/\n/, '').strip end - def config - @config ||= Hash.new { |hash, key| hash[key] = {} } - end + attr_reader :config def descriptive? text.split(/\s+/).length >= 2 end - protected + private def add_to_config(smell, options) options ||= ': { enabled: false }' - config.merge! YAML.load(smell.gsub(/(?:^|_)(.)/) { $1.upcase } + options) - # TODO: extend this to all configs -------------------^ - # TODO: extend to allow configuration of whole smell class, not just subclass + YAML.load(smell + options) end - private - private_attr_reader :text end end diff --git a/spec/reek/code_comment_spec.rb b/spec/reek/code_comment_spec.rb index 676dc8788..f61a602ae 100644 --- a/spec/reek/code_comment_spec.rb +++ b/spec/reek/code_comment_spec.rb @@ -36,17 +36,11 @@ expect(config['Duplication']).to include('enabled') expect(config['Duplication']['enabled']).to be_falsey end - it 'parses hashed options with Ruby names' do - comment = '# :reek:nested_iterators: { enabled: true }' - config = described_class.new(comment).config - expect(config).to include('NestedIterators') - expect(config['NestedIterators']).to include('enabled') - expect(config['NestedIterators']['enabled']).to be_truthy - end + it 'parses multiple hashed options' do config = described_class.new(' # :reek:Duplication: { enabled: false } - :reek:nested_iterators: { enabled: true } + # :reek:NestedIterators: { enabled: true } ').config expect(config).to include('Duplication', 'NestedIterators') expect(config['Duplication']).to include('enabled') @@ -54,9 +48,10 @@ expect(config['NestedIterators']).to include('enabled') expect(config['NestedIterators']['enabled']).to be_truthy end + it 'parses multiple hashed options on the same line' do config = described_class.new(' - #:reek:Duplication: { enabled: false } and :reek:nested_iterators: { enabled: true } + #:reek:Duplication: { enabled: false } and :reek:NestedIterators: { enabled: true } ').config expect(config).to include('Duplication', 'NestedIterators') expect(config['Duplication']).to include('enabled') @@ -64,8 +59,9 @@ expect(config['NestedIterators']).to include('enabled') expect(config['NestedIterators']['enabled']).to be_truthy end + it 'parses multiple unhashed options on the same line' do - comment = '# :reek:Duplication and :reek:nested_iterators' + comment = '# :reek:Duplication and :reek:NestedIterators' config = described_class.new(comment).config expect(config).to include('Duplication', 'NestedIterators') expect(config['Duplication']).to include('enabled') @@ -73,12 +69,14 @@ expect(config['NestedIterators']).to include('enabled') expect(config['NestedIterators']['enabled']).to be_falsey end + it 'disables the smell if no options are specifed' do config = described_class.new('# :reek:Duplication').config expect(config).to include('Duplication') expect(config['Duplication']).to include('enabled') expect(config['Duplication']['enabled']).to be_falsey end + it 'ignores smells after a space' do config = described_class.new('# :reek: Duplication').config expect(config).not_to include('Duplication')