reek 4.5.0 → 4.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +10 -7
  3. data/.travis.yml +13 -9
  4. data/CHANGELOG.md +36 -3
  5. data/Dockerfile +6 -5
  6. data/Gemfile +8 -7
  7. data/README.md +45 -27
  8. data/docs/How-To-Write-New-Detectors.md +6 -6
  9. data/docs/Irresponsible-Module.md +8 -1
  10. data/docs/Nil-Check.md +1 -1
  11. data/docs/Prima-Donna-Method.md +27 -0
  12. data/docs/RSpec-matchers.md +5 -10
  13. data/docs/Unused-Private-Method.md +27 -0
  14. data/docs/templates/default/docstring/setup.rb +1 -8
  15. data/features/command_line_interface/options.feature +5 -1
  16. data/features/command_line_interface/stdin.feature +1 -1
  17. data/features/configuration_files/exclude_paths_directives.feature +43 -0
  18. data/features/configuration_files/warn_about_multiple_configuration_files.feature +44 -0
  19. data/features/configuration_via_source_comments/erroneous_source_comments.feature +15 -0
  20. data/features/samples.feature +3 -8
  21. data/features/step_definitions/reek_steps.rb +5 -5
  22. data/features/todo_list.feature +1 -2
  23. data/lib/reek/ast/reference_collector.rb +2 -4
  24. data/lib/reek/ast/sexp_extensions/arguments.rb +0 -5
  25. data/lib/reek/ast/sexp_extensions/constant.rb +1 -0
  26. data/lib/reek/cli/application.rb +7 -8
  27. data/lib/reek/cli/command/report_command.rb +3 -1
  28. data/lib/reek/cli/options.rb +29 -13
  29. data/lib/reek/cli/status.rb +10 -0
  30. data/lib/reek/code_comment.rb +48 -6
  31. data/lib/reek/configuration/configuration_file_finder.rb +87 -27
  32. data/lib/reek/context/ghost_context.rb +1 -2
  33. data/lib/reek/context_builder.rb +26 -1
  34. data/lib/reek/detector_repository.rb +64 -0
  35. data/lib/reek/errors/bad_detector_configuration_key_in_comment_error.rb +37 -0
  36. data/lib/reek/errors/bad_detector_in_comment_error.rb +2 -1
  37. data/lib/reek/errors/base_error.rb +9 -0
  38. data/lib/reek/errors/garbage_detector_configuration_in_comment_error.rb +2 -1
  39. data/lib/reek/errors/incomprehensible_source_error.rb +47 -0
  40. data/lib/reek/errors/parse_error.rb +19 -0
  41. data/lib/reek/examiner.rb +17 -41
  42. data/lib/reek/logging_error_handler.rb +15 -0
  43. data/lib/reek/report/code_climate/code_climate_configuration.rb +12 -0
  44. data/lib/reek/report/code_climate/code_climate_configuration.yml +156 -0
  45. data/lib/reek/report/code_climate/code_climate_fingerprint.rb +4 -2
  46. data/lib/reek/report/code_climate/code_climate_formatter.rb +2 -2
  47. data/lib/reek/smell_configuration.rb +64 -0
  48. data/lib/reek/smell_detectors/attribute.rb +0 -2
  49. data/lib/reek/smell_detectors/base_detector.rb +24 -4
  50. data/lib/reek/smell_detectors/boolean_parameter.rb +0 -1
  51. data/lib/reek/smell_detectors/class_variable.rb +0 -1
  52. data/lib/reek/smell_detectors/control_parameter.rb +0 -1
  53. data/lib/reek/smell_detectors/data_clump.rb +0 -1
  54. data/lib/reek/smell_detectors/duplicate_method_call.rb +0 -1
  55. data/lib/reek/smell_detectors/feature_envy.rb +0 -1
  56. data/lib/reek/smell_detectors/instance_variable_assumption.rb +0 -1
  57. data/lib/reek/smell_detectors/irresponsible_module.rb +0 -1
  58. data/lib/reek/smell_detectors/long_parameter_list.rb +0 -2
  59. data/lib/reek/smell_detectors/long_yield_list.rb +0 -1
  60. data/lib/reek/smell_detectors/manual_dispatch.rb +4 -6
  61. data/lib/reek/smell_detectors/module_initialize.rb +5 -8
  62. data/lib/reek/smell_detectors/nested_iterators.rb +0 -1
  63. data/lib/reek/smell_detectors/nil_check.rb +0 -1
  64. data/lib/reek/smell_detectors/prima_donna_method.rb +30 -1
  65. data/lib/reek/smell_detectors/repeated_conditional.rb +0 -1
  66. data/lib/reek/smell_detectors/subclassed_from_core_class.rb +0 -1
  67. data/lib/reek/smell_detectors/too_many_constants.rb +0 -1
  68. data/lib/reek/smell_detectors/too_many_instance_variables.rb +0 -1
  69. data/lib/reek/smell_detectors/too_many_methods.rb +0 -1
  70. data/lib/reek/smell_detectors/too_many_statements.rb +0 -1
  71. data/lib/reek/smell_detectors/uncommunicative_method_name.rb +0 -1
  72. data/lib/reek/smell_detectors/uncommunicative_module_name.rb +0 -1
  73. data/lib/reek/smell_detectors/uncommunicative_parameter_name.rb +0 -1
  74. data/lib/reek/smell_detectors/uncommunicative_variable_name.rb +0 -1
  75. data/lib/reek/smell_detectors/unused_parameters.rb +0 -1
  76. data/lib/reek/smell_detectors/unused_private_method.rb +0 -2
  77. data/lib/reek/smell_detectors/utility_function.rb +0 -1
  78. data/lib/reek/smell_warning.rb +85 -0
  79. data/lib/reek/source/source_code.rb +2 -1
  80. data/lib/reek/source/source_locator.rb +15 -3
  81. data/lib/reek/spec/should_reek_of.rb +1 -1
  82. data/lib/reek/spec.rb +6 -4
  83. data/lib/reek/version.rb +1 -1
  84. data/reek.gemspec +1 -1
  85. data/samples/configuration/more_than_one_configuration_file/todo.reek +0 -0
  86. data/samples/configuration/single_configuration_file/.reek +0 -0
  87. data/spec/factories/factories.rb +2 -10
  88. data/spec/quality/reek_source_spec.rb +5 -3
  89. data/spec/reek/ast/reference_collector_spec.rb +0 -17
  90. data/spec/reek/cli/application_spec.rb +25 -1
  91. data/spec/reek/cli/command/report_command_spec.rb +2 -2
  92. data/spec/reek/cli/command/todo_list_command_spec.rb +14 -71
  93. data/spec/reek/cli/options_spec.rb +4 -0
  94. data/spec/reek/code_comment_spec.rb +47 -0
  95. data/spec/reek/configuration/configuration_file_finder_spec.rb +38 -15
  96. data/spec/reek/context/code_context_spec.rb +10 -10
  97. data/spec/reek/context/method_context_spec.rb +1 -1
  98. data/spec/reek/context/module_context_spec.rb +8 -4
  99. data/spec/reek/{smell_detectors/detector_repository_spec.rb → detector_repository_spec.rb} +3 -3
  100. data/spec/reek/examiner_spec.rb +39 -40
  101. data/spec/reek/logging_error_handler_spec.rb +24 -0
  102. data/spec/reek/report/code_climate/code_climate_configuration_spec.rb +24 -0
  103. data/spec/reek/report/code_climate/code_climate_fingerprint_spec.rb +9 -9
  104. data/spec/reek/report/yaml_report_spec.rb +4 -4
  105. data/spec/reek/{smell_detectors/smell_configuration_spec.rb → smell_configuration_spec.rb} +3 -3
  106. data/spec/reek/smell_detectors/base_detector_spec.rb +18 -0
  107. data/spec/reek/smell_detectors/duplicate_method_call_spec.rb +2 -2
  108. data/spec/reek/smell_detectors/feature_envy_spec.rb +18 -8
  109. data/spec/reek/smell_detectors/manual_dispatch_spec.rb +13 -0
  110. data/spec/reek/smell_detectors/module_initialize_spec.rb +23 -2
  111. data/spec/reek/smell_detectors/nested_iterators_spec.rb +1 -1
  112. data/spec/reek/smell_detectors/prima_donna_method_spec.rb +12 -0
  113. data/spec/reek/smell_detectors/subclassed_from_core_class_spec.rb +0 -5
  114. data/spec/reek/smell_detectors/uncommunicative_variable_name_spec.rb +2 -2
  115. data/spec/reek/smell_detectors/unused_parameters_spec.rb +1 -1
  116. data/spec/reek/{smell_detectors/smell_warning_spec.rb → smell_warning_spec.rb} +9 -9
  117. data/spec/reek/source/source_code_spec.rb +6 -29
  118. data/spec/reek/source/source_locator_spec.rb +48 -16
  119. data/spec/reek/spec/should_reek_of_spec.rb +1 -1
  120. data/spec/reek/spec/should_reek_only_of_spec.rb +4 -4
  121. data/spec/spec_helper.rb +4 -3
  122. data/tasks/configuration.rake +2 -2
  123. metadata +26 -14
  124. data/lib/reek/smell_detectors/detector_repository.rb +0 -66
  125. data/lib/reek/smell_detectors/smell_configuration.rb +0 -66
  126. data/lib/reek/smell_detectors/smell_warning.rb +0 -88
  127. data/tasks/mutant.rake +0 -14
  128. /data/samples/configuration/{.reek → more_than_one_configuration_file/regular.reek} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f44c19009380c9dff7c4d8ef4dcdbe6f788d46b2
