reek 6.0.2 → 6.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (271) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +13 -0
  3. data/.github/workflows/ruby.yml +57 -0
  4. data/.rubocop.yml +6 -12
  5. data/.rubocop_todo.yml +6 -4
  6. data/CHANGELOG.md +95 -0
  7. data/CONTRIBUTING.md +10 -10
  8. data/Dockerfile +1 -1
  9. data/Gemfile +8 -7
  10. data/README.md +29 -29
  11. data/bin/code_climate_reek +56 -8
  12. data/lib/reek/ast/ast_node_class_map.rb +1 -1
  13. data/lib/reek/ast/node.rb +1 -1
  14. data/lib/reek/ast/sexp_extensions/arguments.rb +20 -0
  15. data/lib/reek/ast/sexp_extensions/case.rb +1 -1
  16. data/lib/reek/ast/sexp_extensions/if.rb +1 -1
  17. data/lib/reek/ast/sexp_extensions/send.rb +22 -7
  18. data/lib/reek/cli/command/todo_list_command.rb +3 -3
  19. data/lib/reek/cli/options.rb +6 -6
  20. data/lib/reek/{report/code_climate → code_climate}/code_climate_configuration.rb +1 -1
  21. data/lib/reek/{report/code_climate → code_climate}/code_climate_configuration.yml +41 -41
  22. data/lib/reek/{report/code_climate → code_climate}/code_climate_fingerprint.rb +2 -2
  23. data/lib/reek/{report/code_climate → code_climate}/code_climate_formatter.rb +2 -4
  24. data/lib/reek/{report/code_climate → code_climate}/code_climate_report.rb +3 -3
  25. data/lib/reek/code_comment.rb +25 -20
  26. data/lib/reek/configuration/app_configuration.rb +5 -5
  27. data/lib/reek/configuration/configuration_converter.rb +1 -1
  28. data/lib/reek/configuration/configuration_file_finder.rb +5 -4
  29. data/lib/reek/configuration/default_directive.rb +1 -1
  30. data/lib/reek/configuration/directory_directives.rb +1 -1
  31. data/lib/reek/configuration/excluded_paths.rb +3 -2
  32. data/lib/reek/configuration/schema.rb +177 -0
  33. data/lib/reek/configuration/schema_validator.rb +12 -13
  34. data/lib/reek/context/attribute_context.rb +1 -1
  35. data/lib/reek/context/code_context.rb +1 -1
  36. data/lib/reek/context/method_context.rb +1 -1
  37. data/lib/reek/context/module_context.rb +4 -0
  38. data/lib/reek/context/refinement_context.rb +16 -0
  39. data/lib/reek/context/send_context.rb +7 -1
  40. data/lib/reek/context_builder.rb +17 -3
  41. data/lib/reek/documentation_link.rb +3 -5
  42. data/lib/reek/errors/bad_detector_configuration_key_in_comment_error.rb +2 -2
  43. data/lib/reek/errors/bad_detector_in_comment_error.rb +2 -2
  44. data/lib/reek/errors/encoding_error.rb +1 -1
  45. data/lib/reek/errors/garbage_detector_configuration_in_comment_error.rb +2 -2
  46. data/lib/reek/errors/incomprehensible_source_error.rb +1 -1
  47. data/lib/reek/errors/legacy_comment_separator_error.rb +2 -2
  48. data/lib/reek/errors/syntax_error.rb +1 -1
  49. data/lib/reek/rake/task.rb +5 -5
  50. data/lib/reek/smell_detectors/base_detector.rb +1 -1
  51. data/lib/reek/smell_detectors/class_variable.rb +2 -2
  52. data/lib/reek/smell_detectors/control_parameter_helpers/candidate.rb +6 -6
  53. data/lib/reek/smell_detectors/control_parameter_helpers/control_parameter_finder.rb +1 -1
  54. data/lib/reek/smell_detectors/duplicate_method_call.rb +5 -5
  55. data/lib/reek/smell_detectors/instance_variable_assumption.rb +8 -8
  56. data/lib/reek/smell_detectors/nested_iterators.rb +4 -3
  57. data/lib/reek/smell_detectors/unused_private_method.rb +3 -2
  58. data/lib/reek/smell_warning.rb +1 -1
  59. data/lib/reek/source/source_locator.rb +1 -3
  60. data/lib/reek/spec/should_reek_of.rb +11 -9
  61. data/lib/reek/spec.rb +1 -1
  62. data/lib/reek/version.rb +2 -2
  63. data/reek.gemspec +29 -25
  64. metadata +37 -250
  65. data/.travis.yml +0 -40
  66. data/docs/API.md +0 -174
  67. data/docs/Attribute.md +0 -39
  68. data/docs/Basic-Smell-Options.md +0 -85
  69. data/docs/Boolean-Parameter.md +0 -54
  70. data/docs/Class-Variable.md +0 -40
  71. data/docs/Code-Smells.md +0 -39
  72. data/docs/Command-Line-Options.md +0 -119
  73. data/docs/Control-Couple.md +0 -26
  74. data/docs/Control-Parameter.md +0 -32
  75. data/docs/Data-Clump.md +0 -46
  76. data/docs/Duplicate-Method-Call.md +0 -264
  77. data/docs/Feature-Envy.md +0 -93
  78. data/docs/How-To-Write-New-Detectors.md +0 -132
  79. data/docs/How-reek-works-internally.md +0 -114
  80. data/docs/Instance-Variable-Assumption.md +0 -163
  81. data/docs/Irresponsible-Module.md +0 -47
  82. data/docs/Large-Class.md +0 -16
  83. data/docs/Long-Parameter-List.md +0 -39
  84. data/docs/Long-Yield-List.md +0 -37
  85. data/docs/Manual-Dispatch.md +0 -30
  86. data/docs/Missing-Safe-Method.md +0 -92
  87. data/docs/Module-Initialize.md +0 -62
  88. data/docs/Nested-Iterators.md +0 -59
  89. data/docs/Nil-Check.md +0 -47
  90. data/docs/RSpec-matchers.md +0 -129
  91. data/docs/Rake-Task.md +0 -66
  92. data/docs/Reek-4-to-Reek-5-migration.md +0 -188
  93. data/docs/Reek-Driven-Development.md +0 -46
  94. data/docs/Repeated-Conditional.md +0 -47
  95. data/docs/Simulated-Polymorphism.md +0 -16
  96. data/docs/Smell-Suppression.md +0 -96
  97. data/docs/Style-Guide.md +0 -19
  98. data/docs/Subclassed-From-Core-Class.md +0 -79
  99. data/docs/Too-Many-Constants.md +0 -37
  100. data/docs/Too-Many-Instance-Variables.md +0 -43
  101. data/docs/Too-Many-Methods.md +0 -56
  102. data/docs/Too-Many-Statements.md +0 -54
  103. data/docs/Uncommunicative-Method-Name.md +0 -94
  104. data/docs/Uncommunicative-Module-Name.md +0 -92
  105. data/docs/Uncommunicative-Name.md +0 -18
  106. data/docs/Uncommunicative-Parameter-Name.md +0 -90
  107. data/docs/Uncommunicative-Variable-Name.md +0 -96
  108. data/docs/Unused-Parameters.md +0 -28
  109. data/docs/Unused-Private-Method.md +0 -101
  110. data/docs/Utility-Function.md +0 -56
  111. data/docs/Versioning-Policy.md +0 -7
  112. data/docs/YAML-Reports.md +0 -93
  113. data/docs/defaults.reek.yml +0 -129
  114. data/docs/templates/default/docstring/html/public_api_marker.erb +0 -3
  115. data/docs/templates/default/docstring/setup.rb +0 -37
  116. data/docs/templates/default/fulldoc/html/css/common.css +0 -1
  117. data/docs/yard_plugin.rb +0 -17
  118. data/features/command_line_interface/basic_usage.feature +0 -15
  119. data/features/command_line_interface/options.feature +0 -123
  120. data/features/command_line_interface/show_progress.feature +0 -33
  121. data/features/command_line_interface/smell_selection.feature +0 -15
  122. data/features/command_line_interface/smells_count.feature +0 -38
  123. data/features/command_line_interface/stdin.feature +0 -65
  124. data/features/configuration_files/accept_setting.feature +0 -87
  125. data/features/configuration_files/directory_specific_directives.feature +0 -274
  126. data/features/configuration_files/exclude_directives.feature +0 -35
  127. data/features/configuration_files/exclude_paths_directives.feature +0 -42
  128. data/features/configuration_files/masking_smells.feature +0 -94
  129. data/features/configuration_files/mix_accept_reject_setting.feature +0 -84
  130. data/features/configuration_files/reject_setting.feature +0 -89
  131. data/features/configuration_files/schema_validation.feature +0 -59
  132. data/features/configuration_files/show_configuration_file.feature +0 -44
  133. data/features/configuration_files/unused_private_method.feature +0 -68
  134. data/features/configuration_loading.feature +0 -91
  135. data/features/configuration_via_source_comments/erroneous_source_comments.feature +0 -68
  136. data/features/configuration_via_source_comments/well_formed_source_comments.feature +0 -116
  137. data/features/locales.feature +0 -32
  138. data/features/programmatic_access.feature +0 -41
  139. data/features/rake_task/rake_task.feature +0 -138
  140. data/features/reports/codeclimate.feature +0 -59
  141. data/features/reports/json.feature +0 -59
  142. data/features/reports/reports.feature +0 -219
  143. data/features/reports/yaml.feature +0 -52
  144. data/features/rspec_matcher.feature +0 -41
  145. data/features/samples.feature +0 -305
  146. data/features/step_definitions/.rubocop.yml +0 -5
  147. data/features/step_definitions/reek_steps.rb +0 -102
  148. data/features/step_definitions/sample_file_steps.rb +0 -63
  149. data/features/support/env.rb +0 -33
  150. data/features/todo_list.feature +0 -108
  151. data/lib/reek/configuration/schema.yml +0 -210
  152. data/samples/checkstyle.xml +0 -7
  153. data/samples/clean_source/clean.rb +0 -6
  154. data/samples/configuration/accepts_rejects_and_excludes_for_detectors.reek.yml +0 -29
  155. data/samples/configuration/accepts_rejects_and_excludes_for_directory_directives.reek.yml +0 -30
  156. data/samples/configuration/corrupt.reek +0 -1
  157. data/samples/configuration/empty.reek +0 -0
  158. data/samples/configuration/full_configuration.reek +0 -13
  159. data/samples/configuration/full_mask.reek +0 -6
  160. data/samples/configuration/home/home.reek.yml +0 -4
  161. data/samples/configuration/partial_mask.reek +0 -4
  162. data/samples/configuration/regular_configuration/.reek.yml +0 -4
  163. data/samples/configuration/regular_configuration/empty_sub_directory/.gitignore +0 -0
  164. data/samples/configuration/with_excluded_paths.reek +0 -5
  165. data/samples/no_config_file/.keep +0 -0
  166. data/samples/paths.rb +0 -5
  167. data/samples/smelly_source/inline.rb +0 -704
  168. data/samples/smelly_source/optparse.rb +0 -1788
  169. data/samples/smelly_source/redcloth.rb +0 -1130
  170. data/samples/smelly_source/ruby.rb +0 -368
  171. data/samples/smelly_source/smelly.rb +0 -7
  172. data/samples/source_with_exclude_paths/ignore_me/uncommunicative_method_name.rb +0 -5
  173. data/samples/source_with_exclude_paths/nested/ignore_me_as_well/irresponsible_module.rb +0 -2
  174. data/samples/source_with_exclude_paths/nested/uncommunicative_parameter_name.rb +0 -6
  175. data/samples/source_with_exclude_paths/nested/uncommunicative_variable_name.rb +0 -6
  176. data/samples/source_with_hidden_directories/.hidden/hidden.rb +0 -1
  177. data/samples/source_with_hidden_directories/not_hidden.rb +0 -1
  178. data/samples/source_with_non_ruby_files/gibberish +0 -1
  179. data/samples/source_with_non_ruby_files/python_source.py +0 -1
  180. data/samples/source_with_non_ruby_files/ruby.rb +0 -6
  181. data/spec/performance/reek/smell_detectors/runtime_speed_spec.rb +0 -15
  182. data/spec/quality/documentation_spec.rb +0 -41
  183. data/spec/quality/reek_source_spec.rb +0 -11
  184. data/spec/reek/ast/node_spec.rb +0 -211
  185. data/spec/reek/ast/object_refs_spec.rb +0 -83
  186. data/spec/reek/ast/reference_collector_spec.rb +0 -47
  187. data/spec/reek/ast/sexp_extensions_spec.rb +0 -498
  188. data/spec/reek/cli/application_spec.rb +0 -168
  189. data/spec/reek/cli/command/report_command_spec.rb +0 -44
  190. data/spec/reek/cli/command/todo_list_command_spec.rb +0 -86
  191. data/spec/reek/cli/options_spec.rb +0 -51
  192. data/spec/reek/cli/silencer_spec.rb +0 -28
  193. data/spec/reek/code_comment_spec.rb +0 -184
  194. data/spec/reek/configuration/app_configuration_spec.rb +0 -195
  195. data/spec/reek/configuration/configuration_file_finder_spec.rb +0 -230
  196. data/spec/reek/configuration/default_directive_spec.rb +0 -13
  197. data/spec/reek/configuration/directory_directives_spec.rb +0 -122
  198. data/spec/reek/configuration/excluded_paths_spec.rb +0 -16
  199. data/spec/reek/configuration/rake_task_converter_spec.rb +0 -33
  200. data/spec/reek/configuration/schema_validator_spec.rb +0 -165
  201. data/spec/reek/context/code_context_spec.rb +0 -192
  202. data/spec/reek/context/ghost_context_spec.rb +0 -60
  203. data/spec/reek/context/method_context_spec.rb +0 -72
  204. data/spec/reek/context/module_context_spec.rb +0 -55
  205. data/spec/reek/context/root_context_spec.rb +0 -12
  206. data/spec/reek/context/statement_counter_spec.rb +0 -24
  207. data/spec/reek/context_builder_spec.rb +0 -457
  208. data/spec/reek/detector_repository_spec.rb +0 -22
  209. data/spec/reek/documentation_link_spec.rb +0 -20
  210. data/spec/reek/errors/base_error_spec.rb +0 -13
  211. data/spec/reek/examiner_spec.rb +0 -309
  212. data/spec/reek/logging_error_handler_spec.rb +0 -24
  213. data/spec/reek/rake/task_spec.rb +0 -56
  214. data/spec/reek/report/code_climate/code_climate_configuration_spec.rb +0 -22
  215. data/spec/reek/report/code_climate/code_climate_fingerprint_spec.rb +0 -126
  216. data/spec/reek/report/code_climate/code_climate_formatter_spec.rb +0 -51
  217. data/spec/reek/report/code_climate/code_climate_report_spec.rb +0 -56
  218. data/spec/reek/report/html_report_spec.rb +0 -19
  219. data/spec/reek/report/json_report_spec.rb +0 -58
  220. data/spec/reek/report/location_formatter_spec.rb +0 -32
  221. data/spec/reek/report/progress_formatter_spec.rb +0 -68
  222. data/spec/reek/report/text_report_spec.rb +0 -89
  223. data/spec/reek/report/xml_report_spec.rb +0 -24
  224. data/spec/reek/report/yaml_report_spec.rb +0 -55
  225. data/spec/reek/report_spec.rb +0 -28
  226. data/spec/reek/smell_configuration_spec.rb +0 -56
  227. data/spec/reek/smell_detectors/attribute_spec.rb +0 -197
  228. data/spec/reek/smell_detectors/base_detector_spec.rb +0 -50
  229. data/spec/reek/smell_detectors/boolean_parameter_spec.rb +0 -93
  230. data/spec/reek/smell_detectors/class_variable_spec.rb +0 -106
  231. data/spec/reek/smell_detectors/control_parameter_spec.rb +0 -300
  232. data/spec/reek/smell_detectors/data_clump_spec.rb +0 -134
  233. data/spec/reek/smell_detectors/duplicate_method_call_spec.rb +0 -211
  234. data/spec/reek/smell_detectors/feature_envy_spec.rb +0 -295
  235. data/spec/reek/smell_detectors/instance_variable_assumption_spec.rb +0 -96
  236. data/spec/reek/smell_detectors/irresponsible_module_spec.rb +0 -226
  237. data/spec/reek/smell_detectors/long_parameter_list_spec.rb +0 -61
  238. data/spec/reek/smell_detectors/long_yield_list_spec.rb +0 -49
  239. data/spec/reek/smell_detectors/manual_dispatch_spec.rb +0 -75
  240. data/spec/reek/smell_detectors/missing_safe_method_spec.rb +0 -68
  241. data/spec/reek/smell_detectors/module_initialize_spec.rb +0 -77
  242. data/spec/reek/smell_detectors/nested_iterators_spec.rb +0 -333
  243. data/spec/reek/smell_detectors/nil_check_spec.rb +0 -100
  244. data/spec/reek/smell_detectors/repeated_conditional_spec.rb +0 -100
  245. data/spec/reek/smell_detectors/subclassed_from_core_class_spec.rb +0 -77
  246. data/spec/reek/smell_detectors/too_many_constants_spec.rb +0 -144
  247. data/spec/reek/smell_detectors/too_many_instance_variables_spec.rb +0 -132
  248. data/spec/reek/smell_detectors/too_many_methods_spec.rb +0 -54
  249. data/spec/reek/smell_detectors/too_many_statements_spec.rb +0 -90
  250. data/spec/reek/smell_detectors/uncommunicative_method_name_spec.rb +0 -78
  251. data/spec/reek/smell_detectors/uncommunicative_module_name_spec.rb +0 -78
  252. data/spec/reek/smell_detectors/uncommunicative_parameter_name_spec.rb +0 -147
  253. data/spec/reek/smell_detectors/uncommunicative_variable_name_spec.rb +0 -201
  254. data/spec/reek/smell_detectors/unused_parameters_spec.rb +0 -114
  255. data/spec/reek/smell_detectors/unused_private_method_spec.rb +0 -205
  256. data/spec/reek/smell_detectors/utility_function_spec.rb +0 -293
  257. data/spec/reek/smell_warning_spec.rb +0 -137
  258. data/spec/reek/source/source_code_spec.rb +0 -79
  259. data/spec/reek/source/source_locator_spec.rb +0 -166
  260. data/spec/reek/spec/should_reek_of_spec.rb +0 -153
  261. data/spec/reek/spec/should_reek_only_of_spec.rb +0 -91
  262. data/spec/reek/spec/should_reek_spec.rb +0 -52
  263. data/spec/reek/spec/smell_matcher_spec.rb +0 -87
  264. data/spec/reek/tree_dresser_spec.rb +0 -46
  265. data/spec/spec_helper.rb +0 -110
  266. data/tasks/configuration.rake +0 -18
  267. data/tasks/console.rake +0 -5
  268. data/tasks/reek.rake +0 -6
  269. data/tasks/rubocop.rake +0 -11
  270. data/tasks/test.rake +0 -32
  271. /data/lib/reek/{report/code_climate.rb → code_climate.rb} +0 -0
