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
@@ -1,9 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative '../cli/silencer'
4
- Reek::CLI::Silencer.silently do
5
- require 'parser/ruby25'
6
- end
4
+ Reek::CLI::Silencer.without_warnings { require 'parser/ruby25' }
7
5
  require_relative '../tree_dresser'
8
6
  require_relative '../ast/node'
9
7
  require_relative '../ast/builder'
@@ -14,94 +12,82 @@ Reek::AST::Builder.emit_lambda = true
14
12
  module Reek
15
13
  module Source
16
14
  #
17
- # A +Source+ object represents a chunk of Ruby source code.
15
+ # A +SourceCode+ object represents a chunk of Ruby source code.
18
16
  #
19
17
  class SourceCode
20
- # Consume and store parser diagnostics
21
- class DiagnosticsConsumer
22
- def initialize
23
- @diagnostics = []
24
- end
25
-
26
- def call(item)
27
- @diagnostics << item
28
- end
29
-
30
- def result
31
- @diagnostics
32
- end
33
- end
34
-
35
- IO_IDENTIFIER = 'STDIN'.freeze
36
- STRING_IDENTIFIER = 'string'.freeze
37
-
38
- attr_reader :origin
18
+ IO_IDENTIFIER = 'STDIN'
19
+ STRING_IDENTIFIER = 'string'
39
20
 
40
21
  # Initializer.
41
22
  #
42
- # code - Ruby code as String
43
- # origin - 'STDIN', 'string' or a filepath as String
44
- # parser - the parser to use for generating AST's out of the given code
45
- def initialize(code:, origin:, parser: self.class.default_parser)
23
+ # @param source [File|Pathname|IO|String] Ruby source code
24
+ # @param origin [String] Origin of the source code. Will be determined
25
+ # automatically if left blank.
26
+ # @param parser the parser to use for generating AST's out of the given code
27
+ def initialize(source:, origin: nil, parser: self.class.default_parser)
46
28
  @origin = origin
47
29
  @parser = parser
48
- code.force_encoding(Encoding::UTF_8)
49
- @code = code
30
+ @source = source
50
31
  end
51
32
 
52
33
  # Initializes an instance of SourceCode given a source.
53
- # This source can come via 4 different ways:
34
+ # This source can come via several different ways:
54
35
  # - from Files or Pathnames a la `reek lib/reek/`
55
36
  # - from IO (STDIN) a la `echo "class Foo; end" | reek`
56
37
  # - from String via our rspec matchers a la `expect("class Foo; end").to reek`
38
+ # - from an existing SourceCode object. This is passed through unchanged
57
39
  #
58
- # @param source [File|IO|String] - the given source
40
+ # @param source [SourceCode|File|Pathname|IO|String] the given source
41
+ # @param origin [String|nil]
59
42
  #
60
43
  # @return an instance of SourceCode
61
- # :reek:DuplicateMethodCall: { max_calls: 2 }
62
- def self.from(source)
44
+ def self.from(source, origin: nil)
63
45
  case source
64
- when File then new(code: source.read, origin: source.path)
65
- when IO then new(code: source.readlines.join, origin: IO_IDENTIFIER)
66
- when Pathname then new(code: source.read, origin: source.to_s)
67
- when String then new(code: source, origin: STRING_IDENTIFIER)
46
+ when self then source
47
+ else new(source: source, origin: origin)
68
48
  end
69
49
  end
70
50
 
71
- def diagnostics
72
- parse_result.last
73
- end
74
-
75
51
  def syntax_tree
76
- parse_result.first
52
+ @syntax_tree ||= parse
77
53
  end
78
54
 
79
55
  def self.default_parser
80
56
  Parser::Ruby25.new(AST::Builder.new).tap do |parser|
81
57
  diagnostics = parser.diagnostics
82
- diagnostics.all_errors_are_fatal = false
83
- diagnostics.ignore_warnings = false
84
- diagnostics.consumer = DiagnosticsConsumer.new
58
+ diagnostics.all_errors_are_fatal = true
59
+ diagnostics.ignore_warnings = true
85
60
  end
86
61
  end
87
62
 
63
+ def origin
64
+ @origin ||=
65
+ case source
66
+ when File then source.path
67
+ when IO then IO_IDENTIFIER
68
+ when Pathname then source.to_s
69
+ when String then STRING_IDENTIFIER
70
+ end
71
+ end
72
+
88
73
  private
89
74
 
90
- def parse_result
91
- @parse_result ||= parse
75
+ def code
76
+ @code ||=
77
+ case source
78
+ when File, Pathname then source.read
79
+ when IO then source.readlines.join
80
+ when String then source
81
+ end.force_encoding(Encoding::UTF_8)
92
82
  end
93
83
 
94
- attr_reader :code
95
- attr_reader :parser
84
+ attr_reader :parser, :source
96
85
 
