reek 4.8.2 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (213) hide show
  1. checksums.yaml +5 -5
  2. data/{samples/configuration/more_than_one_configuration_file/regular.reek → .reek.yml} +0 -0
  3. data/.rubocop.yml +17 -3
  4. data/.simplecov +1 -0
  5. data/.travis.yml +0 -5
  6. data/.yardopts +1 -1
  7. data/CHANGELOG.md +28 -0
  8. data/Gemfile +1 -1
  9. data/README.md +113 -98
  10. data/Rakefile +16 -3
  11. data/bin/reek +1 -3
  12. data/docs/API.md +2 -9
  13. data/docs/Basic-Smell-Options.md +51 -11
  14. data/docs/Code-Smells.md +1 -1
  15. data/docs/Command-Line-Options.md +14 -4
  16. data/docs/Duplicate-Method-Call.md +49 -1
  17. data/docs/Feature-Envy.md +44 -0
  18. data/docs/How-To-Write-New-Detectors.md +2 -3
  19. data/docs/{Prima-Donna-Method.md → Missing-Safe-Method.md} +11 -9
  20. data/docs/Rake-Task.md +1 -1
  21. data/docs/Reek-4-to-Reek-5-migration.md +193 -0
  22. data/docs/Reek-Driven-Development.md +1 -1
  23. data/docs/Uncommunicative-Method-Name.md +43 -4
  24. data/docs/Uncommunicative-Module-Name.md +48 -6
  25. data/docs/Uncommunicative-Parameter-Name.md +42 -4
  26. data/docs/Uncommunicative-Variable-Name.md +73 -2
  27. data/docs/Unused-Private-Method.md +1 -1
  28. data/docs/defaults.reek.yml +129 -0
  29. data/docs/yard_plugin.rb +1 -0
  30. data/features/command_line_interface/options.feature +46 -4
  31. data/features/command_line_interface/stdin.feature +27 -5
  32. data/features/configuration_files/accept_setting.feature +39 -22
  33. data/features/configuration_files/directory_specific_directives.feature +58 -53
  34. data/features/configuration_files/exclude_directives.feature +8 -7
  35. data/features/configuration_files/masking_smells.feature +35 -6
  36. data/features/configuration_files/mix_accept_reject_setting.feature +24 -21
  37. data/features/configuration_files/reject_setting.feature +45 -34
  38. data/features/configuration_files/schema_validation.feature +59 -0
  39. data/features/configuration_files/unused_private_method.feature +14 -12
  40. data/features/configuration_loading.feature +50 -7
  41. data/features/rake_task/rake_task.feature +5 -5
  42. data/features/reports/json.feature +4 -1
  43. data/features/reports/reports.feature +12 -12
  44. data/features/reports/yaml.feature +3 -0
  45. data/features/rspec_matcher.feature +9 -1
  46. data/features/step_definitions/reek_steps.rb +4 -0
  47. data/features/step_definitions/sample_file_steps.rb +9 -4
  48. data/features/support/env.rb +2 -2
  49. data/features/todo_list.feature +16 -13
  50. data/lib/reek/ast/node.rb +3 -6
  51. data/lib/reek/ast/object_refs.rb +1 -1
  52. data/lib/reek/ast/sexp_extensions/if.rb +1 -1
  53. data/lib/reek/ast/sexp_extensions/methods.rb +1 -1
  54. data/lib/reek/cli/application.rb +4 -3
  55. data/lib/reek/cli/command/report_command.rb +1 -2
  56. data/lib/reek/cli/command/todo_list_command.rb +4 -2
  57. data/lib/reek/cli/options.rb +27 -13
  58. data/lib/reek/cli/silencer.rb +14 -3
  59. data/lib/reek/code_comment.rb +14 -16
  60. data/lib/reek/configuration/app_configuration.rb +32 -28
  61. data/lib/reek/configuration/configuration_converter.rb +110 -0
  62. data/lib/reek/configuration/configuration_file_finder.rb +15 -40
  63. data/lib/reek/configuration/configuration_validator.rb +12 -23
  64. data/lib/reek/configuration/default_directive.rb +17 -3
  65. data/lib/reek/configuration/directory_directives.rb +17 -11
  66. data/lib/reek/configuration/excluded_paths.rb +1 -1
  67. data/lib/reek/configuration/rake_task_converter.rb +29 -0
  68. data/lib/reek/configuration/schema.yml +210 -0
  69. data/lib/reek/configuration/schema_validator.rb +38 -0
  70. data/lib/reek/context/attribute_context.rb +1 -1
  71. data/lib/reek/context/code_context.rb +4 -4
  72. data/lib/reek/context/method_context.rb +2 -2
  73. data/lib/reek/context/module_context.rb +1 -1
  74. data/lib/reek/context_builder.rb +9 -9
  75. data/lib/reek/detector_repository.rb +6 -0
  76. data/lib/reek/documentation_link.rb +2 -2
  77. data/lib/reek/errors/bad_detector_configuration_key_in_comment_error.rb +1 -1
  78. data/lib/reek/errors/bad_detector_in_comment_error.rb +1 -1
  79. data/lib/reek/errors/config_file_error.rb +11 -0
  80. data/lib/reek/errors/encoding_error.rb +2 -2
  81. data/lib/reek/errors/garbage_detector_configuration_in_comment_error.rb +1 -1
  82. data/lib/reek/errors/incomprehensible_source_error.rb +2 -2
  83. data/lib/reek/errors/syntax_error.rb +41 -0
  84. data/lib/reek/examiner.rb +9 -19
  85. data/lib/reek/rake/task.rb +3 -3
  86. data/lib/reek/report.rb +15 -10
  87. data/lib/reek/report/base_report.rb +8 -12
  88. data/lib/reek/report/code_climate/code_climate_configuration.yml +5 -9
  89. data/lib/reek/report/documentation_link_warning_formatter.rb +17 -0
  90. data/lib/reek/report/heading_formatter.rb +54 -0
  91. data/lib/reek/report/json_report.rb +1 -1
  92. data/lib/reek/report/location_formatter.rb +40 -0
  93. data/lib/reek/report/progress_formatter.rb +79 -0
  94. data/lib/reek/report/simple_warning_formatter.rb +34 -0
  95. data/lib/reek/report/text_report.rb +1 -2
  96. data/lib/reek/report/xml_report.rb +3 -3
  97. data/lib/reek/report/yaml_report.rb +1 -1
  98. data/lib/reek/smell_configuration.rb +2 -2
  99. data/lib/reek/smell_detectors.rb +1 -2
  100. data/lib/reek/smell_detectors/attribute.rb +0 -1
  101. data/lib/reek/smell_detectors/base_detector.rb +8 -11
  102. data/lib/reek/smell_detectors/boolean_parameter.rb +0 -1
  103. data/lib/reek/smell_detectors/class_variable.rb +0 -1
  104. data/lib/reek/smell_detectors/control_parameter.rb +17 -32
  105. data/lib/reek/smell_detectors/data_clump.rb +3 -4
  106. data/lib/reek/smell_detectors/duplicate_method_call.rb +5 -6
  107. data/lib/reek/smell_detectors/feature_envy.rb +0 -1
  108. data/lib/reek/smell_detectors/instance_variable_assumption.rb +0 -1
  109. data/lib/reek/smell_detectors/irresponsible_module.rb +0 -1
  110. data/lib/reek/smell_detectors/long_parameter_list.rb +1 -2
  111. data/lib/reek/smell_detectors/long_yield_list.rb +2 -3
  112. data/lib/reek/smell_detectors/manual_dispatch.rb +2 -2
  113. data/lib/reek/smell_detectors/{prima_donna_method.rb → missing_safe_method.rb} +6 -7
  114. data/lib/reek/smell_detectors/module_initialize.rb +0 -1
  115. data/lib/reek/smell_detectors/nested_iterators.rb +4 -5
  116. data/lib/reek/smell_detectors/nil_check.rb +0 -1
  117. data/lib/reek/smell_detectors/repeated_conditional.rb +3 -4
  118. data/lib/reek/smell_detectors/subclassed_from_core_class.rb +0 -1
  119. data/lib/reek/smell_detectors/too_many_constants.rb +1 -2
  120. data/lib/reek/smell_detectors/too_many_instance_variables.rb +1 -2
  121. data/lib/reek/smell_detectors/too_many_methods.rb +1 -2
  122. data/lib/reek/smell_detectors/too_many_statements.rb +1 -2
  123. data/lib/reek/smell_detectors/uncommunicative_method_name.rb +2 -3
  124. data/lib/reek/smell_detectors/uncommunicative_module_name.rb +2 -3
  125. data/lib/reek/smell_detectors/uncommunicative_parameter_name.rb +2 -3
  126. data/lib/reek/smell_detectors/uncommunicative_variable_name.rb +4 -5
  127. data/lib/reek/smell_detectors/unused_parameters.rb +0 -1
  128. data/lib/reek/smell_detectors/unused_private_method.rb +0 -1
  129. data/lib/reek/smell_detectors/utility_function.rb +1 -2
  130. data/lib/reek/smell_warning.rb +10 -8
  131. data/lib/reek/source/source_code.rb +40 -55
  132. data/lib/reek/source/source_locator.rb +7 -7
  133. data/lib/reek/spec.rb +6 -6
  134. data/lib/reek/spec/should_reek.rb +2 -2
  135. data/lib/reek/spec/should_reek_of.rb +9 -16
  136. data/lib/reek/spec/should_reek_only_of.rb +4 -4
  137. data/lib/reek/tree_dresser.rb +5 -5
  138. data/lib/reek/version.rb +1 -1
  139. data/reek.gemspec +3 -3
  140. data/samples/checkstyle.xml +1 -1
  141. data/samples/{clean.rb → clean_source/clean.rb} +0 -0
  142. data/samples/configuration/accepts_rejects_and_excludes_for_detectors.reek.yml +29 -0
  143. data/samples/configuration/accepts_rejects_and_excludes_for_directory_directives.reek.yml +30 -0
  144. data/samples/configuration/full_configuration.reek +8 -4
  145. data/samples/configuration/full_mask.reek +5 -4
  146. data/samples/{exceptions.reek → configuration/home/home.reek.yml} +0 -0
  147. data/samples/configuration/partial_mask.reek +3 -2
  148. data/samples/configuration/regular_configuration/.reek.yml +4 -0
  149. data/samples/configuration/{more_than_one_configuration_file/todo.reek → regular_configuration/empty_sub_directory/.gitignore} +0 -0
  150. data/samples/{configuration/single_configuration_file/.reek → no_config_file/.keep} +0 -0
  151. data/samples/paths.rb +5 -4
  152. data/samples/{inline.rb → smelly_source/inline.rb} +0 -0
  153. data/samples/{optparse.rb → smelly_source/optparse.rb} +0 -0
  154. data/samples/{redcloth.rb → smelly_source/redcloth.rb} +0 -0
  155. data/samples/{smelly.rb → smelly_source/smelly.rb} +0 -0
  156. data/samples/source_with_hidden_directories/.hidden/hidden.rb +1 -0
  157. data/samples/source_with_hidden_directories/not_hidden.rb +1 -0
  158. data/samples/{source_with_hidden_directories/uncommunicative_parameter_name.rb → source_with_non_ruby_files/ruby.rb} +0 -0
  159. data/spec/reek/ast/node_spec.rb +5 -5
  160. data/spec/reek/cli/application_spec.rb +18 -4
  161. data/spec/reek/cli/command/todo_list_command_spec.rb +4 -2
  162. data/spec/reek/cli/silencer_spec.rb +28 -0
  163. data/spec/reek/code_comment_spec.rb +0 -7
  164. data/spec/reek/configuration/app_configuration_spec.rb +44 -31
  165. data/spec/reek/configuration/configuration_file_finder_spec.rb +133 -49
  166. data/spec/reek/configuration/default_directive_spec.rb +1 -1
  167. data/spec/reek/configuration/directory_directives_spec.rb +3 -4
  168. data/spec/reek/configuration/excluded_paths_spec.rb +5 -5
  169. data/spec/reek/configuration/rake_task_converter_spec.rb +33 -0
  170. data/spec/reek/configuration/schema_validator_spec.rb +165 -0
  171. data/spec/reek/context/code_context_spec.rb +1 -1
  172. data/spec/reek/examiner_spec.rb +28 -1
  173. data/spec/reek/report/json_report_spec.rb +13 -46
  174. data/spec/reek/report/{formatter/location_formatter_spec.rb → location_formatter_spec.rb} +5 -5
  175. data/spec/reek/report/{formatter/progress_formatter_spec.rb → progress_formatter_spec.rb} +4 -4
  176. data/spec/reek/report/text_report_spec.rb +4 -4
  177. data/spec/reek/report/xml_report_spec.rb +1 -1
  178. data/spec/reek/report/yaml_report_spec.rb +9 -38
  179. data/spec/reek/report_spec.rb +3 -3
  180. data/spec/reek/smell_detectors/feature_envy_spec.rb +2 -2
  181. data/spec/reek/smell_detectors/{prima_donna_method_spec.rb → missing_safe_method_spec.rb} +9 -9
  182. data/spec/reek/smell_detectors/too_many_constants_spec.rb +3 -3
  183. data/spec/reek/smell_detectors/too_many_instance_variables_spec.rb +1 -1
  184. data/spec/reek/smell_detectors/uncommunicative_method_name_spec.rb +6 -6
  185. data/spec/reek/smell_detectors/uncommunicative_module_name_spec.rb +6 -4
  186. data/spec/reek/smell_detectors/uncommunicative_parameter_name_spec.rb +6 -4
  187. data/spec/reek/smell_detectors/uncommunicative_variable_name_spec.rb +6 -6
  188. data/spec/reek/smell_detectors/unused_private_method_spec.rb +1 -1
  189. data/spec/reek/smell_warning_spec.rb +4 -0
  190. data/spec/reek/source/source_code_spec.rb +16 -22
  191. data/spec/reek/source/source_locator_spec.rb +11 -11
  192. data/spec/reek/spec/should_reek_of_spec.rb +0 -4
  193. data/spec/reek/spec/should_reek_only_of_spec.rb +2 -2
  194. data/spec/reek/spec/should_reek_spec.rb +1 -1
  195. data/spec/reek/tree_dresser_spec.rb +2 -6
  196. data/spec/spec_helper.rb +3 -5
  197. data/tasks/configuration.rake +8 -5
  198. metadata +56 -35
  199. data/defaults.reek +0 -131
  200. data/features/configuration_files/warn_about_multiple_configuration_files.feature +0 -44
  201. data/lib/reek/report/formatter.rb +0 -33
  202. data/lib/reek/report/formatter/heading_formatter.rb +0 -52
  203. data/lib/reek/report/formatter/location_formatter.rb +0 -42
  204. data/lib/reek/report/formatter/progress_formatter.rb +0 -81
  205. data/lib/reek/report/formatter/simple_warning_formatter.rb +0 -35
  206. data/lib/reek/report/formatter/wiki_link_warning_formatter.rb +0 -23
  207. data/lib/reek/smell_detectors/syntax.rb +0 -37
  208. data/samples/configuration/non_public_modifiers_mask.reek +0 -3
  209. data/samples/smelly_with_inline_mask.rb +0 -8
  210. data/samples/smelly_with_modifiers.rb +0 -12
  211. data/samples/source_with_hidden_directories/.hidden/uncommunicative_method_name.rb +0 -5
  212. data/samples/source_with_non_ruby_files/uncommunicative_parameter_name.rb +0 -6
  213. data/spec/reek/smell_detectors/syntax_spec.rb +0 -17
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base_error'
4
+
5
+ module Reek
6
+ module Errors
7
+ # Gets raised when Reek is unable to process the source due to bad config file
8
+ class ConfigFileError < BaseError
9
+ end
10
+ end
11
+ end
@@ -6,9 +6,9 @@ module Reek
6
6
  module Errors
