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
@@ -25,6 +25,7 @@ Feature: Report smells using simple YAML layout
25
25
  smell_type: UncommunicativeMethodName
26
26
  source: smelly.rb
27
27
  name: x
28
+ documentation_link: https://github.com/troessner/reek/blob/v5.0.0/docs/Uncommunicative-Method-Name.md
28
29
  - context: Smelly#x
29
30
  lines:
30
31
  - 5
@@ -32,6 +33,7 @@ Feature: Report smells using simple YAML layout
32
33
  smell_type: UncommunicativeVariableName
33
34
  source: smelly.rb
34
35
  name: y
36
+ documentation_link: https://github.com/troessner/reek/blob/v5.0.0/docs/Uncommunicative-Variable-Name.md
35
37
  """
36
38
 
37
39
  Scenario: Indicate smells and print them as yaml when using STDIN
@@ -46,4 +48,5 @@ Feature: Report smells using simple YAML layout
46
48
  lines:
47
49
  - 1
48
50
  message: has no descriptive comment
51
+ documentation_link: https://github.com/troessner/reek/blob/v5.0.0/docs/Irresponsible-Module.md
49
52
  """
@@ -24,7 +24,15 @@ Feature: Use reek_of matcher
24
24
  """
25
25
 
26
26
  Scenario: Masking smells with a configuration file
27
- Given a configuration file 'full_mask.reek'
27
+ Given a file named ".reek.yml" with:
28
+ """
29
+ ---
30
+ detectors:
31
+ UncommunicativeMethodName:
32
+ enabled: false
33
+ UncommunicativeVariableName:
34
+ enabled: false
35
+ """
28
36
  When I run `rspec reek_spec.rb`
29
37
  Then stdout should contain:
30
38
  """
@@ -6,6 +6,10 @@ When /^I pass "([^\"]*)" to reek *(.*)$/ do |stdin, args|
6
6
  reek_with_pipe(stdin, args)
7
7
  end
8
8
 
9
+ When /^I pass a stdin to reek *(.*) with:$/ do |args, stdin|
10
+ reek_with_pipe(stdin, args)
11
+ end
12
+
9
13
  Then /^it reports nothing$/ do
10
14
  expect(last_command_started).to have_output_on_stdout('')
11
15
  end
@@ -1,7 +1,7 @@
1
1
  require_relative '../../samples/paths'
2
2
 
3
3
  Given(/^the smelly file '(.+)'$/) do |filename|
4
- write_file(filename, SAMPLES_PATH.join(filename).read)
4
+ write_file(filename, SAMPLES_DIR.join('smelly_source').join(filename).read)
5
5
  end
6
6
 
7
7
  Given(/^the clean file 'clean.rb'$/) do
@@ -28,13 +28,18 @@ Given(/^a directory called 'smelly' containing two smelly files$/) do
28
28
  end
29
29
 
30
30
  Given(/^the smelly file '(.+)' in a subdirectory$/) do |filename|
31
- contents = SAMPLES_PATH.join(filename).read
31
+ contents = SAMPLES_DIR.join('smelly_source').join(filename).read
32
32
 
33
33
  write_file("subdir/#{filename}", contents)
34
34
  end
35
35
 
36
36
  Given(/^a configuration file '(.+)'$/) do |filename|
37
- write_file(filename, CONFIG_PATH.join(filename).read)
37
+ write_file(filename, CONFIGURATION_DIR.join(filename).read)
38
+ end
39
+
40
+ Given(/^our default configuration file$/) do
41
+ default_configuration = File.read SAMPLES_DIR.join('..').join('docs').join('defaults.reek.yml')
42
+ write_file('defaults.reek', default_configuration)
38
43
  end
39
44
 
40
45
  When(/^I run "reek (.*?)" in a subdirectory$/) do |args|
@@ -44,7 +49,7 @@ When(/^I run "reek (.*?)" in a subdirectory$/) do |args|
44
49
  end
45
50
 
46
51
  Given(/^a configuration file '(.+)' in a subdirectory$/) do |filename|
47
- contents = CONFIG_PATH.join(filename).read
52
+ contents = CONFIGURATION_DIR.join(filename).read
48
53
 
49
54
  write_file("subdir/#{filename}", contents)
50
55
  end
@@ -13,11 +13,11 @@ end
13
13
  #
14
14
  class ReekWorld
15
15
  def reek(args)
16
- run_simple("reek --no-color --no-wiki-links #{args}", false)
16
+ run_simple("reek --no-color --no-documentation #{args}", false)
17
17
  end
