reek 3.2.1 → 3.3.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 (112) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/Rakefile +0 -1
  4. data/config/defaults.reek +1 -1
  5. data/features/samples.feature +17 -16
  6. data/lib/reek.rb +0 -1
  7. data/lib/reek/ast/ast_node_class_map.rb +5 -1
  8. data/lib/reek/ast/node.rb +10 -3
  9. data/lib/reek/ast/object_refs.rb +11 -5
  10. data/lib/reek/ast/reference_collector.rb +6 -2
  11. data/lib/reek/ast/sexp_extensions.rb +42 -1
  12. data/lib/reek/ast/sexp_formatter.rb +2 -1
  13. data/lib/reek/cli/application.rb +12 -9
  14. data/lib/reek/cli/command.rb +6 -0
  15. data/lib/reek/cli/input.rb +4 -4
  16. data/lib/reek/cli/option_interpreter.rb +11 -7
  17. data/lib/reek/cli/options.rb +42 -40
  18. data/lib/reek/cli/reek_command.rb +3 -3
  19. data/lib/reek/cli/silencer.rb +12 -3
  20. data/lib/reek/cli/warning_collector.rb +8 -3
  21. data/lib/reek/code_comment.rb +6 -1
  22. data/lib/reek/configuration/app_configuration.rb +65 -100
  23. data/lib/reek/configuration/configuration_file_finder.rb +4 -13
  24. data/lib/reek/configuration/configuration_validator.rb +35 -0
  25. data/lib/reek/configuration/default_directive.rb +12 -0
  26. data/lib/reek/configuration/directory_directives.rb +54 -0
  27. data/lib/reek/configuration/excluded_paths.rb +18 -0
  28. data/lib/reek/context/code_context.rb +19 -17
  29. data/lib/reek/examiner.rb +9 -7
  30. data/lib/reek/rake/task.rb +12 -22
  31. data/lib/reek/report/formatter.rb +6 -1
  32. data/lib/reek/report/report.rb +22 -13
  33. data/lib/reek/smells/attribute.rb +6 -53
  34. data/lib/reek/smells/control_parameter.rb +21 -13
  35. data/lib/reek/smells/data_clump.rb +17 -9
  36. data/lib/reek/smells/duplicate_method_call.rb +12 -6
  37. data/lib/reek/smells/long_parameter_list.rb +2 -2
  38. data/lib/reek/smells/long_yield_list.rb +4 -4
  39. data/lib/reek/smells/nested_iterators.rb +4 -2
  40. data/lib/reek/smells/nil_check.rb +6 -2
  41. data/lib/reek/smells/repeated_conditional.rb +3 -3
  42. data/lib/reek/smells/smell_configuration.rb +17 -7
  43. data/lib/reek/smells/smell_detector.rb +24 -11
  44. data/lib/reek/smells/smell_repository.rb +1 -1
  45. data/lib/reek/smells/smell_warning.rb +6 -6
  46. data/lib/reek/smells/too_many_instance_variables.rb +2 -2
  47. data/lib/reek/smells/too_many_methods.rb +4 -4
  48. data/lib/reek/smells/too_many_statements.rb +4 -4
  49. data/lib/reek/smells/uncommunicative_method_name.rb +5 -5
  50. data/lib/reek/smells/uncommunicative_module_name.rb +6 -6
  51. data/lib/reek/smells/uncommunicative_parameter_name.rb +8 -4
  52. data/lib/reek/smells/uncommunicative_variable_name.rb +9 -5
  53. data/lib/reek/smells/utility_function.rb +1 -1
  54. data/lib/reek/source/source_code.rb +5 -1
  55. data/lib/reek/source/source_locator.rb +3 -2
  56. data/lib/reek/spec.rb +3 -3
  57. data/lib/reek/spec/should_reek.rb +10 -5
  58. data/lib/reek/spec/should_reek_of.rb +9 -6
  59. data/lib/reek/spec/should_reek_only_of.rb +13 -8
  60. data/lib/reek/tree_dresser.rb +6 -2
  61. data/lib/reek/tree_walker.rb +40 -32
  62. data/lib/reek/version.rb +1 -1
  63. data/reek.gemspec +1 -1
  64. data/spec/reek/ast/node_spec.rb +1 -2
  65. data/spec/reek/ast/object_refs_spec.rb +40 -42
  66. data/spec/reek/ast/sexp_extensions_spec.rb +98 -104
  67. data/spec/reek/cli/warning_collector_spec.rb +8 -12
  68. data/spec/reek/code_comment_spec.rb +3 -5
  69. data/spec/reek/configuration/app_configuration_spec.rb +43 -57
  70. data/spec/reek/configuration/configuration_file_finder_spec.rb +5 -7
  71. data/spec/reek/configuration/default_directive_spec.rb +13 -0
  72. data/spec/reek/configuration/directory_directives_spec.rb +89 -0
  73. data/spec/reek/configuration/excluded_paths_spec.rb +30 -0
  74. data/spec/reek/context/code_context_spec.rb +63 -62
  75. data/spec/reek/context/method_context_spec.rb +8 -12
  76. data/spec/reek/context/module_context_spec.rb +1 -1
  77. data/spec/reek/context/root_context_spec.rb +3 -7
  78. data/spec/reek/examiner_spec.rb +14 -25
  79. data/spec/reek/smells/attribute_spec.rb +2 -4
  80. data/spec/reek/smells/boolean_parameter_spec.rb +5 -7
  81. data/spec/reek/smells/class_variable_spec.rb +29 -44
  82. data/spec/reek/smells/control_parameter_spec.rb +7 -9
  83. data/spec/reek/smells/data_clump_spec.rb +25 -32
  84. data/spec/reek/smells/duplicate_method_call_spec.rb +8 -7
  85. data/spec/reek/smells/feature_envy_spec.rb +16 -17
  86. data/spec/reek/smells/irresponsible_module_spec.rb +2 -4
  87. data/spec/reek/smells/long_parameter_list_spec.rb +6 -9
  88. data/spec/reek/smells/long_yield_list_spec.rb +6 -9
  89. data/spec/reek/smells/nested_iterators_spec.rb +14 -16
  90. data/spec/reek/smells/repeated_conditional_spec.rb +25 -25
  91. data/spec/reek/smells/smell_configuration_spec.rb +32 -27
  92. data/spec/reek/smells/smell_detector_shared.rb +12 -13
  93. data/spec/reek/smells/smell_warning_spec.rb +54 -58
  94. data/spec/reek/smells/too_many_instance_variables_spec.rb +9 -9
  95. data/spec/reek/smells/too_many_methods_spec.rb +13 -14
  96. data/spec/reek/smells/too_many_statements_spec.rb +8 -10
  97. data/spec/reek/smells/uncommunicative_method_name_spec.rb +8 -9
  98. data/spec/reek/smells/uncommunicative_module_name_spec.rb +12 -13
  99. data/spec/reek/smells/uncommunicative_parameter_name_spec.rb +7 -10
  100. data/spec/reek/smells/uncommunicative_variable_name_spec.rb +16 -20
  101. data/spec/reek/smells/utility_function_spec.rb +11 -15
  102. data/spec/reek/source/source_code_spec.rb +6 -11
  103. data/spec/reek/spec/should_reek_of_spec.rb +19 -30
  104. data/spec/reek/spec/should_reek_only_of_spec.rb +28 -34
  105. data/spec/reek/tree_walker_spec.rb +14 -2
  106. data/spec/spec_helper.rb +2 -3
  107. data/tasks/test.rake +0 -5
  108. metadata +10 -6
  109. data/docs/Configuration-Files.md +0 -49
  110. data/spec/gem/updates_spec.rb +0 -25
  111. data/spec/gem/yard_spec.rb +0 -11
  112. data/spec/reek/smells/behaves_like_variable_detector.rb +0 -39