7
7
  # Gets raised when Reek is unable to process the source due to an EncodingError
8
8
  class EncodingError < BaseError
9
- TEMPLATE = "Source '%<source>s' cannot be processed by Reek due to an encoding error in the source file.".freeze
9
+ TEMPLATE = "Source '%<source>s' cannot be processed by Reek due to an encoding error in the source file."
10
10
 
11
- LONG_TEMPLATE = <<-MESSAGE.freeze
11
+ LONG_TEMPLATE = <<-MESSAGE
12
12
  !!!
13
13
  %<message>s
14
14
 
@@ -8,7 +8,7 @@ module Reek
8
8
  # Gets raised when trying to use a configuration for a detector
9
9
  # that can't be parsed into a hash.
10
10
  class GarbageDetectorConfigurationInCommentError < BaseError
11
- BAD_DETECTOR_CONFIGURATION_MESSAGE = <<-MESSAGE.freeze
11
+ BAD_DETECTOR_CONFIGURATION_MESSAGE = <<-MESSAGE
12
12
 
13
13
  Error: You are trying to configure the smell detector '%<detector>s'.
14
14
  Unfortunately we cannot parse the configuration you have given.
@@ -6,9 +6,9 @@ module Reek
6
6
  module Errors
7
7
  # Gets raised when Reek is unable to process the source