18
18
 
19
19
  def reek_with_pipe(stdin, args)
20
- run "reek --no-color --no-wiki-links #{args}"
20
+ run "reek --no-color --no-documentation #{args}"
21
21
  type(stdin)
22
22
  close_input
23
23
  end
@@ -29,13 +29,14 @@ Feature: Auto-generate a todo file
29
29
  And the file ".todo.reek" should contain:
30
30
  """
31
31
  ---
32
- UncommunicativeMethodName:
33
- exclude:
34
- - Smelly#x
35
- UncommunicativeVariableName:
36
- exclude:
37
- - Smelly#x
38
- """
32
+ detectors:
33
+ UncommunicativeMethodName:
34
+ exclude:
35
+ - Smelly#x
36
+ UncommunicativeVariableName:
37
+ exclude:
38
+ - Smelly#x
39
+ """
39
40
  When I run reek -c .todo.reek smelly.rb
40
41
  Then it succeeds
41
42
 
@@ -54,10 +55,11 @@ Feature: Auto-generate a todo file
54
55
  And a file named ".todo.reek" with:
55
56
  """
56
57
  ---
57
- # smelly.rb reeks of UncommunicativeMethodName and UncommunicativeVariableName
58
- # so the configuration below will partially mask this
59
- UncommunicativeMethodName:
60
- enabled: false
58
+ detectors:
59
+ # smelly.rb reeks of UncommunicativeMethodName and UncommunicativeVariableName
60
+ # so the configuration below will partially mask this
61
+ UncommunicativeMethodName:
62
+ enabled: false
61
63
  """
62
64
  When I run reek -c .todo.reek smelly.rb
63
65
  Then it reports:
@@ -77,8 +79,9 @@ Feature: Auto-generate a todo file
77
79
  ---
78
80
  # smelly.rb reeks of UncommunicativeMethodName and UncommunicativeVariableName
79
81
  # so the configuration below will partially mask this
80
- UncommunicativeMethodName:
81
- enabled: false
82
+ detectors:
83
+ UncommunicativeMethodName:
84
+ enabled: false
82
85
  """
83
86
  When I run reek -c config.reek smelly.rb
84
87
  Then it reports:
data/lib/reek/ast/node.rb CHANGED
@@ -1,10 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative '../cli/silencer'
4
-
5
- Reek::CLI::Silencer.silently do
6
- require 'parser'
7
- end
4
+ Reek::CLI::Silencer.without_warnings { require 'parser' }
8
5
 
9
6
  module Reek
10
7
  module AST
@@ -72,8 +69,8 @@ module Reek
72
69
  each_node(target_type).any?
73
70
  end
74
71
 
75
- # :reek:DuplicateMethodCall { max_calls: 2 } is ok for lines.first
76
- # :reek:FeatureEnvy
72
+ # @quality :reek:DuplicateMethodCall { max_calls: 2 } is ok for lines.first
73
+ # @quality :reek:FeatureEnvy
77
74
  def format_to_ruby
78
75
  if location
79
76
  lines = location.expression.source.split("\n").map(&:strip)
@@ -50,7 +50,7 @@ module Reek
50
50
  end
51
51
 
52
52
  def self_is_max?
53
- refs.empty? || most_popular.keys.include?(:self)
53
+ refs.empty? || most_popular.key?(:self)
54
54
  end
55
55
 
56
56
  private
@@ -9,7 +9,7 @@ module Reek
9
9
  children.first
10
10
  end
11
11
 
12
- # :reek:FeatureEnvy
12
+ # @quality :reek:FeatureEnvy
13
13
  def body_nodes(type, ignoring = [])
14
14
  children[1..-1].compact.flat_map do |child|
15
15
  if ignoring.include? child.type
@@ -57,7 +57,7 @@ module Reek
57
57
  end
58
58
 
59
59
  def depends_on_instance?
60
- ReferenceCollector.new(self).num_refs_to_self > 0
60
+ ReferenceCollector.new(self).num_refs_to_self.positive?
61
61
  end
62
62
  end
63
63
 
@@ -6,6 +6,7 @@ require_relative '../configuration/app_configuration'
6
6
  require_relative '../source/source_locator'
7
7
  require_relative 'command/report_command'
8
8
  require_relative 'command/todo_list_command'
9
+ require_relative '../errors/config_file_error'
9
10
 
10
11
  module Reek
11
12
  module CLI
