reek 5.6.0 → 6.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (250) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +9 -0
  3. data/.github/workflows/ruby.yml +52 -0
  4. data/.gitignore +1 -0
  5. data/.rubocop.yml +3 -1
  6. data/.rubocop_todo.yml +27 -20
  7. data/.simplecov +1 -0
  8. data/CHANGELOG.md +29 -0
  9. data/CONTRIBUTING.md +3 -0
  10. data/Dockerfile +2 -1
  11. data/Gemfile +14 -17
  12. data/README.md +11 -11
  13. data/bin/code_climate_reek +12 -2
  14. data/lib/reek.rb +1 -0
  15. data/lib/reek/ast/ast_node_class_map.rb +1 -1
  16. data/lib/reek/ast/node.rb +1 -1
  17. data/lib/reek/ast/sexp_extensions/arguments.rb +11 -0
  18. data/lib/reek/cli/options.rb +3 -3
  19. data/lib/reek/code_comment.rb +36 -29
  20. data/lib/reek/configuration/app_configuration.rb +4 -3
  21. data/lib/reek/configuration/configuration_converter.rb +2 -2
  22. data/lib/reek/configuration/directory_directives.rb +9 -3
  23. data/lib/reek/configuration/excluded_paths.rb +2 -1
  24. data/lib/reek/context/code_context.rb +1 -1
  25. data/lib/reek/context/module_context.rb +3 -1
  26. data/lib/reek/context/refinement_context.rb +16 -0
  27. data/lib/reek/context_builder.rb +16 -2
  28. data/lib/reek/errors/legacy_comment_separator_error.rb +36 -0
  29. data/lib/reek/report.rb +5 -7
  30. data/lib/reek/report/code_climate/code_climate_configuration.yml +1 -1
  31. data/lib/reek/report/code_climate/code_climate_formatter.rb +1 -3
  32. data/lib/reek/report/code_climate/code_climate_report.rb +2 -1
  33. data/lib/reek/report/simple_warning_formatter.rb +0 -7
  34. data/lib/reek/smell_detectors/base_detector.rb +2 -10
  35. data/lib/reek/smell_detectors/boolean_parameter.rb +3 -1
  36. data/lib/reek/smell_detectors/data_clump.rb +23 -56
  37. data/lib/reek/smell_detectors/nil_check.rb +1 -12
  38. data/lib/reek/smell_detectors/uncommunicative_variable_name.rb +1 -1
  39. data/lib/reek/smell_warning.rb +2 -3
  40. data/lib/reek/source/source_locator.rb +14 -13
  41. data/lib/reek/spec/smell_matcher.rb +2 -1
  42. data/lib/reek/version.rb +1 -1
  43. data/reek.gemspec +17 -7
  44. metadata +23 -246
  45. data/.travis.yml +0 -35
  46. data/docs/API.md +0 -174
  47. data/docs/Attribute.md +0 -39
  48. data/docs/Basic-Smell-Options.md +0 -85
  49. data/docs/Boolean-Parameter.md +0 -54
  50. data/docs/Class-Variable.md +0 -40
  51. data/docs/Code-Smells.md +0 -39
  52. data/docs/Command-Line-Options.md +0 -119
  53. data/docs/Control-Couple.md +0 -26
  54. data/docs/Control-Parameter.md +0 -32
  55. data/docs/Data-Clump.md +0 -46
  56. data/docs/Duplicate-Method-Call.md +0 -264
  57. data/docs/Feature-Envy.md +0 -93
  58. data/docs/How-To-Write-New-Detectors.md +0 -132
  59. data/docs/How-reek-works-internally.md +0 -114
  60. data/docs/Instance-Variable-Assumption.md +0 -163
  61. data/docs/Irresponsible-Module.md +0 -47
  62. data/docs/Large-Class.md +0 -16
  63. data/docs/Long-Parameter-List.md +0 -39
  64. data/docs/Long-Yield-List.md +0 -37
  65. data/docs/Manual-Dispatch.md +0 -30
  66. data/docs/Missing-Safe-Method.md +0 -92
  67. data/docs/Module-Initialize.md +0 -62
  68. data/docs/Nested-Iterators.md +0 -59
  69. data/docs/Nil-Check.md +0 -44
  70. data/docs/RSpec-matchers.md +0 -129
  71. data/docs/Rake-Task.md +0 -66
  72. data/docs/Reek-4-to-Reek-5-migration.md +0 -188
  73. data/docs/Reek-Driven-Development.md +0 -46
  74. data/docs/Repeated-Conditional.md +0 -47
  75. data/docs/Simulated-Polymorphism.md +0 -16
  76. data/docs/Smell-Suppression.md +0 -96
  77. data/docs/Style-Guide.md +0 -19
  78. data/docs/Subclassed-From-Core-Class.md +0 -79
  79. data/docs/Too-Many-Constants.md +0 -37
  80. data/docs/Too-Many-Instance-Variables.md +0 -43
  81. data/docs/Too-Many-Methods.md +0 -56
  82. data/docs/Too-Many-Statements.md +0 -54
  83. data/docs/Uncommunicative-Method-Name.md +0 -94
  84. data/docs/Uncommunicative-Module-Name.md +0 -92
  85. data/docs/Uncommunicative-Name.md +0 -18
  86. data/docs/Uncommunicative-Parameter-Name.md +0 -90
  87. data/docs/Uncommunicative-Variable-Name.md +0 -96
  88. data/docs/Unused-Parameters.md +0 -28
  89. data/docs/Unused-Private-Method.md +0 -101
  90. data/docs/Utility-Function.md +0 -56
  91. data/docs/Versioning-Policy.md +0 -7
  92. data/docs/YAML-Reports.md +0 -93
  93. data/docs/defaults.reek.yml +0 -129
  94. data/docs/templates/default/docstring/html/public_api_marker.erb +0 -3
  95. data/docs/templates/default/docstring/setup.rb +0 -37
  96. data/docs/templates/default/fulldoc/html/css/common.css +0 -1
  97. data/docs/yard_plugin.rb +0 -17
  98. data/features/command_line_interface/basic_usage.feature +0 -15
  99. data/features/command_line_interface/options.feature +0 -124
  100. data/features/command_line_interface/show_progress.feature +0 -33
  101. data/features/command_line_interface/smell_selection.feature +0 -15
  102. data/features/command_line_interface/smells_count.feature +0 -38
  103. data/features/command_line_interface/stdin.feature +0 -65
  104. data/features/configuration_files/accept_setting.feature +0 -87
  105. data/features/configuration_files/directory_specific_directives.feature +0 -274
  106. data/features/configuration_files/exclude_directives.feature +0 -35
  107. data/features/configuration_files/exclude_paths_directives.feature +0 -42
  108. data/features/configuration_files/masking_smells.feature +0 -94
  109. data/features/configuration_files/mix_accept_reject_setting.feature +0 -84
  110. data/features/configuration_files/reject_setting.feature +0 -89
  111. data/features/configuration_files/schema_validation.feature +0 -59
  112. data/features/configuration_files/show_configuration_file.feature +0 -44
  113. data/features/configuration_files/unused_private_method.feature +0 -68
  114. data/features/configuration_loading.feature +0 -91
  115. data/features/configuration_via_source_comments/erroneous_source_comments.feature +0 -68
  116. data/features/configuration_via_source_comments/well_formed_source_comments.feature +0 -116
  117. data/features/locales.feature +0 -32
  118. data/features/programmatic_access.feature +0 -41
  119. data/features/rake_task/rake_task.feature +0 -138
  120. data/features/reports/codeclimate.feature +0 -59
  121. data/features/reports/json.feature +0 -59
  122. data/features/reports/reports.feature +0 -219
  123. data/features/reports/yaml.feature +0 -52
  124. data/features/rspec_matcher.feature +0 -41
  125. data/features/samples.feature +0 -305
  126. data/features/step_definitions/.rubocop.yml +0 -5
  127. data/features/step_definitions/reek_steps.rb +0 -98
  128. data/features/step_definitions/sample_file_steps.rb +0 -63
  129. data/features/support/env.rb +0 -34
  130. data/features/todo_list.feature +0 -108
  131. data/samples/checkstyle.xml +0 -7
  132. data/samples/clean_source/clean.rb +0 -6
  133. data/samples/configuration/accepts_rejects_and_excludes_for_detectors.reek.yml +0 -29
  134. data/samples/configuration/accepts_rejects_and_excludes_for_directory_directives.reek.yml +0 -30
  135. data/samples/configuration/corrupt.reek +0 -1
  136. data/samples/configuration/empty.reek +0 -0
  137. data/samples/configuration/full_configuration.reek +0 -13
  138. data/samples/configuration/full_mask.reek +0 -6
  139. data/samples/configuration/home/home.reek.yml +0 -4
  140. data/samples/configuration/partial_mask.reek +0 -4
  141. data/samples/configuration/regular_configuration/.reek.yml +0 -4
  142. data/samples/configuration/regular_configuration/empty_sub_directory/.gitignore +0 -0
  143. data/samples/configuration/with_excluded_paths.reek +0 -5
  144. data/samples/no_config_file/.keep +0 -0
  145. data/samples/paths.rb +0 -5
  146. data/samples/smelly_source/inline.rb +0 -704
  147. data/samples/smelly_source/optparse.rb +0 -1788
  148. data/samples/smelly_source/redcloth.rb +0 -1130
  149. data/samples/smelly_source/ruby.rb +0 -368
  150. data/samples/smelly_source/smelly.rb +0 -7
  151. data/samples/source_with_exclude_paths/ignore_me/uncommunicative_method_name.rb +0 -5
  152. data/samples/source_with_exclude_paths/nested/ignore_me_as_well/irresponsible_module.rb +0 -2
  153. data/samples/source_with_exclude_paths/nested/uncommunicative_parameter_name.rb +0 -6
  154. data/samples/source_with_exclude_paths/nested/uncommunicative_variable_name.rb +0 -6
  155. data/samples/source_with_hidden_directories/.hidden/hidden.rb +0 -1
  156. data/samples/source_with_hidden_directories/not_hidden.rb +0 -1
  157. data/samples/source_with_non_ruby_files/gibberish +0 -1
  158. data/samples/source_with_non_ruby_files/python_source.py +0 -1
  159. data/samples/source_with_non_ruby_files/ruby.rb +0 -6
  160. data/spec/factories/factories.rb +0 -37
  161. data/spec/performance/reek/smell_detectors/runtime_speed_spec.rb +0 -17
  162. data/spec/quality/documentation_spec.rb +0 -40
  163. data/spec/quality/reek_source_spec.rb +0 -11
  164. data/spec/reek/ast/node_spec.rb +0 -211
  165. data/spec/reek/ast/object_refs_spec.rb +0 -83
  166. data/spec/reek/ast/reference_collector_spec.rb +0 -47
  167. data/spec/reek/ast/sexp_extensions_spec.rb +0 -516
  168. data/spec/reek/cli/application_spec.rb +0 -168
  169. data/spec/reek/cli/command/report_command_spec.rb +0 -44
  170. data/spec/reek/cli/command/todo_list_command_spec.rb +0 -86
  171. data/spec/reek/cli/options_spec.rb +0 -51
  172. data/spec/reek/cli/silencer_spec.rb +0 -28
  173. data/spec/reek/code_comment_spec.rb +0 -185
  174. data/spec/reek/configuration/app_configuration_spec.rb +0 -195
  175. data/spec/reek/configuration/configuration_file_finder_spec.rb +0 -230
  176. data/spec/reek/configuration/default_directive_spec.rb +0 -13
  177. data/spec/reek/configuration/directory_directives_spec.rb +0 -116
  178. data/spec/reek/configuration/excluded_paths_spec.rb +0 -16
  179. data/spec/reek/configuration/rake_task_converter_spec.rb +0 -33
  180. data/spec/reek/configuration/schema_validator_spec.rb +0 -165
  181. data/spec/reek/context/code_context_spec.rb +0 -192
  182. data/spec/reek/context/ghost_context_spec.rb +0 -60
  183. data/spec/reek/context/method_context_spec.rb +0 -72
  184. data/spec/reek/context/module_context_spec.rb +0 -55
  185. data/spec/reek/context/root_context_spec.rb +0 -12
  186. data/spec/reek/context/statement_counter_spec.rb +0 -24
  187. data/spec/reek/context_builder_spec.rb +0 -460
  188. data/spec/reek/detector_repository_spec.rb +0 -22
  189. data/spec/reek/documentation_link_spec.rb +0 -20
  190. data/spec/reek/errors/base_error_spec.rb +0 -13
  191. data/spec/reek/examiner_spec.rb +0 -309
  192. data/spec/reek/logging_error_handler_spec.rb +0 -24
  193. data/spec/reek/rake/task_spec.rb +0 -56
  194. data/spec/reek/report/code_climate/code_climate_configuration_spec.rb +0 -24
  195. data/spec/reek/report/code_climate/code_climate_fingerprint_spec.rb +0 -126
  196. data/spec/reek/report/code_climate/code_climate_formatter_spec.rb +0 -51
  197. data/spec/reek/report/code_climate/code_climate_report_spec.rb +0 -56
  198. data/spec/reek/report/html_report_spec.rb +0 -19
  199. data/spec/reek/report/json_report_spec.rb +0 -58
  200. data/spec/reek/report/location_formatter_spec.rb +0 -32
  201. data/spec/reek/report/progress_formatter_spec.rb +0 -68
  202. data/spec/reek/report/text_report_spec.rb +0 -89
  203. data/spec/reek/report/xml_report_spec.rb +0 -24
  204. data/spec/reek/report/yaml_report_spec.rb +0 -55
  205. data/spec/reek/report_spec.rb +0 -28
  206. data/spec/reek/smell_configuration_spec.rb +0 -56
  207. data/spec/reek/smell_detectors/attribute_spec.rb +0 -197
  208. data/spec/reek/smell_detectors/base_detector_spec.rb +0 -60
  209. data/spec/reek/smell_detectors/boolean_parameter_spec.rb +0 -93
  210. data/spec/reek/smell_detectors/class_variable_spec.rb +0 -106
  211. data/spec/reek/smell_detectors/control_parameter_spec.rb +0 -300
  212. data/spec/reek/smell_detectors/data_clump_spec.rb +0 -120
  213. data/spec/reek/smell_detectors/duplicate_method_call_spec.rb +0 -211
  214. data/spec/reek/smell_detectors/feature_envy_spec.rb +0 -295
  215. data/spec/reek/smell_detectors/instance_variable_assumption_spec.rb +0 -96
  216. data/spec/reek/smell_detectors/irresponsible_module_spec.rb +0 -226
  217. data/spec/reek/smell_detectors/long_parameter_list_spec.rb +0 -61
  218. data/spec/reek/smell_detectors/long_yield_list_spec.rb +0 -49
  219. data/spec/reek/smell_detectors/manual_dispatch_spec.rb +0 -75
  220. data/spec/reek/smell_detectors/missing_safe_method_spec.rb +0 -62
  221. data/spec/reek/smell_detectors/module_initialize_spec.rb +0 -77
  222. data/spec/reek/smell_detectors/nested_iterators_spec.rb +0 -333
  223. data/spec/reek/smell_detectors/nil_check_spec.rb +0 -100
  224. data/spec/reek/smell_detectors/repeated_conditional_spec.rb +0 -100
  225. data/spec/reek/smell_detectors/subclassed_from_core_class_spec.rb +0 -77
  226. data/spec/reek/smell_detectors/too_many_constants_spec.rb +0 -144
  227. data/spec/reek/smell_detectors/too_many_instance_variables_spec.rb +0 -132
  228. data/spec/reek/smell_detectors/too_many_methods_spec.rb +0 -54
  229. data/spec/reek/smell_detectors/too_many_statements_spec.rb +0 -90
  230. data/spec/reek/smell_detectors/uncommunicative_method_name_spec.rb +0 -78
  231. data/spec/reek/smell_detectors/uncommunicative_module_name_spec.rb +0 -78
  232. data/spec/reek/smell_detectors/uncommunicative_parameter_name_spec.rb +0 -147
  233. data/spec/reek/smell_detectors/uncommunicative_variable_name_spec.rb +0 -201
  234. data/spec/reek/smell_detectors/unused_parameters_spec.rb +0 -114
  235. data/spec/reek/smell_detectors/unused_private_method_spec.rb +0 -205
  236. data/spec/reek/smell_detectors/utility_function_spec.rb +0 -293
  237. data/spec/reek/smell_warning_spec.rb +0 -137
  238. data/spec/reek/source/source_code_spec.rb +0 -66
  239. data/spec/reek/source/source_locator_spec.rb +0 -166
  240. data/spec/reek/spec/should_reek_of_spec.rb +0 -154
  241. data/spec/reek/spec/should_reek_only_of_spec.rb +0 -91
  242. data/spec/reek/spec/should_reek_spec.rb +0 -52
  243. data/spec/reek/spec/smell_matcher_spec.rb +0 -87
  244. data/spec/reek/tree_dresser_spec.rb +0 -46
  245. data/spec/spec_helper.rb +0 -96
  246. data/tasks/configuration.rake +0 -19
  247. data/tasks/console.rake +0 -5
  248. data/tasks/reek.rake +0 -6
  249. data/tasks/rubocop.rake +0 -11
  250. data/tasks/test.rake +0 -32
