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
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  require_relative 'base_detector'
3
- require_relative 'smell_warning'
4
3
 
5
4
  module Reek
6
5
  module SmellDetectors
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  require_relative 'base_detector'
3
- require_relative 'smell_warning'
4
3
 
5
4
  module Reek
6
5
  module SmellDetectors
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  require_relative 'base_detector'
3
- require_relative 'smell_warning'
4
3
 
5
4
  module Reek
6
5
  module SmellDetectors
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  require_relative 'base_detector'
3
- require_relative 'smell_warning'
4
3
 
5
4
  module Reek
6
5
  module SmellDetectors
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  require_relative 'base_detector'
3
- require_relative 'smell_warning'
4
3
 
5
4
  module Reek
6
5
  module SmellDetectors
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  require_relative 'base_detector'
3
- require_relative 'smell_warning'
4
3
 
5
4
  module Reek
6
5
  module SmellDetectors
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
- require_relative 'smell_configuration'
3
2
  require_relative 'base_detector'
4
- require_relative 'smell_warning'
5
3
 
6
4
  module Reek
7
5
  module SmellDetectors
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  require_relative 'base_detector'
3
- require_relative 'smell_warning'
4
3
 
5
4
  module Reek
6
5
  module SmellDetectors
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  require_relative 'base_detector'
3
- require_relative 'smell_warning'
4
3
 
5
4
  module Reek
6
5
  module SmellDetectors
@@ -21,11 +20,10 @@ module Reek
21
20
  #
22
21
  # :reek:FeatureEnvy
23
22
  def sniff(ctx)
24
- ctx.each_node(:send).flat_map do |node|
25
- next unless node.name.equal?(:respond_to?)
26
-
27
- smell_warning(context: ctx, lines: [node.line], message: MESSAGE)
28
- end.compact
23
+ smelly_nodes = ctx.each_node(:send).select { |node| node.name == :respond_to? }
24
+ return [] if smelly_nodes.empty?
25
+ lines = smelly_nodes.map(&:line)
26
+ [smell_warning(context: ctx, lines: lines, message: MESSAGE)]
29
27
  end
30
28
  end
31
29
  end
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  require_relative 'base_detector'
3
- require_relative 'smell_warning'
4
3
 
5
4
  module Reek
6
5
  module SmellDetectors
@@ -23,13 +22,11 @@ module Reek
23
22
  # :reek:FeatureEnvy
24
23
  def sniff(ctx)
25
24
  ctx.local_nodes(:def) do |node|
26
- if node.name.to_s == 'initialize'
27
- return [
28
- smell_warning(
29
- context: ctx,
30
- lines: [ctx.exp.line],
31
- message: 'has initialize method')
32
- ]
25
+ if node.name == :initialize
26
+ return smell_warning(
27
+ context: ctx,
28
+ lines: [ctx.exp.line],
29
+ message: 'has initialize method')
33
30
  end
34
31
  end
35
32
  []
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  require_relative 'base_detector'
3
- require_relative 'smell_warning'
4
3
 
5
4
  module Reek
6
5
  module SmellDetectors
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  require_relative 'base_detector'
3
- require_relative 'smell_warning'
4
3
 
5
4
  module Reek
6
5
  module SmellDetectors
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  require_relative 'base_detector'
3
- require_relative 'smell_warning'
4
3
 
5
4
  module Reek
6
5
  module SmellDetectors
@@ -29,6 +28,24 @@ module Reek
29
28
  [:class]
30
29
  end
31
30
 
31
+ #
32
+ # @param ctx [Context::ModuleContext]
33
+ # @return [Array<SmellWarning>]
34
+ #
35
+ # Given this code:
36
+ #
37
+ # class Alfa
38
+ # def bravo!
39
+ # end
40
+ # end
41
+ #
42
+ # An example `ctx` could look like this:
43
+ #
44
+ # s(:class,
45
+ # s(:const, nil, :Alfa), nil,
46
+ # s(:def, :bravo!,
47
+ # s(:args), nil))
48
+ #
32
49
  def sniff(ctx)
33
50
  ctx.node_instance_methods.select do |method_sexp|
