reek 6.0.3 → 6.0.4

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