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
@@ -16,7 +16,7 @@ RSpec.describe Reek::Report::XMLReport do
16
16
  context 'with a source with violations' do
17
17
  it 'prints non-empty checkstyle XML' do
18
18
  xml_report.add_examiner Reek::Examiner.new(SMELLY_FILE)
19
- xml = SAMPLES_PATH.join('checkstyle.xml').read
19
+ xml = SAMPLES_DIR.join('checkstyle.xml').read
20
20
  xml = xml.gsub(SMELLY_FILE.to_s, SMELLY_FILE.expand_path.to_s)
21
21
  expect { xml_report.show }.to output(xml).to_stdout
22
22
  end
@@ -1,7 +1,6 @@
1
1
  require_relative '../../spec_helper'
2
2
  require_lib 'reek/examiner'
3
3
  require_lib 'reek/report/yaml_report'
4
- require_lib 'reek/report/formatter'
5
4
 
6
5
  require 'yaml'
7
6
  require 'stringio'
@@ -36,49 +35,21 @@ RSpec.describe Reek::Report::YAMLReport do
36
35
  - context: "simple"
37
36
  lines:
38
37
  - 1
39
- message: "has the parameter name 'a'"
40
- smell_type: "UncommunicativeParameterName"
41
- source: "string"
42
- name: "a"
38
+ message: "has the parameter name 'a'"
39
+ smell_type: "UncommunicativeParameterName"
40
+ source: "string"
41
+ name: "a"
42
+ documentation_link: "https://github.com/troessner/reek/blob/v#{Reek::Version::STRING}/docs/Uncommunicative-Parameter-Name.md"
43
43
  - context: "simple"
44
44
  lines:
45
45
  - 1
46
- message: "doesn't depend on instance state (maybe move it to another class?)"
47
- smell_type: "UtilityFunction"
48
- source: "string"
46
+ message: "doesn't depend on instance state (maybe move it to another class?)"
47
+ smell_type: "UtilityFunction"
48
+ source: "string"
49
+ documentation_link: "https://github.com/troessner/reek/blob/v#{Reek::Version::STRING}/docs/Utility-Function.md"
49
50
  EOS
50
51
 
51
52
  expect(result).to eq expected
52
53
  end
53
- context 'with link formatter' do
54
- let(:options) { { warning_formatter: Reek::Report::Formatter::WikiLinkWarningFormatter.new } }
55
-
56
- it 'prints documentation links' do
57
- out = StringIO.new
58
- instance.show(out)
59
- out.rewind
60
- result = YAML.safe_load(out.read)
61
- expected = YAML.safe_load <<-EOS.strip_heredoc
62
- ---
63
- - context: "simple"
64
- lines:
65
- - 1
66
- message: "has the parameter name 'a'"
67
- smell_type: "UncommunicativeParameterName"
68
- source: "string"
69
- name: "a"
70
- wiki_link: "https://github.com/troessner/reek/blob/v#{Reek::Version::STRING}/docs/Uncommunicative-Parameter-Name.md"
71
- - context: "simple"
72
- lines:
73
- - 1
74
- message: "doesn't depend on instance state (maybe move it to another class?)"
75
- smell_type: "UtilityFunction"
76
- source: "string"
77
- wiki_link: "https://github.com/troessner/reek/blob/v#{Reek::Version::STRING}/docs/Utility-Function.md"
78
- EOS
79
-
80
- expect(result).to eq expected
81
- end
82
- end
83
54
  end
84
55
  end
@@ -10,19 +10,19 @@ RSpec.describe Reek::Report do
10
10
 
11
11
  describe '.location_formatter' do
12
12
  it 'returns the correct class' do
13
- expect(described_class.location_formatter(:plain)).to eq Reek::Report::Formatter::BlankLocationFormatter
13
+ expect(described_class.location_formatter(:plain)).to eq Reek::Report::BlankLocationFormatter
14
14
  end
15
15
  end
16
16
 
17
17
  describe '.heading_formatter' do