@@ -42,7 +43,7 @@ module Reek
42
43
 
43
44
  def configure_app_configuration(config_file)
44
45
  Configuration::AppConfiguration.from_path(config_file)
45
- rescue Reek::Configuration::ConfigFileException => error
46
+ rescue Errors::ConfigFileError => error
46
47
  warn "Error: #{error}"
47
48
  exit Status::DEFAULT_ERROR_EXIT_CODE
48
49
  end
@@ -68,7 +69,7 @@ module Reek
68
69
  options.argv
69
70
  end
70
71
 
71
- # :reek:UtilityFunction
72
+ # @quality :reek:UtilityFunction
72
73
  def input_was_piped?
73
74
  !$stdin.tty?
74
75
  end
@@ -88,7 +89,7 @@ module Reek
88
89
  end
89
90
 
90
91
  def source_from_pipe
91
- [$stdin]
92
+ [Source::SourceCode.from($stdin, origin: options.stdin_filename)]
92
93
  end
93
94
 
94
95
  def disable_progress_output_unless_verbose
@@ -38,7 +38,6 @@ module Reek
38
38
  @reporter ||=
39
39
  report_class.new(
40
40
  warning_formatter: warning_formatter,
41
- report_formatter: Report::Formatter,
42
41
  sort_by_issue_count: sort_by_issue_count,
43
42
  heading_formatter: heading_formatter,
44
43
  progress_formatter: progress_formatter.new(sources.length))
@@ -53,7 +52,7 @@ module Reek
53
52
  end
54
53
 
55
54
  def warning_formatter_class
56
- Report.warning_formatter_class(options.show_links ? :wiki_links : :simple)
55
+ Report.warning_formatter_class(options.show_links ? :documentation_links : :simple)
57
56
  end
58
57
 
59
58
  def location_formatter
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative 'base_command'
4
4
  require_relative '../../examiner'
5
+ require_relative '../../configuration/app_configuration'
5
6
 
6
7
  module Reek
7
8
  module CLI
@@ -11,14 +12,15 @@ module Reek
11
12
  # file that can serve as a todo list.
12
13
  #
13
14
  class TodoListCommand < BaseCommand
14
- FILE_NAME = '.todo.reek'.freeze
15
+ FILE_NAME = '.todo.reek'
15
16
 
16
17
  def execute
17
18
  if smells.empty?
18
19
  puts "\n'.todo.reek' not generated because "\
19
20
  'there were no smells found!'
20
21
  else
21
- File.write FILE_NAME, groups.to_yaml
22
+ File.write FILE_NAME,
23
+ { Configuration::AppConfiguration::DETECTORS_KEY => groups }.to_yaml
22
24
  puts "\n'.todo.reek' generated! You can now use "\
23
25
  'this as a starting point for your configuration.'
24
26
  end
@@ -4,6 +4,7 @@ require 'optparse'
4
4
  require 'rainbow'
5
5
  require_relative '../version'
6
6
  require_relative 'status'
7
+ require_relative '../detector_repository'
7
8
  require_relative '../documentation_link'
8
9
 
9
10
  module Reek
@@ -13,9 +14,9 @@ module Reek
13
14
  #
14
15
  # See {file:docs/Command-Line-Options.md} for details.
15
16
  #
16
- # :reek:TooManyInstanceVariables: { max_instance_variables: 12 }
17
- # :reek:TooManyMethods: { max_methods: 18 }
18
- # :reek:Attribute: { enabled: false }
17
+ # @quality :reek:TooManyInstanceVariables { max_instance_variables: 12 }
18
+ # @quality :reek:TooManyMethods { max_methods: 18 }
19
+ # @quality :reek:Attribute { enabled: false }
19
20
  #
20
21
  class Options
21
22
  attr_reader :argv, :parser, :smells_to_detect
@@ -27,6 +28,7 @@ module Reek
27
28
  :show_empty,
28
29
  :show_links,
29
30
  :sorting,
31
+ :stdin_filename,
30
32
  :success_exit_code,
31
33
  :failure_exit_code,
32
34
  :generate_todo_list,
@@ -65,12 +67,12 @@ module Reek
65
67
  # processing by a machine, but will be viewed by a human. This means
66
68
  # features like coloring can be safely enabled by default.
67
69
  #
68
- # :reek:UtilityFunction
70
+ # @quality :reek:UtilityFunction
69
71
  def tty_output?
70
72
  $stdout.tty?
71
73
  end
72
74
 
