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
@@ -5,15 +5,9 @@ module Reek
5
5
  #
6
6
  # A context wrapper for any method definition found in a syntax tree.
7
7
  #
8
- # @api private
9
8
  class MethodContext < CodeContext
10
9
  attr_reader :refs
11
10
 
12
- def envious_receivers
13
- return {} if refs.self_is_max?
14
- refs.most_popular
15
- end
16
-
17
11
  def references_self?
18
12
  exp.depends_on_instance?
19
13
  end
@@ -22,6 +16,7 @@ module Reek
22
16
  local_nodes(:lvar).find { |node| node.var_name == param.to_sym }
23
17
  end
24
18
 
19
+ # :reek:FeatureEnvy
25
20
  def unused_params
26
21
  exp.arguments.select do |param|
27
22
  next if param.anonymous_splat?
@@ -6,7 +6,6 @@ module Reek
6
6
  #
7
7
  # A context wrapper for any module found in a syntax tree.
8
8
  #
9
- # @api private
10
9
  class ModuleContext < CodeContext
11
10
  def node_instance_methods
12
11
  local_nodes(:def)
@@ -5,7 +5,6 @@ module Reek
5
5
  #
6
6
  # A context wrapper representing the root of an abstract syntax tree.
7
7
  #
8
- # @api private
9
8
  class RootContext < CodeContext
10
9
  def initialize(exp)
11
10
  super(nil, exp)
@@ -5,7 +5,6 @@ module Reek
5
5
  #
6
6
  # A context wrapper for any singleton method definition found in a syntax tree.
7
7
  #
8
- # @api private
9
8
  class SingletonMethodContext < MethodContext
10
9
  def envious_receivers
11
10
  {}
data/lib/reek/examiner.rb CHANGED
@@ -13,6 +13,9 @@ module Reek
13
13
  #
14
14
  # Applies all available smell detectors to a source.
15
15
  #
16
+ # @public
17
+ #
18
+ # :reek:TooManyInstanceVariables: { max_instance_variables: 6 }
16
19
  class Examiner
17
20
  #
18
21
  # Creates an Examiner which scans the given +source+ for code smells.
@@ -26,27 +29,32 @@ module Reek
26
29
  #
27
30
  # @param configuration [Configuration::AppConfiguration]
28
31
  # The configuration for this Examiner.
32
+ #
33
+ # @public
29
34
  def initialize(source,
30
35
  filter_by_smells = [],
31
36
  configuration: Configuration::AppConfiguration.default)
32
37
  @source = Source::SourceCode.from(source)
33
38
  @configuration = configuration
34
39
  @collector = CLI::WarningCollector.new
35
- @smell_types = eligible_smell_types(filter_by_smells)
40
+ @smell_types = Smells::SmellRepository.eligible_smell_types(filter_by_smells)
36
41
 
37
42
  run
38
43
  end
39
44
 
45
+ # FIXME: Should be named "origin"
40
46
  #
41
47
  # @return [String] description of the source being analysed
42
48
  #
49
+ # @public
43
50
  def description
44
- @description ||= source.description
51
+ @description ||= source.origin
45
52
  end
46
53
 
47
54
  #
48
55
  # @return [Array<SmellWarning>] the smells found in the source
49
56
  #
57
+ # @public
50
58
  def smells
51
59
  @smells ||= collector.warnings
52
60
  end
@@ -54,6 +62,7 @@ module Reek
54
62
  #
55
63
  # @return [Integer] the number of smells found in the source
56
64
  #
65
+ # @public
57
66
  def smells_count
58
67
  smells.length
59
68
  end
@@ -61,6 +70,7 @@ module Reek
61
70
  #
62
71
  # @return [Boolean] true if and only if there are code smells in the source.
63
72
  #
73
+ # @public
64
74
  def smelly?
65
75
  !smells.empty?
66
76
  end
@@ -70,22 +80,12 @@ module Reek
70
80
  private_attr_reader :configuration, :collector, :smell_types, :source