@@ -13,11 +13,11 @@ module Reek
13
13
 
14
14
  extend Forwardable
15
15
 
16
- def_delegators :@options, :smells_to_detect
16
+ def_delegators :options, :smells_to_detect
17
17
 
18
18
  def initialize(options)
19
19
  @options = options
20
- @argv = @options.argv
20
+ @argv = options.argv
21
21
  end
22
22
 
23
23
  def reporter
@@ -30,7 +30,7 @@ module Reek
30
30
  end
31
31
 
32
32
  def report_class
33
- Report.report_class(@options.report_format)
33
+ Report.report_class(options.report_format)
34
34
  end
35
35
 
36
36
  def warning_formatter
@@ -38,20 +38,24 @@ module Reek
38
38
  end
39
39
 
40
40
  def warning_formatter_class
41
- Report.warning_formatter_class(@options.show_links ? :wiki_links : :simple)
41
+ Report.warning_formatter_class(options.show_links ? :wiki_links : :simple)
42
42
  end
43
43
 
44
44
  def location_formatter
45
- Report.location_formatter(@options.location_format)
45
+ Report.location_formatter(options.location_format)
46
46
  end
47
47
 
48
48
  def heading_formatter
49
- Report.heading_formatter(@options.show_empty ? :verbose : :quiet)
49
+ Report.heading_formatter(options.show_empty ? :verbose : :quiet)
50
50
  end