8
8
  class IncomprehensibleSourceError < BaseError
9
- TEMPLATE = 'Source %<source>s cannot be processed by Reek.'.freeze
9
+ TEMPLATE = 'Source %<source>s cannot be processed by Reek.'
10
10
 
11
- LONG_TEMPLATE = <<-MESSAGE.freeze
11
+ LONG_TEMPLATE = <<-MESSAGE
12
12
  !!!
13
13
  %<message>s
14
14
 
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base_error'
4
+
5
+ module Reek
6
+ module Errors
7
+ # Gets raised when Reek is unable to process the source due to a SyntaxError
8
+ class SyntaxError < BaseError
9
+ TEMPLATE = "Source '%<source>s' cannot be processed by Reek due to a syntax error in the source file."
10
+
11
+ LONG_TEMPLATE = <<-MESSAGE
12
+ !!!
13
+ %<message>s
14
+
15
+ This is a problem that is outside of Reek's scope and should be fixed by you, the
16
+ user, in order for Reek being able to continue.
17
+
18
+ Exception message:
19
+
20
+ %<exception>s
21
+
22
+ Original backtrace:
23
+
24
+ %<original>s
25
+
26
+ !!!
27
+ MESSAGE
28
+
29
+ def initialize(origin:)
30
+ super format(TEMPLATE, source: origin)
31
+ end
32
+
33
+ def long_message
34
+ format(LONG_TEMPLATE,
35
+ message: message,
36
+ exception: cause.inspect,
37
+ original: cause.backtrace.join("\n\t"))
38
+ end
39
+ end
40
+ end
41
+ end
data/lib/reek/examiner.rb CHANGED
@@ -4,6 +4,7 @@ require_relative 'context_builder'
4
4
  require_relative 'detector_repository'
