reek 3.3.1 → 3.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (123) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -0
  3. data/CHANGELOG.md +6 -0
  4. data/CONTRIBUTING.md +3 -0
  5. data/README.md +12 -4
  6. data/Rakefile +1 -0
  7. data/config/defaults.reek +1 -2
  8. data/docs/Nested-Iterators.md +6 -1
  9. data/docs/Smell-Suppression.md +69 -5
  10. data/docs/Uncommunicative-Module-Name.md +1 -1
  11. data/docs/Utility-Function.md +13 -1
  12. data/docs/style-guide.md +18 -0
  13. data/docs/templates/default/docstring/html/public_api_marker.erb +3 -0
  14. data/docs/templates/default/docstring/setup.rb +41 -0
  15. data/docs/templates/default/fulldoc/html/css/common.css +1 -0
  16. data/docs/yard_plugin.rb +2 -0
  17. data/features/command_line_interface/smell_selection.feature +1 -0
  18. data/features/configuration_files/masking_smells.feature +12 -0
  19. data/features/samples.feature +27 -26
  20. data/features/step_definitions/sample_file_steps.rb +25 -30
  21. data/lib/reek/ast/ast_node_class_map.rb +1 -1
  22. data/lib/reek/ast/node.rb +3 -4
  23. data/lib/reek/ast/object_refs.rb +2 -2
  24. data/lib/reek/ast/reference_collector.rb +0 -1
  25. data/lib/reek/ast/sexp_extensions.rb +1 -2
  26. data/lib/reek/ast/sexp_formatter.rb +1 -2
  27. data/lib/reek/cli/application.rb +0 -1
  28. data/lib/reek/cli/command.rb +0 -1
  29. data/lib/reek/cli/input.rb +2 -1
  30. data/lib/reek/cli/option_interpreter.rb +0 -1
  31. data/lib/reek/cli/options.rb +3 -1
  32. data/lib/reek/cli/reek_command.rb +0 -1
  33. data/lib/reek/cli/silencer.rb +4 -4
  34. data/lib/reek/cli/warning_collector.rb +0 -1
  35. data/lib/reek/code_comment.rb +6 -11
  36. data/lib/reek/configuration/app_configuration.rb +0 -3
  37. data/lib/reek/configuration/configuration_file_finder.rb +4 -1
  38. data/lib/reek/configuration/configuration_validator.rb +1 -0
  39. data/lib/reek/configuration/directory_directives.rb +4 -0
  40. data/lib/reek/configuration/excluded_paths.rb +2 -1
  41. data/lib/reek/context/code_context.rb +11 -4
  42. data/lib/reek/context/method_context.rb +1 -6
  43. data/lib/reek/context/module_context.rb +0 -1
  44. data/lib/reek/context/root_context.rb +0 -1
  45. data/lib/reek/context/singleton_method_context.rb +0 -1
  46. data/lib/reek/examiner.rb +15 -15
  47. data/lib/reek/rake/task.rb +14 -0
  48. data/lib/reek/report.rb +0 -8
  49. data/lib/reek/report/formatter.rb +13 -12
  50. data/lib/reek/report/heading_formatter.rb +2 -1
  51. data/lib/reek/report/location_formatter.rb +0 -3
  52. data/lib/reek/report/report.rb +34 -14
  53. data/lib/reek/smells/attribute.rb +6 -6
  54. data/lib/reek/smells/boolean_parameter.rb +8 -8
  55. data/lib/reek/smells/class_variable.rb +7 -6
  56. data/lib/reek/smells/control_parameter.rb +8 -7
  57. data/lib/reek/smells/data_clump.rb +18 -20
  58. data/lib/reek/smells/duplicate_method_call.rb +10 -6
  59. data/lib/reek/smells/feature_envy.rb +17 -9
  60. data/lib/reek/smells/irresponsible_module.rb +6 -6
  61. data/lib/reek/smells/long_parameter_list.rb +7 -7
  62. data/lib/reek/smells/long_yield_list.rb +10 -9
  63. data/lib/reek/smells/module_initialize.rb +7 -6
  64. data/lib/reek/smells/nested_iterators.rb +5 -6
  65. data/lib/reek/smells/nil_check.rb +4 -5
  66. data/lib/reek/smells/prima_donna_method.rb +5 -5
  67. data/lib/reek/smells/repeated_conditional.rb +9 -6
  68. data/lib/reek/smells/smell_configuration.rb +1 -7
  69. data/lib/reek/smells/smell_detector.rb +28 -25
  70. data/lib/reek/smells/smell_repository.rb +18 -19
  71. data/lib/reek/smells/smell_warning.rb +34 -21
  72. data/lib/reek/smells/too_many_instance_variables.rb +5 -6
  73. data/lib/reek/smells/too_many_methods.rb +6 -6
  74. data/lib/reek/smells/too_many_statements.rb +5 -6
  75. data/lib/reek/smells/uncommunicative_method_name.rb +6 -6
  76. data/lib/reek/smells/uncommunicative_module_name.rb +36 -22
  77. data/lib/reek/smells/uncommunicative_parameter_name.rb +27 -19
  78. data/lib/reek/smells/uncommunicative_variable_name.rb +13 -7
  79. data/lib/reek/smells/unused_parameters.rb +10 -9
  80. data/lib/reek/smells/utility_function.rb +22 -11
  81. data/lib/reek/source/source_code.rb +11 -12
  82. data/lib/reek/source/source_locator.rb +6 -1
  83. data/lib/reek/spec.rb +11 -0
  84. data/lib/reek/spec/should_reek.rb +0 -3
  85. data/lib/reek/spec/should_reek_of.rb +1 -1
  86. data/lib/reek/spec/should_reek_only_of.rb +0 -1
  87. data/lib/reek/tree_dresser.rb +3 -1
  88. data/lib/reek/tree_walker.rb +4 -5
  89. data/lib/reek/version.rb +4 -1
  90. data/reek.gemspec +1 -1
  91. data/spec/factories/factories.rb +17 -6
  92. data/spec/quality/reek_source_spec.rb +3 -1
  93. data/spec/reek/cli/warning_collector_spec.rb +3 -2
  94. data/spec/reek/code_comment_spec.rb +8 -10
  95. data/spec/reek/configuration/directory_directives_spec.rb +2 -2
  96. data/spec/reek/configuration/excluded_paths_spec.rb +2 -2
  97. data/spec/reek/context/method_context_spec.rb +0 -26
  98. data/spec/reek/report/json_report_spec.rb +83 -6
  99. data/spec/reek/report/yaml_report_spec.rb +76 -6
  100. data/spec/reek/smells/attribute_spec.rb +1 -1
  101. data/spec/reek/smells/boolean_parameter_spec.rb +2 -3
  102. data/spec/reek/smells/class_variable_spec.rb +1 -1
  103. data/spec/reek/smells/control_parameter_spec.rb +1 -1
  104. data/spec/reek/smells/data_clump_spec.rb +1 -1
  105. data/spec/reek/smells/duplicate_method_call_spec.rb +1 -1
  106. data/spec/reek/smells/feature_envy_spec.rb +1 -0
  107. data/spec/reek/smells/irresponsible_module_spec.rb +1 -1
  108. data/spec/reek/smells/long_parameter_list_spec.rb +1 -1
  109. data/spec/reek/smells/long_yield_list_spec.rb +1 -1
  110. data/spec/reek/smells/nested_iterators_spec.rb +1 -1
  111. data/spec/reek/smells/repeated_conditional_spec.rb +1 -1
  112. data/spec/reek/smells/smell_configuration_spec.rb +9 -9
  113. data/spec/reek/smells/smell_detector_shared.rb +0 -9
  114. data/spec/reek/smells/smell_repository_spec.rb +1 -8
  115. data/spec/reek/smells/smell_warning_spec.rb +3 -2
  116. data/spec/reek/smells/too_many_instance_variables_spec.rb +1 -1
  117. data/spec/reek/smells/too_many_methods_spec.rb +2 -4
  118. data/spec/reek/smells/uncommunicative_method_name_spec.rb +1 -1
  119. data/spec/reek/smells/uncommunicative_module_name_spec.rb +22 -5
  120. data/spec/reek/smells/uncommunicative_parameter_name_spec.rb +1 -1
  121. data/spec/reek/smells/uncommunicative_variable_name_spec.rb +1 -1
  122. data/spec/reek/smells/utility_function_spec.rb +49 -0
  123. metadata +9 -5