73
- # :reek:TooManyStatements: { max_statements: 7 }
75
+ # @quality :reek:TooManyStatements { max_statements: 7 }
74
76
  def set_up_parser
75
77
  set_banner
76
78
  set_configuration_options
@@ -92,12 +94,12 @@ module Reek
92
94
  #{program_name} -s lib
93
95
  cat my_class.rb | #{program_name}
94
96
 
95
- See https://wiki.github.com/troessner/reek for detailed help.
97
+ See https://github.com/troessner/reek for detailed help.
96
98
 
97
99
  BANNER
98
100
  end
99
101
 
100
- # :reek:TooManyStatements: { max_statements: 6 }
102
+ # @quality :reek:TooManyStatements { max_statements: 7 }
101
103
  def set_configuration_options
102
104
  parser.separator 'Configuration:'
103
105
  parser.on('-c', '--config FILE', 'Read configuration options from FILE') do |file|
@@ -105,11 +107,16 @@ module Reek
105
107
  end
106
108
  parser.on('--smell SMELL',
107
109
  'Only look for a specific smell.',
108
- 'Call it like this: reek --smell PrimaDonnaMethod source.rb',
110
+ 'Call it like this: reek --smell MissingSafeMethod source.rb',
109
111
  "Check out #{DocumentationLink.build('Code Smells')} "\
110
112
  'for a list of smells') do |smell|
111
113
  smells_to_detect << smell
112
114
  end
115
+ parser.on('--stdin-filename FILE',
116
+ 'When passing code in via pipe, assume this filename when '\
117
+ 'checking file or directory rules in the config.') do |file|
118
+ self.stdin_filename = file
119
+ end
113
120
  end
114
121
 
115
122
  def set_generate_todo_list_options
@@ -129,7 +136,7 @@ module Reek
129
136
  end
130
137
  end
131
138
 
132
- # :reek:TooManyStatements: { max_statements: 7 }
139
+ # @quality :reek:TooManyStatements { max_statements: 7 }
133
140
  def set_report_formatting_options
134
141
  parser.separator "\nText format options:"
135
142
  set_up_color_option
@@ -151,8 +158,8 @@ module Reek
151
158
  'Show headings for smell-free source files (default: false)') do |show_empty|
152
159
  self.show_empty = show_empty
153
160
  end
154
- parser.on('-U', '--[no-]wiki-links',
155
- 'Show link to related wiki page for each smell (default: true)') do |show_links|
161
+ parser.on('-U', '--[no-]documentation',
162
+ 'Show link to related documentation page for each smell (default: true)') do |show_links|
156
163
  self.show_links = show_links
157
164
  end
158
165
  end
@@ -192,7 +199,7 @@ module Reek
192
199
  end
193
200
  end
194
201
 
195
- # :reek:DuplicateMethodCall: { max_calls: 2 }
202
+ # @quality :reek:DuplicateMethodCall { max_calls: 2 }
196
203
  def set_exit_codes
197
204
  parser.separator "\nExit codes:"