5
5
  require_relative 'errors/incomprehensible_source_error'
6
6
  require_relative 'errors/encoding_error'
7
+ require_relative 'errors/syntax_error'
7
8
  require_relative 'source/source_code'
8
9
 
9
10
  module Reek
@@ -11,6 +12,7 @@ module Reek
11
12
  # Applies all available smell detectors to a source.
12
13
  #
13
14
  # @public
15
+ # @quality :reek:TooManyInstanceVariables { max_instance_variables: 5 }
14
16
  class Examiner
15
17
  # Handles no errors
16
18
  class NullHandler
@@ -39,26 +41,17 @@ module Reek
39
41
  detector_repository_class: DetectorRepository,
40
42
  error_handler: NullHandler.new)
41
43
  @source = Source::SourceCode.from(source)
44
+ @origin = @source.origin
42
45
  @smell_types = detector_repository_class.eligible_smell_types(filter_by_smells)
43
46
  @detector_repository = detector_repository_class.new(smell_types: @smell_types,
44
- configuration: configuration.directive_for(description))
47
+ configuration: configuration.directive_for(@origin))
45
48
  @error_handler = error_handler
46
49
  end
47
50
 
48
51
  # @return [String] origin of the source being analysed
49
52
  #
50
53
  # @public
51
- def origin
52
- @origin ||= source.origin
53
- end
54
-
55
- # @return [String] description of the source being analysed
56
- #
57
- # @public
58
- # @deprecated Use origin
59
- def description
60
- origin
61
- end
54
+ attr_reader :origin
62
55
 