51
51
 
52
52
  def sort_by_issue_count
53
- @options.sorting == :smelliness
53
+ options.sorting == :smelliness
54
54
  end
55
+
56
+ private
57
+
58
+ private_attr_reader :argv, :options
55
59
  end
56
60
  end
57
61
  end
@@ -23,14 +23,16 @@ module Reek
23
23
  end
24
24
 
25
25
  def parse
26
- @parser.parse!(@argv)
27
- @options.argv = @argv
28
- Rainbow.enabled = @options.colored
29
- @options
26
+ parser.parse!(argv)
27
+ options.argv = argv
28
+ Rainbow.enabled = options.colored
29
+ options
30
30
  end
31
31
 
32
32
  private
33
33
 
34
+ private_attr_reader :argv, :options, :parser
35
+
34
36
  def color_support?
35
37
  $stdout.tty?
36
38
  end
@@ -44,8 +46,8 @@ module Reek
44
46
  end
45
47
 
46
48
  def set_banner
47
- program_name = @parser.program_name
48
- @parser.banner = <<-EOB.gsub(/^[ ]+/, '')
49
+ program_name = parser.program_name
50
+ parser.banner = <<-EOB.gsub(/^[ ]+/, '')
49
51
  Usage: #{program_name} [options] [files]
50
52
 
51
53
  Examples:
@@ -60,29 +62,29 @@ module Reek
60
62
  end
61
63
 
62
64
  def set_alternative_formatter_options
