reek 6.1.4 → 6.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +4 -4
  3. data/.rubocop.yml +1 -9
  4. data/CHANGELOG.md +53 -0
  5. data/CONTRIBUTING.md +6 -9
  6. data/Gemfile +5 -4
  7. data/README.md +27 -27
  8. data/bin/code_climate_reek +54 -5
  9. data/lib/reek/ast/sexp_extensions/send.rb +21 -6
  10. data/lib/reek/cli/command/todo_list_command.rb +1 -1
  11. data/lib/reek/{report/code_climate → code_climate}/code_climate_configuration.rb +1 -1
  12. data/lib/reek/{report/code_climate → code_climate}/code_climate_configuration.yml +38 -38
  13. data/lib/reek/{report/code_climate → code_climate}/code_climate_fingerprint.rb +2 -2
  14. data/lib/reek/{report/code_climate → code_climate}/code_climate_formatter.rb +1 -1
  15. data/lib/reek/{report/code_climate → code_climate}/code_climate_report.rb +3 -3
  16. data/lib/reek/code_comment.rb +3 -3
  17. data/lib/reek/configuration/app_configuration.rb +5 -5
  18. data/lib/reek/configuration/configuration_converter.rb +1 -1
  19. data/lib/reek/configuration/configuration_file_finder.rb +3 -3
  20. data/lib/reek/configuration/default_directive.rb +1 -1
  21. data/lib/reek/configuration/directory_directives.rb +1 -1
  22. data/lib/reek/configuration/excluded_paths.rb +1 -1
  23. data/lib/reek/configuration/schema.rb +177 -0
  24. data/lib/reek/configuration/schema_validator.rb +12 -13
  25. data/lib/reek/context/attribute_context.rb +1 -1
  26. data/lib/reek/context/method_context.rb +1 -1
  27. data/lib/reek/context/send_context.rb +1 -1
  28. data/lib/reek/documentation_link.rb +3 -5
  29. data/lib/reek/errors/bad_detector_configuration_key_in_comment_error.rb +2 -2
  30. data/lib/reek/errors/bad_detector_in_comment_error.rb +2 -2
  31. data/lib/reek/errors/encoding_error.rb +1 -1
  32. data/lib/reek/errors/garbage_detector_configuration_in_comment_error.rb +2 -2
  33. data/lib/reek/errors/incomprehensible_source_error.rb +1 -1
  34. data/lib/reek/errors/legacy_comment_separator_error.rb +2 -2
  35. data/lib/reek/errors/syntax_error.rb +1 -1
  36. data/lib/reek/smell_detectors/control_parameter_helpers/control_parameter_finder.rb +1 -1
  37. data/lib/reek/smell_detectors/instance_variable_assumption.rb +8 -8
  38. data/lib/reek/smell_detectors/nested_iterators.rb +4 -3
  39. data/lib/reek/smell_detectors/unused_private_method.rb +2 -2
  40. data/lib/reek/version.rb +1 -1
  41. data/reek.gemspec +3 -2
  42. metadata +28 -14
  43. data/lib/reek/configuration/schema.yml +0 -210
  44. /data/lib/reek/{report/code_climate.rb → code_climate.rb} +0 -0
@@ -1,9 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'yaml'
4
- require_relative '../cli/silencer'
5
- Reek::CLI::Silencer.without_warnings { require 'kwalify' }
6
3
  require_relative '../errors/config_file_error'
4
+ require_relative 'schema'
7
5
 
8
6
  module Reek
9
7
  module Configuration
@@ -11,28 +9,29 @@ module Reek
11
9
  # Schema validator module.
12
10
  #
13
11
  class SchemaValidator
14
- SCHEMA_FILE_PATH = File.expand_path('./schema.yml', __dir__)
15
-
16
12
  def initialize(configuration)
17
13
  @configuration = configuration
18
- @validator = CLI::Silencer.without_warnings do
19
- schema_file = Kwalify::Yaml.load_file(SCHEMA_FILE_PATH)
20
- Kwalify::Validator.new(schema_file)
21
- end
14
+ config_directories = configuration['directories']&.keys || []
15
+ @validator = Reek::Configuration::Schema.schema(config_directories)
22
16
  end