34
51
  prima_donna_method?(method_sexp, ctx)
@@ -46,6 +63,7 @@ module Reek
46
63
 
47
64
  def prima_donna_method?(method_sexp, ctx)
48
65
  return false unless method_sexp.ends_with_bang?
66
+ return false if ignore_method?(method_sexp, ctx)
49
67
  return false if version_without_bang_exists?(method_sexp, ctx)
50
68
  true
51
69
  end
@@ -56,6 +74,17 @@ module Reek
56
74
  sexp_item.name.to_s == method_sexp.name_without_bang
57
75
  end
58
76
  end
77
+
78
+ #
79
+ # @param method_node [Reek::AST::Node],
80
+ # e.g. s(:def, :bravo!, s(:args), nil)
81
+ # @param ctx [Context::ModuleContext]
82
+ # @return [Boolean]
83
+ #
84
+ def ignore_method?(method_node, ctx)
85
+ ignore_method_names = value(EXCLUDE_KEY, ctx) # e.g. ["bravo!"]
86
+ ignore_method_names.include? method_node.name.to_s # method_node.name is e.g.: :bravo!
87
+ end
59
88
  end
60
89
  end
61
90
  end
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  require_relative '../ast/node'
3
3
  require_relative 'base_detector'
4
- require_relative 'smell_warning'
5
4
 
6
5
  module Reek
7
6
  module SmellDetectors
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  require_relative 'base_detector'
3
- require_relative 'smell_warning'
4
3
 
5
4
  module Reek
6
5
  module SmellDetectors
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  require_relative 'base_detector'
3
- require_relative 'smell_warning'
4
3
 
5
4
  module Reek
6
5
  module SmellDetectors
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  require_relative 'base_detector'
3
- require_relative 'smell_warning'
4
3
 
5
4
  module Reek
6
5
  module SmellDetectors
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  require_relative 'base_detector'
3
- require_relative 'smell_warning'
4
3
 
5
4
  module Reek
6
5
  module SmellDetectors
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  require_relative 'base_detector'
3
- require_relative 'smell_warning'
4
3
 
5
4
  module Reek
6
5
  module SmellDetectors
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  require_relative 'base_detector'
3
- require_relative 'smell_warning'
4
3
 
5
4
  module Reek
6
5
  module SmellDetectors
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  require_relative 'base_detector'
3
- require_relative 'smell_warning'
4
3
 
5
4
  module Reek
6
5
  module SmellDetectors
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  require_relative 'base_detector'
3
- require_relative 'smell_warning'
4
3
 
5
4
  module Reek
6
5
  module SmellDetectors
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  require_relative 'base_detector'
3
- require_relative 'smell_warning'
4
3
 
5
4
  module Reek
6
5
  module SmellDetectors
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  require_relative 'base_detector'
3
- require_relative 'smell_warning'
4
3
 
5
4
  module Reek
6
5
  module SmellDetectors
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  require_relative 'base_detector'
3
- require_relative 'smell_warning'
4
- require_relative '../context/method_context'
5
3
 
6
4
  module Reek
7
5
  module SmellDetectors
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  require_relative '../ast/reference_collector'
3
3
  require_relative 'base_detector'
4
- require_relative 'smell_warning'
5
4
 
6
5
  module Reek