63
- @parser.separator "\nReport format:"
64
- @parser.on(
65
+ parser.separator "\nReport format:"
66
+ parser.on(
65
67
  '-f', '--format FORMAT', [:html, :text, :yaml, :json, :xml],
66
68
  'Report smells in the given format:',
67
69
  ' html', ' text (default)', ' yaml', ' json', ' xml'
68
70
  ) do |opt|
69
- @options.report_format = opt
71
+ options.report_format = opt
70
72
  end
71
73
  end
72
74
 
73
75
  def set_configuration_options
74
- @parser.separator 'Configuration:'
75
- @parser.on('-c', '--config FILE', 'Read configuration options from FILE') do |file|
76
+ parser.separator 'Configuration:'
77
+ parser.on('-c', '--config FILE', 'Read configuration options from FILE') do |file|
76
78
  raise ArgumentError, "Config file #{file} doesn't exist" unless File.exist?(file)
77
- @options.config_file = Pathname.new(file)
79
+ options.config_file = Pathname.new(file)
78
80
  end
79
- @parser.on('--smell SMELL', 'Detect smell SMELL (default: all enabled smells)') do |smell|
80
- @options.smells_to_detect << smell
81
+ parser.on('--smell SMELL', 'Detect smell SMELL (default: all enabled smells)') do |smell|
82
+ options.smells_to_detect << smell
81
83
  end
82
84
  end
83
85
 
84
86
  def set_report_formatting_options
85
- @parser.separator "\nText format options:"
87
+ parser.separator "\nText format options:"
86
88
  set_up_color_option
87
89
  set_up_verbosity_options
88
90
  set_up_location_formatting_options
@@ -90,50 +92,50 @@ module Reek
90
92
  end
91
93
 
92
94
  def set_up_color_option
93
- @parser.on('--[no-]color', 'Use colors for the output (default: true)') do |opt|
94
- @options.colored = opt
95
+ parser.on('--[no-]color', 'Use colors for the output (default: true)') do |opt|
96
+ options.colored = opt
95
97
  end
96
98
  end
97
99
 
98
100
  def set_up_verbosity_options
99
- @parser.on('-V', '--[no-]empty-headings',
100
- 'Show headings for smell-free source files (default: false)') do |show_empty|
101
- @options.show_empty = show_empty
101
+ parser.on('-V', '--[no-]empty-headings',
102
+ 'Show headings for smell-free source files (default: false)') do |show_empty|
103
+ options.show_empty = show_empty
102
104
  end
103
- @parser.on('-U', '--[no-]wiki-links',
104
- 'Show link to related wiki page for each smell (default: false)') do |show_links|
105
- @options.show_links = show_links
105
+ parser.on('-U', '--[no-]wiki-links',
106
+ 'Show link to related wiki page for each smell (default: false)') do |show_links|
107
+ options.show_links = show_links
106
108
  end
107
109
  end
108
110
 
109
111
  def set_up_location_formatting_options
110
- @parser.on('-n', '--[no-]line-numbers',
111
- 'Show line numbers in the output (default: true)') do |show_numbers|
112
- @options.location_format = show_numbers ? :numbers : :plain
112
+ parser.on('-n', '--[no-]line-numbers',
113
+ 'Show line numbers in the output (default: true)') do |show_numbers|
114
+ options.location_format = show_numbers ? :numbers : :plain
113
115
  end
114
- @parser.on('-s', '--single-line',
115
- 'Show location in editor-compatible single-line-per-smell format') do
116
- @options.location_format = :single_line
116
+ parser.on('-s', '--single-line',
117
+ 'Show location in editor-compatible single-line-per-smell format') do
118
+ options.location_format = :single_line
117
119
  end
118
120
  end
119
121
 
120
122
  def set_up_sorting_option
121
- @parser.on('--sort-by SORTING', [:smelliness, :none],
122
- 'Sort reported files by the given criterium:',
123
- ' smelliness ("smelliest" files first)',
124
- ' none (default - output in processing order)') do |sorting|
125
- @options.sorting = sorting
126
- end
123
+ parser.on('--sort-by SORTING', [:smelliness, :none],
124
+ 'Sort reported files by the given criterium:',
125
+ ' smelliness ("smelliest" files first)',
126
+ ' none (default - output in processing order)') do |sorting|
127
+ options.sorting = sorting
128
+ end
127
129
  end
128
130
 
129
131
  def set_utility_options
130
- @parser.separator "\nUtility options:"
131
- @parser.on_tail('-h', '--help', 'Show this message') do
132
- puts @parser
132
+ parser.separator "\nUtility options:"
133
+ parser.on_tail('-h', '--help', 'Show this message') do
134
+ puts parser
133
135
  exit
134
136
  end
135
- @parser.on_tail('-v', '--version', 'Show version') do
136
- puts "#{@parser.program_name} #{Reek::Version::STRING}\n"
137
+ parser.on_tail('-v', '--version', 'Show version') do
138
+ puts "#{parser.program_name} #{Reek::Version::STRING}\n"
137
139
  exit
138
140
  end
139
141
  end
@@ -10,7 +10,7 @@ module Reek
10
10
  # @api private
11
11
  class ReekCommand < Command
12
12
  def execute(app)
13
- @options.sources.each do |source|
13
+ options.sources.each do |source|
14
14
  reporter.add_examiner Examiner.new(source, smell_names, configuration: app.configuration)
15
15
  end
16
16
  reporter.smells? ? app.report_smells : app.report_success
@@ -20,11 +20,11 @@ module Reek
20
20
  private
21
21
 
22
22
  def reporter
23
- @reporter ||= @options.reporter
23
+ @reporter ||= options.reporter
24
24
  end
25
25
 
26
26
  def smell_names
27
- @smell_names ||= @options.smells_to_detect
27
+ @smell_names ||= options.smells_to_detect
28
28
  end
29
29
  end
30
30
  end
@@ -1,13 +1,22 @@
1
+ require 'stringio'
2
+
1
3
  module Reek
2
4
  module CLI
3
5
  # CLI silencer
4
6
  # @api private
5
7
  module Silencer
6
- def self.silently
7
- old_verbose, $VERBOSE = $VERBOSE, nil
8
- yield if block_given?
8
+ module_function
9
+
10
+ def silently(stderr: nil, stdout: nil)
11
+ old_verbose = $VERBOSE
12
+ $VERBOSE = false
13
+ $stderr = StringIO.new if stderr
14
+ $stdout = StringIO.new if stdout
15
+ yield
9
16
  ensure
10
17
  $VERBOSE = old_verbose
18
+ $stderr = STDERR
19
+ $stdout = STDOUT
11
20
  end
12
21
  end
13
22
  end
@@ -1,3 +1,4 @@
1
+ require 'private_attr/everywhere'
1
2
  require 'set'
2
3
 
3
4
  module Reek
@@ -8,16 +9,20 @@ module Reek
8
9
  # @api private
9
10
  class WarningCollector
10
11
  def initialize
11
- @warnings = Set.new
12
+ @warnings_set = Set.new
12
13
  end
13
14
 
14
15
  def found_smell(warning)
15
- @warnings.add(warning)
16
+ warnings_set.add(warning)
16
17
  end
17
18
 
18
19
  def warnings
19
- @warnings.to_a.sort
20
+ warnings_set.to_a.sort
20
21
  end
22
+
23
+ private
24
+
25
+ private_attr_reader :warnings_set
21
26
  end
22
27
  end
23
28
  end
@@ -1,4 +1,5 @@
1
1
  require 'yaml'
2
+ require 'private_attr/everywhere'
2
3
 
3
4
  module Reek
4
5
  #
@@ -21,7 +22,7 @@ module Reek
21
22
  end
22
23
 
23
24
  def descriptive?
24
- @text.split(/\s+/).length >= 2
25
+ text.split(/\s+/).length >= 2
25
26
  end
26
27
 
27
28
  protected
@@ -32,5 +33,9 @@ module Reek
32
33
  # TODO: extend this to all configs -------------------^
33
34
  # TODO: extend to allow configuration of whole smell class, not just subclass
34
35
  end
36
+
37
+ private
38
+
39
+ private_attr_reader :text
35
40
  end
36
41
  end
@@ -1,5 +1,10 @@
1
1
  require 'pathname'
2
+ require 'private_attr/everywhere'
2
3
  require_relative './configuration_file_finder'
4
+ require_relative './configuration_validator'
5
+ require_relative './default_directive'
6
+ require_relative './directory_directives'
7
+ require_relative './excluded_paths'
3
8
 
4
9
  module Reek
5
10
  # @api private
@@ -10,135 +15,95 @@ module Reek
10
15
  #
11
16
  # @api private
12
17
  class AppConfiguration
18
+ include ConfigurationValidator
13
19
  EXCLUDE_PATHS_KEY = 'exclude_paths'
14
- attr_reader :exclude_paths, :default_directive, :directory_directives
20
+ private_attr_writer :directory_directives, :default_directive, :excluded_paths
15
21
 
16
- # Given this configuration file:
22
+ # Instantiate a configuration via given path.
17
23
  #
18
- # ---
19
- # IrresponsibleModule:
20
- # enabled: false
21
- # "app/helpers":
22
- # UtilityFunction:
23
- # enabled: false
24
- # exclude_paths:
25
- # - "app/controllers"
24
+ # @param path [Pathname] the path to the config file
26
25
  #
27
- # this would result in the following configuration:
28
- #
29
- # exclude_paths = [ Pathname('spec/samples/two_smelly_files') ]
30
- # default_directive = { Reek::Smells::IrresponsibleModule => { "enabled" => false } }
31
- # directory_directives = { Pathname("spec/samples/three_clean_files/") =>
32
- # { Reek::Smells::UtilityFunction => { "enabled" => false } } }
26
+ # @return [AppConfiguration]
27
+ def self.from_path(path = nil)
28
+ allocate.tap do |instance|
29
+ instance.instance_eval { find_and_load(path: path) }
30
+ end
31
+ end
32
+
33
+ # Instantiate a configuration by passing everything in.
33
34
  #
35
+ # @param map [Hash] can have the following 3 keys:
36
+ # 1.) directory_directives [Hash] for instance:
37
+ # { Pathname("spec/samples/three_clean_files/") =>
38
+ # { Reek::Smells::UtilityFunction => { "enabled" => false } } }
39
+ # 2.) default_directive [Hash] for instance:
40
+ # { Reek::Smells::IrresponsibleModule => { "enabled" => false } }
41
+ # 3.) excluded_paths [Array] for instance:
42
+ # [ Pathname('spec/samples/two_smelly_files') ]
34
43
  #
35
- # @param options [OpenStruct]
36
- # e.g.: #<OpenStruct report_format =: text,
37
- # location_format =: numbers,
38
- # colored = true,
39
- # smells_to_detect = [],
40
- # config_file = #<Pathname:config/defaults.reek>,
41
- # argv = [ "lib/reek/spec" ]>
42
- def initialize(options = nil)
43
- @directory_directives = {}
44
- @default_directive = {}
45
- @exclude_paths = []
44
+ # @return [AppConfiguration]
45
+ def self.from_map(map = {})
46
+ allocate.tap do |instance|
47
+ instance.instance_eval do
48
+ self.directory_directives = map.fetch(:directory_directives, {}).
49
+ extend(DirectoryDirectives)
50
+ self.default_directive = map.fetch(:default_directive, {}).extend(DefaultDirective)
51
+ self.excluded_paths = map.fetch(:excluded_paths, []).extend(ExcludedPaths)
52
+ end
53
+ end
54
+ end
46
55
 
47
- load options
56
+ def self.default
57
+ from_path nil
48
58
  end
49
59
 
60
+ def self.new(*)
61
+ raise NotImplementedError,
62
+ 'Calling `new` is not supported, please use one of the factory methods'
63
+ end
64
+
65
+ # Returns the directive for a given directory.
66
+ #
50
67
  # @param source_via [String] - the source of the code inspected
68
+ #
51
69
  # @return [Hash] the directory directive for the source or, if there is
52
70
  # none, the default directive
53
71
  def directive_for(source_via)
54
- directory_directive_for_source(source_via) || default_directive
72
+ directory_directives.directive_for(source_via) || default_directive
73
+ end
74
+
75
+ def path_excluded?(path)
76
+ excluded_paths.include?(path)
55
77
  end
56
78
 
57
79
  private
58
80
 
59
- private_attr_writer :exclude_paths
81
+ def directory_directives
82
+ @directory_directives ||= {}.extend(DirectoryDirectives)
83
+ end
60
84
 
61
- # @param source_via [String] - the source of the code inspected
62
- # Might be a string, STDIN or Filename / Pathname. We're only interested in the source
63
- # when it's coming from file since a directory_directive doesn't make sense
64
- # for anything else.
65
- # @return [Hash | nil] the configuration for the source or nil
66
- def directory_directive_for_source(source_via)
67
- return unless source_via
68
- source_base_dir = Pathname.new(source_via).dirname
69
- hit = best_directory_match_for source_base_dir
70
- directory_directives[hit]
85
+ def default_directive
86
+ @default_directive ||= {}.extend(DefaultDirective)
71
87
  end
72
88
 
73
- def load(options)
74
- configuration_file = ConfigurationFileFinder.find_and_load(options: options)
89
+ def excluded_paths
90
+ @excluded_paths ||= [].extend(ExcludedPaths)
91
+ end
92
+
93
+ def find_and_load(path: nil)
94
+ configuration_file = ConfigurationFileFinder.find_and_load(path: path)
75
95
 
76
96
  configuration_file.each do |key, value|
77
97
  case
78
98
  when key == EXCLUDE_PATHS_KEY
79
- handle_exclude_paths(value)
99
+ excluded_paths.add value
80
100
  when smell_type?(key)
81
- handle_default_directive(key, value)
101
+ default_directive.add key, value
82
102
  else
83
- handle_directory_directive(key, value)
103
+ directory_directives.add key, value
84
104
  end
85
105
  end
86
106
  end
87
-
88
- def handle_exclude_paths(paths)
89
- self.exclude_paths = paths.map do |path|
90
- pathname = Pathname.new path.chomp('/')
91
- raise ArgumentError, "Excluded directory #{path} does not exists" unless pathname.exist?
92
- pathname
93
- end
94
- end
95
-
96
- def handle_default_directive(key, config)
97
- klass = Reek::Smells.const_get(key)
98
- default_directive[klass] = config
99
- end
100
-
101
- def handle_directory_directive(path, config)
102
- pathname = Pathname.new path.chomp('/')
103
- validate_directive pathname
104
-
105
- directory_directives[pathname] = config.each_with_object({}) do |(key, value), hash|
106
- abort(error_message_for_invalid_smell_type(key)) unless smell_type?(key)
107
- hash[Reek::Smells.const_get(key)] = value
108
- end
109
- end
110
-
111
- def best_directory_match_for(source_base_dir)
112
- directory_directives.
113
- keys.
114
- select { |pathname| source_base_dir.to_s =~ /#{pathname}/ }.
115
- max_by { |pathname| pathname.to_s.length }
116
- end
117
-
118
- def smell_type?(key)
119
- Reek::Smells.const_get key
120
- rescue NameError
121
- false
122
- end
123
-
124
- def error_message_for_invalid_smell_type(klass)
125
- "You are trying to configure smell type #{klass} but we can't find one with that name.\n" \
126
- "Please make sure you spelled it right (see 'config/defaults.reek' in the reek\n" \
127
- 'repository for a list of all available smell types.'
128
- end
129
-
130
- def error_message_for_missing_directory(pathname)
131
- "Configuration error: Directory `#{pathname}` does not exist"
132
- end
133
-
134
- def error_message_for_file_given(pathname)
135
- "Configuration error: `#{pathname}` is supposed to be a directory but is a file"
136
- end
137
-
138
- def validate_directive(pathname)
139
- abort(error_message_for_missing_directory(pathname)) unless pathname.exist?
140
- abort(error_message_for_file_given(pathname)) unless pathname.directory?
141
- end
142
107
  end
143
108
  end
144
109
  end