23
17
 
24
18
  def validate
25
- errors = CLI::Silencer.without_warnings { @validator.validate @configuration }
26
- return if !errors || errors.empty?
19
+ result = @validator.call(@configuration)
20
+ return if result.success?
27
21
 
28
- raise Errors::ConfigFileError, error_message(errors)
22
+ raise Errors::ConfigFileError, error_message(result.errors)
23
+ rescue NoMethodError
24
+ raise Errors::ConfigFileError, 'unrecognized configuration data'
29
25
  end
30
26
 
31
27
  private
32
28
 
33
29
  # :reek:UtilityFunction
34
30
  def error_message(errors)
35
- "We found some problems with your configuration file: #{CLI::Silencer.silently { errors.join(', ') }}"
31
+ messages = errors.map do |error|
32
+ "[/#{error.path.join('/')}] #{error.text}."
33
+ end.join("\n")
34
+ "\n#{messages}"
36
35
  end
37
36
  end
38
37
  end
@@ -14,7 +14,7 @@ module Reek
14
14
  def initialize(exp, send_expression)
15
15
  @visibility = :public
16
16
  @send_expression = send_expression
17
- super exp
17
+ super(exp)
18
18
  end
19
19
 
20
20
  def full_comment
@@ -15,7 +15,7 @@ module Reek
15
15
  def initialize(exp, parent_exp)
16
16
  @parent_exp = parent_exp
17
17
  @visibility = :public
18
- super exp
18
+ super(exp)
19
19
  end
20
20
 
21
21
  def references_self?
@@ -12,7 +12,7 @@ module Reek
12
12
 
13
13
  def initialize(exp, name)
14
14
  @name = name
15
- super exp
15
+ super(exp)
16
16
  end
17
17
 
18
18
  def method_name_called_to_call
@@ -17,12 +17,10 @@ module Reek
17
17
  Kernel.format(HELP_LINK_TEMPLATE, version: Version::STRING, item: name_to_param(subject))
18
18
  end
19
19
 
20
- # Convert the given subject name to a form that is acceptable in a URL.
20
+ # Convert the given subject name to a form that is acceptable in a URL, by
21
+ # dasherizeing it at the start of capitalized words. Spaces are discared.
21
22
  def name_to_param(name)
22
- # Splits the subject on the start of capitalized words, optionally
23
- # preceded by a space. The space is discarded, the start of the word is
24
- # not.
25
- name.split(/ *(?=[A-Z][a-z])/).join('-')
23
+ name.split(/([A-Z][a-z][a-z]*)/).map(&:strip).reject(&:empty?).join('-')
26
24
  end
27
25
  end
28
26
  end
@@ -8,7 +8,7 @@ module Reek
8
8
  # Gets raised when trying to configure a detector with an option
9
9
  # which is unknown to it.
10
10
  class BadDetectorConfigurationKeyInCommentError < BaseError
11
- UNKNOWN_SMELL_DETECTOR_MESSAGE = <<-MESSAGE
11
+ UNKNOWN_SMELL_DETECTOR_MESSAGE = <<-MESSAGE.freeze
12
12
 
13
13
  Error: You are trying to configure the smell detector '%<detector>s'
14
14
  in one of your source code comments with the unknown option %<option>s.
@@ -32,7 +32,7 @@ module Reek
32
32
  source: source,
33
33
  line: line,
34
34
  comment: original_comment)
35
- super message
35
+ super(message)
36
36
  end
37
37
  end
38
38
  end
@@ -9,7 +9,7 @@ module Reek
9
9
  # This might happen for multiple reasons. The users might have a typo in
10
10
  # his comment or he might use a detector that does not exist anymore.
11
11
  class BadDetectorInCommentError < BaseError
12
- UNKNOWN_SMELL_DETECTOR_MESSAGE = <<-MESSAGE
12
+ UNKNOWN_SMELL_DETECTOR_MESSAGE = <<-MESSAGE.freeze
13
13
 