7
6
  module SmellDetectors
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+ require 'forwardable'
3
+
4
+ module Reek
5
+ #
6
+ # Reports a warning that a smell has been found.
7
+ #
8
+ # @public
9
+ #
10
+ # :reek:TooManyInstanceVariables: { max_instance_variables: 6 }
11
+ class SmellWarning
12
+ include Comparable
13
+ extend Forwardable
14
+
15
+ # @public
16
+ attr_reader :context, :lines, :message, :parameters, :smell_detector, :source
17
+ def_delegators :smell_detector, :smell_type
18
+
19
+ # @note When using Reek's public API, you should not create SmellWarning
20
+ # objects yourself. This is why the initializer is not part of the
21
+ # public API.
22
+ #
23
+ # :reek:LongParameterList: { max_params: 6 }
24
+ def initialize(smell_detector, context: '', lines:, message:,
25
+ source:, parameters: {})
26
+ @smell_detector = smell_detector
27
+ @source = source
28
+ @context = context.to_s
29
+ @lines = lines
30
+ @message = message
31
+ @parameters = parameters
32
+
33
+ freeze
34
+ end
35
+
36
+ # @public
37
+ def hash
38
+ identifying_values.hash
39
+ end
40
+
41
+ # @public
42
+ def <=>(other)
43
+ identifying_values <=> other.identifying_values
44
+ end
45
+
46
+ # @public
47
+ def eql?(other)
48
+ (self <=> other).zero?
49
+ end
50
+
51
+ # @public
52
+ def to_hash
53
+ stringified_params = Hash[parameters.map { |key, val| [key.to_s, val] }]
54
+ base_hash.merge(stringified_params)
55
+ end
56
+
57
+ alias yaml_hash to_hash
58
+
59
+ def base_message
60
+ "#{smell_type}: #{context} #{message}"
61
+ end
62
+
63
+ def smell_class
64
+ smell_detector.class
65
+ end
66
+
67
+ protected
68
+
69
+ def identifying_values
70
+ [smell_type, context, message, lines]
71
+ end
72
+
73
+ private
74
+
75
+ def base_hash
76
+ {
77
+ 'context' => context,
78
+ 'lines' => lines,
79
+ 'message' => message,
80
+ 'smell_type' => smell_type,
81
+ 'source' => source
82
+ }
83
+ end
84
+ end
85
+ end
@@ -5,6 +5,7 @@ Reek::CLI::Silencer.silently do
5
5
  end
6
6
  require_relative '../tree_dresser'
7
7
  require_relative '../ast/node'
8
+ require_relative '../errors/parse_error'
8
9
 
9
10
  # Opt in to new way of representing lambdas
10
11
  Parser::Builders::Default.emit_lambda = true
@@ -87,7 +88,7 @@ module Reek
87
88
  begin
88
89
  ast, comments = parser.parse_with_comments(source, origin)
89
90
  rescue Racc::ParseError, Parser::SyntaxError => error
90
- $stderr.puts "#{origin}: #{error.class.name}: #{error}"
91
+ raise Errors::ParseError, origin: origin, original_exception: error
91
92
  end
92
93
 
93
94
  # See https://whitequark.github.io/parser/Parser/Source/Comment/Associator.html
@@ -11,7 +11,8 @@ module Reek
11
11
  # Initialize with the paths we want to search.
12
12
  #
13
13
  # paths - a list of paths as Strings
14
- def initialize(paths, configuration: Configuration::AppConfiguration.default)
14
+ def initialize(paths, configuration: Configuration::AppConfiguration.default, options: Reek::CLI::Options.new)
15
+ @options = options
15
16
  @paths = paths.flat_map do |string|
16
17
  path = Pathname.new(string)
17
18
  current_directory?(path) ? path.entries : path
@@ -29,7 +30,7 @@ module Reek
29
30
 
30
31
  private
31
32
 
32
- attr_reader :configuration, :paths
33
+ attr_reader :configuration, :paths, :options
33
34
 
34
35
  # :reek:TooManyStatements: { max_statements: 7 }
35
36
  # :reek:NestedIterators: { max_allowed_nesting: 2 }
@@ -44,12 +45,23 @@ module Reek
44
45
  if path.directory?
45
46
  ignore_path?(path) ? Find.prune : next
46
47
  elsif ruby_file?(path)
47
- relevant_paths << path
48
+ relevant_paths << path unless ignore_file?(path)
48
49
  end
49
50
  end
50
51
  end
51
52
  end
52
53
 
54
+ def ignore_file?(path)
55
+ if options.force_exclusion?
56
+ path.ascend do |ascendant|
57
+ break true if path_excluded?(ascendant)
58
+ false
59
+ end
60
+ else
61
+ false
62
+ end
63
+ end
64
+
53
65
  def path_excluded?(path)
54
66
  configuration.path_excluded?(path)
55
67
  end
@@ -25,7 +25,7 @@ module Reek
25
25
  configuration = Configuration::AppConfiguration.default)