18
18
  it 'returns the correct class' do
19
- expect(described_class.heading_formatter(:quiet)).to eq Reek::Report::Formatter::QuietHeadingFormatter
19
+ expect(described_class.heading_formatter(:quiet)).to eq Reek::Report::QuietHeadingFormatter
20
20
  end
21
21
  end
22
22
 
23
23
  describe '.warning_formatter_class' do
24
24
  it 'returns the correct class' do
25
- expect(described_class.warning_formatter_class(:simple)).to eq Reek::Report::Formatter::SimpleWarningFormatter
25
+ expect(described_class.warning_formatter_class(:simple)).to eq Reek::Report::SimpleWarningFormatter
26
26
  end
27
27
  end
28
28
  end
@@ -130,7 +130,7 @@ RSpec.describe Reek::SmellDetectors::FeatureEnvy do
130
130
  delta += bravo.foxtrot
131
131
  delta *= 1.15
132
132
  end
133
- EOS
133
+ EOS
134
134
 
135
135
  expect(src).
136
136
  to reek_of(:FeatureEnvy, name: 'delta').
@@ -145,7 +145,7 @@ RSpec.describe Reek::SmellDetectors::FeatureEnvy do
145
145
  delta += bravo.echo
146
146
  delta += bravo.foxtrot
147
147
  end
148
- EOS
148
+ EOS
149
149
 
150
150
  expect(src).
151
151
  to reek_of(:FeatureEnvy, name: 'delta').
@@ -1,7 +1,7 @@
1
1
  require_relative '../../spec_helper'
2
- require_lib 'reek/smell_detectors/prima_donna_method'
2
+ require_lib 'reek/smell_detectors/missing_safe_method'
3
3
 
4
- RSpec.describe Reek::SmellDetectors::PrimaDonnaMethod do
4
+ RSpec.describe Reek::SmellDetectors::MissingSafeMethod do
5
5
  it 'reports the right values' do
6
6
  src = <<-EOS
7
7
  class Alfa
@@ -10,10 +10,10 @@ RSpec.describe Reek::SmellDetectors::PrimaDonnaMethod do
10
10
  end
11
11
  EOS
12
12
 