data/lib/reek/spec.rb CHANGED
@@ -39,6 +39,7 @@ module Reek
39
39
  # ruby.should reek_of(:Duplication, /@other.thing.foo/)
40
40
  # ruby.should_not reek_of(:FeatureEnvy)
41
41
  #
42
+ # @public
42
43
  module Spec
43
44
  #
44
45
  # Checks the target source code for instances of "smell category"
@@ -85,6 +86,9 @@ module Reek
85
86
  #
86
87
  # expect(src).to reek_of(Reek::Smells::DuplicateMethodCall, name: '@other.thing')
87
88
  #
89
+ # @public
90
+ #
91
+ # :reek:UtilityFunction
88
92
  def reek_of(smell_category,
89
93
  smell_details = {},
90
94
  configuration = Configuration::AppConfiguration.default)
@@ -98,6 +102,10 @@ module Reek
98
102
  # 1.) "reek_of" doesn't mind if there are other smells of a different category.
99
103
  # "reek_only_of" will fail in that case.
100
104
  # 2.) "reek_only_of" doesn't support the additional smell_details hash.
105
+ #
106
+ # @public
107
+ #
108
+ # :reek:UtilityFunction
101
109
  def reek_only_of(smell_category, configuration = Configuration::AppConfiguration.default)
102
110
  ShouldReekOnlyOf.new(smell_category, configuration)