@@ -1,72 +0,0 @@
1
- require_relative '../../spec_helper'
2
- require_lib 'reek/context/method_context'
3
-
4
- RSpec.describe Reek::Context::MethodContext do
5
- let(:method_context) { described_class.new(exp, nil) }
6
-
7
- describe '#matches?' do
8
- let(:exp) { instance_double('Reek::AST::SexpExtensions::ModuleNode').as_null_object }
9
-
10
- before do
11
- allow(exp).to receive(:full_name).at_least(:once).and_return('mod')
12
- end
13
-
14
- it 'recognises itself in a collection of names' do
15
- expect(method_context.matches?(['banana', 'mod'])).to eq(true)
16
- end
17
-
18
- it 'does not recognise itself in a collection of names that does not include it' do
19
- expect(method_context.matches?(['banana'])).to eq(false)
20
- end
21
-
22
- it 'recognises itself in a collection of regular expressions' do
23
- expect(method_context.matches?([/banana/, /mod/])).to eq(true)
24
- end
25
-
26
- it 'does not recognise itself in a collection of regular expressions that do not match it' do
27
- expect(method_context.matches?([/banana/])).to eq(false)
28
- end
29
- end
30
-
31
- describe '#default_assignments' do
32
- def assignments_from(src)
33
- exp = Reek::Source::SourceCode.from(src).syntax_tree
34
- ctx = Reek::Context::MethodContext.new(exp, nil)
35
- ctx.default_assignments
36
- end
37
-
38
- context 'with no defaults' do
39
- it 'returns an empty hash' do
40
- src = 'def meth(arga, argb, &blk) end'
41
- expect(assignments_from(src)).to be_empty
42
- end
43
- end
44
-
45
- context 'with 1 default' do
46
- let(:defaults) { assignments_from('def meth(arga, argb=456, &blk) end') }
47
-
48
- it 'returns the param-value pair' do
49
- expect(defaults[0]).to eq [:argb, sexp(:int, 456)]
50
- end
51
-
52
- it 'returns the nothing else' do
53
- expect(defaults.length).to eq(1)
54
- end
55
- end
56
-
57
- context 'with 2 defaults' do
58
- let(:defaults) do
59
- assignments_from('def meth(arga=123, argb=456, &blk) end')
60
- end
61
-
62
- it 'returns both param-value pairs' do
63
- expect(defaults).to eq [[:arga, sexp(:int, 123)],
64
- [:argb, sexp(:int, 456)]]
65
- end
66
-
67
- it 'returns nothing else' do
68
- expect(defaults.length).to eq(2)
69
- end
70
- end
71
- end
72
- end
@@ -1,55 +0,0 @@
1
- require_relative '../../spec_helper'
2
- require_lib 'reek/context/module_context'
3
- require_lib 'reek/context/root_context'
4
-
5
- RSpec.describe Reek::Context::ModuleContext do
6
- it 'reports module name for smell in method' do
7
- expect('
8
- module Fred
9
- def simple(x) x + 1; end
10
- end
11
- ').to reek_of(:UncommunicativeParameterName, name: 'x', context: 'Fred#simple')
12
- end
13
-
14
- it 'does not report module with empty class' do
15
- expect('
16
- # module for test
17
- module Fred
18
- # module for test
19
- class Jim; end; end').not_to reek
20
- end
21
-
22
- it 'recognises global constant' do
23
- expect('
24
- # module for test
25
- module ::Global
26
- # module for test
27
- class Inside; end; end').not_to reek
28
- end
29
-
30
- describe '#track_visibility' do
31
- let(:main_exp) { instance_double('Reek::AST::Node') }
32
- let(:first_def) { instance_double('Reek::AST::SexpExtensions::DefNode', name: :foo) }
33
- let(:second_def) { instance_double('Reek::AST::SexpExtensions::DefNode') }
34
-
35
- let(:context) { described_class.new(main_exp) }
36
- let(:first_child) { Reek::Context::MethodContext.new(first_def, main_exp) }
37
- let(:second_child) { Reek::Context::MethodContext.new(second_def, main_exp) }
38
-
39
- it 'sets visibility on subsequent child contexts' do
40
- context.append_child_context first_child
41
- context.track_visibility :private, []
42
- context.append_child_context second_child
43
- expect(first_child.visibility).to eq :public
44
- expect(second_child.visibility).to eq :private
45
- end
46
-
47
- it 'sets visibility on specifically mentioned child contexts' do
48
- context.append_child_context first_child
49
- context.track_visibility :private, [first_child.name]
50
- context.append_child_context second_child
51
- expect(first_child.visibility).to eq :private
52
- expect(second_child.visibility).to eq :public
53
- end
54
- end
55
- end
@@ -1,12 +0,0 @@
1
- require_relative '../../spec_helper'
2
- require_lib 'reek/context/root_context'
3
-
4
- RSpec.describe Reek::Context::RootContext do
5
- describe '#full_name' do
6
- it 'reports full context' do
7
- ast = Reek::Source::SourceCode.from('foo = 1').syntax_tree
8
- root = described_class.new(ast)
9
- expect(root.full_name).to eq('')
10
- end
11
- end
12
- end
@@ -1,24 +0,0 @@
1
- require_relative '../../spec_helper'
2
- require_lib 'reek/context/statement_counter'
3
-
4
- RSpec.describe Reek::Context::StatementCounter do
5
- let(:counter) { described_class.new }
6
-
7
- describe '#increase_by' do
8
- it 'does not increase if passed a falsy value' do
9
- counter.increase_by(nil)
10
- expect(counter.value).to eq 0
11
- end
12
-
13
- it 'increase by the lengh of the passed in argument' do
14
- counter.increase_by([1, 2, 3])
15
- expect(counter.value).to eq 3
16
- end
17
-
18
- it 'accumulates increases' do
19
- counter.increase_by([1, 2, 3])
20
- counter.increase_by([1, 2, 3])
21
- expect(counter.value).to eq 6
22
- end
23
- end
24
- end
@@ -1,460 +0,0 @@
1
- require_relative '../spec_helper'
2
- require_lib 'reek/context_builder'
3
-
4
- RSpec.describe Reek::ContextBuilder do
5
- describe '#context_tree' do
6
- let(:walker) do
7
- code = 'class Car; def drive; end; end'
8
- described_class.new(syntax_tree(code))
9
- end
10
- let(:context_tree) { walker.context_tree }
11
- let(:module_context) { context_tree.children.first }
12
- let(:method_context) { module_context.children.first }
13
-
14
- it 'starts with a root node' do
15
- expect(context_tree.type).to eq(:root)
16
- expect(context_tree).to be_a(Reek::Context::RootContext)
17
- end
18
-
19
- it 'has one child' do
20
- expect(context_tree.children.size).to eq(1)
21
- end
22
-
23
- describe 'the root node' do
24
- it 'has one module_context' do
25
- expect(module_context).to be_a(Reek::Context::ModuleContext)
26
- end
27
-
28
- it 'holds a reference to the parent context' do
29
- expect(module_context.parent).to eq(context_tree)
30
- end
31
- end
32
-
33
- describe 'the module node' do
34
- it 'has one method_context' do
35
- expect(method_context).to be_a(Reek::Context::MethodContext)
36
- expect(module_context.children.size).to eq(1)
37
- end
38
-
39
- it 'holds a reference to the parent context' do
40
- expect(method_context.parent).to eq(module_context)
41
- end
42
- end
43
- end
44
-
45
- describe 'statement counting' do
46
- def tree(code)
47
- described_class.new(syntax_tree(code)).context_tree
48
- end
49
-
50
- def number_of_statements_for(code)
51
- tree(code).children.first.number_of_statements
52
- end
53
-
54
- it 'counts 1 assignment' do
55
- code = 'def one() val = 4; end'
56
- expect(number_of_statements_for(code)).to eq(1)
57
- end
58
-
59
- it 'counts 3 assignments' do
60
- code = 'def one() val = 4; val = 4; val = 4; end'
61
- expect(number_of_statements_for(code)).to eq(3)
62
- end
63
-
64
- it 'counts 1 attr assignment' do
65
- code = 'def one() val[0] = 4; end'
66
- expect(number_of_statements_for(code)).to eq(1)
67
- end
68
-
69
- it 'counts 1 increment assignment' do
70
- code = 'def one() val += 4; end'
71
- expect(number_of_statements_for(code)).to eq(1)
72
- end
73
-
74
- it 'counts 1 increment attr assignment' do
75
- code = 'def one() val[0] += 4; end'
76
- expect(number_of_statements_for(code)).to eq(1)
77
- end
78
-
79
- it 'counts 1 nested assignment' do
80
- code = 'def one() val = fred = 4; end'
81
- expect(number_of_statements_for(code)).to eq(1)
82
- end
83
-
84
- it 'counts returns' do
85
- code = 'def one() val = 4; true; end'
86
- expect(number_of_statements_for(code)).to eq(2)
87
- end
88
-
89
- it 'counts nil returns' do
90
- code = 'def one() val = 4; nil; end'
91
- expect(number_of_statements_for(code)).to eq(2)
92
- end
93
-
94
- context 'with control statements' do
95
- it 'counts 3 statements in a conditional expression' do
96
- code = 'def one() if val == 4; callee(); callee(); callee(); end; end'
97
- expect(number_of_statements_for(code)).to eq(3)
98
- end
99
-
100
- it 'counts 3 statements in an else' do
101
- code = <<-RUBY
102
- def one()
103
- if val == 4
104
- callee(); callee(); callee()
105
- else
106
- callee(); callee(); callee()
107
- end
108
- end
109
- RUBY
110
-
111
- expect(number_of_statements_for(code)).to eq(6)
112
- end
113
-
114
- it 'does not count constant assignment with or equals' do
115
- code = 'class Hi; CONST ||= 1; end'
116
- expect(number_of_statements_for(code)).to eq(0)
117
- end
118
-
119
- it 'does not count multi constant assignment' do
120
- code = 'class Hi; CONST, OTHER_CONST = 1, 2; end'
121
- expect(number_of_statements_for(code)).to eq(0)
122
- end
123
-
124
- it 'does not count empty conditional expression' do
125
- code = 'def one() if val == 4; ; end; end'
126
- expect(number_of_statements_for(code)).to eq(0)
127
- end
128
-
129
- it 'does not count empty else' do
130
- code = 'def one() if val == 4; ; else; ; end; end'
131
- expect(number_of_statements_for(code)).to eq(0)
132
- end
133
-
134
- it 'counts extra statements in an if condition' do
135
- code = 'def one() if begin val = callee(); val < 4 end; end; end'
136
- expect(number_of_statements_for(code)).to eq(1)
137
- end
138
-
139
- it 'counts 3 statements in a while loop' do
140
- code = 'def one() while val < 4; callee(); callee(); callee(); end; end'
141
- expect(number_of_statements_for(code)).to eq(3)
142
- end
143
-
144
- it 'counts extra statements in a while condition' do
145
- code = 'def one() while begin val = callee(); val < 4 end; end; end'
146
- expect(number_of_statements_for(code)).to eq(1)
147
- end
148
-
149
- it 'counts 3 statements in a until loop' do
150
- code = 'def one() until val < 4; callee(); callee(); callee(); end; end'
151
- expect(number_of_statements_for(code)).to eq(3)
152
- end
153
-
154
- it 'counts 3 statements in a for loop' do
155
- code = 'def one() for i in 0..4; callee(); callee(); callee(); end; end'
156
- expect(number_of_statements_for(code)).to eq(3)
157
- end
158
-
159
- it 'counts 3 statements in a rescue' do
160
- code = <<-RUBY
161
- def one()
162
- begin
163
- callee(); callee(); callee()
164
- rescue
165
- callee(); callee(); callee()
166
- end
167
- end
168
- RUBY
169
- expect(number_of_statements_for(code)).to eq(6)
170
- end
171
-
172
- it 'counts 3 statements in a when' do
173
- code = <<-RUBY
174
- def one()
175
- case fred
176
- when "hi" then callee(); callee()
177
- when "lo" then callee()
178
- end
179
- end
180
- RUBY
181
- expect(number_of_statements_for(code)).to eq(3)
182
- end
183
-
184
- it 'counts 3 statements in a case else' do
185
- code = <<-RUBY
186
- def one()
187
- case fred
188
- when "hi" then callee(); callee(); callee()
189
- else callee(); callee(); callee()
190
- end
191
- end
192
- RUBY
193
- expect(number_of_statements_for(code)).to eq(6)
194
- end
195
-
196
- it 'does not count empty case' do
197
- code = 'def one() case fred; when "hi"; ; when "lo"; ; end; end'
198
- expect(number_of_statements_for(code)).to eq(0)
199
- end
200
-
201
- it 'does not count empty case else' do
202
- code = 'def one() case fred; when "hi"; ; else; ; end; end'
203
- expect(number_of_statements_for(code)).to eq(0)
204
- end
205
-
206
- it 'counts 4 statements in an iterator' do
207
- code = 'def one() fred.each do; callee(); callee(); callee(); end; end'
208
- expect(number_of_statements_for(code)).to eq(4)
209
- end
210
-
211
- it 'counts 1 statement in a singleton method' do
212
- code = 'def self.foo; callee(); end'
213
- expect(number_of_statements_for(code)).to eq(1)
214
- end
215
- end
216
- end
217
-
218
- describe 'visibility tracking' do
219
- def context_tree_for(code)
220
- described_class.new(syntax_tree(code)).context_tree
221
- end
222
-
223
- it 'marks instance methods when using a def modifier' do
224
- code = <<-RUBY
225
- class Foo
226
- private def bar
227
- end
228
-
229
- def baz
230
- end
231
- end
232
- RUBY
233
-
234
- root = context_tree_for(code)
235
- module_context = root.children.first
236
- method_contexts = module_context.children
237
- aggregate_failures do
238
- expect(method_contexts[0].visibility).to eq :private
239
- expect(method_contexts[1].visibility).to eq :public
240
- end
241
- end
242
-
243
- it 'does not mark class methods with instance visibility' do
244
- code = <<-RUBY
245
- class Foo
246
- private
247
- def bar
248
- end
249
- def self.baz
250
- end
251
- end
252
- RUBY
253
-
254
- root = context_tree_for(code)
255
- module_context = root.children.first
256
- method_contexts = module_context.children
257
- expect(method_contexts[0].visibility).to eq :private
258
- expect(method_contexts[1].visibility).to eq :public
259
- end
260
-
261
- it 'only marks existing instance methods using later instance method modifiers' do
262
- code = <<-RUBY
263
- class Foo
264
- def bar
265
- end
266
-
267
- def baz
268
- end
269
-
270
- def self.bar
271
- end
272
-
273
- class << self
274
- def bar
275
- end
276
- end
277
-
278
- private :bar, :baz
279
- end
280
- RUBY
281
-
282
- root = context_tree_for(code)
283
- module_context = root.children.first
284
- method_contexts = module_context.children
285
- expect(method_contexts[0].visibility).to eq :private
286
- expect(method_contexts[1].visibility).to eq :private
287
- expect(method_contexts[2].visibility).to eq :public
288
- expect(method_contexts[3].visibility).to eq :public
289
- end
290
-
291
- it 'only marks existing instance attributes using later instance method modifiers' do
292
- code = <<-RUBY
293
- class Foo
294
- attr_writer :bar
295
-
296
- class << self
297
- attr_writer :bar
298
- end
299
-
300
- private :bar
301
- end
302
- RUBY
303
-
304
- root = context_tree_for(code)
305
- module_context = root.children.first
306
- method_contexts = module_context.children
307
- expect(method_contexts[0].visibility).to eq :private
308
- expect(method_contexts[1].visibility).to eq :public
309
- end
310
-
311
- it 'marks class method visibility using private_class_method' do
312
- code = <<-RUBY
313
- class Foo
314
- def self.baz
315
- end
316
-
317
- private_class_method :baz
318
- end
319
- RUBY
320
-
321
- root = context_tree_for(code)
322
- module_context = root.children.first
323
- method_contexts = module_context.children
324
- expect(method_contexts[0].visibility).to eq :private
325
- end
326
-
327
- it 'marks class method visibility using public_class_method' do
328
- code = <<-RUBY
329
- class Foo
330
- class << self
331
- private
332
-
333
- def baz
334
- end
335
- end
336
-
337
- public_class_method :baz
338
- end
339
- RUBY
340
-
341
- root = context_tree_for(code)
342
- module_context = root.children.first
343
- method_contexts = module_context.children
344
- expect(method_contexts[0].visibility).to eq :public
345
- end
346
-
347
- it 'correctly skips nested modules' do
348
- code = <<-RUBY
349
- class Foo
350
- class Bar
351
- def baz
352
- end
353
- end
354
-
355
- def baz
356
- end
357
-
358
- def self.bar
359
- end
360
-
361
- private :baz
362
- private_class_method :bar
363
- end
364
- RUBY
365
-
366
- root = context_tree_for(code)
367
- foo_context = root.children.first
368
- bar_context = foo_context.children.first
369
- nested_baz_context = bar_context.children.first
370
- expect(nested_baz_context.visibility).to eq :public
371
- end
372
- end
373
-
374
- describe '#context_tree' do
375
- it 'creates the proper context for all kinds of singleton methods' do
376
- src = <<-RUBY
377
- class Car
378
- def self.start; end
379
-
380
- class << self
381
- def drive; end
382
- end
383
- end
384
- RUBY
385
-
386
- syntax_tree = Reek::Source::SourceCode.from(src).syntax_tree
387
- context_tree = described_class.new(syntax_tree).context_tree
388
-
389
- class_node = context_tree.children.first
390
- start_method = class_node.children.first
391
- drive_method = class_node.children.last
392
-
393
- expect(start_method).to be_instance_of Reek::Context::SingletonMethodContext
394
- expect(drive_method).to be_instance_of Reek::Context::SingletonMethodContext
395
- end
396
-
397
- it 'returns something sensible for nested metaclasses' do
398
- src = <<-RUBY
399
- class Foo
400
- class << self
401
- class << self
402
- def bar; end
403
- end
404
- end
405
- end
406
- RUBY
407
-
408
- syntax_tree = Reek::Source::SourceCode.from(src).syntax_tree
409
- context_tree = described_class.new(syntax_tree).context_tree
410
-
411
- class_context = context_tree.children.first
412
- method_context = class_context.children.first
413
-
414
- expect(method_context).to be_instance_of Reek::Context::SingletonMethodContext
415
- expect(method_context.parent).to eq class_context
416
- end
417
-
418
- it 'returns something sensible for nested method definitions' do
419
- src = <<-RUBY
420
- class Foo
421
- def foo
422
- def bar
423
- end
424
- end
425
- end
426
- RUBY
427
-
428
- syntax_tree = Reek::Source::SourceCode.from(src).syntax_tree
429
- context_tree = described_class.new(syntax_tree).context_tree
430
-
431
- class_context = context_tree.children.first
432
- foo_context = class_context.children.first
433
-
434
- bar_context = foo_context.children.first
435
- expect(bar_context).to be_instance_of Reek::Context::MethodContext
436
- expect(bar_context.parent).to eq foo_context
437
- end
438
-
439
- it 'returns something sensible for method definitions nested in singleton methods' do
440
- src = <<-RUBY
441
- class Foo
442
- def self.foo
443
- def bar
444
- end
445
- end
446
- end
447
- RUBY
448
-
449
- syntax_tree = Reek::Source::SourceCode.from(src).syntax_tree
450
- context_tree = described_class.new(syntax_tree).context_tree
451
-
452
- class_context = context_tree.children.first
453
- foo_context = class_context.children.first
454
-
455
- bar_context = foo_context.children.first
456
- expect(bar_context).to be_instance_of Reek::Context::SingletonMethodContext
457
- expect(bar_context.parent).to eq foo_context
458
- end
459
- end
460
- end