198
205
  parser.on('--success-exit-code CODE',
@@ -207,13 +214,20 @@ module Reek
207
214
  end
208
215
  end
209
216
 
210
- # :reek:TooManyStatements: { max_statements: 7 }
217
+ # @quality :reek:TooManyStatements { max_statements: 12 }
211
218
  def set_utility_options
212
219
  parser.separator "\nUtility options:"
213
220
  parser.on_tail('-h', '--help', 'Show this message') do
214
221
  puts parser
215
222
  exit
216
223
  end
224
+ parser.on_tail('-l', '--list', 'List all available smell detectors') do
225
+ puts "All available smell detectors:\n\n"
226
+ puts DetectorRepository.available_detector_names
227
+ puts "\nCheck out #{DocumentationLink.build('Code Smells')} "\
228
+ 'for a details on each detector'
229
+ exit
230
+ end
217
231
  parser.on_tail('-v', '--version', 'Show version') do
218
232
  puts "#{parser.program_name} #{Reek::Version::STRING}\n"
219
233
  exit
@@ -8,17 +8,28 @@ module Reek
8
8
  module Silencer
9
9
  module_function
10
10
 
11
- # :reek:TooManyStatements: { max_statements: 7 }
11
+ # @quality :reek:TooManyStatements { max_statements: 9 }
12
12
  def silently
13
13
  old_verbose = $VERBOSE
14
+ old_stderr = $stderr
15
+ old_stdout = $stdout
16
+
14
17
  $VERBOSE = false
15
18
  $stderr = StringIO.new
16
19
  $stdout = StringIO.new
17
20
  yield
18
21
  ensure
19
22
  $VERBOSE = old_verbose
20
- $stderr = STDERR
21
- $stdout = STDOUT
23
+ $stderr = old_stderr
24
+ $stdout = old_stdout
25
+ end
26
+
27
+ def without_warnings
28
+ old_verbose = $VERBOSE
29
+ $VERBOSE = false
30
+ yield
31
+ ensure
32
+ $VERBOSE = old_verbose
22
33
  end
23
34
  end
24
35
  end
@@ -17,22 +17,20 @@ module Reek
17
17
  :reek: # prefix
18
18
  (\w+) # smell detector e.g.: UncommunicativeVariableName
19
19
  (
20
- :? # legacy separator
21
20
  \s*
22
21
  (\{.*?\}) # optional details in hash style e.g.: { max_methods: 30 }
23
22
  )?
24
23
  /x
25
24
  SANITIZE_REGEX = /(#|\n|\s)+/ # Matches '#', newlines and > 1 whitespaces.
26
- DISABLE_DETECTOR_CONFIGURATION = '{ enabled: false }'.freeze
25
+ DISABLE_DETECTOR_CONFIGURATION = '{ enabled: false }'
27
26
  MINIMUM_CONTENT_LENGTH = 2
28
- LEGACY_SEPARATOR = ':'.freeze
29
27
 
30
28
  attr_reader :config
31
29
 
32
30
  #
33
- # @param comment [String] - the original comment as found in the source code
34
- # @param line [Integer] - start of the expression the comment belongs to
35
- # @param source [String] - Path to source file or "string"
31
+ # @param comment [String] the original comment as found in the source code
32
+ # @param line [Integer] start of the expression the comment belongs to
33
+ # @param source [String] Path to source file or "string"
36
34
  #
37
35
  def initialize(comment:, line: nil, source: nil)
38
36
  @original_comment = comment
@@ -80,15 +78,15 @@ module Reek
80
78
  # This class validates [1], [2] and [3] at the moment but will also validate
81
79
  # [4] in the future.
82
80
  #
83
- # :reek:TooManyInstanceVariables: { max_instance_variables: 7 }
81
+ # @quality :reek:TooManyInstanceVariables { max_instance_variables: 7 }
84
82
  class CodeCommentValidator
85
83
  #
86
- # @param detector_name [String] - the detector class that was parsed out of the original
84
+ # @param detector_name [String] the detector class that was parsed out of the original
87
85
  # comment, e.g. "DuplicateMethodCall" or "UnknownSmellDetector"
88
- # @param original_comment [String] - the original comment as found in the source code
89
- # @param line [Integer] - start of the expression the comment belongs to
90
- # @param source [String] - path to source file or "string"
91
- # @param options [String] - the configuration options as String for the detector that were
86
+ # @param original_comment [String] the original comment as found in the source code
87
+ # @param line [Integer] start of the expression the comment belongs to
88
+ # @param source [String] path to source file or "string"
89
+ # @param options [String] the configuration options as String for the detector that were
92
90
  # extracted from the original comment
93
91
  def initialize(detector_name:, original_comment:, line:, source:, options: {})
94
92
  @detector_name = detector_name
@@ -151,24 +149,24 @@ module Reek
151
149
  line: line
152
150
  end
153
151
 
154
- # @return [Boolean] - all keys in code comment are applicable to the detector in question
152
+ # @return [Boolean] all keys in code comment are applicable to the detector in question
155
153
  def given_keys_legit?
156
154
  given_configuration_keys.subset? valid_detector_keys
157
155
  end
158
156
 
159
- # @return [Set] - the configuration keys that are found in the code comment
157
+ # @return [Set] the configuration keys that are found in the code comment
160
158
  def given_configuration_keys
161
159
  parsed_options.keys.map(&:to_sym).to_set
162
160
  end
163
161
 
164
- # @return [String] - all keys from the code comment that look bad
162
+ # @return [String] all keys from the code comment that look bad
165
163
  def configuration_keys_difference
166
164
  given_configuration_keys.difference(valid_detector_keys).
167
165
  to_a.map { |key| "'#{key}'" }.
168
166
  join(', ')
169
167
  end
170
168
 
171
- # @return [Set] - all keys that are legit for the given detector
169
+ # @return [Set] all keys that are legit for the given detector
172
170
  def valid_detector_keys
173
171
  detector_class.configuration_keys
174
172
  end