26
26
  @smell_type = normalize smell_type_or_class
27
27
  @smell_details = smell_details
28
- configuration.load_values(smell_type => { SmellDetectors::SmellConfiguration::ENABLED_KEY => true })
28
+ configuration.load_values(smell_type => { SmellConfiguration::ENABLED_KEY => true })
29
29
  @configuration = configuration
30
30
  end
31
31
 
data/lib/reek/spec.rb CHANGED
@@ -48,10 +48,10 @@ module Reek
48
48
  # Checks the target source code for instances of "smell type"
49
49
  # and returns true only if it can find one of them that matches.
50
50
  #
51
- # You could pass many different types of input here:
51
+ # You can pass the smell type you want to check for as String or as Symbol:
52
+ #
52
53
  # - :UtilityFunction
53
54
  # - "UtilityFunction"
54
- # - Reek::Smells::UtilityFunction
55
55
  #
56
56
  # It is recommended to pass this as a symbol like :UtilityFunction. However we don't
57
57
  # enforce this.
@@ -70,7 +70,7 @@ module Reek
70
70
  # @example Without smell_details
71
71
  #
72
72
  # reek_of(:FeatureEnvy)
73
- # reek_of(Reek::Smells::UtilityFunction)
73
+ # reek_of(:UtilityFunction)
74
74
  #
75
75
  # @example With smell_details
76
76
  #
@@ -79,7 +79,7 @@ module Reek
79
79
  #
80
80
  # @example From a real spec
81
81
  #
82
- # expect(src).to reek_of(Reek::Smells::DuplicateMethodCall, name: '@other.thing')
82
+ # expect(src).to reek_of(:DuplicateMethodCall, name: '@other.thing')
83
83
  #
84
84
  # @public
85
85
  #
@@ -98,6 +98,8 @@ module Reek
98
98
  # "reek_only_of" will fail in that case.
99
99
  # 2.) "reek_only_of" doesn't support the additional smell_details hash.
100
100
  #
101
+ # @param smell_type [Symbol, String, Class] The "smell type" to check for.
102
+ #
101
103
  # @public
102
104
  #
103
105
  # :reek:UtilityFunction
data/lib/reek/version.rb CHANGED
@@ -7,6 +7,6 @@ module Reek
7
7
  # @public
8
8
  module Version
9
9
  # @public
10
- STRING = '4.5.0'.freeze
10
+ STRING = '4.6.0'.freeze
11
11
  end
12
12
  end
data/reek.gemspec CHANGED
@@ -22,6 +22,6 @@ Gem::Specification.new do |s|
22
22
  s.summary = 'Code smell detector for Ruby'
23
23
 
24
24
  s.add_runtime_dependency 'codeclimate-engine-rb', '~> 0.4.0'
25
- s.add_runtime_dependency 'parser', '~> 2.3.1', '>= 2.3.1.2'
25
+ s.add_runtime_dependency 'parser', '< 2.5', '>= 2.3.1.2'
26
26
  s.add_runtime_dependency 'rainbow', '~> 2.0'
27
27
  end
@@ -1,17 +1,9 @@
1
1
  require_relative '../../lib/reek/smell_detectors'
2
2
  require_relative '../../lib/reek/smell_detectors/base_detector'
3
- require_relative '../../lib/reek/smell_detectors/smell_warning'
3
+ require_relative '../../lib/reek/smell_warning'
4
4
  require_relative '../../lib/reek/cli/options'
5
5
 
6
6
  FactoryGirl.define do
7
- factory :context, class: Reek::Context::CodeContext do
8
- skip_create
9
-
10
- initialize_with do
11
- new(nil, nil)
12
- end
13
- end
14
-
15
7
  factory :method_context, class: Reek::Context::MethodContext do
16
8
  skip_create
17
9
  transient do
@@ -34,7 +26,7 @@ FactoryGirl.define do
34
26
  end
35
27
  end
36
28
 
37
- factory :smell_warning, class: Reek::SmellDetectors::SmellWarning do
29
+ factory :smell_warning, class: Reek::SmellWarning do
38
30
  skip_create