13
- expect(src).to reek_of(:PrimaDonnaMethod,
13
+ expect(src).to reek_of(:MissingSafeMethod,
14
14
  lines: [2],
15
15
  context: 'Alfa',
16
- message: "has prima donna method 'bravo!'",
16
+ message: "has missing safe method 'bravo!'",
17
17
  source: 'string',
18
18
  name: 'bravo!')
19
19
  end
@@ -30,8 +30,8 @@ RSpec.describe Reek::SmellDetectors::PrimaDonnaMethod do
30
30
  EOS
31
31
 
32
32
  expect(src).
33
- to reek_of(:PrimaDonnaMethod, lines: [2], name: 'bravo!').
34
- and reek_of(:PrimaDonnaMethod, lines: [5], name: 'charlie!')
33
+ to reek_of(:MissingSafeMethod, lines: [2], name: 'bravo!').
34
+ and reek_of(:MissingSafeMethod, lines: [5], name: 'charlie!')
35
35
  end
36
36
 
37
37
  it 'reports nothing when method and bang counterpart exist' do
@@ -45,18 +45,18 @@ RSpec.describe Reek::SmellDetectors::PrimaDonnaMethod do
45
45
  end
46
46
  EOS
47
47
 
48
- expect(src).not_to reek_of(:PrimaDonnaMethod)
48
+ expect(src).not_to reek_of(:MissingSafeMethod)
49
49
  end
50
50
 
51
51
  it 'does not report methods we excluded via comment' do
52
52
  source = <<-EOF
53
- # :reek:PrimaDonnaMethod: { exclude: [ bravo! ] }
53
+ # :reek:MissingSafeMethod: { exclude: [ bravo! ] }
54
54
  class Alfa
55
55
  def bravo!
56
56
  end
57
57
  end
58
58
  EOF
59
59
 
60
- expect(source).not_to reek_of(:PrimaDonnaMethod)
60
+ expect(source).not_to reek_of(:MissingSafeMethod)
61
61
  end
62
62
  end
@@ -33,7 +33,7 @@ RSpec.describe Reek::SmellDetectors::TooManyConstants do
33
33
 
34
34
  it 'does not report when increasing default' do
35
35
  src = <<-EOS
36
- # :reek:TooManyConstants: { max_constants: 3 }
36
+ # :reek:TooManyConstants { max_constants: 3 }
37
37
  class Alfa
38
38
  Bravo = Charlie = Delta = 1
39
39
  end
@@ -44,7 +44,7 @@ RSpec.describe Reek::SmellDetectors::TooManyConstants do
44
44
 
45
45
  it 'does not report when disabled' do
46
46
  src = <<-EOS
47
- # :reek:TooManyConstants: { enabled: false }
47
+ # :reek:TooManyConstants { enabled: false }
48
48
  class Alfa
49
49
  Bravo = Charlie = Delta = 1
50
50
  end
@@ -96,7 +96,7 @@ RSpec.describe Reek::SmellDetectors::TooManyConstants do
96
96
  it 'does not report outer module when inner module suppressed' do
97
97
  src = <<-EOS
98
98
  module Alfa
99
- # ignore :reek:TooManyConstants:
99
+ # ignore :reek:TooManyConstants
100
100
  module Bravo
101
101
  Charlie = Delta = Echo = 1
102
102
  end
@@ -37,7 +37,7 @@ RSpec.describe Reek::SmellDetectors::TooManyInstanceVariables do
37
37
 
38
38
  it 'has a configurable maximum' do
39
39
  src = <<-EOS
40
- # :reek:TooManyInstanceVariables: { max_instance_variables: 3 }
40
+ # :reek:TooManyInstanceVariables { max_instance_variables: 3 }
41
41
  class Alfa
42
42
  def bravo
43
43
  @charlie = @delta = @echo = 1
@@ -41,18 +41,18 @@ RSpec.describe Reek::SmellDetectors::UncommunicativeMethodName do
41
41
  describe '`accept` patterns' do
42
42
  let(:source) { 'def x; end' }
43
43
 
44
- it 'make smelly names pass via regex / strings given by list / literal' do
45
- [[/x/], /x/, ['x'], 'x'].each do |pattern|
46
- expect(source).not_to reek_of(:UncommunicativeMethodName).with_config('accept' => pattern)
47
- end
44
+ it 'make smelly names pass' do
45
+ pattern = /x/
46
+ expect(source).not_to reek_of(:UncommunicativeMethodName).with_config('accept' => pattern)
48
47
  end
49
48
  end
50
49
 
51
50
  describe '`reject` patterns' do
52
51
  let(:source) { 'def alfa; end' }
53
52
 
54
- it 'reject smelly names via regex / strings given by list / literal' do
55
- [[/alfa/], /alfa/, ['alfa'], 'alfa'].each do |pattern|
53
+ it 'reject smelly names' do
54
+ patterns = [/alf/, /lfa/]
55
+ patterns.each do |pattern|
56
56
  expect(source).to reek_of(:UncommunicativeMethodName).with_config('reject' => pattern)
57
57
  end
58
58
  end
@@ -39,8 +39,9 @@ RSpec.describe Reek::SmellDetectors::UncommunicativeModuleName do
39
39
  describe '`accept` patterns' do
40
40
  let(:source) { 'class Alfa1; end' }
41
41
 
42
- it 'makes smelly names pass via regex / strings given by list / literal' do
43
- [[/lfa/], /lfa/, ['lfa'], 'lfa'].each do |pattern|
42
+ it 'make smelly names pass ' do
43
+ patterns = [/lfa1/, /Alfa1/]
44
+ patterns.each do |pattern|
44
45
  expect(source).not_to reek_of(:UncommunicativeModuleName).with_config('accept' => pattern)
45
46
  end
46
47
  end
@@ -49,8 +50,9 @@ RSpec.describe Reek::SmellDetectors::UncommunicativeModuleName do
49
50
  describe '`reject` patterns' do
50
51
  let(:source) { 'class Alfa; end' }
51
52
 
52
- it 'rejects smelly names via regex / strings given by list / literal' do
53
- [[/Alfa/], /Alfa/, ['Alfa'], 'Alfa'].each do |pattern|
53
+ it 'reject smelly names' do
54
+ patterns = [/lfa/, /Alf/]
55
+ patterns.each do |pattern|
54
56
  expect(source).to reek_of(:UncommunicativeModuleName).with_config('reject' => pattern)
55
57
  end
56
58
  end
@@ -107,8 +107,9 @@ RSpec.describe Reek::SmellDetectors::UncommunicativeParameterName do
107
107
  describe '`accept` patterns' do
108
108
  let(:source) { 'def alfa(bar2); charlie(bar2); end' }
109
109
 
110
- it 'make smelly names pass via regex / strings given by list / literal' do
111
- [[/bar2/], /bar2/, ['bar2'], 'bar2'].each do |pattern|
110
+ it 'make smelly names pass' do
111
+ patterns = [/bar2/, /ar2/]
112
+ patterns.each do |pattern|
112
113
  expect(source).not_to reek_of(:UncommunicativeParameterName).with_config('accept' => pattern)
113
114
  end
114
115
  end
@@ -117,8 +118,9 @@ RSpec.describe Reek::SmellDetectors::UncommunicativeParameterName do
117
118
  describe '`reject` patterns' do
118
119
  let(:source) { 'def alfa(bravo); charlie(bravo); end' }
119
120
 
120
- it 'reject smelly names via regex / strings given by list / literal' do
121
- [[/bravo/], /bravo/, ['bravo'], 'bravo'].each do |pattern|
121
+ it 'reject smelly names' do
122
+ patterns = [/brav/, /ravo/]
123
+ patterns.each do |pattern|
122
124
  expect(source).to reek_of(:UncommunicativeParameterName).with_config('reject' => pattern)
123
125
  end
124
126
  end
@@ -159,9 +159,9 @@ RSpec.describe Reek::SmellDetectors::UncommunicativeVariableName do
159
159
  describe '`accept` patterns' do
160
160
  let(:src) { 'def alfa; bravo2 = 42; end' }
161
161
 
162
- # FIXME: Move the loop out of the it?
163
- it 'make smelly names pass via regex / strings given by list / literal' do
164
- [[/bravo2/], /bravo2/, ['bravo2'], 'bravo2'].each do |pattern|
162
+ it 'make smelly names pass' do
163
+ patterns = [/ravo2/, /bravo2/]
164
+ patterns.each do |pattern|
165
165
  expect(src).to reek_of(:UncommunicativeVariableName).
166
166
  and not_reek_of(:UncommunicativeVariableName).with_config('accept' => pattern)
167
167
  end
@@ -171,9 +171,9 @@ RSpec.describe Reek::SmellDetectors::UncommunicativeVariableName do
171
171
  describe '`reject` patterns' do
172
172
  let(:src) { 'def alfa; foobar = 42; end' }
173
173
 
174
- # FIXME: Move the loop out of the it?
175
- it 'reject smelly names via regex / strings given by list / literal' do
176
- [[/foobar/], /foobar/, ['foobar'], 'foobar'].each do |pattern|
174
+ it 'reject smelly names' do
175
+ patterns = [/fooba/, /oobar/]
176
+ patterns.each do |pattern|
177
177
  expect(src).to not_reek_of(:UncommunicativeVariableName).
178
178
  and reek_of(:UncommunicativeVariableName).with_config('reject' => pattern)
179
179
  end
@@ -119,7 +119,7 @@ RSpec.describe Reek::SmellDetectors::UnusedPrivateMethod do
119
119
  context 'when the detector is configured via a source code comment' do
120
120
  it 'does not report methods we excluded' do
121
121
  source = <<-EOF
122
- # :reek:UnusedPrivateMethod: { exclude: [ bravo ] }
122
+ # :reek:UnusedPrivateMethod { exclude: [ bravo ] }
123
123
  class Alfa
124
124
  private
125
125
  def bravo; end
@@ -135,6 +135,10 @@ RSpec.describe Reek::SmellWarning do
135
135
  expect(yaml['source']).to eq source
136
136
  end
137
137
 
138
+ it 'includes the documentation link' do
139
+ expect(yaml['documentation_link']).to eq Reek::DocumentationLink.build('FeatureEnvy')
140
+ end
141
+
138
142
  it 'includes the parameters' do
139
143
  parameters.each do |key, value|
140
144
  expect(yaml[key]).to eq value
@@ -6,62 +6,56 @@ RSpec.describe Reek::Source::SourceCode do
6
6
  describe '#syntax_tree' do
7
7
  it 'associates comments with the AST' do
8
8
  source = "# this is\n# a comment\ndef foo; end"
9
- source_code = described_class.new(code: source, origin: '(string)')
9
+ source_code = described_class.new(source: source, origin: '(string)')
10
10
  result = source_code.syntax_tree
11
11
  expect(result.leading_comment).to eq "# this is\n# a comment"
12
12
  end
13
13
 
14
14
  it 'cleanly processes empty source' do
15
- source_code = described_class.new(code: '', origin: '(string)')
15
+ source_code = described_class.new(source: '', origin: '(string)')
16
16
  result = source_code.syntax_tree
17
- expect(result).to be_nil
17
+ expect(result.type).to eq :empty
18
18
  end
19
19
 
20
20
  it 'cleanly processes empty source with comments' do
21
21
  source = "# this is\n# a comment\n"
22
- source_code = described_class.new(code: source, origin: '(string)')
22
+ source_code = described_class.new(source: source, origin: '(string)')
23
23
  result = source_code.syntax_tree
24
- expect(result).to be_nil
24
+ expect(result.type).to eq :empty
25
25
  end
26
26
 
27
27
  it 'does not crash with sequences incompatible with UTF-8' do
28
28
  source = '"\xFF"'
29
- source_code = described_class.new(code: source, origin: '(string)')
29
+ source_code = described_class.new(source: source, origin: '(string)')
30
30
  result = source_code.syntax_tree
31
31
  expect(result.children.first).to eq "\xFF"
32
32
  end
33
33
 
34
34
  it 'returns a :lambda node for lambda expressions' do
35
35
  source = '->() { }'
36
- source_code = described_class.new(code: source, origin: '(string)')
36
+ source_code = described_class.new(source: source, origin: '(string)')
37
37
  result = source_code.syntax_tree
38
38
  expect(result.children.first.type).to eq :lambda
39
39
  end
40
- end
41
-
42
- context 'when the parser fails' do
43
- let(:source_name) { 'Test source' }
44
- let(:src) { described_class.new(code: code, origin: source_name, **options) }
45
40
 
46
- context 'with a Parser::SyntaxError' do
41
+ context 'when the parser fails with a Parser::SyntaxError' do
42
+ let(:src) { described_class.new(source: code) }
47
43
  let(:code) { '== Invalid Syntax ==' }
48
- let(:options) { {} }
49
44
 
50
- it 'adds a diagnostic' do
51
- expect(src.diagnostics.size).to eq 2
45
+ it 'raises the error' do
46
+ expect { src.syntax_tree }.to raise_error Parser::SyntaxError
52
47
  end
53
48
  end
54
49
 
55
- context 'with a generic error' do
50
+ context 'when the parser fails with a generic error' do
56
51
  let(:code) { '' }
52
+ let(:parser) { instance_double('Parser::Ruby25') }
53
+ let(:src) { described_class.new(source: code, parser: parser) }
57
54
  let(:error_class) { RuntimeError }
58
55
  let(:error_message) { 'An error' }
59
- let(:options) do
60
- parser = instance_double('Parser::Ruby25')
56
+
57
+ before do
61
58
  allow(parser).to receive(:parse_with_comments).and_raise(error_class, error_message)
62
- {
63
- parser: parser
64
- }
65
59
  end
66
60
 
67
61
  it 'raises the error' do
@@ -6,14 +6,14 @@ require_lib 'reek/source/source_locator'
6
6
  RSpec.describe Reek::Source::SourceLocator do
7
7
  describe '#sources' do
8
8
  context 'when applied to hidden directories' do
9
- let(:path) { SAMPLES_PATH.join('source_with_hidden_directories') }
9
+ let(:path) { SAMPLES_DIR.join('source_with_hidden_directories') }
10
10
 
11
11
  let(:expected_paths) do
12
- [path.join('uncommunicative_parameter_name.rb')]
12
+ [path.join('not_hidden.rb')]
13
13
  end
14
14
 
15
15
  let(:paths_that_are_expected_to_be_ignored) do
16
- [path.join('.hidden/uncommunicative_method_name.rb')]
16
+ [path.join('.hidden/hidden.rb')]
17
17
  end
18
18
 
19
19
  it 'does not scan hidden directories' do
@@ -32,16 +32,16 @@ RSpec.describe Reek::Source::SourceLocator do
32
32
  # rubocop:disable RSpec/NestedGroups
33
33
  context 'with excluded paths' do
34
34
  let(:configuration) do
35
- test_configuration_for(CONFIG_PATH.join('with_excluded_paths.reek'))
35
+ test_configuration_for(CONFIGURATION_DIR.join('with_excluded_paths.reek'))
36
36
  end
37
37
 
38
38
  let(:options) { instance_double('Reek::CLI::Options', force_exclusion?: false) }
39
39
 
40
40
  context 'when the path is absolute' do
41
41
  let(:path) do
42
- SAMPLES_PATH.join('source_with_exclude_paths',
43
- 'ignore_me',
44
- 'uncommunicative_method_name.rb').expand_path
42
+ SAMPLES_DIR.join('source_with_exclude_paths',
43
+ 'ignore_me',
44
+ 'uncommunicative_method_name.rb').expand_path
45
45
  end
46
46
 
47
47
  context 'when options.force_exclusion? is true' do
@@ -68,7 +68,7 @@ RSpec.describe Reek::Source::SourceLocator do
68
68
  end
69
69
 
70
70
  context 'when the path is a file name in an excluded directory' do
71
- let(:path) { SAMPLES_PATH.join('source_with_exclude_paths', 'ignore_me', 'uncommunicative_method_name.rb') }
71
+ let(:path) { SAMPLES_DIR.join('source_with_exclude_paths', 'ignore_me', 'uncommunicative_method_name.rb') }
72
72
 
73
73
  context 'when options.force_exclusion? is true' do
74
74
  before do
@@ -94,7 +94,7 @@ RSpec.describe Reek::Source::SourceLocator do
94
94
  end
95
95
 
96
96
  context 'when path is a directory' do
97
- let(:path) { SAMPLES_PATH.join('source_with_exclude_paths') }
97
+ let(:path) { SAMPLES_DIR.join('source_with_exclude_paths') }
98
98
 
99
99
  let(:expected_paths) do
100
100
  [path.join('nested/uncommunicative_parameter_name.rb')]
@@ -121,9 +121,9 @@ RSpec.describe Reek::Source::SourceLocator do
121
121
  # rubocop:enable RSpec/NestedGroups
122
122
 
123
123
  context 'with non-Ruby paths' do
124
- let(:path) { SAMPLES_PATH.join('source_with_non_ruby_files') }
124
+ let(:path) { SAMPLES_DIR.join('source_with_non_ruby_files') }
125
125
  let(:expected_sources) do
126
- [path.join('uncommunicative_parameter_name.rb')]
126
+ [path.join('ruby.rb')]
127
127
  end
128
128
  let(:paths_that_are_expected_to_be_ignored) do
129
129
  [