97
86
  # Parses the given code into an AST and associates the source code comments with it.
98
87
  # This AST is then traversed by a TreeDresser which adorns the nodes in the AST
99
88
  # with our SexpExtensions.
100
89
  # Finally this AST is returned where each node is an anonymous subclass of Reek::AST::Node
101
90
  #
102
- # Important to note is that Reek will not fail on unparseable files but rather register a
103
- # parse error to @diagnostics and then just continue.
104
- #
105
91
  # Given this @code:
106
92
  #
107
93
  # # comment about C
@@ -123,8 +109,7 @@ module Reek
123
109
  # where each node is possibly adorned with our SexpExtensions (see ast/ast_node_class_map
124
110
  # and ast/sexp_extensions for details).
125
111
  #
126
- # @return [Anonymous subclass of Reek::AST::Node, Array] the AST presentation
127
- # for the given code, List of diagnostics messages
112
+ # @return Reek::AST::Node the AST presentation for the given code
128
113
  def parse
129
114
  buffer = Parser::Source::Buffer.new(origin, 1)
130
115
  buffer.source = code
@@ -132,7 +117,7 @@ module Reek
132
117
 
133
118
  # See https://whitequark.github.io/parser/Parser/Source/Comment/Associator.html
134
119
  comment_map = Parser::Source::Comment.associate(ast, comments)
135
- [TreeDresser.new.dress(ast, comment_map), parser.diagnostics.consumer.result]
120
+ TreeDresser.new.dress(ast, comment_map) || AST::Node.new(:empty)
136
121
  end
137
122
  end
138
123
  end
@@ -24,7 +24,7 @@ module Reek
24
24
  # Traverses all paths we initialized the SourceLocator with, finds
25
25
  # all relevant Ruby files and returns them as a list.
26
26
  #
27
- # @return [Array<Pathname>] - Ruby paths found
27
+ # @return [Array<Pathname>] Ruby paths found
28
28
  def sources
29
29
  source_paths
30
30
  end
@@ -33,8 +33,8 @@ module Reek
33
33
 
34
34
  attr_reader :configuration, :paths, :options
35
35
 
36
- # :reek:TooManyStatements: { max_statements: 7 }
37
- # :reek:NestedIterators: { max_allowed_nesting: 2 }
36
+ # @quality :reek:TooManyStatements { max_statements: 7 }
37
+ # @quality :reek:NestedIterators { max_allowed_nesting: 2 }
38
38
  def source_paths
39
39
  paths.each_with_object([]) do |given_path, relevant_paths|
40
40
  unless given_path.exist?
@@ -67,12 +67,12 @@ module Reek
67
67
  configuration.path_excluded?(path)
68
68
  end
69
69
 
70
- # :reek:UtilityFunction
70
+ # @quality :reek:UtilityFunction
71
71
  def print_no_such_file_error(path)
72
72
  warn "Error: No such file - #{path}"
73
73
  end
74
74
 
75
- # :reek:UtilityFunction
75
+ # @quality :reek:UtilityFunction
76
76
  def hidden_directory?(path)
77
77
  path.basename.to_s.start_with? '.'
78
78
  end
@@ -81,12 +81,12 @@ module Reek
81
81
  path_excluded?(path) || hidden_directory?(path)
82
82
  end
83
83
 
84
- # :reek:UtilityFunction
84
+ # @quality :reek:UtilityFunction
85
85
  def ruby_file?(path)
86
86
  path.extname == '.rb'
87
87
  end
88
88
 
89
- # :reek:UtilityFunction
89
+ # @quality :reek:UtilityFunction
90
90
  def current_directory?(path)
91
91
  [Pathname.new('.'), Pathname.new('./')].include?(path)
92
92
  end
data/lib/reek/spec.rb CHANGED
@@ -65,7 +65,7 @@ module Reek
65
65
  # raise an ArgumentError to give you a hint that you passed something that doesn't make
66
66
  # much sense.
67
67
  #
68
- # @param smell_type [Symbol, String, Class] The "smell type" to check for.
68
+ # @param smell_type [Symbol, String] The "smell type" to check for.
69
69
  # @param smell_details [Hash] A hash containing "smell warning" parameters
70
70
  #
71
71
  # @example Without smell_details
@@ -84,7 +84,7 @@ module Reek
84
84
  #
85
85
  # @public
86
86
  #
87
- # :reek:UtilityFunction
87
+ # @quality :reek:UtilityFunction
88
88
  def reek_of(smell_type,
89
89
  smell_details = {},
90
90
  configuration = Configuration::AppConfiguration.default)
@@ -99,11 +99,11 @@ module Reek
99
99
  # "reek_only_of" will fail in that case.
100
100
  # 2.) "reek_only_of" doesn't support the additional smell_details hash.
101
101
  #