39
31
  smell_detector
40
32
  context 'self'
@@ -1,9 +1,11 @@
1
1
  require_relative '../spec_helper'
2
2
 
3
3
  RSpec.describe 'Reek source code' do
4
- it 'has no smells' do
5
- Pathname.glob('lib/**/*.rb').each do |pathname|
6
- expect(pathname).not_to reek
4
+ Pathname.glob('lib/**/*.rb').each do |pathname|
5
+ describe pathname do
6
+ it 'has no smells' do
7
+ expect(pathname).not_to reek
8
+ end
7
9
  end
8
10
  end
9
11
  end
@@ -43,22 +43,5 @@ RSpec.describe Reek::AST::ReferenceCollector do
43
43
  it 'ignores global variables' do
44
44
  expect(refs_to_self('def no_envy(arga) $s2.to_a; $s2[arga] end')).to eq(0)
45
45
  end
46
-
47
- it 'ignores global variables' do
48
- src = <<-EOS
49
- def accept(t, pat = /.*/nm, &block)
50
- if pat
51
- pat.respond_to?(:match) or raise TypeError, "has no `match'"
52
- else
53
- pat = t if t.respond_to?(:match)
54
- end
55
- unless block
56
- block = pat.method(:convert).to_proc if pat.respond_to?(:convert)
57
- end
58
- @atype[t] = [pat, block]
59
- end
60
- EOS
61
- expect(refs_to_self(src)).to eq(2)
62
- end
63
46
  end
64
47
  end
@@ -10,7 +10,7 @@ RSpec.describe Reek::CLI::Application do
10
10
  end
11
11
  end
12
12
  expect(call).to raise_error(SystemExit) do |error|
13
- expect(error.status).to eq Reek::CLI::Options::DEFAULT_ERROR_EXIT_CODE
13
+ expect(error.status).to eq Reek::CLI::Status::DEFAULT_ERROR_EXIT_CODE
14
14
  end
15
15
  end
16
16
  end
@@ -100,6 +100,30 @@ RSpec.describe Reek::CLI::Application do
100
100
  configuration: Reek::Configuration::AppConfiguration,
101
101
  options: Reek::CLI::Options)
102
102
  end
103
+
104
+ context 'when source files are excluded through configuration' do
105
+ let(:app) { described_class.new ['--config', 'some_file.reek', '.'] }
106
+
107
+ before do
108
+ allow(Reek::Configuration::AppConfiguration).
109
+ to receive(:from_path).
110
+ with(Pathname.new('some_file.reek')).
111
+ and_return configuration
112
+ end
113
+
114
+ it 'uses configuration for excluded paths' do
115
+ expected_sources = Reek::Source::SourceLocator.
116
+ new(['.'], configuration: configuration).sources
117
+ expect(expected_sources).not_to include(path_excluded_in_configuration)
118
+
119
+ app.execute
120
+
121
+ expect(Reek::CLI::Command::ReportCommand).to have_received(:new).
122
+ with(sources: expected_sources,
123
+ configuration: configuration,
124
+ options: Reek::CLI::Options)
125
+ end
126
+ end
103
127
  end
104
128
  end
105
129
  end
@@ -26,7 +26,7 @@ RSpec.describe Reek::CLI::Command::ReportCommand do
26
26
  result = Reek::CLI::Silencer.silently do
27
27
  command.execute
28
28
  end
29
- expect(result).to eq Reek::CLI::Options::DEFAULT_SUCCESS_EXIT_CODE
29
+ expect(result).to eq Reek::CLI::Status::DEFAULT_SUCCESS_EXIT_CODE
30
30
  end
31
31
  end
32
32
 
@@ -37,7 +37,7 @@ RSpec.describe Reek::CLI::Command::ReportCommand do
37
37
  result = Reek::CLI::Silencer.silently do
38
38
  command.execute
39
39
  end
40
- expect(result).to eq Reek::CLI::Options::DEFAULT_FAILURE_EXIT_CODE
40
+ expect(result).to eq Reek::CLI::Status::DEFAULT_FAILURE_EXIT_CODE
41
41
  end
42
42
  end
43
43
  end