71
81
 
72
82
  def run
73
- smell_repository = Smells::SmellRepository.new(source_description: description,
74
- smell_types: smell_types,
75
- configuration: configuration)
83
+ smell_repository = Smells::SmellRepository.new(
84
+ smell_types: smell_types,
85
+ configuration: configuration.directive_for(description))
76
86
  syntax_tree = source.syntax_tree
77
87
  TreeWalker.new(smell_repository, syntax_tree).walk if syntax_tree
78
88
  smell_repository.report_on(collector)
79
89
  end
80
-
81
- def eligible_smell_types(filter_by_smells = [])
82
- if filter_by_smells.any?
83
- Smells::SmellRepository.smell_types.select do |klass|
84
- filter_by_smells.include? klass.smell_type
85
- end
86
- else
87
- Smells::SmellRepository.smell_types
88
- end
89
- end
90
90
  end
91
91
  end
@@ -12,6 +12,7 @@ module Reek
12
12
  # (Classes here will be configured via the Rakefile, and therefore will
13
13
  # possess a :reek:attribute or two.)
14
14
  #
15
+ # @public
15
16
  module Rake
16
17
  # A Rake task that runs reek on a set of source files.
17
18
  #
@@ -33,32 +34,43 @@ module Reek
33
34
  # rake reek REEK_SRC=just_one_file.rb # checks a single source file
34
35
  # rake reek REEK_OPTS=-s # sorts the report by smell
35
36
  #
37
+ # @public
38
+ #
39
+ # :reek:TooManyInstanceVariables: { max_instance_variables: 6 }
40
+ # :reek:Attribute
36
41
  class Task < ::Rake::TaskLib
37
42
  # Name of reek task. Defaults to :reek.
43
+ # @public
38
44
  attr_writer :name
39
45
 
40
46
  # Path to reek's config file.
41
47
  # Setting the REEK_CFG environment variable overrides this.
48
+ # @public
42
49
  attr_accessor :config_file
43
50
 
44
51
  # Glob pattern to match source files.
45
52
  # Setting the REEK_SRC environment variable overrides this.
46
53
  # Defaults to 'lib/**/*.rb'.
54
+ # @public
47
55
  attr_reader :source_files
48
56
 
49
57
  # String containing commandline options to be passed to Reek.
50
58
  # Setting the REEK_OPTS environment variable overrides this value.
51
59
  # Defaults to ''.
60
+ # @public
52
61
  attr_accessor :reek_opts
53
62
 
54
63
  # Whether or not to fail Rake when an error occurs (typically when smells are found).
55
64
  # Defaults to true.
65
+ # @public
56
66
  attr_writer :fail_on_error
57
67
 
58
68
  # Use verbose output. If this is set to true, the task will print
59
69
  # the reek command to stdout. Defaults to false.
70
+ # @public
60
71
  attr_writer :verbose
61
72
 
73
+ # @public
62
74
  def initialize(name = :reek)
63
75
  @config_file = ENV['REEK_CFG']
64
76
  @name = name
@@ -71,6 +83,7 @@ module Reek
71
83
  define_task
72
84
  end
73
85
 
86
+ # @public
74
87
  def source_files=(files)
75
88
  raise ArgumentError, no_string_given_for_file_list_warning unless files.is_a?(String)
76
89
  @source_files = FileList[files]
@@ -101,6 +114,7 @@ module Reek
101
114
  reject(&:empty?)
102
115
  end
103
116
 
117
+ # :reek:UtilityFunction
104
118
  def sys_call_failed?
105
119
  !$CHILD_STATUS.success?
106
120
  end
data/lib/reek/report.rb CHANGED
@@ -7,7 +7,6 @@ module Reek
7
7
  module Report
8
8
  module_function
9
9
 