102
- # @param smell_type [Symbol, String, Class] The "smell type" to check for.
102
+ # @param smell_type [Symbol, String] The "smell type" to check for.
103
103
  #
104
104
  # @public
105
105
  #
106
- # :reek:UtilityFunction
106
+ # @quality :reek:UtilityFunction
107
107
  def reek_only_of(smell_type, configuration = Configuration::AppConfiguration.default)
108
108
  ShouldReekOnlyOf.new(smell_type, configuration)
109
109
  end
@@ -113,8 +113,8 @@ module Reek
113
113
  #
114
114
  # @public
115
115
  #
116
- # :reek:UtilityFunction
117
- def reek(configuration = Configuration::AppConfiguration.from_path)
116
+ # @quality :reek:UtilityFunction
117
+ def reek(configuration = Configuration::AppConfiguration.from_default_path)
118
118
  ShouldReek.new(configuration: configuration)
119
119
  end
120
120
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative '../examiner'
4
- require_relative '../report/formatter'
4
+ require_relative '../report/simple_warning_formatter'
5
5
 
6
6
  module Reek
7
7
  module Spec
@@ -23,7 +23,7 @@ module Reek
23
23
  end
24
24
 
25
25
  def failure_message_when_negated
26
- rpt = Report::Formatter.format_list(examiner.smells)
26
+ rpt = Report::SimpleWarningFormatter.new.format_list(examiner.smells)
27
27
  "Expected no smells, but got:\n#{rpt}"
28
28
  end
29
29
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative '../examiner'
4
4
  require_relative 'smell_matcher'
5
+ require_relative '../configuration/app_configuration'
5
6
 
6
7
  module Reek
7
8
  module Spec
@@ -14,12 +15,13 @@ module Reek
14
15
 
15
16
  attr_reader :failure_message, :failure_message_when_negated
16
17
 