4
- data.tar.gz: b9cfe47dc250a613611f414463a6dbca748690c8
3
+ metadata.gz: 5c827e3718e3a4f1524fdaf0d6c28df6e86b671b
4
+ data.tar.gz: 9755661abe970fb1499ee2b9de2f6d701b8c8ee2
5
5
  SHA512:
6
- metadata.gz: 221c0dbe79b6a6758a30ded23285fd715634843c3ac9bb0b9883aef9a0ebffcf84531dc6e492f091b2fa11cb7087470c96632aa45b53704da831a0a64feb7c1a
7
- data.tar.gz: 51c17f02b1aa2c8ff8cf701ba7bc9d98c058a9c4e62fc2b6f246fd43f3be17ed12b6cc58ccb247f99527f909db50c5b4ab7085b08392a4b2c9e26137c8081bb2
6
+ metadata.gz: 77122032bb96bbd32994195c9745acc214ecfbfff7963348aff01239402deefb74032883eed3762df8eda34c6054447a5ca076dfe707a9a1460a5c14bc85ddf7
7
+ data.tar.gz: e86a819d479502f6f091c6d6f8b7d1b6c1aae20779131a3e6e62445eb048db3f1f0e1226b59a0b11ca82e9f3c4471578ce4c71c19d0a1fdff96b51f8f5e7d752
data/.rubocop.yml CHANGED
@@ -8,6 +8,15 @@ AllCops:
8
8
  - 'vendor/**/*'
