reek 6.0.3 → 6.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (231) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +31 -26
  3. data/.rubocop.yml +5 -3
  4. data/CHANGELOG.md +22 -1
  5. data/CONTRIBUTING.md +3 -0
  6. data/Dockerfile +1 -1
  7. data/Gemfile +7 -7
  8. data/README.md +1 -1
  9. data/bin/code_climate_reek +2 -3
  10. data/lib/reek/ast/ast_node_class_map.rb +1 -1
  11. data/lib/reek/ast/sexp_extensions/arguments.rb +11 -0
  12. data/lib/reek/ast/sexp_extensions/case.rb +1 -1
  13. data/lib/reek/ast/sexp_extensions/if.rb +1 -1
  14. data/lib/reek/ast/sexp_extensions/send.rb +1 -1
  15. data/lib/reek/cli/command/todo_list_command.rb +1 -1
  16. data/lib/reek/cli/options.rb +1 -1
  17. data/lib/reek/code_comment.rb +22 -17
  18. data/lib/reek/context_builder.rb +1 -1
  19. data/lib/reek/rake/task.rb +1 -1
  20. data/lib/reek/report/code_climate/code_climate_formatter.rb +1 -3
  21. data/lib/reek/smell_detectors/base_detector.rb +1 -1
  22. data/lib/reek/smell_warning.rb +1 -1
  23. data/lib/reek/source/source_locator.rb +1 -3
  24. data/lib/reek/spec/should_reek_of.rb +6 -4
  25. data/lib/reek/version.rb +2 -2
  26. data/reek.gemspec +28 -25
  27. metadata +7 -225
  28. data/docs/API.md +0 -174
  29. data/docs/Attribute.md +0 -39
  30. data/docs/Basic-Smell-Options.md +0 -85
  31. data/docs/Boolean-Parameter.md +0 -54
  32. data/docs/Class-Variable.md +0 -40
  33. data/docs/Code-Smells.md +0 -39
  34. data/docs/Command-Line-Options.md +0 -119
  35. data/docs/Control-Couple.md +0 -26
  36. data/docs/Control-Parameter.md +0 -32
  37. data/docs/Data-Clump.md +0 -46
  38. data/docs/Duplicate-Method-Call.md +0 -264
  39. data/docs/Feature-Envy.md +0 -93
  40. data/docs/How-To-Write-New-Detectors.md +0 -132
  41. data/docs/How-reek-works-internally.md +0 -114
  42. data/docs/Instance-Variable-Assumption.md +0 -163
  43. data/docs/Irresponsible-Module.md +0 -47
  44. data/docs/Large-Class.md +0 -16
  45. data/docs/Long-Parameter-List.md +0 -39
  46. data/docs/Long-Yield-List.md +0 -37
  47. data/docs/Manual-Dispatch.md +0 -30
  48. data/docs/Missing-Safe-Method.md +0 -92
  49. data/docs/Module-Initialize.md +0 -62
  50. data/docs/Nested-Iterators.md +0 -59
  51. data/docs/Nil-Check.md +0 -47
  52. data/docs/RSpec-matchers.md +0 -129
  53. data/docs/Rake-Task.md +0 -66
  54. data/docs/Reek-4-to-Reek-5-migration.md +0 -188
  55. data/docs/Reek-Driven-Development.md +0 -46
  56. data/docs/Repeated-Conditional.md +0 -47
  57. data/docs/Simulated-Polymorphism.md +0 -16
  58. data/docs/Smell-Suppression.md +0 -96
  59. data/docs/Style-Guide.md +0 -19
  60. data/docs/Subclassed-From-Core-Class.md +0 -79
  61. data/docs/Too-Many-Constants.md +0 -37
  62. data/docs/Too-Many-Instance-Variables.md +0 -43
  63. data/docs/Too-Many-Methods.md +0 -56
  64. data/docs/Too-Many-Statements.md +0 -54
  65. data/docs/Uncommunicative-Method-Name.md +0 -94
  66. data/docs/Uncommunicative-Module-Name.md +0 -92
  67. data/docs/Uncommunicative-Name.md +0 -18
  68. data/docs/Uncommunicative-Parameter-Name.md +0 -90
  69. data/docs/Uncommunicative-Variable-Name.md +0 -96
  70. data/docs/Unused-Parameters.md +0 -28
  71. data/docs/Unused-Private-Method.md +0 -101
  72. data/docs/Utility-Function.md +0 -56
  73. data/docs/Versioning-Policy.md +0 -7
  74. data/docs/YAML-Reports.md +0 -93
  75. data/docs/defaults.reek.yml +0 -129
  76. data/docs/templates/default/docstring/html/public_api_marker.erb +0 -3
  77. data/docs/templates/default/docstring/setup.rb +0 -35
  78. data/docs/templates/default/fulldoc/html/css/common.css +0 -1
  79. data/docs/yard_plugin.rb +0 -17
  80. data/features/command_line_interface/basic_usage.feature +0 -15
  81. data/features/command_line_interface/options.feature +0 -123
  82. data/features/command_line_interface/show_progress.feature +0 -33
  83. data/features/command_line_interface/smell_selection.feature +0 -15
  84. data/features/command_line_interface/smells_count.feature +0 -38
  85. data/features/command_line_interface/stdin.feature +0 -65
  86. data/features/configuration_files/accept_setting.feature +0 -87
  87. data/features/configuration_files/directory_specific_directives.feature +0 -274
  88. data/features/configuration_files/exclude_directives.feature +0 -35
  89. data/features/configuration_files/exclude_paths_directives.feature +0 -42
  90. data/features/configuration_files/masking_smells.feature +0 -94
  91. data/features/configuration_files/mix_accept_reject_setting.feature +0 -84
  92. data/features/configuration_files/reject_setting.feature +0 -89
  93. data/features/configuration_files/schema_validation.feature +0 -59
  94. data/features/configuration_files/show_configuration_file.feature +0 -44
  95. data/features/configuration_files/unused_private_method.feature +0 -68
  96. data/features/configuration_loading.feature +0 -91
  97. data/features/configuration_via_source_comments/erroneous_source_comments.feature +0 -68
  98. data/features/configuration_via_source_comments/well_formed_source_comments.feature +0 -116
  99. data/features/locales.feature +0 -32
  100. data/features/programmatic_access.feature +0 -41
  101. data/features/rake_task/rake_task.feature +0 -138
  102. data/features/reports/codeclimate.feature +0 -59
  103. data/features/reports/json.feature +0 -59
  104. data/features/reports/reports.feature +0 -219
  105. data/features/reports/yaml.feature +0 -52
  106. data/features/rspec_matcher.feature +0 -41
  107. data/features/samples.feature +0 -305
  108. data/features/step_definitions/.rubocop.yml +0 -5
  109. data/features/step_definitions/reek_steps.rb +0 -102
  110. data/features/step_definitions/sample_file_steps.rb +0 -63
  111. data/features/support/env.rb +0 -33
  112. data/features/todo_list.feature +0 -108
  113. data/samples/checkstyle.xml +0 -7
  114. data/samples/clean_source/clean.rb +0 -6
  115. data/samples/configuration/accepts_rejects_and_excludes_for_detectors.reek.yml +0 -29
  116. data/samples/configuration/accepts_rejects_and_excludes_for_directory_directives.reek.yml +0 -30
  117. data/samples/configuration/corrupt.reek +0 -1
  118. data/samples/configuration/empty.reek +0 -0
  119. data/samples/configuration/full_configuration.reek +0 -13
  120. data/samples/configuration/full_mask.reek +0 -6
  121. data/samples/configuration/home/home.reek.yml +0 -4
  122. data/samples/configuration/partial_mask.reek +0 -4
  123. data/samples/configuration/regular_configuration/.reek.yml +0 -4
  124. data/samples/configuration/regular_configuration/empty_sub_directory/.gitignore +0 -0
  125. data/samples/configuration/with_excluded_paths.reek +0 -5
  126. data/samples/no_config_file/.keep +0 -0
  127. data/samples/paths.rb +0 -5
  128. data/samples/smelly_source/inline.rb +0 -704
  129. data/samples/smelly_source/optparse.rb +0 -1788
  130. data/samples/smelly_source/redcloth.rb +0 -1130
  131. data/samples/smelly_source/ruby.rb +0 -368
  132. data/samples/smelly_source/smelly.rb +0 -7
  133. data/samples/source_with_exclude_paths/ignore_me/uncommunicative_method_name.rb +0 -5
  134. data/samples/source_with_exclude_paths/nested/ignore_me_as_well/irresponsible_module.rb +0 -2
  135. data/samples/source_with_exclude_paths/nested/uncommunicative_parameter_name.rb +0 -6
  136. data/samples/source_with_exclude_paths/nested/uncommunicative_variable_name.rb +0 -6
  137. data/samples/source_with_hidden_directories/.hidden/hidden.rb +0 -1
  138. data/samples/source_with_hidden_directories/not_hidden.rb +0 -1
  139. data/samples/source_with_non_ruby_files/gibberish +0 -1
  140. data/samples/source_with_non_ruby_files/python_source.py +0 -1
  141. data/samples/source_with_non_ruby_files/ruby.rb +0 -6
  142. data/spec/performance/reek/smell_detectors/runtime_speed_spec.rb +0 -15
  143. data/spec/quality/documentation_spec.rb +0 -41
  144. data/spec/quality/reek_source_spec.rb +0 -11
  145. data/spec/reek/ast/node_spec.rb +0 -211
  146. data/spec/reek/ast/object_refs_spec.rb +0 -83
  147. data/spec/reek/ast/reference_collector_spec.rb +0 -47
  148. data/spec/reek/ast/sexp_extensions_spec.rb +0 -498
  149. data/spec/reek/cli/application_spec.rb +0 -168
  150. data/spec/reek/cli/command/report_command_spec.rb +0 -44
  151. data/spec/reek/cli/command/todo_list_command_spec.rb +0 -86
  152. data/spec/reek/cli/options_spec.rb +0 -51
  153. data/spec/reek/cli/silencer_spec.rb +0 -28
  154. data/spec/reek/code_comment_spec.rb +0 -184
  155. data/spec/reek/configuration/app_configuration_spec.rb +0 -195
  156. data/spec/reek/configuration/configuration_file_finder_spec.rb +0 -230
  157. data/spec/reek/configuration/default_directive_spec.rb +0 -13
  158. data/spec/reek/configuration/directory_directives_spec.rb +0 -122
  159. data/spec/reek/configuration/excluded_paths_spec.rb +0 -25
  160. data/spec/reek/configuration/rake_task_converter_spec.rb +0 -33
  161. data/spec/reek/configuration/schema_validator_spec.rb +0 -165
  162. data/spec/reek/context/code_context_spec.rb +0 -192
  163. data/spec/reek/context/ghost_context_spec.rb +0 -60
  164. data/spec/reek/context/method_context_spec.rb +0 -72
  165. data/spec/reek/context/module_context_spec.rb +0 -55
  166. data/spec/reek/context/root_context_spec.rb +0 -12
  167. data/spec/reek/context/statement_counter_spec.rb +0 -24
  168. data/spec/reek/context_builder_spec.rb +0 -457
  169. data/spec/reek/detector_repository_spec.rb +0 -22
  170. data/spec/reek/documentation_link_spec.rb +0 -20
  171. data/spec/reek/errors/base_error_spec.rb +0 -13
  172. data/spec/reek/examiner_spec.rb +0 -309
  173. data/spec/reek/logging_error_handler_spec.rb +0 -24
  174. data/spec/reek/rake/task_spec.rb +0 -56
  175. data/spec/reek/report/code_climate/code_climate_configuration_spec.rb +0 -22
  176. data/spec/reek/report/code_climate/code_climate_fingerprint_spec.rb +0 -126
  177. data/spec/reek/report/code_climate/code_climate_formatter_spec.rb +0 -51
  178. data/spec/reek/report/code_climate/code_climate_report_spec.rb +0 -56
  179. data/spec/reek/report/html_report_spec.rb +0 -19
  180. data/spec/reek/report/json_report_spec.rb +0 -58
  181. data/spec/reek/report/location_formatter_spec.rb +0 -32
  182. data/spec/reek/report/progress_formatter_spec.rb +0 -68
  183. data/spec/reek/report/text_report_spec.rb +0 -89
  184. data/spec/reek/report/xml_report_spec.rb +0 -24
  185. data/spec/reek/report/yaml_report_spec.rb +0 -55
  186. data/spec/reek/report_spec.rb +0 -28
  187. data/spec/reek/smell_configuration_spec.rb +0 -56
  188. data/spec/reek/smell_detectors/attribute_spec.rb +0 -197
  189. data/spec/reek/smell_detectors/base_detector_spec.rb +0 -50
  190. data/spec/reek/smell_detectors/boolean_parameter_spec.rb +0 -93
  191. data/spec/reek/smell_detectors/class_variable_spec.rb +0 -106
  192. data/spec/reek/smell_detectors/control_parameter_spec.rb +0 -300
  193. data/spec/reek/smell_detectors/data_clump_spec.rb +0 -134
  194. data/spec/reek/smell_detectors/duplicate_method_call_spec.rb +0 -211
  195. data/spec/reek/smell_detectors/feature_envy_spec.rb +0 -295
  196. data/spec/reek/smell_detectors/instance_variable_assumption_spec.rb +0 -96
  197. data/spec/reek/smell_detectors/irresponsible_module_spec.rb +0 -226
  198. data/spec/reek/smell_detectors/long_parameter_list_spec.rb +0 -61
  199. data/spec/reek/smell_detectors/long_yield_list_spec.rb +0 -49
  200. data/spec/reek/smell_detectors/manual_dispatch_spec.rb +0 -75
  201. data/spec/reek/smell_detectors/missing_safe_method_spec.rb +0 -68
  202. data/spec/reek/smell_detectors/module_initialize_spec.rb +0 -77
  203. data/spec/reek/smell_detectors/nested_iterators_spec.rb +0 -333
  204. data/spec/reek/smell_detectors/nil_check_spec.rb +0 -100
  205. data/spec/reek/smell_detectors/repeated_conditional_spec.rb +0 -100
  206. data/spec/reek/smell_detectors/subclassed_from_core_class_spec.rb +0 -77
  207. data/spec/reek/smell_detectors/too_many_constants_spec.rb +0 -144
  208. data/spec/reek/smell_detectors/too_many_instance_variables_spec.rb +0 -132
  209. data/spec/reek/smell_detectors/too_many_methods_spec.rb +0 -54
  210. data/spec/reek/smell_detectors/too_many_statements_spec.rb +0 -90
  211. data/spec/reek/smell_detectors/uncommunicative_method_name_spec.rb +0 -78
  212. data/spec/reek/smell_detectors/uncommunicative_module_name_spec.rb +0 -78
  213. data/spec/reek/smell_detectors/uncommunicative_parameter_name_spec.rb +0 -147
  214. data/spec/reek/smell_detectors/uncommunicative_variable_name_spec.rb +0 -201
  215. data/spec/reek/smell_detectors/unused_parameters_spec.rb +0 -114
  216. data/spec/reek/smell_detectors/unused_private_method_spec.rb +0 -205
  217. data/spec/reek/smell_detectors/utility_function_spec.rb +0 -309
  218. data/spec/reek/smell_warning_spec.rb +0 -137
  219. data/spec/reek/source/source_code_spec.rb +0 -79
  220. data/spec/reek/source/source_locator_spec.rb +0 -166
  221. data/spec/reek/spec/should_reek_of_spec.rb +0 -153
  222. data/spec/reek/spec/should_reek_only_of_spec.rb +0 -91
  223. data/spec/reek/spec/should_reek_spec.rb +0 -52
  224. data/spec/reek/spec/smell_matcher_spec.rb +0 -87
  225. data/spec/reek/tree_dresser_spec.rb +0 -46
  226. data/spec/spec_helper.rb +0 -110
  227. data/tasks/configuration.rake +0 -18
  228. data/tasks/console.rake +0 -5
  229. data/tasks/reek.rake +0 -6
  230. data/tasks/rubocop.rake +0 -11
  231. data/tasks/test.rake +0 -32