63
56
  #
64
57
  # @return [Array<SmellWarning>] the smells found in the source
@@ -98,20 +91,22 @@ module Reek
98
91
  #
99
92
  def run
100
93
  wrap_exceptions do
101
- examine_tree || report_syntax_errors
94
+ examine_tree
102
95
  end
103
96
  rescue StandardError => exception
104
97
  raise unless @error_handler.handle exception
105
98
  []
106
99
  end
107
100
 
108
- # :reek:TooManyStatements { max_statements: 6 }
101
+ # @quality :reek:TooManyStatements { max_statements: 6 }
109
102
  def wrap_exceptions
110
103
  yield
111
104
  rescue Errors::BaseError
112
105
  raise
113
106
  rescue EncodingError
114
107
  raise Errors::EncodingError, origin: origin
108
+ rescue Parser::SyntaxError
109
+ raise Errors::SyntaxError, origin: origin
115
110
  rescue StandardError
116
111
  raise Errors::IncomprehensibleSourceError, origin: origin
117
112
  end
@@ -121,14 +116,9 @@ module Reek
121
116
  end
122
117
 
123
118
  def examine_tree
124
- return unless syntax_tree
125
119
  ContextBuilder.new(syntax_tree).context_tree.flat_map do |element|
126
120
  detector_repository.examine(element)