10
- # @api private
11
10
  REPORT_CLASSES = {
12
11
  yaml: YAMLReport,
13
12
  json: JSONReport,
@@ -16,19 +15,16 @@ module Reek
16
15
  text: TextReport
17
16
  }
18
17
 
19
- # @api private
20
18
  LOCATION_FORMATTERS = {
21
19
  single_line: SingleLineLocationFormatter,
22
20
  plain: BlankLocationFormatter,
23
21
  numbers: DefaultLocationFormatter
24
22
  }
25
23
 
26
- # @api private
27
24
  HEADING_FORMATTERS = {
28
25
  verbose: HeadingFormatter::Verbose,
29
26
  quiet: HeadingFormatter::Quiet }
30
27
 
31
- # @api private
32
28
  WARNING_FORMATTER_CLASSES = {
33
29
  wiki_links: WikiLinkWarningFormatter,
34
30
  simple: SimpleWarningFormatter
@@ -40,28 +36,24 @@ module Reek
40
36
  #
41
37
  # @return The mapped report class
42
38
  #
43
- # @api private
44
39
  def report_class(report_format)
45
40
  REPORT_CLASSES.fetch(report_format) do
46
41
  raise "Unknown report format: #{report_format}"
47
42
  end
48
43
  end
49
44
 
50
- # @api private
51
45
  def location_formatter(location_format)
52
46
  LOCATION_FORMATTERS.fetch(location_format) do
53
47
  raise "Unknown location format: #{location_format}"
54
48
  end
55
49
  end
56
50
 
57
- # @api private
58
51
  def heading_formatter(heading_format)
59
52
  HEADING_FORMATTERS.fetch(heading_format) do
60
53
  raise "Unknown heading format: #{heading_format}"
61
54
  end
62
55
  end
63
56
 
64
- # @api private
65
57
  def warning_formatter_class(warning_format)
66
58
  WARNING_FORMATTER_CLASSES.fetch(warning_format) do
67
59
  raise "Unknown warning format: #{warning_format}"
@@ -8,7 +8,6 @@ module Reek
8
8
  # Formatting of the individual warnings is handled by the
9
9
  # passed-in warning formatter.
10
10
  #
11
- # @api private
12
11
  module Formatter
13
12
  def self.format_list(warnings, formatter: SimpleWarningFormatter.new)
14
13
  warnings.map do |warning|
@@ -29,24 +28,20 @@ module Reek
29
28
  # Basic formatter that just shows a simple message for each warning,
30
29
  # prepended with the result of the passed-in location formatter.
31
30
  #
32
- # @api private
33
31
  class SimpleWarningFormatter
34
32
  def initialize(location_formatter: BlankLocationFormatter)
35
33
  @location_formatter = location_formatter
36
34
  end
37
35
 
38
36
  def format(warning)
39
- "#{location_formatter.format(warning)}#{base_format(warning)}"
37
+ "#{location_formatter.format(warning)}#{warning.base_message}"
40
38
  end
41
39
 
42
- private
43
-
44
- def base_format(warning)
45
- "#{warning.context} #{warning.message} (#{warning.smell_type})"
40
+ # :reek:UtilityFunction
41
+ def format_hash(warning)
42
+ warning.yaml_hash
46
43
  end
47
44
 
48
- private
49
-
50
45
  private_attr_reader :location_formatter
51
46
  end
52
47
 
@@ -54,19 +49,25 @@ module Reek
54
49
  # Formatter that adds a link to the wiki to the basic message from
55
50
  # SimpleWarningFormatter.
56
51
  #
57
- # @api private
58
52
  class WikiLinkWarningFormatter < SimpleWarningFormatter
59
53
  BASE_URL_FOR_HELP_LINK = 'https://github.com/troessner/reek/blob/master/docs/'
60
54
 
61
55
  def format(warning)
62
56
  "#{super} " \
63
- "[#{explanatory_link(warning)}.md]"
57
+ "[#{explanatory_link(warning)}]"
64
58
  end
65
59
 
60
+ def format_hash(warning)
61
+ super(warning).merge('wiki_link' => explanatory_link(warning))
62
+ end
63
+
64
+ private
65
+
66
66
  def explanatory_link(warning)
67
- "#{BASE_URL_FOR_HELP_LINK}#{class_name_to_param(warning.smell_type)}"
67
+ "#{BASE_URL_FOR_HELP_LINK}#{class_name_to_param(warning.smell_type)}.md"
68
68
  end
69
69
 
70
+ # :reek:UtilityFunction
70
71
  def class_name_to_param(name)
71
72
  name.split(/(?=[A-Z])/).join('-')
72
73
  end
@@ -1,6 +1,5 @@
1
1
  module Reek
2
2
  module Report
3
- # @api private
4
3
  module HeadingFormatter
5
4
  #
6
5
  # Base class for heading formatters.
@@ -14,6 +13,7 @@ module Reek
14
13
  @report_formatter = report_formatter
15
14
  end
16
15
 
16
+ # :reek:UtilityFunction
17
17
  def show_header?(_examiner)
18
18
  raise NotImplementedError
19
19
  end
@@ -40,6 +40,7 @@ module Reek
40
40
  # Lists only smelly examiners
41
41
  #
42
42
  class Quiet < Base
43
+ # :reek:UtilityFunction
43
44
  def show_header?(examiner)
44
45
  examiner.smelly?
45
46
  end
@@ -3,7 +3,6 @@ module Reek
3
3
  #
4
4
  # Formats the location of a warning as an empty string.
5
5
  #
6
- # @api private
7
6
  module BlankLocationFormatter
8
7
  def self.format(_warning)
9
8
  ''
@@ -13,7 +12,6 @@ module Reek
13
12
  #
14
13
  # Formats the location of a warning as an array of line numbers.
15
14
  #
16
- # @api private
17
15
  module DefaultLocationFormatter
18
16
  def self.format(warning)
19
17
  "#{warning.lines.inspect}:"
@@ -25,7 +23,6 @@ module Reek
25
23
  # and line number. In this format, it is not possible to show more than
26
24
  # one line number, so the first number is displayed.
27
25
  #
28
- # @api private
29
26
  module SingleLineLocationFormatter
30
27
  def self.format(warning)
31
28
  "#{warning.source}:#{warning.lines.first}: "
@@ -5,17 +5,23 @@ require_relative 'formatter'
5
5
  require_relative 'heading_formatter'
6
6
 
7
7
  module Reek
8
+ # @public
8
9
  module Report
9
10
  #
10
11
  # A report that contains the smells and smell counts following source code analysis.
11
12
  #
12
13
  # @abstract Subclass and override {#show} to create a concrete report class.
14
+ #
15
+ # @public
16
+ #
17
+ # :reek:TooManyInstanceVariables: { max_instance_variables: 6 }
13
18
  class Base
14
- # @api private
15
19
  NO_WARNINGS_COLOR = :green
16
- # @api private
17
20
  WARNINGS_COLOR = :red
18
21
 
22
+ # @public
23
+ #
24
+ # :reek:BooleanParameter
19
25
  def initialize(heading_formatter: HeadingFormatter::Quiet,
20
26
  report_formatter: Formatter, sort_by_issue_count: false,
21
27
  warning_formatter: SimpleWarningFormatter.new)
@@ -25,12 +31,16 @@ module Reek
25
31
  @sort_by_issue_count = sort_by_issue_count
26
32
  @total_smell_count = 0
27
33
  @warning_formatter = warning_formatter
34
+
35
+ # TODO: Only used in TextReport and YAMLReport
28
36
  end
29
37
 
30
38
  # Add Examiner to report on. The report will output results for all
31
39
  # added examiners.
32
40
  #
33
41
  # @param [Reek::Examiner] examiner object to report on
42
+ #
43
+ # @public
34
44
  def add_examiner(examiner)
35
45
  self.total_smell_count += examiner.smells_count
36
46
  examiners << examiner
@@ -38,16 +48,16 @@ module Reek
38
48
  end
39
49
 
40
50
  # Render the report results on STDOUT
51
+ #
52
+ # @public
41
53
  def show
42
54
  raise NotImplementedError
43
55
  end
44
56
 
45
- # @api private
46
57
  def smells?
47
58
  total_smell_count > 0
48
59
  end
49
60
 
50
- # @api private
51
61
  def smells
52
62
  examiners.map(&:smells).flatten
53
63
  end
@@ -65,7 +75,9 @@ module Reek
65
75
  #
66
76
  # Generates a sorted, text summary of smells in examiners
67
77
  #
78
+ # @public
68
79
  class TextReport < Base
80
+ # @public
69
81
  def show
70
82
  sort_examiners if smells?
71
83
  display_summary
@@ -103,39 +115,42 @@ module Reek
103
115
 
104
116
  def total_smell_count_message
105
117
  colour = smells? ? WARNINGS_COLOR : NO_WARNINGS_COLOR
106
- s = total_smell_count == 1 ? '' : 's'
107
- Rainbow("#{total_smell_count} total warning#{s}\n").color(colour)
118
+ Rainbow("#{total_smell_count} total warning#{total_smell_count == 1 ? '' : 's'}\n").color(colour)
108
119
  end
109
120
  end
110
121
 
111
122
  #
112
123
  # Displays a list of smells in YAML format
113
124
  # YAML with empty array for 0 smells
125
+ #
126
+ # @public
114
127
  class YAMLReport < Base
115
- def show
116
- print smells.map(&:yaml_hash).to_yaml
128
+ # @public
129
+ def show(out = $stdout)
130
+ out.print smells.map { |smell| warning_formatter.format_hash(smell) }.to_yaml
117
131
  end
118
132
  end
119
133
 
120
134
  #
121
135
  # Displays a list of smells in JSON format
122
136
  # JSON with empty array for 0 smells
137
+ #
138
+ # @public
123
139
  class JSONReport < Base
124
- def show
125
- print ::JSON.generate(
126
- smells.map do |smell|
127
- smell.yaml_hash(warning_formatter)
128
- end
129
- )
140
+ # @public
141
+ def show(out = $stdout)
142
+ out.print ::JSON.generate smells.map { |smell| warning_formatter.format_hash(smell) }
130
143
  end
131
144
  end
132
145
 
133
146
  #
134
147
  # Saves the report as a HTML file
135
148
  #
149
+ # @public
136
150
  class HTMLReport < Base
137
151
  require 'erb'
138
152
 
153
+ # @public
139
154
  def show(target_path: Pathname.new('reek.html'))
140
155
  template_path = Pathname.new("#{__dir__}/html_report.html.erb")
141
156
  File.write target_path, ERB.new(template_path.read).result(binding)
@@ -146,9 +161,11 @@ module Reek
146
161
  #
147
162
  # Generates a list of smells in XML format
148
163
  #
164
+ # @public
149
165
  class XMLReport < Base
150
166
  require 'rexml/document'
151
167
 
168
+ # @public
152
169
  def show
153
170
  document.write output: $stdout, indent: 2
154
171
  $stdout.puts
@@ -170,6 +187,8 @@ module Reek
170
187
  end
171
188
  end
172
189
 
190
+ # :reek:FeatureEnvy
191
+ # :reek:NestedIterators: { max_allowed_nesting: 2 }
173
192
  def file(name, smells)
174
193
  REXML::Element.new('file').tap do |file|
175
194
  file.add_attribute 'name', File.realpath(name)
@@ -181,6 +200,7 @@ module Reek
181
200
  end
182
201
  end
183
202
 
203
+ # :reek:UtilityFunction
184
204
  def error(smell, line)
185
205
  REXML::Element.new('error').tap do |error|
186
206
  error.add_attributes 'column' => 0,