@@ -1,132 +0,0 @@
1
- ## How to write new detectors
2
-
3
- ### Outline what you have in mind
4
-
5
- Before starting to code you should discuss the overall idea for your new smell detector with
6
- us in a corresponding github issue.
7
- We all should have a solid understanding of what this detector actually reports, the edgecases
8
- it covers and the overall rationale behind it.
9
-
10
- ### Structure
11
-
12
- All smell detectors reside in `lib/reek/smell_detectors` and have the following base structure:
13
-
14
- ```Ruby
15
- require_relative 'base_detector'
16
- require_relative 'smell_warning'
17
-
18
- module Reek
19
- module SmellDetectors
20
- #
21
- # Here goes your introduction for this detector.
22
- #
23
- # See {file:docs/Your-Detector.md} for details.
24
- class YourDetector < BaseDetector
25
- def self.contexts
26
- [:class] # In case you're operating on class contexts only - just an example.
27
- end
28
-
29
- #
30
- # Here you should document what you expect the detector's context to look
31
- # like.
32
- #
33
- # @return [Array<SmellWarning>]
34
- #
35
- def sniff
36
- # "found_smells" below is just an abstraction for
37
- # "find the smells in question" and iterate over them.
38
- # This can just be a method but it can also be a more sophisticated set up.
39
- # Check out other smell detectors to get a feeling for what to do here.
40
- found_smells.map do |smell|
41
- # "smell_warning" is defined in BaseDetector and should be used by you
42
- # to construct smell warnings
43
- smell_warning(
44
- lines: [], # lines on which the smell was detected
45
- message: "...", # the message that is printed on STDOUT
46
- # whatever you interpolate into the "message" should go into
47
- # parameters below - if you do not interpolate anything you
48
- # can omit this
49
- parameters: { })
50
- end
51
- end
52
- end
53
-
54
- private
55
-
56
- # Here goes everything you need for finding smells.
57
- end
58
- end
59
- end
60
- ```
61
-
62
- For your detector to be properly loaded you need to require it in `lib/reek/smell_detectors.rb` as well.
63
-
64
- ### defaults.reek.yml
65
-
66
- After you ran
67
-
68
- ```
69
- bundle exec rake
70
- ```
71
-
72
- for the first time with your shiny new detector in place the `docs/defaults.reek.yml`
73
- file should have been updated automatically. Make sure you don't forget to check
74
- in those changes as well.
75
-
76
- ### Documentation
77
-
78
- * Above every `SmellDetector::sniff` method it should be documented what the expected AST is
79
- * Every detector should have a separate documentation page in /docs. You can
80
- take any arbitrary existing smell detector documentation page as template (since
81
- they all have the same structure already)
82
- * The detector should be listed under [Code Smells](docs/Code-Smells.md)
83
- * Depending on what your detector does it might make sense to add it to other doc pages as
84
- well e.g. [Simulated Polymorphism](docs/Simulated-Polymorphism.md)
85
-
86
- ### Rspec examples
87
-
88
- All smell detector specs start out with 2 generic examples like below - the second one
89
- only if it makes sense.
90
- Here's what it looks like for `UncommunicativeVariableName`:
91
-
92
- ```Ruby
93
- it 'reports the right values' do
94
- src = <<-RUBY
95
- def alfa
96
- bravo = 5
97
- end
98
- RUBY
99
-
100
- expect(src).to reek_of(:UncommunicativeVariableName,
101
- lines: [2],
102
- context: 'alfa',
103
- message: "has the variable name 'bravo'",
104
- source: 'string',
105
- name: 'bravo')
106
- end
107
-
108
- it 'does count all occurences' do
109
- src = <<-RUBY
110
- def alfa
111
- bravo = 3
112
- charlie = 7
113
- end
114
- RUBY
115
-
116
- expect(src).to reek_of(:UncommunicativeVariableName,
117
- lines: [2],
118
- name: 'bravo')
119
- expect(src).to reek_of(:UncommunicativeVariableName,
120
- lines: [3],
121
- name: 'charlie')
122
- end
123
- ```
124
-
125
- The following examples should then cover the detector specific features.
126
-
127
- ### Cucumber features
128
-
129
- We are trying to write as few Cucumber features as possible.
130
- Normally, there should be no need to write a new feature for a new smell detector.
131
- If you feel like this is necessary in this case, please discuss this with us via
132
- github issue or in your work-in-progress pull request before doing anything.
@@ -1,114 +0,0 @@
1
- # How Reek works internally
2
-
3
-
4
- ## The big picture
5
-
6
- ```
7
- ["class C; end" | reek] [reek lib/*.rb] [expect(files).not_to reek_of(:LargeClass)]
8
- \ | |
9
- \ | |
10
- \ | |
11
- \ creates a | |
12
- \ | |
13
- \ | |
14
- \ | |
15
- \ | |
16
- \---------- Application (cli/application.rb) + |
17
- Options (cli/options) |
18
- | |
19
- | |
20
- | |
21
- | |
22
- creates a | |
23
- | |
24
- | |
25
- | |
26
- | |
27
- ReekCommand (cli/reek_command) |
28
- * uses a reporter (report/report) |
29
- * uses a SourceLocator (source/source_locator) |
30
- / | \ |
31
- / | \ |
32
- / | \ |
33
- Source Source Source (source/source_code) |
34
- | | | |
35
- | | | |
36
- | | | |
37
- Examiner | Examiner |
38
- | |
39
- | |
40
- Examiner (core/examiner) --------------------------------------
41
- * generates the AST out of the given source
42
- * adorns the generated AST via a TreeDresser (core/tree_dresser)
43
- * initializes a DetectorRepository with all relevant smells (smells/detector_repository)
44
- * builds a tree of Contexts using ContextBuilder
45
- * tells the DetectorRepository above to run each of its smell detectors above on each of the contexts
46
- / | \
47
- / | \
48
- / | \
49
- UtilityFunction FeatureEnvy TooManyMethods
50
- \ | /
51
- \ | /
52
- \ | /
53
- DetectorRepository
54
- |
55
- |
56
- |
57
- Application output
58
-
59
- ## A closer look at how an Examiner works
60
-
61
- The core foundation of Reek and its API is the Examiner.
62
- As you can see above, the Examiner is run for every source it gets passed and then runs the configured SmellDetectors.
63
- The overall workflow is like this:
64
-
65
- Examiner
66
- |
67
- |
68
- |
69
- Initialize DetectorRepository only with eligible SmellDetectors
70
- |
71
- |
72
- |
73
- Generate the AST out of the given source using SourceCode#syntax_tree, which works like this:
74
-
75
- - We generate a "rough" AST using the "parser" gem
76
- - We then obtain the comments from the source code separately
77
- - We pass this unprocessed AST and the comment_map to TreeDresser#dress which
78
- returns an instance of Reek::AST::SexpNode with type-dependent SexpExtensions mixed in.
79
-
80
- An example should make this more palpable.
81
- Given:
82
-
83
- class C
84
- def m
85
- puts 'nada'
86
- end
87
- end
88
-
89
- The AST generated by the parser gem (consisting of Parser::AST::Node) looks like this:
90
-
91
- (class
92
- (const nil :C)
93
- nil
94
- (def :m
95
- (args)
96
- (send nil :puts
97
- (str "nada"))))
98
-
99
- TreeDresser#dress would transform this into a very similar tree, but this time not consisting
100
- of Parser::AST::Node but of Reek::AST::SexpNode and with node-dependent SexpExtensions
101
- mixed in (noted in []):
102
-
103
- (class [AST::SexpExtensions::ClassNode, AST::SexpExtensions::ModuleNode]
104
- (const nil :C) [AST::SexpExtensions::ConstNode]
105
- nil
106
- (def :m [AST::SexpExtensions::DefNode, AST::SexpExtensions::MethodNodeBase]
107
- (args) [AST::SexpExtensions::ArgsNode]
108
- (send nil :puts [AST::SexpExtensions::SendNode]
109
- (str "nada"))))
110
- |
111
- |
112
- |
113
- A ContextBuilder then traverses this now adorned tree again and
114
- runs all SmellDetectors from the DetectorRepository above
@@ -1,163 +0,0 @@
1
- # Instance Variable Assumption
2
-
3
- ## Introduction
4
-
5
- Classes should not assume that instance variables are set or present outside of the current class definition.
6
-
7
- Good:
8
-
9
- ```Ruby
10
- class Foo
11
- def initialize
12
- @bar = :foo
13
- end
14
-
15
- def foo?
16
- @bar == :foo
17
- end
18
- end
19
- ```
20
-
21
- Good as well:
22
-
23
- ```Ruby
24
- class Foo
25
- def foo?
26
- bar == :foo
27
- end
28
-
29
- def bar
30
- @bar ||= :foo
31
- end
32
- end
33
- ```
34
-
35
- Bad:
36
-
37
- ```Ruby
38
- class Foo
39
- def go_foo!
40
- @bar = :foo
41
- end
42
-
43
- def foo?
44
- @bar == :foo
45
- end
46
- end
47
- ```
48
-
49
- ## Example
50
-
51
- Running Reek on:
52
-
53
- ```Ruby
54
- class Dummy
55
- def test
56
- @ivar
57
- end
58
- end
59
- ```
60
-
61
- would report:
62
-
63
- ```Bash
64
- [1]:InstanceVariableAssumption: Dummy assumes too much for instance variable @ivar
65
- ```
66
-
67
- Note that this example would trigger this smell warning as well:
68
-
69
- ```Ruby
70
- class Parent
71
- def initialize(omg)
72
- @omg = omg
73
- end
74
- end
75
-
76
- class Child < Parent
77
- def foo
78
- @omg
79
- end
80
- end
81
- ```
82
-
83
- The way to address the smell warning is that you should create an `attr_reader` to use `@omg` in the subclass and not access `@omg` directly like this:
84
-
85
- ```Ruby
86
- class Parent
87
- attr_reader :omg
88
-
89
- def initialize(omg)
90
- @omg = omg
91
- end
92
- end
93
-
94
- class Child < Parent
95
- def foo
96
- omg
97
- end
98
- end
99
- ```
100
-
101
- Directly accessing instance variables is considered a smell because it [breaks encapsulation](http://designisrefactoring.com/2015/03/29/organizing-data-self-encapsulation/) and makes it harder to reason about code.
102
-
103
- If you don't want to expose those methods as public API just make them private like this:
104
-
105
- ```Ruby
106
- class Parent
107
- def initialize(omg)
108
- @omg = omg
109
- end
110
-
111
- private
112
- attr_reader :omg
113
- end
114
-
115
- class Child < Parent
116
- def foo
117
- omg
118
- end
119
- end
120
- ```
121
-
122
-
123
- ## Current Support in Reek
124
-
125
- An instance variable must:
126
-
127
- * be set in the constructor
128
- * or be accessed through a method with lazy initialization / memoization.
129
-
130
- If not, _Instance Variable Assumption_ will be reported.
131
-
132
- ## Using Instance Variable Assumption in a Rails context
133
-
134
- In ActiveRecord it seems common to use callbacks like `after_initialize` to initialize instance variables as
135
- outlined [here](https://stackoverflow.com/questions/41165520/overriding-applicationrecord-initialize-bad-idea)
136
- or [here](http://blog.dalethatcher.com/2008/03/rails-dont-override-initialize-on.html)
137
- instead of overriding the `initialize` method.
138
- If an instance variable is initialized in such a callback Reek will report it correspondingly.
139
-
140
- This would smell for instance:
141
-
142
- ```Ruby
143
- class Sample < ApplicationRecord
144
- after_initialize do
145
- @my_var = false
146
- end
147
- end
148
- ```
149
-
150
- Since Reek cannot reliably detect that is used in a Rails context we recommend to disable this detector
151
- for "app/models" like this:
152
-
153
- ```Yaml
154
- directories:
155
- # Your other configuration....
156
- "app/models":
157
- InstanceVariableAssumption:
158
- enabled: false
159
- ```
160
-
161
- ## Configuration
162
-
163
- _Instance Variable Assumption_ supports the [Basic Smell Options](Basic-Smell-Options.md).
@@ -1,47 +0,0 @@
1
- # Irresponsible Module
2
-
3
- ## Introduction
4
-
5
- Classes and modules are the units of reuse and release. It is therefore
6
- considered good practice to annotate every class and module with a brief
7
- comment outlining its responsibilities.
8
-
9
- For further guideline on how to write good documentation in Ruby, see these
10
- links:
11
- - [Rails API documentation guidelines](http://edgeguides.rubyonrails.org/api_documentation_guidelines.html)
12
- - [Comments tell you why](https://blog.codinghorror.com/code-tells-you-how-comments-tell-you-why/)
13
-
14
- ## Example
15
-
16
- Given
17
-
18
- ```Ruby
19
- class Dummy
20
- # Do things...
21
- end
22
- ```
23
-
24
- Reek would emit the following warning:
25
-
26
- ```
27
- test.rb -- 1 warning:
28
- [1]:IrresponsibleModule: Dummy has no descriptive comment
29
- ```
30
-
31
- Fixing this is simple - just an explaining comment:
32
-
33
- ```Ruby
34
- # The Dummy class is responsible for ...
35
- class Dummy
36
- # Do things...
37
- end
38
- ```
39
-
40
- ## Current Support in Reek
41
-
42
- _Irresponsible Module_ checks classes and modules, including those
43
- created through `Struct.new` and `Class.new` and directly assigned to a constant.
44
-
45
- ## Configuration
46
-
47
- _Irresponsible Module_ supports only the [Basic Smell Options](Basic-Smell-Options.md).
data/docs/Large-Class.md DELETED
@@ -1,16 +0,0 @@
1
- # Large Class
2
-
3
- ## Introduction
4
-
5
- A _Large Class_ is a class or module that has a large number of instance
6
- variables, methods or lines of code in any one piece of its specification.
7
- (That is, this smell relates to pieces of the class's specification, not to the
8
- size of the corresponding instance of `Class`.)
9
-
10
- ## Current Support in Reek
11
-
12
- Reek offers three checks in this category.
13
-
14
- * [Too Many Constants](Too-Many-Constants.md)
15
- * [Too Many Instance Variables](Too-Many-Instance-Variables.md)
16
- * [Too Many Methods](Too-Many-Methods.md)
@@ -1,39 +0,0 @@
1
- # Long Parameter List
2
-
3
- ## Introduction
4
-
5
- A _Long Parameter List_ occurs when a method has a lot of parameters.
6
-
7
- ## Example
8
-
9
- Given
10
-
11
- ```Ruby
12
- class Dummy
13
- def long_list(foo,bar,baz,fling,flung)
14
- puts foo,bar,baz,fling,flung
15
- end
16
- end
17
- ```
18
-
19
- Reek would report the following warning:
20
-
21
- ```
22
- test.rb -- 1 warning:
23
- [2]:Dummy#long_list has 5 parameters (LongParameterList)
24
- ```
25
-
26
- A common solution to this problem would be the introduction of parameter objects.
27
-
28
- ## Current Support in Reek
29
-
30
- _Long Parameter List_ reports any method or block with more than 3 parameters.
31
-
32
- ## Configuration
33
-
34
- Reek's _Long Parameter List_ detector supports the
35
- [Basic Smell Options](Basic-Smell-Options.md), plus:
36
-
37
- | Option | Value | Effect |
38
- | -------------|---------|---------|
39
- | `max_params` | integer | The maximum number of parameters allowed in a method or block before a warning is issued. Defaults to 3. |
@@ -1,37 +0,0 @@
1
- # Long Yield List
2
-
3
- ## Introduction
4
-
5
- A _Long Yield List_ occurs when a method yields a lot of arguments to the block
6
- it gets passed. It is a special case of [Long Parameter List](Long-Parameter-List.md).
7
-
8
- ## Example
9
-
10
- ```Ruby
11
- class Dummy
12
- def yields_a_lot(foo,bar,baz,fling,flung)
13
- yield foo,bar,baz,fling,flung
14
- end
15
- end
16
- ```
17
-
18
- Reek would report the following warning:
19
-
20
- ```
21
- test.rb -- 1 warning:
22
- [4]:Dummy#yields_a_lot yields 5 parameters (LongYieldList)
23
- ```
24
-
25
- A common solution to this problem would be the introduction of parameter objects.
26
-
27
- ## Current Support in Reek
28
-
29
- Currently _Long Yield List_ reports any method or block with more than 3 parameters.
30
-
31
- ## Configuration
32
-
33
- Reek's _Long Yield List_ detector supports the [Basic Smell Options](Basic-Smell-Options.md), plus:
34
-
35
- | Option | Value | Effect |
36
- | -------------|---------|---------|
37
- | `max_params` | integer | The maximum number of parameters allowed in a method or block before a warning is issued. Defaults to 3. |
@@ -1,30 +0,0 @@
1
- ## Introduction
2
-
3
- Reek reports a _Manual Dispatch_ smell if it finds source code that manually checks whether an object responds to a method before that method is called. Manual dispatch is a type of [Simulated Polymorphism](Simulated-Polymorphism.md) which leads to code that is harder to reason about, debug, and refactor.
4
-
5
- ## Example
6
-
7
- ```Ruby
8
- class MyManualDispatcher
9
- attr_reader :foo
10
-
11
- def initialize(foo)
12
- @foo = foo
13
- end
14
-
15
- def call
16
- foo.bar if foo.respond_to?(:bar)
17
- end
18
- end
19
- ```
20
-
21
- Reek would emit the following warning:
22
-
23
- ```
24
- test.rb -- 1 warning:
25
- [9]: MyManualDispatcher manually dispatches method call (ManualDispatch)
26
- ```
27
-
28
- ## Configuration
29
-
30
- _Manual Dispatch_ offers the [Basic Smell Options](Basic-Smell-Options.md).
@@ -1,92 +0,0 @@
1
- # Missing Safe Method
2
-
3
- ## Introduction
4
-
5
- Candidate methods for the _Missing Safe Method_ smell are methods whose names
6
- end with an exclamation mark.
7
-
8
- An exclamation mark in method names means (the explanation below is taken from
9
- [here](http://dablog.rubypal.com/2007/8/15/bang-methods-or-danger-will-rubyist)):
10
-
11
- > The ! in method names that end with ! means, “This method is dangerous”—or,
12
- > more precisely, this method is the “dangerous” version of an otherwise
13
- > equivalent method, with the same name minus the !. “Danger” is relative; the
14
- > ! doesn’t mean anything at all unless the method name it’s in corresponds to
15
- > a similar but bang-less method name.
16
- >
17
- > So, for example, gsub! is the dangerous version of gsub. exit! is the
18
- > dangerous version of exit. flatten! is the dangerous version of flatten. And
19
- > so forth.
20
-
21
- Such a method is called _Missing Safe Method_ if and only if the non-bang
22
- version does not exist and this method is reported as a smell.
23
-
24
- Missing Safe Method was formerly known as Prima Donna Method.
25
-
26
- ## Example
27
-
28
- Given
29
-
30
- ```Ruby
31
- class C
32
- def foo; end
33
- def foo!; end
34
- def bar!; end
35
- end
36
- ```
37
-
38
- Reek would report the _Missing Safe Method_ smell for `bar!`, but not for `foo!`.
39
-
40
- Reek reports this smell only in a class context, not in a module context in order to allow perfectly legit code like this:
41
-
42
-
43
- ```Ruby
44
- class Parent
45
- def foo; end
46
- end
47
-
48
- module Dangerous
49
- def foo!; end
50
- end
51
-
52
- class Son < Parent
53
- include Dangerous
54
- end
55
-
56
- class Daughter < Parent
57
- end
58
- ```
59
-
60
- In this example, Reek would not report the _Missing Safe Method_ smell for the
61
- method `foo` of the `Dangerous` module.
62
-
63
- ## Configuration
64
-
65
- _Missing Safe Method_ offers the [Basic Smell Options](Basic-Smell-Options.md).
66
-
67
- ## Example configuration via source comment
68
-
69
- Imagine code like this:
70
-
71
- ```Ruby
72
- class Alfa
73
- def bravo!
74
- end
75
- end
76
- ```
77
-
78
- This would report:
79
-
80
- >>
81
- ruby.rb -- 1 warning:
82
- [1]:MissingSafeMethod: Alfa has missing safe method 'bravo!'
83
-
84
- If you want to suppress this warning you can do this via source comment like this:
85
-
86
- ```Ruby
87
- # :reek:MissingSafeMethod { exclude: [ bravo! ] }
88
- class Alfa
89
- def bravo!
90
- end
91
- end
92
- ```