14
14
  Error: You are trying to configure an unknown smell detector '%<detector>s' in one
15
15
  of your source code comments.
@@ -31,7 +31,7 @@ module Reek
31
31
  source: source,
32
32
  line: line,
33
33
  comment: original_comment)
34
- super message
34
+ super(message)
35
35
  end
36
36
  end
37
37
  end
@@ -29,7 +29,7 @@ module Reek
29
29
  MESSAGE
30
30
 
31
31
  def initialize(origin:)
32
- super format(TEMPLATE, source: origin)
32
+ super(format(TEMPLATE, source: origin))
33
33
  end
34
34
 
35
35
  def long_message
@@ -8,7 +8,7 @@ module Reek
8
8
  # Gets raised when trying to use a configuration for a detector
9
9
  # that can't be parsed into a hash.
10
10
  class GarbageDetectorConfigurationInCommentError < BaseError
11
- BAD_DETECTOR_CONFIGURATION_MESSAGE = <<-MESSAGE
11
+ BAD_DETECTOR_CONFIGURATION_MESSAGE = <<-MESSAGE.freeze
12
12
 
13
13
  Error: You are trying to configure the smell detector '%<detector>s'.
14
14
  Unfortunately we cannot parse the configuration you have given.
@@ -30,7 +30,7 @@ module Reek
30
30
  source: source,
31
31
  line: line,
32
32
  comment: original_comment)
33
- super message
33
+ super(message)
34
34
  end
35
35
  end
36
36
  end
@@ -32,7 +32,7 @@ module Reek
32
32
  MESSAGE
33
33
 
34
34
  def initialize(origin:)
35
- super format(TEMPLATE, source: origin)
35
+ super(format(TEMPLATE, source: origin))
36
36
  end
37
37
 
38
38
  def long_message
@@ -6,7 +6,7 @@ module Reek
6
6
  module Errors
7
7
  # Gets raised for old-style comment configuration format.
8
8
  class LegacyCommentSeparatorError < BaseError
9
- MESSAGE = <<-MESSAGE
9
+ MESSAGE = <<-MESSAGE.freeze
10
10
  Error: You are using the legacy configuration format (including three
11
11
  colons) to configure Reek in one your source code comments.
12
12
 
@@ -29,7 +29,7 @@ module Reek
29
29
  source: source,
30
30
  line: line,
31
31
  comment: original_comment)
32
- super message
32
+ super(message)
33
33
  end
34
34
  end
35
35
  end
@@ -31,7 +31,7 @@ module Reek
31
31
  MESSAGE
32
32
 
33
33
  def initialize(origin:)
34
- super format(TEMPLATE, source: origin)
34
+ super(format(TEMPLATE, source: origin))
35
35
  end
36
36
 
37
37
  def long_message
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative './call_in_condition_finder'
3
+ require_relative 'call_in_condition_finder'
4
4
  require_relative '../../ast/node'
5
5
 
6
6
  module Reek
@@ -20,7 +20,7 @@ module Reek
20
20
  # @return [Array<SmellWarning>]
21
21
  #
22
22
  def sniff
23
- assumptions = (variables_from_context - variables_from_initialize).uniq
23
+ assumptions = (variables_from_context - variables_from_initializers).uniq
24
24
 
25
25
  assumptions.map do |assumption|
26
26
  build_smell_warning(assumption)
@@ -42,14 +42,14 @@ module Reek
42
42
  parameters: { assumption: assumption.to_s })
43
43
  end
44
44
 
45
- def variables_from_initialize
46
- initialize_exp = method_expressions.detect do |method|
47
- method.name == :initialize
48
- end
49
-
50
- return [] unless initialize_exp
45
+ def variables_from_initializers
46
+ variables_from_initialize.map do |method|
47
+ method.each_node(:ivasgn).map(&:name)
48
+ end.flatten
49
+ end
51
50
 
52
- initialize_exp.each_node(:ivasgn).map(&:name)
51
+ def variables_from_initialize
52
+ method_expressions.select { |method| method.name == :initialize }
53
53
  end
54
54
 
55
55
  def variables_from_context