127
121
  end
128
122
  end
129
-
130
- def report_syntax_errors
131
- SmellDetectors::Syntax.smells_from_source(source)
132
- end
133
123
  end
134
124
  end
@@ -33,8 +33,8 @@ module Reek
33
33
  #
34
34
  # @public
35
35
  #
36
- # :reek:TooManyInstanceVariables: { max_instance_variables: 6 }
37
- # :reek:Attribute
36
+ # @quality :reek:TooManyInstanceVariables { max_instance_variables: 6 }
37
+ # @quality :reek:Attribute
38
38
  class Task < ::Rake::TaskLib
39
39
  # Name of Reek task. Defaults to :reek.
40
40
  # @public
@@ -114,7 +114,7 @@ module Reek
114
114
  reject(&:empty?)
115
115
  end
116
116
 
117
- # :reek:UtilityFunction
117
+ # @quality :reek:UtilityFunction
118
118
  def sys_call_failed?
119
119
  !$CHILD_STATUS.success?
120
120
  end
data/lib/reek/report.rb CHANGED
@@ -6,7 +6,12 @@ require_relative 'report/json_report'
6
6
  require_relative 'report/text_report'
7
7
  require_relative 'report/xml_report'
8
8
  require_relative 'report/yaml_report'
9
- require_relative 'report/formatter'
9
+
10
+ require_relative 'report/heading_formatter'
11
+ require_relative 'report/location_formatter'
12
+ require_relative 'report/progress_formatter'
13
+ require_relative 'report/simple_warning_formatter'
14
+ require_relative 'report/documentation_link_warning_formatter'
10
15
 
11
16
  module Reek
12
17
  # Reek reporting functionality.
@@ -21,24 +26,24 @@ module Reek
21
26
  }.freeze
22
27
 
23
28
  LOCATION_FORMATTERS = {
24
- single_line: Formatter::SingleLineLocationFormatter,
25
- plain: Formatter::BlankLocationFormatter,
26
- numbers: Formatter::DefaultLocationFormatter
29
+ single_line: SingleLineLocationFormatter,
30
+ plain: BlankLocationFormatter,
31
+ numbers: DefaultLocationFormatter
27
32
  }.freeze
28
33
 
29
34
  HEADING_FORMATTERS = {
30
- verbose: Formatter::VerboseHeadingFormatter,
31
- quiet: Formatter::QuietHeadingFormatter
35
+ verbose: VerboseHeadingFormatter,
36
+ quiet: QuietHeadingFormatter
32
37
  }.freeze
33
38
 
34
39
  PROGRESS_FORMATTERS = {
35
- dots: Formatter::ProgressFormatter::Dots,
36
- quiet: Formatter::ProgressFormatter::Quiet
40
+ dots: ProgressFormatter::Dots,
41
+ quiet: ProgressFormatter::Quiet
37
42
  }.freeze
38
43
 
39
44
  WARNING_FORMATTER_CLASSES = {
40
- wiki_links: Formatter::WikiLinkWarningFormatter,
41
- simple: Formatter::SimpleWarningFormatter
45
+ documentation_links: DocumentationLinkWarningFormatter,
46
+ simple: SimpleWarningFormatter
42
47
  }.freeze