9
9
  TargetRubyVersion: 2.1
10
10
 
11
+ Lint/HandleExceptions:
12
+ Exclude:
13
+ - 'spec/reek/configuration/configuration_file_finder_spec.rb'
14
+
15
+ # Spec blocks can be any size
16
+ Metrics/BlockLength:
17
+ Exclude:
18
+ - 'spec/**/*'
19
+
11
20
  # FIXME: Make the class shorter
12
21
  Metrics/ClassLength:
13
22
  Exclude:
@@ -64,16 +73,10 @@ RSpec/NestedGroups:
64
73
  Exclude:
65
74
  - 'spec/reek/cli/application_spec.rb'
66
75
 
67
- # FIXME: Update specs to avoid offenses
68
- RSpec/VerifiedDoubles:
69
- Exclude:
70
- - 'spec/reek/context/code_context_spec.rb'
71
- - 'spec/reek/context/method_context_spec.rb'
72
- - 'spec/reek/context/module_context_spec.rb'
73
-
74
76
  # rubocop-rspec expects a CodeClimate namespace to go with the code_climate directory.
75
77
  RSpec/FilePath:
76
78
  Exclude:
79
+ - 'spec/reek/report/code_climate/code_climate_configuration_spec.rb'
77
80
  - 'spec/reek/report/code_climate/code_climate_fingerprint_spec.rb'
78
81
  - 'spec/reek/report/code_climate/code_climate_formatter_spec.rb'
79
82
  - 'spec/reek/report/code_climate/code_climate_report_spec.rb'
data/.travis.yml CHANGED
@@ -1,4 +1,5 @@
1
1
  sudo: false
2
+ dist: trusty
2
3
  cache: bundler
3
4
  language: ruby
4
5
  bundler_args: --without debugging
@@ -6,21 +7,24 @@ script: bundle exec rake ci
6
7
  rvm:
7
8
  - 2.1
8
9
  - 2.2
9
- - 2.3.0
10
- - rbx-2
10
+ - 2.3
11
+ - 2.4
12
+ - jruby-9.1.7.0
13
+ - jruby-head
11
14
  - ruby-head
15
+ - rubinius-3
12
16
  matrix:
13
- include:
14
- - rvm: jruby
15
- env: JRUBY_OPTS='--2.0 --server -Xcompile.invokedynamic=false'
16
- - rvm: jruby-head
17
- env: JRUBY_OPTS='--server -Xcompile.invokedynamic=false'
18
17
  allow_failures:
19
- - rvm: jruby
18
+ - rvm: jruby-9.1.7.0
20
19
  - rvm: jruby-head