@@ -26,7 +26,7 @@ module Reek
26
26
  # The name of the config field that sets the names of any
27
27
  # methods for which nesting should not be considered
28
28
  IGNORE_ITERATORS_KEY = 'ignore_iterators'
29
- DEFAULT_IGNORE_ITERATORS = ['tap'].freeze
29
+ DEFAULT_IGNORE_ITERATORS = ['tap', 'Tempfile.create'].freeze
30
30
 
31
31
  def self.default_config
32
32
  super.merge(
@@ -128,8 +128,9 @@ module Reek
128
128
 
129
129
  # @quality :reek:FeatureEnvy
130
130
  def ignored_iterator?(exp)
131
- ignore_iterators.any? { |pattern| /#{pattern}/ =~ exp.call.name } ||
132
- exp.without_block_arguments?
131
+ ignore_iterators.any? do |pattern|
132
+ /#{pattern}/ =~ exp.call.format_to_ruby
133
+ end || exp.without_block_arguments?
133
134
  end
134
135
  end
135
136
  end
@@ -50,9 +50,9 @@ module Reek
50
50
  # @return [Array<Hit>]
51
51
  #
52
52
  def hits
53
- unused_private_methods.map do |defined_method|
53
+ unused_private_methods.filter_map do |defined_method|
54
54
  Hit.new(defined_method) unless ignore_method?(defined_method)
55
- end.compact
55
+ end
56
56
  end
57
57
 
58
58
  #
data/lib/reek/version.rb CHANGED
@@ -8,6 +8,6 @@ module Reek
8
8
  # @public
9
9
  module Version
10
10
  # @public
11
- STRING = '6.1.4'
11
+ STRING = '6.2.0'
12
12
  end
13
13
  end
data/reek.gemspec CHANGED
@@ -20,7 +20,7 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.executables = spec.files.grep(%r{^bin/}).map { |path| File.basename(path) }
22
22
  spec.rdoc_options = %w(--main README.md -x assets/|bin/|config/|features/|spec/|tasks/)
23
- spec.required_ruby_version = '>= 2.6.0'
23
+ spec.required_ruby_version = '>= 3.0.0'
24
24
 
25
25
  spec.metadata = {
26
26
  'homepage_uri' => 'https://github.com/troessner/reek',
@@ -31,7 +31,8 @@ Gem::Specification.new do |spec|
31
31
  'rubygems_mfa_required' => 'true'
32
32
  }
33
33
 
34
- spec.add_runtime_dependency 'kwalify', '~> 0.7.0'
34
+ spec.add_runtime_dependency 'dry-schema', '~> 1.13.0'
35
35
  spec.add_runtime_dependency 'parser', '~> 3.2.0'
36
36
  spec.add_runtime_dependency 'rainbow', '>= 2.0', '< 4.0'
37
+ spec.add_runtime_dependency 'rexml', '~> 3.1'
37
38
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reek
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.1.4
4
+ version: 6.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin Rutherford
@@ -11,22 +11,22 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2023-01-14 00:00:00.000000000 Z
14
+ date: 2023-12-31 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
- name: kwalify
17
+ name: dry-schema
18
18
  requirement: !ruby/object:Gem::Requirement
19
19
  requirements:
20
20
  - - "~>"
21
21
  - !ruby/object:Gem::Version
22
- version: 0.7.0
22
+ version: 1.13.0
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
27
  - - "~>"
28
28
  - !ruby/object:Gem::Version
29
- version: 0.7.0
29
+ version: 1.13.0
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: parser
32
32
  requirement: !ruby/object:Gem::Requirement
@@ -61,6 +61,20 @@ dependencies:
61
61
  - - "<"
62
62
  - !ruby/object:Gem::Version
63
63
  version: '4.0'
64
+ - !ruby/object:Gem::Dependency
65
+ name: rexml
66
+ requirement: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - "~>"
69
+ - !ruby/object:Gem::Version
70
+ version: '3.1'
71
+ type: :runtime
72
+ prerelease: false
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - "~>"
76
+ - !ruby/object:Gem::Version
77
+ version: '3.1'
64
78
  description: Reek is a tool that examines Ruby classes, modules and methods and reports
65
79
  any code smells it finds.
66
80
  email:
@@ -124,6 +138,12 @@ files:
124
138
  - lib/reek/cli/options.rb
125
139
  - lib/reek/cli/silencer.rb
126
140
  - lib/reek/cli/status.rb
141
+ - lib/reek/code_climate.rb
142
+ - lib/reek/code_climate/code_climate_configuration.rb
143
+ - lib/reek/code_climate/code_climate_configuration.yml
144
+ - lib/reek/code_climate/code_climate_fingerprint.rb
145
+ - lib/reek/code_climate/code_climate_formatter.rb
146
+ - lib/reek/code_climate/code_climate_report.rb
127
147
  - lib/reek/code_comment.rb
128
148
  - lib/reek/configuration/app_configuration.rb
129
149
  - lib/reek/configuration/configuration_converter.rb
@@ -133,7 +153,7 @@ files:
133
153
  - lib/reek/configuration/directory_directives.rb
134
154
  - lib/reek/configuration/excluded_paths.rb
135
155
  - lib/reek/configuration/rake_task_converter.rb
136
- - lib/reek/configuration/schema.yml
156
+ - lib/reek/configuration/schema.rb
137
157
  - lib/reek/configuration/schema_validator.rb
138
158
  - lib/reek/context/attribute_context.rb
139
159
  - lib/reek/context/class_context.rb
@@ -165,12 +185,6 @@ files:
165
185
  - lib/reek/rake/task.rb
166
186
  - lib/reek/report.rb
167
187
  - lib/reek/report/base_report.rb
168
- - lib/reek/report/code_climate.rb
169
- - lib/reek/report/code_climate/code_climate_configuration.rb
170
- - lib/reek/report/code_climate/code_climate_configuration.yml
171
- - lib/reek/report/code_climate/code_climate_fingerprint.rb
172
- - lib/reek/report/code_climate/code_climate_formatter.rb
173
- - lib/reek/report/code_climate/code_climate_report.rb
174
188
  - lib/reek/report/documentation_link_warning_formatter.rb
175
189
  - lib/reek/report/heading_formatter.rb
176
190
  - lib/reek/report/html_report.rb
@@ -256,14 +270,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
256
270
  requirements:
257
271
  - - ">="
258
272
  - !ruby/object:Gem::Version
259
- version: 2.6.0
273
+ version: 3.0.0
260
274
  required_rubygems_version: !ruby/object:Gem::Requirement
261
275
  requirements:
262
276
  - - ">="
263
277
  - !ruby/object:Gem::Version
264
278
  version: '0'
265
279
  requirements: []
266
- rubygems_version: 3.4.1
280
+ rubygems_version: 3.5.3
267
281
  signing_key:
268
282
  specification_version: 4
269
283
  summary: Code smell detector for Ruby
@@ -1,210 +0,0 @@
1
- ---
2
- type: map
3
- mapping:
4
- "detectors":
5
- type: map
6
- mapping: &all_detectors
7
- Attribute:
8
- type: map
9
- mapping: &detector_base
10
- "enabled":
11
- type: bool
12
- "exclude":
13
- type: seq
14
- sequence:
15
- - type: str
16
- BooleanParameter:
17
- type: map
18
- mapping:
19
- <<: *detector_base
20
- ClassVariable:
21
- type: map
22
- mapping:
23
- <<: *detector_base
24
- ControlParameter:
25
- type: map
26
- mapping:
27
- <<: *detector_base
28
- DataClump:
29
- type: map
30
- mapping:
31
- <<: *detector_base
32
- max_copies:
33
- type: number
34
- min_clump_size:
35
- type: number
36
- DuplicateMethodCall:
37
- type: map
38
- mapping:
39
- <<: *detector_base
40
- max_calls:
41
- type: number
42
- allow_calls:
43
- type: seq
44
- sequence:
45
- - type: str
46
- FeatureEnvy:
47
- type: map
48
- mapping:
49
- <<: *detector_base
50
- InstanceVariableAssumption:
51
- type: map
52
- mapping:
53
- <<: *detector_base
54
- IrresponsibleModule:
55
- type: map
56
- mapping:
57
- <<: *detector_base
58
- LongParameterList:
59
- type: map
60
- mapping:
61
- <<: *detector_base
62
- max_params:
63
- type: number
64
- overrides:
65
- type: map
66
- mapping:
67
- initialize:
68
- type: map
69
- mapping:
70
- max_params:
71
- type: number
72
- LongYieldList:
73
- type: map
74
- mapping:
75
- <<: *detector_base
76
- max_params:
77
- type: number
78
- ManualDispatch:
79
- type: map
80
- mapping:
81
- <<: *detector_base
82
- MissingSafeMethod:
83
- type: map
84
- mapping:
85
- <<: *detector_base
86
- ModuleInitialize:
87
- type: map
88
- mapping:
89
- <<: *detector_base
90
- NestedIterators:
91
- type: map
92
- mapping:
93
- <<: *detector_base
94
- max_allowed_nesting:
95
- type: number
96
- ignore_iterators:
97
- type: seq
98
- sequence:
99
- - type: str
100
- NilCheck:
101
- type: map
102
- mapping:
103
- <<: *detector_base
104
- RepeatedConditional:
105
- type: map
106
- mapping:
107
- <<: *detector_base
108
- max_ifs:
109
- type: number
110
- SubclassedFromCoreClass:
111
- type: map
112
- mapping:
113
- <<: *detector_base
114
- Syntax:
115
- type: map
116
- mapping:
117
- <<: *detector_base
118
- TooManyConstants:
119
- type: map
120
- mapping:
121
- <<: *detector_base
122
- max_constants:
123
- type: number
124
- TooManyInstanceVariables:
125
- type: map
126
- mapping:
127
- <<: *detector_base
128
- max_instance_variables:
129
- type: number
130
- TooManyMethods:
131
- type: map
132
- mapping:
133
- <<: *detector_base
134
- max_methods:
135
- type: number
136
- TooManyStatements:
137
- type: map
138
- mapping:
139
- <<: *detector_base
140
- max_statements:
141
- type: number
142
- UncommunicativeMethodName:
143
- type: map
144
- mapping:
145
- <<: *detector_base
146
- reject: &reject_settings
147
- type: seq
148
- sequence:
149
- - type: str
150
- accept: &accept_settings
151
- type: seq
152
- sequence:
153
- - type: str
154
- UncommunicativeModuleName:
155
- type: map
156
- mapping:
157
- <<: *detector_base
158
- reject: *reject_settings
159
- accept: *accept_settings
160
- UncommunicativeParameterName:
161
- type: map
162
- mapping:
163
- <<: *detector_base
164
- reject: *reject_settings
165
- accept: *accept_settings
166
- UncommunicativeVariableName:
167
- type: map
168
- mapping:
169
- <<: *detector_base
170
- reject: *reject_settings
171
- accept: *accept_settings
172
- UnusedParameters:
173
- type: map
174
- mapping:
175
- <<: *detector_base
176
- UnusedPrivateMethod:
177
- type: map
178
- mapping:
179
- <<: *detector_base
180
- UtilityFunction:
181
- type: map
182
- mapping:
183
- <<: *detector_base
184
- public_methods_only:
185
- type: bool
186
-
187
- "directories":
188
- type: map
189
- mapping:
190
- # For any given key that is not matched somewhere else we'll apply the schema below.
191
- # So this will just slurp in every directory we throw at it and then validate everything under
192
- # it against all detectors - for instance:
193
- #
194
- # directories:
195
- # "web_app/app/controllers":
196
- # NestedIterators:
197
- # enabled: false
198
- # "web_app/app/helpers":
199
- # UtilityFunction:
200
- # enabled: false
201
- #
202
- # For details check out: http://www.kuwata-lab.com/kwalify/ruby/users-guide.02.html#tips-default
203
- =:
204
- type: map
205
- mapping: *all_detectors
206
-
207
- "exclude_paths":
208
- type: seq
209
- sequence:
210
- - type: str