@@ -1,309 +0,0 @@
1
- require_relative '../spec_helper'
2
- require_lib 'reek/examiner'
3
- require_lib 'reek/logging_error_handler'
4
-
5
- RSpec.shared_examples_for 'no smells found' do
6
- it 'is not smelly' do
7
- expect(examiner).not_to be_smelly
8
- end
9
-
10
- it 'finds no smells' do
11
- expect(examiner.smells.length).to eq(0)
12
- end
13
- end
14
-
15
- RSpec.shared_examples_for 'one smell found' do
16
- it 'is smelly' do
17
- expect(examiner).to be_smelly
18
- end
19
-
20
- it 'reports the smell' do
21
- expect(examiner.smells.length).to eq(1)
22
- end
23
-
24
- it 'reports the correct smell' do
25
- expect(examiner.smells[0].smell_type).to eq(expected_first_smell)
26
- end
27
- end
28
-
29
- RSpec.describe Reek::Examiner do
30
- context 'with a fragrant String' do
31
- let(:examiner) { described_class.new('def good() true; end') }
32
-
33
- it_behaves_like 'no smells found'
34
- end
35
-
36
- context 'with a smelly String' do
37
- let(:examiner) { described_class.new('def fine() y = 4; end') }
38
- let(:expected_first_smell) { 'UncommunicativeVariableName' }
39
-
40
- it_behaves_like 'one smell found'
41
- end
42
-
43
- context 'with a partially masked smelly File' do
44
- let(:configuration) { test_configuration_for(path) }
45
- let(:examiner) do
46
- described_class.new(SMELLY_FILE,
47
- filter_by_smells: [],
48
- configuration: configuration)
49
- end
50
- let(:path) { CONFIGURATION_DIR.join('partial_mask.reek') }
51
- let(:expected_first_smell) { 'UncommunicativeVariableName' }
52
-
53
- it_behaves_like 'one smell found'
54
- end
55
-
56
- context 'with a fragrant File' do
57
- let(:examiner) { described_class.new(CLEAN_FILE) }
58
-
59
- it_behaves_like 'no smells found'
60
- end
61
-
62
- describe '#origin' do
63
- let(:source) { 'class C; def f; end; end' }
64
- let(:examiner) { described_class.new(source) }
65
-
66
- it 'returns "string" for a string source' do
67
- expect(examiner.origin).to eq('string')
68
- end
69
- end
70
-
71
- describe '#smells' do
72
- it 'returns the detected smell warnings' do
73
- code = 'def foo; bar.call_me(); bar.call_me(); end'
74
- examiner = described_class.new code, filter_by_smells: ['DuplicateMethodCall']
75
-
76
- smell = examiner.smells.first
77
- expect(smell).to be_a(Reek::SmellWarning)
78
- expect(smell.message).to eq("calls 'bar.call_me()' 2 times")
79
- end
80
-
81
- context 'with a source with three smells' do
82
- let(:source) { 'class C; def f; end; end' }
83
- let(:examiner) { described_class.new(source) }
84
-
85
- it 'has the right smells' do
86
- smells = examiner.smells
87
- expect(smells.map(&:message)).
88
- to eq ['has no descriptive comment',
89
- "has the name 'f'",
90
- "has the name 'C'"]
91
- end
92
- end
93
-
94
- context 'when source only contains comments' do
95
- let(:source) do
96
- <<-RUBY
97
- # Just a comment
98
- # And another
99
- RUBY
100
- end
101
- let(:examiner) do
102
- described_class.new(source)
103
- end
104
-
105
- it 'has no warnings' do
106
- expect(examiner.smells).to eq([])
107
- end
108
- end
109
-
110
- context 'with an incomprehensible source that causes the detectors to crash' do
111
- let(:source) { 'class C; def does_crash_reek; end; end' }
112
-
113
- let(:examiner) do
114
- detector_repository = instance_double 'Reek::DetectorRepository'
115
- allow(detector_repository).to receive(:examine) do
116
- raise ArgumentError, 'Looks like bad source'
117
- end
118
- class_double('Reek::DetectorRepository').as_stubbed_const
119
- allow(Reek::DetectorRepository).to receive(:eligible_smell_types)
120
- allow(Reek::DetectorRepository).to receive(:new).and_return detector_repository
121
-
122
- described_class.new source
123
- end
124
-
125
- it 'raises an incomprehensible source error' do
126
- expect { examiner.smells }.to raise_error Reek::Errors::IncomprehensibleSourceError
127
- end
128
-
129
- it 'explains the origin of the error' do
130
- origin = 'string'
131
- expect { examiner.smells }.
132
- to raise_error.with_message("Source #{origin} cannot be processed by Reek.")
133
- end
134
-
135
- it 'explains what to do' do
136
- explanation = 'It would be great if you could report this back to the Reek team'
137
- expect { examiner.smells }.
138
- to raise_error { |it| expect(it.long_message).to match(/#{explanation}/) }
139
- end
140
-
141
- it 'contains the original error message' do
142
- original = 'Looks like bad source'
143
- expect { examiner.smells }.
144
- to raise_error { |it| expect(it.long_message).to match(/#{original}/) }
145
- end
146
-
147
- it 'shows the original exception class' do
148
- expect { examiner.smells }.
149
- to raise_error { |it| expect(it.long_message).to match(/ArgumentError/) }
150
- end
151
- end
152
- end
153
-
154
- describe '#smells_count' do
155
- let(:source) { 'class C; def f; end; end' }
156
- let(:examiner) { described_class.new(source) }
157
-
158
- it 'has the right smell count' do
159
- expect(examiner.smells_count).to eq(3)
160
- end
161
- end
162
-
163
- context 'when the source causes the source buffer to crash' do
164
- let(:source) { 'I make the buffer crash' }
165
-
166
- before do
167
- buffer = double
168
- allow(buffer).to receive(:source=) { raise RuntimeError }
169
- allow(Parser::Source::Buffer).to receive(:new).and_return(buffer)
170
- end
171
-
172
- context 'when the error handler does not handle the error' do
173
- let(:examiner) { described_class.new(source) }
174
-
175
- it 'does not raise an error during initialization' do
176
- expect { examiner }.not_to raise_error
177
- end
178
-
179
- it 'raises an incomprehensible source error when asked for smells' do
180
- expect { examiner.smells }.to raise_error Reek::Errors::IncomprehensibleSourceError
181
- end
182
- end
183
-
184
- context 'when the error handler handles the error' do
185
- let(:handler) { instance_double(Reek::LoggingErrorHandler, handle: true) }
186
- let(:examiner) { described_class.new(source, error_handler: handler) }
187
-
188
- it 'does not raise an error when asked for smells' do
189
- expect { examiner.smells }.not_to raise_error
190
- end
191
-
192
- it 'passes the wrapped error to the handler' do
193
- examiner.smells
194
- expect(handler).to have_received(:handle).with(Reek::Errors::IncomprehensibleSourceError)
195
- end
196
- end
197
- end
198
-
199
- context 'with a source that triggers a syntax error' do
200
- let(:examiner) { described_class.new(source) }
201
- let(:source) do
202
- <<~RUBY
203
- 1 2 3
204
- RUBY
205
- end
206
-
207
- it 'does not raise an error during initialization' do
208
- expect { examiner }.not_to raise_error
209
- end
210
-
211
- it 'raises an encoding error when asked for smells' do
212
- expect { examiner.smells }.to raise_error Reek::Errors::SyntaxError
213
- end
214
-
215
- it 'explains the origin of the error' do
216
- message = "Source 'string' cannot be processed by Reek due to a syntax error in the source file."
217
- expect { examiner.smells }.to raise_error.with_message(/#{message}/)
218
- end
219
-
220
- it 'shows the original exception class' do
221
- expect { examiner.smells }.
222
- to raise_error { |it| expect(it.long_message).to match(/Parser::SyntaxError/) }
223
- end
224
- end
225
-
226
- context 'with a source that triggers an encoding error' do
227
- let(:examiner) { described_class.new(source) }
228
- let(:source) do
229
- <<~RUBY
230
- # encoding: US-ASCII
231
- puts 'こんにちは世界'
232
- RUBY
233
- end
234
-
235
- it 'does not raise an error during initialization' do
236
- expect { examiner }.not_to raise_error
237
- end
238
-
239
- it 'raises an encoding error when asked for smells' do
240
- expect { examiner.smells }.to raise_error Reek::Errors::EncodingError
241
- end
242
-
243
- it 'explains the origin of the error' do
244
- message = "Source 'string' cannot be processed by Reek due to an encoding error in the source file."
245
- expect { examiner.smells }.to raise_error.with_message(/#{message}/)
246
- end
247
-
248
- it 'shows the original exception class' do
249
- expect { examiner.smells }.
250
- to raise_error { |it| expect(it.long_message).to match(/InvalidByteSequenceError/) }
251
- end
252
- end
253
-
254
- describe 'bad comment config' do
255
- let(:examiner) { described_class.new(source) }
256
-
257
- context 'with an unknown smell detector' do
258
- let(:source) do
259
- <<-RUBY
260
- # :reek:DoesNotExist
261
- def alfa; end
262
- RUBY
263
- end
264
-
265
- it 'raises a bad detector name error' do
266
- expect { examiner.smells }.to raise_error Reek::Errors::BadDetectorInCommentError
267
- end
268
-
269
- it 'explains the reason for the error' do
270
- message = "You are trying to configure an unknown smell detector 'DoesNotExist'"
271
-
272
- expect { examiner.smells }.to raise_error.with_message(/#{message}/)
273
- end
274
-
275
- it 'explains the origin of the error' do
276
- details = "The source is 'string' and the comment belongs "\
277
- 'to the expression starting in line 2.'
278
-
279
- expect { examiner.smells }.to raise_error.with_message(/#{details}/)
280
- end
281
- end
282
-
283
- context 'with garbage in detector config' do
284
- let(:source) do
285
- <<-RUBY
286
- # :reek:UncommunicativeMethodName { thats: a: bad: config }
287
- def alfa; end
288
- RUBY
289
- end
290
-
291
- it 'raises a garbarge configuration error' do
292
- expect { examiner.smells }.to raise_error Reek::Errors::GarbageDetectorConfigurationInCommentError
293
- end
294
-
295
- it 'explains the reason for the error' do
296
- message = "Error: You are trying to configure the smell detector 'UncommunicativeMethodName'"
297
-
298
- expect { examiner.smells }.to raise_error.with_message(/#{message}/)
299
- end
300
-
301
- it 'explains the origin of the error' do
302
- details = "The source is 'string' and the comment belongs "\
303
- 'to the expression starting in line 2.'
304
-
305
- expect { examiner.smells }.to raise_error.with_message(/#{details}/)
306
- end
307
- end
308
- end
309
- end
@@ -1,24 +0,0 @@
1
- require_relative '../spec_helper'
2
- require_lib 'reek/logging_error_handler'
3
-
4
- RSpec.describe Reek::LoggingErrorHandler do
5
- describe '#handle' do
6
- let(:exception) { RuntimeError.new('some message') }
7
- let(:handler) { described_class.new }
8
-
9
- it "outputs the exception's message to stderr" do
10
- expect { handler.handle(exception) }.
11
- to output(/some message/).to_stderr
12
- end
13
-
14
- it 'indicates the exception has been appropriately handled' do
15
- result = false
16
-
17
- Reek::CLI::Silencer.silently do
18
- result = handler.handle(exception)
19
- end
20
-
21
- expect(result).to be_truthy
22
- end
23
- end
24
- end
@@ -1,56 +0,0 @@
1
- require_relative '../../spec_helper'
2
- require_lib 'reek/rake/task'
3
-
4
- RSpec.describe Reek::Rake::Task do
5
- describe '#source_files' do
6
- it 'is set to "lib/**/*.rb" by default' do
7
- task = described_class.new
8
- expect(task.source_files).to eq FileList['lib/**/*.rb']
9
- end
10
-
11
- it 'is set to ENV["REEK_SRC"]' do
12
- begin
13
- ENV['REEK_SRC'] = '*.rb'
14
- task = described_class.new
15
- expect(task.source_files).to eq FileList['*.rb']
16
- ensure
17
- ENV['REEK_SRC'] = nil
18
- end
19
- end
20
- end
21
-
22
- describe '#source_files=' do
23
- it 'sets source_files to a FileList when passed a string' do
24
- task = described_class.new do |it|
25
- it.source_files = '*.rb'
26
- end
27
- expect(task.source_files).to eq FileList['*.rb']
28
- end
29
-
30
- it 'has no effect when ENV["REEK_SRC"] is set' do
31
- begin
32
- ENV['REEK_SRC'] = '*.rb'
33
- task = described_class.new do |it|
34
- it.source_files = 'lib/*.rb'
35
- end
36
- expect(task.source_files).to eq FileList['*.rb']
37
- ensure
38
- ENV['REEK_SRC'] = nil
39
- end
40
- end
41
- end
42
-
43
- # SMELL: Testing a private method
44
- describe '#command' do
45
- let(:task) { described_class.new }
46
-
47
- it 'does not include a config file by default' do
48
- expect(task.send(:command)).not_to include '-c'
49
- end
50
-
51
- it 'includes a config file when set' do
52
- task.config_file = 'foo.reek'
53
- expect(task.send(:command)[1..2]).to eq ['-c', 'foo.reek']
54
- end
55
- end
56
- end
@@ -1,22 +0,0 @@
1
- require_relative '../../../spec_helper'
2
- require_lib 'reek/report/code_climate/code_climate_configuration'
3
-
4
- RSpec.describe Reek::Report::CodeClimateConfiguration do
5
- yml = described_class.load
6
- smell_types = Reek::SmellDetectors::BaseDetector.descendants.map(&:smell_type)
7
-
8
- smell_types.each do |name|
9
- config = yml.fetch(name)
10
- it "provides remediation_points for #{name}" do
11
- expect(config['remediation_points']).to be_a Integer
12
- end
13
-
14
- it "provides content for #{name}" do
15
- expect(config['content']).to be_a String
16
- end
17
- end
18
-
19
- it 'does not include extraneous configuration' do
20
- expect(smell_types).to match_array(yml.keys)
21
- end
22
- end
@@ -1,126 +0,0 @@
1
- require_relative '../../../spec_helper'
2
- require_lib 'reek/report/code_climate/code_climate_fingerprint'
3
-
4
- RSpec.describe Reek::Report::CodeClimateFingerprint do
5
- describe '#compute' do
6
- let(:computed) { described_class.new(warning).compute }
7
-
8
- context 'when fingerprinting a warning with no parameters' do
9
- let(:expected_fingerprint) { 'e68badd29db51c92363a7c6a2438d722' }
10
- let(:warning) do
11
- Reek::SmellWarning.new(
12
- 'UtilityFunction',
13
- context: 'alfa',
14
- message: "doesn't depend on instance state (maybe move it to another class?)",
15
- lines: lines,
16
- source: 'a/ruby/source/file.rb')
17
- end
18
-
19
- context 'with code at a specific location' do
20
- let(:lines) { [1] }
21
-
22
- it 'computes the fingerprint' do
23
- expect(computed).to eq expected_fingerprint
24
- end
25
- end
26
-
27
- context 'with code at a different location' do
28
- let(:lines) { [5] }
29
-
30
- it 'computes the same fingerprint' do
31
- expect(computed).to eq expected_fingerprint
32
- end
33
- end
34
- end
35
-
36
- context 'when the fingerprint should not be computed' do
37
- let(:warning) do
38
- Reek::SmellWarning.new(
39
- 'ManualDispatch',
40
- context: 'Alfa#bravo',
41
- message: 'manually dispatches method call',
42
- lines: [4],
43
- source: 'a/ruby/source/file.rb')
44
- end
45
-
46
- it 'returns nil' do
47
- expect(computed).to be_nil
48
- end
49
- end
50
-
51
- context 'when the smell warning has only identifying parameters' do
52
- let(:warning) do
53
- Reek::SmellWarning.new(
54
- 'ClassVariable',
55
- context: 'Alfa',
56
- message: "declares the class variable '@@#{name}'",
57
- lines: [4],
58
- parameters: { name: "@@#{name}" },
59
- source: 'a/ruby/source/file.rb')
60
- end
61
-
62
- context 'when the name is one thing' do
63
- let(:name) { 'bravo' }
64
- let(:expected_fingerprint) { '9c3fd378178118a67e9509f87cae24f9' }
65
-
66
- it 'computes the fingerprint' do
67
- expect(computed).to eq expected_fingerprint
68
- end
69
- end
70
-
71
- context 'when the name is another thing' do
72
- let(:name) { 'echo' }
73
- let(:expected_fingerprint) { 'd2a6d2703ce04cca65e7300b7de4b89f' }
74
-
75
- it 'computes another fingerprint' do
76
- expect(computed).to eq expected_fingerprint
77
- end
78
- end
79
- end
80
-
81
- context 'when the smell warning has identifying and non-identifying parameters' do
82
- let(:warning) do
83
- Reek::SmellWarning.new(
84
- 'DuplicateMethodCall',
85
- context: "Alfa##{name}",
86
- message: "calls '#{name}' #{count} times",
87
- lines: lines,
88
- parameters: { name: "@@#{name}", count: count },
89
- source: 'a/ruby/source/file.rb')
90
- end
91
-
92
- context 'when the parameters are provided' do
93
- let(:name) { 'bravo' }
94
- let(:count) { 5 }
95
- let(:lines) { [1, 7, 10, 13, 15] }
96
- let(:expected_fingerprint) { '238733f4f51ba5473dcbe94a43ec5400' }
97
-
98
- it 'computes the fingerprint' do
99
- expect(computed).to eq expected_fingerprint
100
- end
101
- end
102
-
103
- context 'when the non-identifying parameters change' do
104
- let(:name) { 'bravo' }
105
- let(:count) { 9 }
106
- let(:lines) { [1, 7, 10, 13, 15, 17, 19, 20, 25] }
107
- let(:expected_fingerprint) { '238733f4f51ba5473dcbe94a43ec5400' }
108
-
109
- it 'computes the same fingerprint' do
110
- expect(computed).to eq expected_fingerprint
111
- end
112
- end
113
-
114
- context 'when the identifying parameters change' do
115
- let(:name) { 'echo' }
116
- let(:count) { 5 }
117
- let(:lines) { [1, 7, 10, 13, 15] }
118
- let(:expected_fingerprint) { 'e0c35e9223cc19bdb9a04fb3e60573e1' }
119
-
120
- it 'computes a different fingerprint' do
121
- expect(computed).to eq expected_fingerprint
122
- end
123
- end
124
- end
125
- end
126
- end
@@ -1,51 +0,0 @@
1
- require_relative '../../../spec_helper'
2
- require_lib 'reek/report/code_climate/code_climate_formatter'
3
-
4
- RSpec.describe Reek::Report::CodeClimateFormatter do
5
- describe '#render' do
6
- let(:warning) do
7
- Reek::SmellWarning.new(
8
- 'UtilityFunction',
9
- context: 'context foo',
10
- message: 'message bar',
11
- lines: [1, 2],
12
- source: 'a/ruby/source/file.rb')
13
- end
14
- let(:rendered) { described_class.new(warning).render }
15
- let(:json) { JSON.parse rendered.chop }
16
-
17
- it "sets the type as 'issue'" do
18
- expect(json['type']).to eq 'issue'
19
- end
20
-
21
- it 'sets the category' do
22
- expect(json['categories']).to eq ['Complexity']
23
- end
24
-
25
- it 'constructs a description based on the context and message' do
26
- expect(json['description']).to eq 'context foo message bar'
27
- end
28
-
29
- it 'sets a check name based on the smell detector' do
30
- expect(json['check_name']).to eq 'UtilityFunction'
31
- end
32
-
33
- it 'sets the location' do
34
- expect(json['location']).to eq('path' => 'a/ruby/source/file.rb',
35
- 'lines' => { 'begin' => 1, 'end' => 2 })
36
- end
37
-
38
- it 'sets a content based on the smell detector' do
39
- expect(json['content']['body']).
40
- to eq "A _Utility Function_ is any instance method that has no dependency on the state of the instance.\n"
41
- end
42
-
43
- it 'sets remediation points based on the smell detector' do
44
- expect(json['remediation_points']).to eq 250_000
45
- end
46
-
47
- it 'sets fingerprint based on warning context' do
48
- expect(json['fingerprint']).to eq '70c530e45999af129d520f1f579f967f'
49
- end
50
- end
51
- end
@@ -1,56 +0,0 @@
1
- require_relative '../../../spec_helper'
2
- require_lib 'reek/examiner'
3
- require_lib 'reek/report/code_climate'
4
-
5
- require 'json'
6
- require 'stringio'
7
-
8
- RSpec.describe Reek::Report::CodeClimateReport do
9
- let(:options) { {} }
10
- let(:instance) { described_class.new(**options) }
11
- let(:examiner) { Reek::Examiner.new(source) }
12
-
13
- before do
14
- instance.add_examiner examiner
15
- end
16
-
17
- context 'with empty source' do
18
- let(:source) { '' }
19
-
20
- it 'prints an empty string' do
21
- expect { instance.show }.to output('').to_stdout
22
- end
23
- end
24
-
25
- context 'with smelly source' do
26
- let(:source) { 'def simple(a) a[3] end' }
27
-
28
- it 'prints smells as json' do
29
- expected = <<~HERE.delete("\n")
30
- {"type":"issue",
31
- "check_name":"UncommunicativeParameterName",
32
- "description":"simple has the parameter name 'a'",
33
- "categories":["Complexity"],
34
- "location":{"path":"string","lines":{"begin":1,"end":1}},
35
- "remediation_points":150000,
36
- "content":{"body":"An `Uncommunicative Parameter Name` is a parameter name that
37
- doesn't communicate its intent well enough.\\n\\nPoor names make it hard for the reader
38
- to build a mental picture of what's going on in the code. They can also be
39
- mis-interpreted; and they hurt the flow of reading, because the reader must slow down
40
- to interpret the names.\\n"},
41
- "fingerprint":"09970037d92b5a628bf682a3e2bb126d"}\u0000
42
- {"type":"issue",
43
- "check_name":"UtilityFunction",
44
- "description":"simple doesn't depend on instance state (maybe move it to another class?)",
45
- "categories":["Complexity"],
46
- "location":{"path":"string","lines":{"begin":1,"end":1}},
47
- "remediation_points":250000,
48
- "content":{"body":"A _Utility Function_ is any instance method that has no
49
- dependency on the state of the instance.\\n"},
50
- "fingerprint":"db456db7cb344bb5a98b8fc54a2f382e"}\u0000
51
- HERE
52
-
53
- expect { instance.show }.to output(expected).to_stdout
54
- end
55
- end
56
- end
@@ -1,19 +0,0 @@
1
- require_relative '../../spec_helper'
2
- require_lib 'reek/examiner'
3
- require_lib 'reek/report/html_report'
4
-
5
- RSpec.describe Reek::Report::HTMLReport do
6
- let(:instance) { described_class.new }
7
-
8
- context 'with an empty source' do
9
- let(:examiner) { Reek::Examiner.new('') }
10
-
11
- before do
12
- instance.add_examiner examiner
13
- end
14
-
15
- it 'has the text 0 total warnings' do
16
- expect { instance.show }.to output(/0 total warnings/).to_stdout
17
- end
18
- end
19
- end