21
- - rvm: rbx-2
22
20
  - rvm: ruby-head
21
+ - rvm: rubinius-3
23
22
  fast_finish: true
23
+ before_install:
24
+ - rvm use @global
25
+ - gem uninstall bundler -x
26
+ - gem install bundler --version=1.13.7
27
+ - bundler --version
24
28
  notifications:
25
29
  email:
26
30
  - timo.roessner@googlemail.com
data/CHANGELOG.md CHANGED
@@ -1,11 +1,44 @@
1
1
  # Change log
2
2
 
3
+ ## 4.6.0 (2017-04-04)
4
+
5
+ * (IanWhitney) Implement `--force-exclusion` flag
6
+ * (mvz) Raise Reek-specific error on parse errors
7
+
8
+ ## 4.5.6 (2017-02-17)
9
+
10
+ * (mvz) Raise on errors inside of Examiner#smells instead of outputting to STDERR
11
+ * (mvz) Update parser dependency
12
+
13
+ ## 4.5.5 (2017-02-05)
14
+
15
+ * (mvz) Load YAML in code comments safely
16
+ * (mvz) Combine lines for manual dispatch smells
17
+ * (mvz) Respect exclude_paths when passing sources on the command line
18
+ * (mvz) Ensure explicit arguments of super() are processed
19
+
20
+ ## 4.5.4 (2017-01-17)
21
+
22
+ * (troessner) Improve documentation and fix PrimaDonnaMethod detector configuration via comment.
23
+
24
+ ## 4.5.3 (2016-12-05)
25
+
26
+ * (jhubert) Stop reporting FeatureEnvy with super and arguments.
27
+
28
+ ## 4.5.2 (2016-11-06)
29
+
30
+ * (troessner) Warn about multiple configuration files.
31
+
32
+ ## 4.5.1 (2016-10-16)
33
+
34
+ * (troessner) Validate configuration keys in code comments.
35
+
3
36
  ## 4.5.0 (2016-10-12)
4
37
 
5
- * (maxjacobson) Emit fingerprints in Code Climate reporter
6
- * (mvz) Disable progress for piped output
7
- * (mvz) Update progress formatter to match changed file location
8
38
  * (jhubert) Add progress formatters for showing progress on each file
39
+ * (mvz) Update progress formatter to match changed file location
40
+ * (mvz) Disable progress for piped output
41
+ * (maxjacobson) Emit fingerprints in Code Climate reporter
9
42
 
10
43
  ## 4.4.4 (2016-09-29)
11
44
 
data/Dockerfile CHANGED
@@ -3,7 +3,7 @@
3
3
  # Build and run via:
4
4
  # docker build -t codeclimate/codeclimate-reek . && docker run codeclimate/codeclimate-reek
5
5
 
6
- FROM codeclimate/alpine-ruby:b38
6
+ FROM ruby:2.3.3-alpine
7
7
 
8
8
  MAINTAINER The Reek core team
9
9
 
@@ -12,17 +12,18 @@ ENV app_dir /usr/src/app
12
12
  ENV user app
13
13
 
14
14
  RUN apk --update add git
15
-
16
15
  ADD . ${app_dir}
17
16
 
17
+ RUN adduser -u 9000 -D ${user}
18
+ RUN chown -R ${user}:${user} ${app_dir}
19
+ USER ${user}
20
+
18
21
  WORKDIR ${app_dir}
19
22
 
23
+ RUN gem install rake
20
24
  RUN bundle install --without debugging development
21
- RUN adduser -u 9000 -D ${user}
22
- RUN chown -R ${user}:${user} ${app_dir}
23
25
 
24
26
  VOLUME ${code_dir}
25
27
  WORKDIR ${code_dir}
26
- USER ${user}
27
28
 
28
29
  CMD [ "/usr/src/app/bin/code_climate_reek" ]
data/Gemfile CHANGED
@@ -2,25 +2,26 @@ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
4
 
5
+ ruby RUBY_VERSION
6
+
5
7
  group :development do
8
+ gem 'activesupport', '>= 4.2'
6
9
  gem 'aruba', '~> 0.14.0'
7
10
  gem 'ataru', '~> 0.2.0'
8
11
  gem 'cucumber', '~> 2.0'
9
12
  gem 'factory_girl', '~> 4.0'
10
- gem 'mutant-rspec', '~> 0.8.8'
11
- gem 'rake', '~> 11.1'
13
+ gem 'rake', '~> 12.0'
12
14
  gem 'rspec', '~> 3.0'