43
48
 
44
49
  # Map report format symbol to a report class.
@@ -4,8 +4,6 @@ require 'json'
4
4
  require 'pathname'
5
5
  require 'rainbow'
6
6
 
7
- require_relative 'formatter'
8
-
9
7
  module Reek
10
8
  # @public
11
9
  module Report
@@ -16,22 +14,20 @@ module Reek
16
14
  #
17
15
  # @public
18
16
  #
19
- # :reek:TooManyInstanceVariables: { max_instance_variables: 7 }
17
+ # @quality :reek:TooManyInstanceVariables { max_instance_variables: 7 }
20
18
  class BaseReport
21
19
  NO_WARNINGS_COLOR = :green
22
20
  WARNINGS_COLOR = :red
23
21
 
24
22
  # @public
25
23
  #
26
- # :reek:BooleanParameter
27
- def initialize(heading_formatter: Formatter::QuietHeadingFormatter,
28
- report_formatter: Formatter,
24
+ # @quality :reek:BooleanParameter
25
+ def initialize(heading_formatter: QuietHeadingFormatter,
29
26
  sort_by_issue_count: false,
30
- warning_formatter: Formatter::SimpleWarningFormatter.new,
31
- progress_formatter: Formatter::ProgressFormatter::Quiet.new(0))
27
+ warning_formatter: SimpleWarningFormatter.new,
28
+ progress_formatter: ProgressFormatter::Quiet.new(0))
32
29
  @examiners = []
33
- @heading_formatter = heading_formatter.new(report_formatter)
34
- @report_formatter = report_formatter
30
+ @heading_formatter = heading_formatter.new
35
31
  @progress_formatter = progress_formatter
36
32
  @sort_by_issue_count = sort_by_issue_count
37
33
  @total_smell_count = 0
@@ -58,7 +54,7 @@ module Reek
58
54
  end
59
55
 
60
56
  def smells?
61
- total_smell_count > 0
57
+ total_smell_count.positive?
62
58
  end
63
59
 
64
60
  def smells
@@ -71,7 +67,7 @@ module Reek
71
67
 
72
68
  private
73
69
 
74
- attr_reader :examiners, :heading_formatter, :report_formatter,
70
+ attr_reader :examiners, :heading_formatter,
75
71
  :sort_by_issue_count, :warning_formatter, :progress_formatter
76
72
  end
77
73
  end
@@ -565,10 +565,10 @@ NilCheck:
565
565
  test.rb -- 1 warning:
566
566
  [3]:Klass#nil_checker performs a nil-check. (NilCheck)
567
567
  ```
568
- PrimaDonnaMethod:
568
+ MissingSafeMethod:
569
569
  remediation_points: 250_000
570
570
  content: |
571
- A candidate method for the `Prima Donna Method` smell are methods whose names end with an exclamation mark.
571
+ A candidate method for the `Missing Safe Method` smell are methods whose names end with an exclamation mark.
572
572
 
573
573
  An exclamation mark in method names means (the explanation below is taken from [here](http://dablog.rubypal.com/2007/8/15/bang-methods-or-danger-will-rubyist) ):
574
574
 
@@ -576,7 +576,7 @@ PrimaDonnaMethod:
576
576
  The ! in method names that end with ! means, “This method is dangerous”—or, more precisely, this method is the “dangerous” version of an otherwise equivalent method, with the same name minus the !. “Danger” is relative; the ! doesn’t mean anything at all unless the method name it’s in corresponds to a similar but bang-less method name.
577
577
  So, for example, gsub! is the dangerous version of gsub. exit! is the dangerous version of exit. flatten! is the dangerous version of flatten. And so forth.
578
578
 
579
- Such a method is called `Prima Donna Method` if and only if her non-bang version does not exist and this method is reported as a smell.
579
+ Such a method is called `Missing Safe Method` if and only if her non-bang version does not exist and this method is reported as a smell.
580
580
 
581
581
  ## Example
582
582
 
@@ -590,7 +590,7 @@ PrimaDonnaMethod:
590
590
  end
591
591
  ```
592
592
 