103
111
  end
@@ -105,6 +113,9 @@ module Reek
105
113
  #
106
114
  # Returns +true+ if and only if the target source code contains smells.
107
115
  #
116
+ # @public
117
+ #
118
+ # :reek:UtilityFunction
108
119
  def reek(configuration = Configuration::AppConfiguration.default)
109
120
  ShouldReek.new(configuration: configuration)
110
121
  end
@@ -6,7 +6,6 @@ module Reek
6
6
  #
7
7
  # An rspec matcher that matches when the +actual+ has code smells.
8
8
  #
9
- # @api private
10
9
  class ShouldReek
11
10
  def initialize(configuration: Configuration::AppConfiguration.default)
12
11
  @configuration = configuration
@@ -26,8 +25,6 @@ module Reek
26
25
  "Expected no smells, but got:\n#{rpt}"
27
26
  end
28
27
 
29
- private
30
-
31
28
  private_attr_reader :configuration
32
29
  private_attr_accessor :examiner
33
30
  end
@@ -6,7 +6,6 @@ module Reek
6
6
  # An rspec matcher that matches when the +actual+ has the specified
7
7
  # code smell.
8
8
  #
9
- # @api private
10
9
  class ShouldReekOf
11
10
  def initialize(smell_category,
12
11
  smell_details = {},
@@ -35,6 +34,7 @@ module Reek
35
34
  private_attr_reader :configuration, :smell_category, :smell_details
36
35
  private_attr_accessor :all_smells, :examiner
37
36
 
37
+ # :reek:UtilityFunction
38
38
  def normalize(smell_category_or_type)
39
39
  # In theory, users can give us many different types of input (see the documentation for
40
40
  # reek_of below), however we're basically ignoring all of those subleties and just
@@ -8,7 +8,6 @@ module Reek
8
8
  # An rspec matcher that matches when the +actual+ has the specified
9
9
  # code smell and no others.
10
10
  #
11
- # @api private
12
11
  class ShouldReekOnlyOf < ShouldReekOf
13
12
  def matches?(actual)
14
13
  matches_examiner?(Examiner.new(actual, configuration: configuration))
@@ -5,7 +5,6 @@ module Reek
5
5
  # Adorns an abstract syntax tree with mix-in modules to make accessing
6
6
  # the tree more understandable and less implementation-dependent.
7
7
  #
8
- # @api private
9
8
  class TreeDresser
10
9
  def initialize(klass_map: AST::ASTNodeClassMap.new)
11
10
  @klass_map = klass_map
@@ -35,6 +34,9 @@ module Reek
35
34
  # @param parent [Parser::AST::Node] - the parent sexp
36
35
  #
37
36
  # @return an instance of Reek::AST::Node with type-dependent sexp extensions mixed in.
37
+ #
38
+ # :reek:FeatureEnvy
39
+ # :reek:TooManyStatements: { max_statements: 6 }
38
40
  def dress(sexp, comment_map, parent: nil)
39
41
  return sexp unless sexp.is_a? ::Parser::AST::Node
40
42
  type = sexp.type
@@ -15,7 +15,7 @@ module Reek
15
15
  # TODO: Make TreeWalker responsible only for creating Context objects, and
16
16
  # loop over the created set of contexts elsewhere.
17
17
  #
18
- # @api private
18
+ # :reek:TooManyMethods: { max_methods: 29 }
19
19
  class TreeWalker
20
20
  def initialize(smell_repository, exp)
21
21
  @smell_repository = smell_repository
@@ -86,10 +86,8 @@ module Reek
86
86
 
87
87
  def process_args(_) end
88
88
 
89
- #
90
- # Recording of calls to methods and self
91
- #
92
-
89
+ # :reek:TooManyStatements: { max_statements: 6 }
90
+ # :reek:FeatureEnvy
93
91
  def process_send(exp)
94
92
  if exp.visibility_modifier?
95
93
  element.track_visibility(exp.method_name, exp.arg_names)
@@ -188,6 +186,7 @@ module Reek
188
186
  self.class.private_method_defined?(name)
189
187
  end
190
188
 
189
+ # :reek:ControlParameter
191
190
  def count_clause(sexp)
192
191
  element.count_statements(1) if sexp
193
192
  end
data/lib/reek/version.rb CHANGED
@@ -1,8 +1,11 @@
1
+ # @public
1
2
  module Reek
2
3
  #
3
4
  # This module holds the Reek version informations
4
5
  #
6
+ # @public
5
7
  module Version
6
- STRING = '3.3.1'
8
+ # @public
9
+ STRING = '3.4.0'
7
10
  end
8
11
  end
data/reek.gemspec CHANGED
@@ -35,5 +35,5 @@ Gem::Specification.new do |s|
35
35
  s.add_development_dependency 'factory_girl', '~> 4.0'
36
36
  s.add_development_dependency 'rake', '~> 10.0'
37
37
  s.add_development_dependency 'rspec', '~> 3.0'
38
- s.add_development_dependency 'rubocop', '~> 0.32.1'
38
+ s.add_development_dependency 'rubocop', '~> 0.33.0'
39
39
  end
@@ -3,15 +3,23 @@ require_relative '../../lib/reek/smells/smell_detector'
3
3
  require_relative '../../lib/reek/smells/smell_warning'
4
4
 
5
5
  FactoryGirl.define do
6
+ factory :context, class: Reek::Context::CodeContext do
7
+ skip_create
8
+
9
+ initialize_with do
10
+ new(nil, nil)
11
+ end
12
+ end
13
+
6
14
  factory :smell_detector, class: Reek::Smells::SmellDetector do
7
15
  skip_create
8
16
  transient do
9
17
  smell_type 'FeatureEnvy'
18
+ source 'foo'
10
19
  end
11
- source 'dummy_file'
12
20
 
13
21
  initialize_with do
14
- ::Reek::Smells.const_get(smell_type).new(source)
22
+ ::Reek::Smells.const_get(smell_type).new
15
23
  end
16
24
  end
17
25
 
@@ -19,15 +27,18 @@ FactoryGirl.define do
19
27
  skip_create
20
28
  smell_detector
21
29
  context 'self'
30
+ source 'dummy_file'
22
31
  lines [42]
23
32
  message 'smell warning message'
24
33
  parameters { {} }
25
34
 
26
35
  initialize_with do
27
- new(smell_detector, context: context,
28
- lines: lines,
29
- message: message,
30
- parameters: parameters)
36
+ new(smell_detector,
37
+ source: source,
38
+ context: context,
39
+ lines: lines,
40
+ message: message,
41
+ parameters: parameters)
31
42
  end
32
43
  end
33
44
  end
@@ -2,6 +2,8 @@ require_relative '../spec_helper'
2
2
 
3
3
  RSpec.describe 'Reek source code' do
4
4
  it 'has no smells' do
5
- expect(Dir['lib/**/*.rb']).to_not reek
5
+ Pathname.glob('lib/**/*.rb').each do |pathname|
6
+ expect(pathname).to_not reek
7
+ end
6
8
  end
7
9
  end
@@ -13,8 +13,9 @@ RSpec.describe Reek::CLI::WarningCollector do
13
13
 
14
14
  context 'with one warning' do
15
15
  it 'reports that warning' do
16
- warning = Reek::Smells::SmellWarning.new(Reek::Smells::FeatureEnvy.new(''),
17
- context: 'fred',
16
+ warning = Reek::Smells::SmellWarning.new(Reek::Smells::FeatureEnvy.new,
17
+ source: 'string',
18
+ context: 'foo',
18
19
  lines: [1, 2, 3],
19
20
  message: 'hello')
20
21
  collector.found_smell(warning)
@@ -36,17 +36,11 @@ RSpec.describe Reek::CodeComment do
36
36
  expect(config['Duplication']).to include('enabled')
37
37
  expect(config['Duplication']['enabled']).to be_falsey
38
38
  end
39
- it 'parses hashed options with Ruby names' do
40
- comment = '# :reek:nested_iterators: { enabled: true }'
41
- config = described_class.new(comment).config
42
- expect(config).to include('NestedIterators')
43
- expect(config['NestedIterators']).to include('enabled')
44
- expect(config['NestedIterators']['enabled']).to be_truthy
45
- end
39
+
46
40
  it 'parses multiple hashed options' do
47
41
  config = described_class.new('
48
42
  # :reek:Duplication: { enabled: false }
49
- :reek:nested_iterators: { enabled: true }
43
+ # :reek:NestedIterators: { enabled: true }
50
44
  ').config
51
45
  expect(config).to include('Duplication', 'NestedIterators')
52
46
  expect(config['Duplication']).to include('enabled')
@@ -54,9 +48,10 @@ RSpec.describe Reek::CodeComment do
54
48
  expect(config['NestedIterators']).to include('enabled')
55
49
  expect(config['NestedIterators']['enabled']).to be_truthy
56
50
  end
51
+
57
52
  it 'parses multiple hashed options on the same line' do
58
53
  config = described_class.new('
59
- #:reek:Duplication: { enabled: false } and :reek:nested_iterators: { enabled: true }
54
+ #:reek:Duplication: { enabled: false } and :reek:NestedIterators: { enabled: true }
60
55
  ').config
61
56
  expect(config).to include('Duplication', 'NestedIterators')
62
57
  expect(config['Duplication']).to include('enabled')
@@ -64,8 +59,9 @@ RSpec.describe Reek::CodeComment do
64
59
  expect(config['NestedIterators']).to include('enabled')
65
60
  expect(config['NestedIterators']['enabled']).to be_truthy
66
61
  end
62
+
67
63
  it 'parses multiple unhashed options on the same line' do
68
- comment = '# :reek:Duplication and :reek:nested_iterators'
64
+ comment = '# :reek:Duplication and :reek:NestedIterators'
69
65
  config = described_class.new(comment).config
70
66
  expect(config).to include('Duplication', 'NestedIterators')
71
67
  expect(config['Duplication']).to include('enabled')
@@ -73,12 +69,14 @@ RSpec.describe Reek::CodeComment do
73
69
  expect(config['NestedIterators']).to include('enabled')
74
70
  expect(config['NestedIterators']['enabled']).to be_falsey
75
71
  end
72
+
76
73
  it 'disables the smell if no options are specifed' do
77
74
  config = described_class.new('# :reek:Duplication').config
78
75
  expect(config).to include('Duplication')
79
76
  expect(config['Duplication']).to include('enabled')
80
77
  expect(config['Duplication']['enabled']).to be_falsey
81
78
  end
79
+
82
80
  it 'ignores smells after a space' do
83
81
  config = described_class.new('# :reek: Duplication').config
84
82
  expect(config).not_to include('Duplication')
@@ -36,7 +36,7 @@ RSpec.describe Reek::Configuration::DirectoryDirectives do
36
36
  let(:bogus_path) { Pathname('does/not/exist') }
37
37
 
38
38
  it 'raises an error' do
39
- Reek::CLI::Silencer.silently(stderr: true) do
39
+ Reek::CLI::Silencer.silently do
40
40
  expect { subject.add(bogus_path, {}) }.to raise_error(SystemExit)
41
41
  end
42
42
  end
@@ -46,7 +46,7 @@ RSpec.describe Reek::Configuration::DirectoryDirectives do
46
46
  let(:file_as_path) { SAMPLES_PATH.join('inline.rb') }
47
47
 
48
48
  it 'raises an error' do
49
- Reek::CLI::Silencer.silently(stderr: true) do
49
+ Reek::CLI::Silencer.silently do
50
50
  expect { subject.add(file_as_path, {}) }.to raise_error(SystemExit)
51
51
  end
52
52
  end
@@ -10,7 +10,7 @@ RSpec.describe Reek::Configuration::ExcludedPaths do
10
10
  let(:paths) { [SAMPLES_PATH, bogus_path] }
11
11
 
12
12
  it 'raises an error' do
13
- Reek::CLI::Silencer.silently(stderr: true) do
13
+ Reek::CLI::Silencer.silently do
14
14
  expect { subject.add(paths) }.to raise_error(SystemExit)
15
15
  end
16
16
  end
@@ -21,7 +21,7 @@ RSpec.describe Reek::Configuration::ExcludedPaths do
21
21
  let(:paths) { [SAMPLES_PATH, file_as_path] }
22
22
 
23
23
  it 'raises an error if one of the given paths is a file' do
24
- Reek::CLI::Silencer.silently(stderr: true) do
24
+ Reek::CLI::Silencer.silently do
25
25
  expect { subject.add(paths) }.to raise_error(SystemExit)
26
26
  end
27
27
  end
@@ -22,32 +22,6 @@ RSpec.describe Reek::Context::MethodContext do
22
22
  end
23
23
  end
24
24
 
25
- describe '#envious_receivers' do
26
- let(:exp) { sexp(:def, :foo, sexp(:args, sexp(:arg, :bar)), nil) }
27
-
28
- it 'should ignore ivars as refs to self' do
29
- method_context.record_call_to sexp(:send, sexp(:ivar, :@cow), :feed_to)
30
- expect(method_context.envious_receivers).to be_empty
31
- end
32
-
33
- it 'should ignore explicit calls to self' do
34
- method_context.refs.record_reference_to :other
35
- method_context.record_call_to sexp(:send, sexp(:self), :thing)
36
- expect(method_context.envious_receivers).to be_empty
37
- end
38
-
39
- it 'should ignore implicit calls to self' do
40
- method_context.record_call_to sexp(:send, sexp(:lvar, :text), :each, sexp(:arglist))
41
- method_context.record_call_to sexp(:send, nil, :shelve, sexp(:arglist))
42
- expect(method_context.envious_receivers).to be_empty
43
- end
44
-
45
- it 'should record envious calls' do
46
- method_context.record_call_to sexp(:send, sexp(:lvar, :bar), :baz)
47
- expect(method_context.envious_receivers).to include(:bar)
48
- end
49
- end
50
-
51
25
  describe '#default_assignments' do
52
26
  def assignments_from(src)
53
27
  exp = Reek::Source::SourceCode.from(src).syntax_tree
@@ -3,18 +3,95 @@ require_relative '../../../lib/reek/examiner'
3
3
  require_relative '../../../lib/reek/report/report'
4
4
  require_relative '../../../lib/reek/report/formatter'
5
5
 
6
+ require 'json'
7
+ require 'stringio'
8
+
6
9
  RSpec.describe Reek::Report::JSONReport do
7
- let(:instance) { Reek::Report::JSONReport.new }
10
+ let(:options) { {} }
11
+ let(:instance) { Reek::Report::JSONReport.new(options) }
12
+ let(:examiner) { Reek::Examiner.new(source) }
8
13
 
9
- context 'empty source' do
10
- let(:examiner) { Reek::Examiner.new('') }
14
+ before do
15
+ instance.add_examiner examiner
16
+ end
11
17
 
12
- before do
13
- instance.add_examiner examiner
14
- end
18
+ context 'with empty source' do
19
+ let(:source) { '' }
15
20
 
16
21
  it 'prints empty json' do
17
22
  expect { instance.show }.to output(/^\[\]$/).to_stdout
18
23
  end
19
24
  end
25
+
26
+ context 'with smelly source' do
27
+ let(:source) { 'def simple(a) a[3] end' }
28
+
29
+ it 'prints smells as json' do
30
+ out = StringIO.new
31
+ instance.show(out)
32
+ out.rewind
33
+ result = JSON.parse(out.read)
34
+ expected = JSON.parse <<-EOS
35
+ [
36
+ {
37
+ "context": "simple",
38
+ "lines": [1],
39
+ "message": "doesn't depend on instance state (maybe move it to another class?)",
40
+ "smell_category": "LowCohesion",
41
+ "smell_type": "UtilityFunction",
42
+ "source": "string",
43
+ "name": "simple"
44
+ },
45
+ {
46
+ "context": "simple",
47
+ "lines": [1],
48
+ "message": "has the parameter name 'a'",
49
+ "smell_category": "UncommunicativeName",
50
+ "smell_type": "UncommunicativeParameterName",
51
+ "source": "string",
52
+ "name": "a"
53
+ }
54
+ ]
55
+ EOS
56
+
57
+ expect(result).to eq expected
58
+ end
59
+
60
+ context 'with link formatter' do
61
+ let(:options) { { warning_formatter: Reek::Report::WikiLinkWarningFormatter.new } }
62
+
63
+ it 'prints documentation links' do
64
+ out = StringIO.new
65
+ instance.show(out)
66
+ out.rewind
67
+ result = JSON.parse(out.read)
68
+ expected = JSON.parse <<-EOS
69
+ [
70
+ {
71
+ "context": "simple",
72
+ "lines": [1],
73
+ "message": "doesn't depend on instance state (maybe move it to another class?)",
74
+ "smell_category": "LowCohesion",
75
+ "smell_type": "UtilityFunction",
76
+ "source": "string",
77
+ "name": "simple",
78
+ "wiki_link": "https://github.com/troessner/reek/blob/master/docs/Utility-Function.md"
79
+ },
80
+ {
81
+ "context": "simple",
82
+ "lines": [1],
83
+ "message": "has the parameter name 'a'",
84
+ "smell_category": "UncommunicativeName",
85
+ "smell_type": "UncommunicativeParameterName",
86
+ "source": "string",
87
+ "name": "a",
88
+ "wiki_link": "https://github.com/troessner/reek/blob/master/docs/Uncommunicative-Parameter-Name.md"
89
+ }
90
+ ]
91
+ EOS
92
+
93
+ expect(result).to eq expected
94
+ end
95
+ end
96
+ end
20
97
  end