13
- gem 'simplecov', '~> 0.12.0'
15
+ gem 'simplecov', '~> 0.14.0'
14
16
  gem 'yard', '~> 0.9.5'
15
- gem 'activesupport', '~> 4.2'
16
17
 
17
18
  if RUBY_VERSION >= '2.3'
18
- gem 'rubocop', '~> 0.42.0'
19
- gem 'rubocop-rspec', '~> 1.7'
19
+ gem 'rubocop', '~> 0.47.1'
20
+ gem 'rubocop-rspec', '~> 1.13.0'
20
21
  end
21
22
 
22
23
  platforms :mri do
23
- gem 'redcarpet', '~> 3.3.1'
24
+ gem 'redcarpet', '~> 3.4.0'
24
25
  end
25
26
  end
26
27
 
data/README.md CHANGED
@@ -16,8 +16,9 @@
16
16
  - [Configuration file](#configuration-file)
17
17
  - [Configuration loading](#configuration-loading)
18
18
  - [Configuration options](#configuration-options)
19
- - [Source code comments](#source-code-comments)
20
19
  - [Generating a 'todo' list](#generating-a-todo-list)
20
+ - [Beware of multiple configuration files](#beware-of-multiple-configuration-files)
21
+ - [Source code comments](#source-code-comments)
21
22
  - [Usage](#usage)
22
23
  - [Developing Reek / Contributing](#developing-reek--contributing)
23
24
  - [Output formats](#output-formats)
@@ -355,30 +356,6 @@ configurations you can also check out [the `default.reek` file in this repositor
355
356
  Note that you do not need a configuration file at all.
356
357
  If you're fine with all the [defaults](defaults.reek) we set you can skip this completely.
357
358
 
358
- ### Source code comments
359
-
360
- In case you need to suppress a smell warning and you can't or don't want to
361
- use configuration files for whatever reasons you can also use special
362
- source code comments like this:
363
-
364
- ```Ruby
365
- # This method smells of :reek:NestedIterators
366
- def smelly_method foo
367
- foo.each {|bar| bar.each {|baz| baz.qux}}
368
- end
369
- ```
370
-
371
- You can even pass in smell specific configuration settings:
372
-
373
- ```Ruby
374
- # :reek:NestedIterators { max_allowed_nesting: 2 }
375
- def smelly_method foo
376
- foo.each {|bar| bar.each {|baz| baz.qux}}
377
- end
378
- ```
379
-
380
- This is an incredible powerful feature and further explained under [Smell Suppresion](docs/Smell-Suppression.md).
381
-
382
359
  ### Generating a 'todo' list
383
360
 
384
361
  Integrating tools like Reek into an existing larger codebase can be daunting when you have to fix
@@ -425,6 +402,42 @@ reek -c other_configuration.reek --todo lib/
425
402
  `other_configuration.reek` will simply be ignored (as outlined before, Reek
426
403
  is supposed to have one configuration file and one file only).
427
404
 
405
+ ### Beware of multiple configuration files
406
+
407
+ Reek takes one configuration file and one configuration file only.
408
+
409
+ If you have more than one configuration file in the same directory Reek
410
+ will not know what configuration file to use. If this happens Reek will
411
+ print a warning on STDERR and exit with the failure exit status 1.
412
+
413
+ In case you have to have one or more configuration files in the directory (e.g. you're
414
+ toying around with different, mutually exclusive settings) you need to tell Reek
415
+ explicitly which file to use via `reek -c config.reek`.
416
+
417
+ ### Source code comments
418
+
419
+ In case you need to suppress a smell warning and you can't or don't want to
420
+ use configuration files for whatever reasons you can also use special
421
+ source code comments like this:
422
+
423
+ ```Ruby
424
+ # This method smells of :reek:NestedIterators
425
+ def smelly_method foo
426
+ foo.each {|bar| bar.each {|baz| baz.qux}}
427
+ end
428
+ ```
429
+
430
+ You can even pass in smell specific configuration settings:
431
+
432
+ ```Ruby
433
+ # :reek:NestedIterators { max_allowed_nesting: 2 }
434
+ def smelly_method foo
435
+ foo.each {|bar| bar.each {|baz| baz.qux}}
436
+ end
437
+ ```
438
+
439
+ This is an incredible powerful feature and further explained under [Smell Suppresion](docs/Smell-Suppression.md).
440
+
428
441
  ## Usage
429
442
 
430
443
  Besides the obvious
@@ -462,7 +475,7 @@ Or just run the whole test suite:
462
475
  bundle exec rake
463
476
  ```
464
477
 
465
- This will run the tests (RSpec and Cucumber), RuboCop and Reek itself.
478
+ This will run the RSpec tests, RuboCop and Reek itself.
466
479
 
467
480
  You can also run:
468
481
 
@@ -470,7 +483,9 @@ You can also run:
470
483
  bundle exec rake ci
471
484
  ```
472
485
 
473
- This will run everything the default task runs and also [Ataru](https://github.com/CodePadawans/ataru) and [Mutant](https://github.com/mbj/mutant). This is the task that we run on Travis as well and that determines if your pull request is green or red.
486
+ This will run everything the default task runs and also
487
+ our Cucumber features and [Ataru](https://github.com/CodePadawans/ataru). This is the task that we run on
488
+ Travis as well and that determines if your pull request is green or red.
474
489
 
475
490
  Another useful Rake task is the `console` task. This will throw you right into an environment where you can play around with Reeks modules and classes:
476
491
 
@@ -542,6 +557,9 @@ Just add this to your configuration file:
542
557
  enabled: false
543
558
  UtilityFunction:
544
559
  enabled: false
560
+ "app/mailers":
561
+ InstanceVariableAssumption:
562
+ enabled: false
545
563
  ```
546
564
 
547
565
  Be careful though, Reek does not merge your configuration entries, so if you already have a directory directive for "app/controllers" or "app/helpers" you need to update those directives instead of copying the above YAML sample into your configuration file.
@@ -9,19 +9,19 @@ it covers and the overall rationale behind it.
9
9
 
10
10
  ### Structure
11
11
 
12
- All smell detectors reside in `lib/reek/smells` and have the following base structure:
12
+ All smell detectors reside in `lib/reek/smell_detectors` and have the following base structure:
13
13
 
14
14
  ```Ruby
15
- require_relative 'smell_detector'
15
+ require_relative 'base_detector'
16
16
  require_relative 'smell_warning'
17
17
 
18
18
  module Reek
19
- module Smells
19
+ module SmellDetectors
20
20
  #
21
21
  # Here goes your introduction for this detector.
22
22
  #
23
23
  # See {file:docs/Your-Detector.md} for details.
24
- class YourDetector < SmellDetector
24
+ class YourDetector < BaseDetector
25
25
  def self.contexts
26
26
  [:class] # In case you're operating on class contexts only - just an example.
27
27
  end
@@ -37,7 +37,7 @@ module Reek
37
37
  # This can just be a method but it can also be a more sophisticated set up.
38
38
  # Check out other smell detectors to get a feeling for what to do here.
39
39
  found_smells(ctx).map do |smell|
40
- # "smell_warning" is defined in SmellDetector and should be used by you
40
+ # "smell_warning" is defined in BaseDetector and should be used by you
41
41
  # to construct smell warnings
42
42
  smell_warning(
43
43
  context: ctx,
@@ -59,7 +59,7 @@ module Reek
59
59
  end
60
60
  ```
61
61
 
62
- For your detector to be properly loaded you need to require it in `lib/reek/smells.rb` as well.
62
+ For your detector to be properly loaded you need to require it in `lib/reek/smell_detectors.rb` as well.
63
63
 
64
64
  ### defaults.reek
65
65
 
@@ -2,7 +2,14 @@
2
2
 
3
3
  ## Introduction
4
4
 
5
- Classes and modules are the units of reuse and release. It is therefore considered good practice to annotate every class and module with a brief comment outlining its responsibilities.
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/)
6
13
 
7
14
  ## Example
8
15
 
data/docs/Nil-Check.md CHANGED
@@ -17,7 +17,7 @@ Given
17
17
  class Klass
18
18
  def nil_checker(argument)
19
19
  if argument.nil?
20
- puts "argument isn't nil!"
20
+ puts "argument is nil!"
21
21
  end
22
22
  end
23
23
  end
@@ -61,3 +61,30 @@ method `foo` of the `Dangerous` module.
61
61
  ## Configuration
62
62
 
63
63
  _Prima Donna Method_ offers the [Basic Smell Options](Basic-Smell-Options.md).
64
+
65
+ ## Example configuration via source comment
66
+
67
+ Imagine code like this:
68
+
69
+ ```Ruby
70
+ class Alfa
71
+ def bravo!
72
+ end
73
+ end
74
+ ```
75
+
76
+ This would report:
77
+
78
+ >>
79
+ ruby.rb -- 1 warning:
80
+ [1]:PrimaDonnaMethod: Alfa has prima donna method 'bravo!'
81
+
82
+ If you want to suppress this warning you can do this via source comment like this:
83
+
84
+ ```Ruby
85
+ # :reek:PrimaDonnaMethod: { exclude: [ bravo! ] }
86
+ class Alfa
87
+ def bravo!
88
+ end
89
+ end
90
+ ```
@@ -74,15 +74,10 @@ See the "Quickstart" example from above.
74
74
  Checks the target source code for instances of "smell type"
75
75
  and returns true only if it can find one of them that matches.
76
76
 
77
- Remember that this includes our "smell types" as well. So it could be the
78
- "smell type" UtilityFunction, which is represented as a concrete class
79
- in Reek but it could also be "Duplication" which is a "smell categgory".
77
+ You can pass the smell type you want to check for as String or as Symbol:
80
78
 
81
- You could pass many different types of input here:
82
79
  - `:UtilityFunction`
83
80
  - `"UtilityFunction"`
84
- - `Reek::Smells::UtilityFunction` (the right way if you really want to pass a
85
- class)
86
81
 
87
82
  It is recommended to pass this as a symbol like `:UtilityFunction`. However we
88
83
  don't enforce this.
@@ -106,20 +101,20 @@ So in a nutshell `reek_of` takes the following two arguments:
106
101
 
107
102
  ```Ruby
108
103
  reek_of(:FeatureEnvy)
109
- reek_of(Reek::Smells::UtilityFunction)
104
+ reek_of(:UtilityFunction)
110
105
  ```
111
106
 
112
107
  With smell_details:
113
108
 
114
109
  ```Ruby
115
- reek_of(UncommunicativeParameterName, name: 'x2')
116
- reek_of(DataClump, count: 3)
110
+ reek_of(:UncommunicativeParameterName, name: 'x2')
111
+ reek_of(:DataClump, count: 3)
117
112
  ```
118
113
 
119
114
  **Examples from a real spec**
120
115
 
121
116
  ```Ruby
122
- expect(src).to reek_of(Reek::Smells::DuplicateMethodCall, name: '@other.thing')
117
+ expect(src).to reek_of(:DuplicateMethodCall, name: '@other.thing')
123
118
  ```
124
119
 
125
120
  ### reek_only_of
@@ -48,6 +48,33 @@ end
48
48
  Note that disabling this detector via comment works on a class scope, not
49
49
  a method scope (like you can see above).
50
50
 
51
+ Another simple example would be:
52
+
53
+ ```Ruby
54
+ class Alfa
55
+ private
56
+ def bravo
57
+ end
58
+ end
59
+ ```
60
+
61
+ This would report:
62
+
63
+ >>
64
+ ruby.rb -- 1 warning:
65
+ [3]:UnusedPrivateMethod: Alfa has the unused private instance method 'bravo'
66
+
67
+ If you want to suppress this warning you can do this via source comment like this:
68
+
69
+ ```Ruby
70
+ # :reek:UnusedPrivateMethod: { exclude: bravo }
71
+ class Alfa
72
+ private
73
+ def bravo
74
+ end
75
+ end
76
+ ```
77
+
51
78
  ## Known limitations
52
79
 
53
80
  * Method calls via dynamic dispatch (e.g. via `send`) is something Reek (or any other
@@ -10,14 +10,7 @@ end
10
10
 
11
11
  def api_marker
12
12
  return if object.type == :root
13
- case api_text
14
- when 'public'
15
- # erb(:public_api_marker)
16
- when 'private'
17
- # Let section 'private' handle this.
18
- else
19
- erb(:private)
20
- end
13
+ erb(:private) unless ['public', 'private'].include? api_text
21
14
  end
22
15
 
23
16
  private
@@ -41,7 +41,9 @@ Feature: Reek can be controlled using command-line options
41
41
 
42
42
  Configuration:
43
43
  -c, --config FILE Read configuration options from FILE
44
- --smell SMELL Detect smell SMELL (default: all enabled smells)
44
+ --smell SMELL Only look for a specific smell.
45
+ Call it like this: reek --smell PrimaDonnaMethod source.rb
46
+ Check out https://github.com/troessner/reek/blob/master/docs/Code-Smells.md for a list of smells
45
47
 
46
48
  Generate a todo list:
47
49
  -t, --todo Generate a todo list
@@ -65,6 +67,8 @@ Feature: Reek can be controlled using command-line options
65
67
  --sort-by SORTING Sort reported files by the given criterium:
66
68
  smelliness ("smelliest" files first)
67
69
  none (default - output in processing order)
70
+ --force-exclusion Force excluding files specified in the configuration `exclude_paths`
71
+ even if they are explicitly passed as arguments
68
72
 
69
73
  Exit codes:
70
74
  --success-exit-code CODE The exit code when no smells are found (default: 0)
@@ -35,5 +35,5 @@ Feature: Reek reads from $stdin when no files are given
35
35
  Scenario: syntax error causes the source to be ignored
36
36
  When I pass "= invalid syntax =" to reek
37
37
  Then it reports a parsing error
38
- Then it succeeds
38
+ And the exit status indicates an error
39
39
  And it reports nothing
@@ -0,0 +1,43 @@
1
+ Feature: Exclude paths directives
2
+ In order to avoid Reek wasting time on files that cannot be fixed
3
+ As a user
4
+ I want to be able to exclude specific paths from being checked
5
+
6
+ Scenario: Exclude some paths
7
+ Given a file named "bad_files_live_here/smelly.rb" with:
8
+ """
9
+ # A smelly example class
10
+ class Smelly
11
+ def alfa(bravo); end
12
+ end
13
+ """
14
+ When I run `reek .`
15
+ Then the exit status indicates smells
16
+ Given a file named "config.reek" with:
17
+ """
18
+ ---
19
+ exclude_paths:
20
+ - bad_files_live_here
21
+ """
22
+ When I run `reek -c config.reek .`
23
+ Then it succeeds
24
+ And it reports nothing
25
+ Scenario: Using a file name within an excluded directory
26
+ Given a file named "bad_files_live_here/smelly.rb" with:
27
+ """
28
+ # A smelly example class
29
+ class Smelly
30
+ def alfa(bravo); end
31
+ end
32
+ """
33
+ And a file named "config.reek" with:
34
+ """
35
+ ---
36
+ exclude_paths:
37
+ - bad_files_live_here
38
+ """
39
+ When I run `reek -c config.reek bad_files_live_here/smelly.rb`
40
+ Then the exit status indicates smells
41
+ When I run `reek -c config.reek --force-exclusion bad_files_live_here/smelly.rb`
42
+ Then it succeeds
43
+ And it reports nothing
@@ -0,0 +1,44 @@
1
+ Feature: Warn on multiple configuration files
2
+ Reek is designed for one configuration file and for one configuration file only.
3
+ We should make this clear to the user by warning him when we detect multiple
4
+ configuration files and then exiting the program.
5
+
6
+ Scenario: Warn on more than one configuration file
7
+ Given the smelly file 'smelly.rb'
8
+ And a file named "config.reek" with:
9
+ """
10
+ ---
11
+ UncommunicativeMethodName:
12
+ enabled: false
13
+ """
14
+ And a file named ".todo.reek" with:
15
+ """
16
+ ---
17
+ UtilityFunction:
18
+ enabled: false
19
+ """
20
+ When I run reek smelly.rb
21
+ Then it reports the error "Error: Found multiple configuration files '.todo.reek', 'config.reek'"
22
+ And it reports the error "Reek supports only one configuration file. You have 2 options now:"
23
+ And it reports the error "1) Remove all offending files"
24
+ And it reports the error "2) Be specific about which one you want to load via the -c switch"
25
+ And the exit status indicates an error
26
+
27
+ Scenario: Do not warn on more than one when we explicitly specify one configuration file
28
+ Given the smelly file 'smelly.rb'
29
+ And a file named "config.reek" with:
30
+ """
31
+ ---
32
+ UncommunicativeMethodName:
33
+ enabled: false
34
+ """
35
+ And a file named ".todo.reek" with:
36
+ """
37
+ ---
38
+ UtilityFunction:
39
+ enabled: false
40
+ """
41
+ When I run reek -c config.reek smelly.rb
42
+ Then the exit status indicates smells
43
+ And it reports no errors
44
+
@@ -51,3 +51,18 @@ Feature: Erroneous source comments are handled properly
51
51
  And it reports the error "Unfortunately we can not parse the configuration you have given."
52
52
  And it reports the error "The source is 'bad_comment.rb'"
53
53
  And it reports the error "the comment belongs to the expression starting in line 3"
54
+
55
+ Scenario: Bad configuration key
56
+ Given a file named "bad_comment.rb" with:
57
+ """
58
+ # Test class
59
+ # exclude -> elude and accept -> accipt are bad keys
60
+ # :reek:UncommunicativeMethodName { elude: 'foo', accipt: 'bar' }
61
+ def x
62
+ end
63
+ """
64
+ When I run reek bad_comment.rb
65
+ Then it reports the error "Error: You are trying to configure the smell detector 'UncommunicativeMethodName'"
66
+ And it reports the error "in one of your source code comments with the unknown option 'elude', 'accipt'"
67
+ And it reports the error "The source is 'bad_comment.rb'"
68
+ And it reports the error "the comment belongs to the expression starting in line 4"