593
- Reek would report `bar!` as `prima donna method` smell but not `foo!`.
593
+ Reek would report `bar!` as `Missing Safe Method` smell but not `foo!`.
594
594
 
595
595
  Reek reports this smell only in a class context, not in a module context in order to allow perfectly legit code like this:
596
596
 
@@ -612,7 +612,7 @@ PrimaDonnaMethod:
612
612
  end
613
613
  ```
614
614
 
615
- In this example, Reek would not report the `prima donna method` smell for the method `foo` of the `Dangerous` module.
615
+ In this example, Reek would not report the `Missing Safe Method` smell for the method `foo` of the `Dangerous` module.
616
616
  RepeatedConditional:
617
617
  remediation_points: 400_000
618
618
  content: |
@@ -860,7 +860,3 @@ SubclassedFromCoreClass:
860
860
  you are gonna have a bad time.
861
861
 
862
862
  Source: http://words.steveklabnik.com/beware-subclassing-ruby-core-classes
863
- Syntax:
864
- remediation_points: 250_000
865
- content: |
866
- Check syntax errors.
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'simple_warning_formatter'
4
+
5
+ module Reek
6
+ module Report
7
+ #
8
+ # Formatter that adds a link to the docs to the basic message from
9
+ # SimpleWarningFormatter.
10
+ #
11
+ class DocumentationLinkWarningFormatter < SimpleWarningFormatter
12
+ def format(warning)
13
+ "#{super} [#{warning.explanatory_link}]"
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Reek
4
+ module Report
5
+ #
6
+ # Base class for heading formatters.
7
+ # Is responsible for formatting the heading emitted for each examiner
8
+ #
9
+ # @abstract Override {#show_header?} to implement a heading formatter.
10
+ class HeadingFormatterBase
11
+ # @quality :reek:UtilityFunction
12
+ def show_header?(_examiner)
13
+ raise NotImplementedError
14
+ end
15
+
16
+ def header(examiner)
17
+ if show_header?(examiner)
18
+ formatted_header examiner
19
+ else
20
+ ''
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ def formatted_header(examiner)
27
+ count = examiner.smells_count
28
+ result = Rainbow("#{examiner.origin} -- ").cyan +
29
+ Rainbow("#{count} warning").yellow
30
+ result += Rainbow('s').yellow unless count == 1
31
+ result
32
+ end
33
+ end
34
+
35
+ #
36
+ # Lists out each examiner, even if it has no smell
37
+ #
38
+ class VerboseHeadingFormatter < HeadingFormatterBase
39
+ def show_header?(_examiner)
40
+ true
41
+ end
42
+ end
43
+
44
+ #
45
+ # Lists only smelly examiners
46
+ #
47
+ class QuietHeadingFormatter < HeadingFormatterBase
48
+ # @quality :reek:UtilityFunction
49
+ def show_header?(examiner)
50
+ examiner.smelly?
51
+ end
52
+ end
53
+ end
54
+ end
@@ -12,7 +12,7 @@ module Reek
12
12
  #
13
13
  class JSONReport < BaseReport
14
14
  def show(out = $stdout)
15
- out.print ::JSON.generate smells.map { |smell| warning_formatter.format_hash(smell) }
15
+ out.print ::JSON.generate smells.map(&:yaml_hash)
16
16
  end
17
17
  end
18
18
  end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Reek
4
+ module Report
5
+ #
6
+ # Formats the location of a warning as an empty string.
7
+ #
8
+ module BlankLocationFormatter
9
+ module_function
10
+
11
+ def format(_warning)
12
+ ''
13
+ end
14
+ end
15
+
16
+ #
17
+ # Formats the location of a warning as an array of line numbers.
18
+ #
19
+ module DefaultLocationFormatter
20
+ module_function
21
+
22
+ def format(warning)
23
+ "#{warning.lines.sort.inspect}:"
24
+ end
25
+ end
26
+
27
+ #
28
+ # Formats the location of a warning as a combination of source file name
29
+ # and line number. In this format, it is not possible to show more than
30
+ # one line number, so the first number is displayed.
31
+ #
32
+ module SingleLineLocationFormatter
33
+ module_function
34
+
35
+ def format(warning)
36
+ "#{warning.source}:#{warning.lines.min}: "
37
+ end
38
+ end
39
+ end
40
+ end