17
- def initialize(smell_type_or_class,
18
+ def initialize(smell_type,
18
19
  smell_details = {},
19
20
  configuration = Configuration::AppConfiguration.default)
20
- @smell_type = normalize smell_type_or_class
21
+ @smell_type = smell_type.to_s
21
22
  @smell_details = smell_details
22
- configuration.load_values(smell_type => { SmellConfiguration::ENABLED_KEY => true })
23
+ configuration.load_values(Configuration::AppConfiguration::DETECTORS_KEY =>
24
+ { smell_type => { SmellConfiguration::ENABLED_KEY => true } })
23
25
  @configuration = configuration
24
26
  end
25
27
 
@@ -34,7 +36,8 @@ module Reek
34
36
 
35
37
  def with_config(config_hash)
36
38
  new_configuration = Configuration::AppConfiguration.default
37
- new_configuration.load_values(smell_type => config_hash)
39
+ new_configuration.load_values(Configuration::AppConfiguration::DETECTORS_KEY =>
40
+ { smell_type => config_hash })
38
41
  self.class.new(smell_type, smell_details, new_configuration)
39
42
  end
40
43
 
@@ -82,7 +85,7 @@ module Reek
82
85
  "#{smell_type} with smell details #{smell_details}, but it did"
83
86
  end
84
87
 
85
- # :reek:FeatureEnvy
88
+ # @quality :reek:FeatureEnvy
86
89
  def all_relevant_smell_details_formatted
87
90
  matching_smell_types.each_with_object([]).with_index do |(smell, accumulator), index|
88
91
  accumulator << "#{index + 1}.)\n"
@@ -93,17 +96,7 @@ module Reek
93
96
  end
94
97
 
95
98
  def origin
96
- examiner.description
97
- end
98
-
99
- # :reek:UtilityFunction
100
- def normalize(smell_type_or_class)
101
- case smell_type_or_class
102
- when Class
103
- smell_type_or_class.smell_type
104
- else
105
- smell_type_or_class.to_s
106
- end
99
+ examiner.origin
107
100
  end
108
101
  end
109
102
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative '../examiner'
4
- require_relative '../report/formatter'
4
+ require_relative '../report/simple_warning_formatter'
5
5
  require_relative 'should_reek_of'
6
6
  require_relative 'smell_matcher'
7
7
 
@@ -24,12 +24,12 @@ module Reek
24
24
  end
25
25
 
26
26
  def failure_message
27
- rpt = Report::Formatter.format_list(warnings)
28
- "Expected #{examiner.description} to reek only of #{smell_type}, but got:\n#{rpt}"
27
+ rpt = Report::SimpleWarningFormatter.new.format_list(warnings)
28
+ "Expected #{examiner.origin} to reek only of #{smell_type}, but got:\n#{rpt}"
29
29
  end
30
30
 
31
31
  def failure_message_when_negated
32
- "Expected #{examiner.description} not to reek only of #{smell_type}, but it did"
32
+ "Expected #{examiner.origin} not to reek only of #{smell_type}, but it did"
33
33
  end
34
34
 
35
35
  private
@@ -31,14 +31,14 @@ module Reek
31
31
  # time the nodes will contain type-dependent mixins, e.g. this:
32
32
  # (const nil :Klazz)
33
33
  # will be of type Reek::AST::Node with Reek::AST::SexpExtensions::ConstNode mixed in.
34
- # @param sexp [Parser::AST::Node] - the given sexp
35
- # @param comment_map [Hash] - see the documentation for SourceCode#syntax_tree
36
- # @param parent [Parser::AST::Node] - the parent sexp
34
+ #
35
+ # @param sexp [Parser::AST::Node] the given sexp
36
+ # @param comment_map [Hash] see the documentation for SourceCode#syntax_tree
37
37
  #
38
38
  # @return an instance of Reek::AST::Node with type-dependent sexp extensions mixed in.
39
39
  #
40
- # :reek:FeatureEnvy
41
- # :reek:TooManyStatements: { max_statements: 6 }
40
+ # @quality :reek:FeatureEnvy
41
+ # @quality :reek:TooManyStatements { max_statements: 6 }
42
42
  def dress(sexp, comment_map)
43
43
  return sexp unless sexp.is_a? ::Parser::AST::Node
44
44
  type = sexp.type
data/lib/reek/version.rb CHANGED
@@ -8,6 +8,6 @@ module Reek
8
8
  # @public
9
9
  module Version
10
10
  # @public
11
- STRING = '4.8.2'.freeze
11
+ STRING = '5.0.0'
12
12
  end
13
13
  end
data/reek.gemspec CHANGED
@@ -5,7 +5,6 @@ Gem::Specification.new do |s|
5
5
  s.version = Reek::Version::STRING
6
6
 
7
7
  s.authors = ['Kevin Rutherford', 'Timo Roessner', 'Matijs van Zuijlen', 'Piotr Szotkowski']
8
- s.default_executable = 'reek'
9
8
  s.description =
10
9
  'Reek is a tool that examines Ruby classes, modules and methods and reports ' \
11
10
  'any code smells it finds.'
@@ -15,12 +14,13 @@ Gem::Specification.new do |s|
15
14
  s.extra_rdoc_files = ['CHANGELOG.md', 'License.txt']
16
15
  s.files = `git ls-files -z`.split("\0")
17
16
  s.executables = s.files.grep(%r{^bin/}).map { |path| File.basename(path) }
18
- s.homepage = 'https://github.com/troessner/reek/wiki'
17
+ s.homepage = 'https://github.com/troessner/reek'
19
18
  s.rdoc_options = %w(--main README.md -x assets/|bin/|config/|features/|spec/|tasks/)
20
- s.required_ruby_version = '>= 2.1.0'
19
+ s.required_ruby_version = '>= 2.3.0'
21
20
  s.summary = 'Code smell detector for Ruby'
22
21
 
23
22
  s.add_runtime_dependency 'codeclimate-engine-rb', '~> 0.4.0'
23
+ s.add_runtime_dependency 'kwalify', '~> 0.7.0'
24
24
  s.add_runtime_dependency 'parser', '< 2.6', '>= 2.5.0.0'
25
25
  s.add_runtime_dependency 'rainbow', '>= 2.0', '< 4.0'
26
26
  end
@@ -1,6 +1,6 @@
1
1
  <?xml version='1.0'?>
2
2
  <checkstyle>
3
- <file name='samples/smelly.rb'>
3
+ <file name='samples/smelly_source/smelly.rb'>
4
4
  <error column='0' line='4' message='has the name &apos;x&apos;' severity='warning' source='UncommunicativeMethodName'/>
5
5
  <error column='0' line='5' message='has the variable name &apos;y&apos;' severity='warning' source='UncommunicativeVariableName'/>
6
6
  </file>
File without changes
@@ -0,0 +1,29 @@
1
+ ---
2
+ detectors:
3
+ UnusedPrivateMethod:
4
+ exclude:
5
+ - "/exclude regexp/"
6
+ UncommunicativeMethodName:
7
+ reject:
8
+ - "reject name"
9
+ accept:
10
+ - "accept name"
11
+ UncommunicativeModuleName:
12
+ reject:
13
+ - "reject name 1"
14
+ - "reject name 2"
15
+ accept:
16
+ - "accept name 1"
17
+ - "accept name 2"
18
+ UncommunicativeParameterName:
19
+ reject:
20
+ - "reject name"
21
+ - "/reject regexp/"
22
+ accept:
23
+ - "accept name"
24
+ - "/accept regexp/"
25
+ UncommunicativeVariableName:
26
+ reject:
27
+ - "/^reject regexp$/"
28
+ accept:
29
+ - "/accept(.*)regexp/"