ruboclean 0.3.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8356a24c5eef21d90f98b6a9d70e05c39eecca00bdad3cc44cf487f7f13d4d3f
4
- data.tar.gz: 547493df65b231feec2b0e110beaca285a4c708726a60f25ce42da25c04297de
3
+ metadata.gz: be162ee85b381ec3596945c154e6a9596a3c1a38ca54932bc172e71bb750f006
4
+ data.tar.gz: ab675e274e9d0774bd654f73e4afc14d6bfbd6d54547685e7794830c2d4b99c5
5
5
  SHA512:
6
- metadata.gz: 2a322034ef76aef728838a67c0400b6a869614765367347582b99a6a0e9d76ceb1c04ac7f93217d35702eb18b9c111958b059ee39716a8f5d2535f00a6e05e0b
7
- data.tar.gz: 2b9895e2eba1124a33fd0808f2622a22e848cfe87ebede24cda7f17dfc7490e233db040342de84343d69f1dd57d430b8feaf5e9aa87d8961c8c3662624d3e583
6
+ metadata.gz: 3177f58dec5a6ea6318b9ba33dbe31e813060d43cff545c5d354d8998efb326b02d2d7b65c3b5850c1fdbfa8d8fe9e27020430e59df16f7c442fe81812e29e28
7
+ data.tar.gz: edc1388ea384c16dac65f59127f887267c560f6b3b4e65cef970304b3932b430d2974a747839cbf4da1665f380021297a4de0915ccf7fb412763785b19954668
@@ -15,7 +15,7 @@ jobs:
15
15
  fail-fast: false
16
16
  matrix:
17
17
  os: [ubuntu-latest]
18
- ruby: ['2.7', '3.0', '3.1', head]
18
+ ruby: ['2.7', '3.0', '3.1', '3.2', '3.3', head]
19
19
  runs-on: ${{ matrix.os }}
20
20
  steps:
21
21
  - uses: actions/checkout@v3
data/.rubocop.yml CHANGED
@@ -4,11 +4,10 @@ require:
4
4
  - rubocop-minitest
5
5
  - rubocop-rake
6
6
 
7
- Style/StringLiterals:
7
+ Gemspec/DeprecatedAttributeAssignment:
8
8
  Enabled: true
9
- EnforcedStyle: double_quotes
10
9
 
11
- Gemspec/DeprecatedAttributeAssignment:
10
+ Gemspec/DevelopmentDependencies:
12
11
  Enabled: true
13
12
 
14
13
  Gemspec/RequireMFA:
@@ -68,6 +67,9 @@ Lint/DuplicateElsifCondition:
68
67
  Lint/DuplicateMagicComment:
69
68
  Enabled: true
70
69
 
70
+ Lint/DuplicateMatchPattern:
71
+ Enabled: true
72
+
71
73
  Lint/DuplicateRegexpCharacterClassElement:
72
74
  Enabled: true
73
75
 
@@ -101,12 +103,21 @@ Lint/IdentityComparison:
101
103
  Lint/IncompatibleIoSelectWithFiberScheduler:
102
104
  Enabled: true
103
105
 
106
+ Lint/ItWithoutArgumentsInBlock:
107
+ Enabled: true
108
+
104
109
  Lint/LambdaWithoutLiteralBlock:
105
110
  Enabled: true
106
111
 
112
+ Lint/LiteralAssignmentInCondition:
113
+ Enabled: true
114
+
107
115
  Lint/MissingSuper:
108
116
  Enabled: true
109
117
 
118
+ Lint/MixedCaseRange:
119
+ Enabled: true
120
+
110
121
  Lint/MixedRegexpCaptureTypes:
111
122
  Enabled: true
112
123
 
@@ -131,6 +142,9 @@ Lint/RaiseException:
131
142
  Lint/RedundantDirGlobSort:
132
143
  Enabled: true
133
144
 
145
+ Lint/RedundantRegexpQuantifiers:
146
+ Enabled: true
147
+
134
148
  Lint/RefinementImportMethods:
135
149
  Enabled: true
136
150
 
@@ -173,18 +187,27 @@ Lint/UnreachableLoop:
173
187
  Lint/UselessMethodDefinition:
174
188
  Enabled: true
175
189
 
190
+ Lint/UselessRescue:
191
+ Enabled: true
192
+
176
193
  Lint/UselessRuby2Keywords:
177
194
  Enabled: true
178
195
 
179
196
  Lint/UselessTimes:
180
197
  Enabled: true
181
198
 
199
+ Metrics/CollectionLiteralLength:
200
+ Enabled: true
201
+
182
202
  Minitest/AssertInDelta:
183
203
  Enabled: true
184
204
 
185
205
  Minitest/AssertKindOf:
186
206
  Enabled: true
187
207
 
208
+ Minitest/AssertOperator:
209
+ Enabled: true
210
+
188
211
  Minitest/AssertOutput:
189
212
  Enabled: true
190
213
 
@@ -200,6 +223,9 @@ Minitest/AssertRaisesCompoundBody:
200
223
  Minitest/AssertRaisesWithRegexpArgument:
201
224
  Enabled: true
202
225
 
226
+ Minitest/AssertSame:
227
+ Enabled: true
228
+
203
229
  Minitest/AssertSilent:
204
230
  Enabled: true
205
231
 
@@ -215,6 +241,9 @@ Minitest/DuplicateTestRun:
215
241
  Minitest/EmptyLineBeforeAssertionMethods:
216
242
  Enabled: true
217
243
 
244
+ Minitest/LifecycleHooksOrder:
245
+ Enabled: true
246
+
218
247
  Minitest/LiteralAsActualArgument:
219
248
  Enabled: true
220
249
 
@@ -222,24 +251,45 @@ Minitest/MultipleAssertions:
222
251
  Enabled: true
223
252
  Max: 5
224
253
 
254
+ Minitest/NonExecutableTestMethod:
255
+ Enabled: true
256
+
257
+ Minitest/NonPublicTestMethod:
258
+ Enabled: true
259
+
260
+ Minitest/RedundantMessageArgument:
261
+ Enabled: true
262
+
225
263
  Minitest/RefuteInDelta:
226
264
  Enabled: true
227
265
 
228
266
  Minitest/RefuteKindOf:
229
267
  Enabled: true
230
268
 
269
+ Minitest/RefuteOperator:
270
+ Enabled: true
271
+
231
272
  Minitest/RefutePathExists:
232
273
  Enabled: true
233
274
 
234
275
  Minitest/RefutePredicate:
235
276
  Enabled: true
236
277
 
278
+ Minitest/RefuteSame:
279
+ Enabled: true
280
+
281
+ Minitest/ReturnInTestMethod:
282
+ Enabled: true
283
+
237
284
  Minitest/SkipEnsure:
238
285
  Enabled: true
239
286
 
240
287
  Minitest/SkipWithoutReason:
241
288
  Enabled: true
242
289
 
290
+ Minitest/TestFileName:
291
+ Enabled: true
292
+
243
293
  Minitest/TestMethodName:
244
294
  Enabled: true
245
295
 
@@ -249,6 +299,9 @@ Minitest/UnreachableAssertion:
249
299
  Minitest/UnspecifiedException:
250
300
  Enabled: true
251
301
 
302
+ Minitest/UselessAssertion:
303
+ Enabled: true
304
+
252
305
  Naming/BlockForwarding:
253
306
  Enabled: true
254
307
 
@@ -282,9 +335,18 @@ Style/CollectionCompact:
282
335
  Style/CombinableLoops:
283
336
  Enabled: true
284
337
 
338
+ Style/ComparableClamp:
339
+ Enabled: true
340
+
285
341
  Style/ConcatArrayLiterals:
286
342
  Enabled: true
287
343
 
344
+ Style/DataInheritance:
345
+ Enabled: true
346
+
347
+ Style/DirEmpty:
348
+ Enabled: true
349
+
288
350
  Style/DocumentDynamicEvalDefinition:
289
351
  Enabled: true
290
352
 
@@ -297,6 +359,9 @@ Style/EndlessMethod:
297
359
  Style/EnvHome:
298
360
  Enabled: true
299
361
 
362
+ Style/ExactRegexpMatch:
363
+ Enabled: true
364
+
300
365
  Style/ExplicitBlockArgument:
301
366
  Enabled: true
302
367
 
@@ -306,6 +371,9 @@ Style/ExponentialNotation:
306
371
  Style/FetchEnvVar:
307
372
  Enabled: true
308
373
 
374
+ Style/FileEmpty:
375
+ Enabled: true
376
+
309
377
  Style/FileRead:
310
378
  Enabled: true
311
379
 
@@ -396,12 +464,18 @@ Style/QuotedSymbols:
396
464
  Style/RedundantArgument:
397
465
  Enabled: true
398
466
 
467
+ Style/RedundantArrayConstructor:
468
+ Enabled: true
469
+
399
470
  Style/RedundantAssignment:
400
471
  Enabled: true
401
472
 
402
473
  Style/RedundantConstantBase:
403
474
  Enabled: true
404
475
 
476
+ Style/RedundantCurrentDirectoryInPath:
477
+ Enabled: true
478
+
405
479
  Style/RedundantDoubleSplatHashBraces:
406
480
  Enabled: true
407
481
 
@@ -414,12 +488,27 @@ Style/RedundantFetchBlock:
414
488
  Style/RedundantFileExtensionInRequire:
415
489
  Enabled: true
416
490
 
491
+ Style/RedundantFilterChain:
492
+ Enabled: true
493
+
494
+ Style/RedundantHeredocDelimiterQuotes:
495
+ Enabled: true
496
+
417
497
  Style/RedundantInitialize:
418
498
  Enabled: true
419
499
 
500
+ Style/RedundantLineContinuation:
501
+ Enabled: true
502
+
503
+ Style/RedundantRegexpArgument:
504
+ Enabled: true
505
+
420
506
  Style/RedundantRegexpCharacterClass:
421
507
  Enabled: true
422
508
 
509
+ Style/RedundantRegexpConstructor:
510
+ Enabled: true
511
+
423
512
  Style/RedundantRegexpEscape:
424
513
  Enabled: true
425
514
 
@@ -432,12 +521,18 @@ Style/RedundantSelfAssignmentBranch:
432
521
  Style/RedundantStringEscape:
433
522
  Enabled: true
434
523
 
524
+ Style/ReturnNilInPredicateMethodDefinition:
525
+ Enabled: true
526
+
435
527
  Style/SelectByRegexp:
436
528
  Enabled: true
437
529
 
438
530
  Style/SingleArgumentDig:
439
531
  Enabled: true
440
532
 
533
+ Style/SingleLineDoEndBlock:
534
+ Enabled: true
535
+
441
536
  Style/SlicingWithRange:
442
537
  Enabled: true
443
538
 
@@ -450,8 +545,18 @@ Style/StringChars:
450
545
  Style/StringConcatenation:
451
546
  Enabled: true
452
547
 
548
+ Style/StringLiterals:
549
+ Enabled: true
550
+ EnforcedStyle: double_quotes
551
+
552
+ Style/SuperWithArgsParentheses:
553
+ Enabled: true
554
+
453
555
  Style/SwapValues:
454
556
  Enabled: true
455
557
 
558
+ Style/YAMLFileRead:
559
+ Enabled: true
560
+
456
561
  Style/YodaExpression:
457
562
  Enabled: true
data/Gemfile.lock CHANGED
@@ -1,45 +1,50 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ruboclean (0.3.0)
4
+ ruboclean (0.5.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
9
  ast (2.4.2)
10
10
  docile (1.4.0)
11
- json (2.6.3)
12
- minitest (5.17.0)
13
- parallel (1.22.1)
14
- parser (3.2.0.0)
11
+ json (2.7.1)
12
+ language_server-protocol (3.17.0.3)
13
+ minitest (5.20.0)
14
+ parallel (1.24.0)
15
+ parser (3.2.2.4)
15
16
  ast (~> 2.4.1)
17
+ racc
18
+ racc (1.7.3)
16
19
  rainbow (3.1.1)
17
- rake (13.0.6)
18
- regexp_parser (2.6.1)
19
- rexml (3.2.5)
20
- rubocop (1.42.0)
20
+ rake (13.1.0)
21
+ regexp_parser (2.8.3)
22
+ rexml (3.2.6)
23
+ rubocop (1.59.0)
21
24
  json (~> 2.3)
25
+ language_server-protocol (>= 3.17.0)
22
26
  parallel (~> 1.10)
23
- parser (>= 3.1.2.1)
27
+ parser (>= 3.2.2.4)
24
28
  rainbow (>= 2.2.2, < 4.0)
25
29
  regexp_parser (>= 1.8, < 3.0)
26
30
  rexml (>= 3.2.5, < 4.0)
27
- rubocop-ast (>= 1.24.1, < 2.0)
31
+ rubocop-ast (>= 1.30.0, < 2.0)
28
32
  ruby-progressbar (~> 1.7)
29
- unicode-display_width (>= 1.4.0, < 3.0)
30
- rubocop-ast (1.24.1)
31
- parser (>= 3.1.1.0)
32
- rubocop-minitest (0.25.1)
33
- rubocop (>= 0.90, < 2.0)
33
+ unicode-display_width (>= 2.4.0, < 3.0)
34
+ rubocop-ast (1.30.0)
35
+ parser (>= 3.2.1.0)
36
+ rubocop-minitest (0.34.2)
37
+ rubocop (>= 1.39, < 2.0)
38
+ rubocop-ast (>= 1.30.0, < 2.0)
34
39
  rubocop-rake (0.6.0)
35
40
  rubocop (~> 1.0)
36
- ruby-progressbar (1.11.0)
41
+ ruby-progressbar (1.13.0)
37
42
  simplecov (0.17.1)
38
43
  docile (~> 1.1)
39
44
  json (>= 1.8, < 3)
40
45
  simplecov-html (~> 0.10.0)
41
46
  simplecov-html (0.10.2)
42
- unicode-display_width (2.4.1)
47
+ unicode-display_width (2.5.0)
43
48
 
44
49
  PLATFORMS
45
50
  ruby
@@ -54,4 +59,4 @@ DEPENDENCIES
54
59
  simplecov (< 0.18)
55
60
 
56
61
  BUNDLED WITH
57
- 2.4.2
62
+ 2.4.13
data/README.md CHANGED
@@ -28,10 +28,14 @@ Rails:
28
28
 
29
29
  AllCops:
30
30
  Exclude:
31
- - bin/**/*
31
+ - path/file_exists.rb
32
+ - path_with_files/**/*
33
+ - path/file_does_not_exist.rb # This entry will be removed if the file doesn't exist. Skip with --preserve-paths option.
34
+ - path_without_files/**/* # Will be removed if no files within pattern exist. Skip with --preserve-paths option.
32
35
 
36
+ # Preceding comments will be removed unless the --preserve-comments option is used.
33
37
  require:
34
- - rubocop-rails
38
+ - rubocop-rails # Inline comments will always be removed.
35
39
  ```
36
40
 
37
41
  ### Output `.rubocop.yml`:
@@ -44,7 +48,8 @@ require:
44
48
 
45
49
  AllCops:
46
50
  Exclude:
47
- - bin/**/*
51
+ - path/file_exists.rb
52
+ - path_with_files/**/*
48
53
 
49
54
  Rails:
50
55
  Enabled: true
@@ -54,10 +59,8 @@ Layout/LineLength:
54
59
 
55
60
  Rails/ShortI18n:
56
61
  Enabled: true
57
-
58
62
  ```
59
63
 
60
-
61
64
  ## Installation
62
65
 
63
66
  Add this line to your application's Gemfile:
@@ -78,27 +81,26 @@ Or install it yourself as:
78
81
  gem install ruboclean
79
82
  ```
80
83
 
81
- ## Usage
84
+ ## Command synopsis
82
85
 
83
86
  ```shell
84
- ruboclean [path]
87
+ ruboclean [path] [--silent] [--preserve-comments] [--preserve-paths]
85
88
  ```
86
89
 
87
- * `path` is optional, it defaults to the current working directory
88
- * `path` can be a directory that contains a `.rubocop.yml`
89
- * `path` can be a path to a `.rubocop.yml` directly
90
+ ### Parameters
90
91
 
91
- ### Examples
92
+ | Parameter | Description |
93
+ |:----------------------|:--------------------------------------------------------------------------------------------------------------------------------------|
94
+ | `path` | Can be a directory that contains a `.rubocop.yml`, or a path to a `.rubocop.yml` directly. Defaults to the current working directory. |
95
+ | `--silent` | Suppress any output displayed on the screen when executing the command. |
96
+ | `--preserve-comments` | Preserves **preceding** comments for each top-level entry in the configuration. Inline comments are **not** preserved. |
97
+ | `--preserve-paths` | Skips the path cleanup that are applied against `Include:` and `Exclude:` configuration. |
92
98
 
93
- ```shell
94
- ruboclean # uses `.rubocop.yml` of current working directory
95
- ```
96
-
97
- ```shell
98
- ruboclean /path/to/dir # uses `.rubocop.yml` of /path/to/dir
99
- ```
99
+ ### Examples
100
100
 
101
101
  ```shell
102
+ ruboclean # uses `.rubocop.yml` of current working directory
103
+ ruboclean /path/to/dir # uses `.rubocop.yml` of /path/to/dir
102
104
  ruboclean /path/to/dir/.rubocop.yml
103
105
  ```
104
106
 
@@ -112,7 +114,6 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
112
114
 
113
115
  Bug reports and pull requests are welcome on GitHub at https://github.com/lxxxvi/ruboclean. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/lxxxvi/ruboclean/blob/master/CODE_OF_CONDUCT.md).
114
116
 
115
-
116
117
  ## License
117
118
 
118
119
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/bin/ruboclean CHANGED
@@ -3,9 +3,4 @@
3
3
  # frozen_string_literal: true
4
4
 
5
5
  require "ruboclean"
6
-
7
- path = ARGV[0] || Dir.pwd
8
-
9
- print "Using path '#{path}' ... "
10
- Ruboclean.run(path)
11
- puts "done."
6
+ Ruboclean.run_from_cli!(ARGV)
data/bin/test CHANGED
@@ -20,7 +20,7 @@ class BinTest
20
20
  system! "bundle exec rake test"
21
21
 
22
22
  puts "\n== Run rubocop =="
23
- system! "bundle exec rubocop -p"
23
+ system! "bundle exec rubocop --parallel"
24
24
  end
25
25
  end
26
26
  end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ruboclean
4
+ # Reads command line arguments and exposes corresponding reader methods
5
+ class CliArguments
6
+ def initialize(command_line_arguments = [])
7
+ @command_line_arguments = Array(command_line_arguments)
8
+ end
9
+
10
+ def path
11
+ @path ||= find_path
12
+ end
13
+
14
+ def verbose?
15
+ !silent?
16
+ end
17
+
18
+ def silent?
19
+ @silent ||= find_argument("--silent")
20
+ end
21
+
22
+ def preserve_comments?
23
+ @preserve_comments ||= find_argument("--preserve-comments")
24
+ end
25
+
26
+ def preserve_paths?
27
+ @preserve_paths ||= find_argument("--preserve-paths")
28
+ end
29
+
30
+ private
31
+
32
+ attr_reader :command_line_arguments
33
+
34
+ def find_path
35
+ command_line_arguments.first.then do |argument|
36
+ return Dir.pwd if argument.nil? || argument.start_with?("--")
37
+
38
+ argument
39
+ end
40
+ end
41
+
42
+ def find_argument(name)
43
+ command_line_arguments.any? { |argument| argument == name }
44
+ end
45
+ end
46
+ end
@@ -6,12 +6,12 @@ module Ruboclean
6
6
  # - namespaces: every item which does **not** include an "/"
7
7
  # - cops: every item which **includes** an "/"
8
8
  class Grouper
9
- def initialize(config_hash)
10
- @config_hash = config_hash
9
+ def initialize(configuration_hash)
10
+ @configuration_hash = configuration_hash
11
11
  end
12
12
 
13
13
  def group_config
14
- @config_hash.each_with_object(empty_groups) do |item, result|
14
+ configuration_hash.each_with_object(empty_groups) do |item, result|
15
15
  key, value = item
16
16
  target_group = find_target_group(key)
17
17
  result[target_group].merge!({ key => value })
@@ -20,6 +20,8 @@ module Ruboclean
20
20
 
21
21
  private
22
22
 
23
+ attr_reader :configuration_hash
24
+
23
25
  def empty_groups
24
26
  { base: {}, namespaces: {}, cops: {} }
25
27
  end
@@ -1,12 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "ruboclean/grouper"
4
-
5
3
  module Ruboclean
6
4
  # Orders the items within the groups alphabetically
7
5
  class Orderer
8
- def initialize(config_hash)
9
- @config_hash = config_hash
6
+ def initialize(configuration_hash)
7
+ @configuration_hash = configuration_hash
10
8
  end
11
9
 
12
10
  def order
@@ -18,12 +16,14 @@ module Ruboclean
18
16
 
19
17
  private
20
18
 
21
- def order_by_key(config_hash)
22
- config_hash.sort_by(&:first).to_h
19
+ attr_reader :configuration_hash
20
+
21
+ def order_by_key(group_items)
22
+ group_items.sort_by(&:first).to_h
23
23
  end
24
24
 
25
25
  def grouped_config
26
- Ruboclean::Grouper.new(@config_hash).group_config
26
+ Ruboclean::Grouper.new(configuration_hash).group_config
27
27
  end
28
28
  end
29
29
  end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ruboclean
4
+ # Cleans up any `Include` or `Exclude` paths that don't exist.
5
+ # The `Include` and `Exclude` paths are relative to the directory
6
+ # where the `.rubocop.yml` file is located. If a path includes a
7
+ # regexp, it's assumed to be valid.
8
+ # If all entries in `Include` or `Exclude` are removed, the entire property is removed.
9
+ # If a Cop gets entirely truncated due to removing all `Includes` and/or `Exclude`, the Cop itself will be removed.
10
+ class PathCleanup
11
+ def initialize(configuration_hash, root_directory)
12
+ @configuration_hash = configuration_hash
13
+ @root_directory = root_directory
14
+ end
15
+
16
+ def cleanup
17
+ configuration_hash.each_with_object({}) do |(top_level_key, top_level_value), hash|
18
+ result = process_top_level_value(top_level_value)
19
+
20
+ next if Array(result).empty? # No configuration keys left in the cop, remove the entire cop
21
+
22
+ hash[top_level_key] = result
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ attr_reader :configuration_hash, :root_directory
29
+
30
+ # top_level_value could be something like this:
31
+ #
32
+ # {
33
+ # Include: [...],
34
+ # Exclude: [...],
35
+ # EnforcedStyle: "..."
36
+ # }
37
+ #
38
+ # We process it further in case of a Hash.
39
+ def process_top_level_value(top_level_value)
40
+ return top_level_value unless top_level_value.is_a?(Hash)
41
+
42
+ top_level_value.each_with_object({}) do |(cop_property_key, cop_property_value), hash|
43
+ result = process_cop_property(cop_property_key, cop_property_value)
44
+
45
+ next if Array(result).empty? # No entries left, will skip adding the key to the hash
46
+
47
+ hash[cop_property_key] = result
48
+ end
49
+ end
50
+
51
+ def process_cop_property(cop_property_key, cop_property_value)
52
+ return cop_property_value unless %w[Include Exclude].include?(cop_property_key.to_s)
53
+ return cop_property_value unless cop_property_value.respond_to?(:filter_map)
54
+
55
+ cop_property_value.find_all do |item|
56
+ path_exists?(item)
57
+ end
58
+ end
59
+
60
+ def path_exists?(item)
61
+ regexp_pattern?(item) ||
62
+ specific_path_exists?(item) ||
63
+ any_global_command_pattern?(item)
64
+ end
65
+
66
+ def specific_path_exists?(item)
67
+ root_directory.join(item).exist?
68
+ end
69
+
70
+ def any_global_command_pattern?(item)
71
+ root_directory.glob(item).any?
72
+ end
73
+
74
+ # We don't support Regexp, so we just say it exists.
75
+ def regexp_pattern?(item)
76
+ item.is_a?(Regexp)
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pathname"
4
+ require "yaml"
5
+
6
+ module Ruboclean
7
+ # Entry point for processing
8
+ class Runner
9
+ def initialize(args = [])
10
+ @cli_arguments = CliArguments.new(args)
11
+ end
12
+
13
+ def run!
14
+ return if source_file_pathname.empty?
15
+
16
+ load_file.then(&method(:order))
17
+ .then(&method(:cleanup_paths))
18
+ .then(&method(:convert_to_yaml))
19
+ .then(&method(:write_file!))
20
+ end
21
+
22
+ def verbose?
23
+ cli_arguments.verbose?
24
+ end
25
+
26
+ def path
27
+ cli_arguments.path
28
+ end
29
+
30
+ private
31
+
32
+ attr_reader :cli_arguments
33
+
34
+ def source_yaml
35
+ @source_yaml ||= source_file_pathname.read
36
+ end
37
+
38
+ def load_file
39
+ YAML.safe_load(source_yaml, permitted_classes: [Regexp])
40
+ end
41
+
42
+ def order(configuration_hash)
43
+ Orderer.new(configuration_hash).order
44
+ end
45
+
46
+ def cleanup_paths(configuration_hash)
47
+ return configuration_hash if cli_arguments.preserve_paths?
48
+
49
+ PathCleanup.new(configuration_hash, source_file_pathname.dirname).cleanup
50
+ end
51
+
52
+ def convert_to_yaml(configuration_hash)
53
+ ToYamlConverter.new(configuration_hash, cli_arguments.preserve_comments?, source_yaml).to_yaml
54
+ end
55
+
56
+ def write_file!(target_yaml)
57
+ source_file_pathname.write(target_yaml)
58
+ end
59
+
60
+ def source_file_pathname
61
+ @source_file_pathname ||= find_source_file_pathname
62
+ end
63
+
64
+ def find_source_file_pathname
65
+ source_path = Pathname.new(cli_arguments.path)
66
+
67
+ source_path = source_path.join(".rubocop.yml") if source_path.directory?
68
+
69
+ return source_path if source_path.exist?
70
+
71
+ raise ArgumentError, "path does not exist: '#{source_path}'"
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ruboclean
4
+ # Converts the configuration hash to YAML and applies modifications on it, if requested
5
+ class ToYamlConverter
6
+ def initialize(configuration_hash, preserve_comments, source_yaml)
7
+ @configuration_hash = configuration_hash
8
+ @preserve_comments = preserve_comments
9
+ @source_yaml = source_yaml
10
+ end
11
+
12
+ def to_yaml
13
+ target_yaml = sanitize_yaml(configuration_hash.transform_keys(&:to_s).to_yaml)
14
+
15
+ return target_yaml unless preserve_comments?
16
+
17
+ preserve_preceding_comments(source_yaml, target_yaml)
18
+ end
19
+
20
+ private
21
+
22
+ attr_reader :configuration_hash, :preserve_comments, :source_yaml
23
+
24
+ def preserve_comments?
25
+ preserve_comments
26
+ end
27
+
28
+ def sanitize_yaml(data)
29
+ data.gsub(/^([a-zA-Z]+)/, "\n\\1")
30
+ end
31
+
32
+ def preserve_preceding_comments(source, target)
33
+ target.dup.tap do |output|
34
+ source.scan(/(((^ *#.*\n|^\s*\n)+)(?![\s#]).+)/) do |groups|
35
+ config_keys_with_preceding_lines = groups.first
36
+ *preceding_lines, config_key = config_keys_with_preceding_lines.split("\n")
37
+
38
+ next if preceding_lines.all?(:empty?)
39
+ next if config_key.gsub(/\s/, "").empty?
40
+
41
+ output.sub!(/^#{config_key}$/, config_keys_with_preceding_lines.strip)
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ruboclean
4
- VERSION = "0.3.0"
4
+ VERSION = "0.5.0"
5
5
  end
data/lib/ruboclean.rb CHANGED
@@ -1,17 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "ruboclean/version"
4
- require "ruboclean/rubocop_configuration"
5
- require "ruboclean/rubocop_configuration_path"
3
+ require "ruboclean/cli_arguments"
6
4
  require "ruboclean/orderer"
5
+ require "ruboclean/grouper"
6
+ require "ruboclean/path_cleanup"
7
+ require "ruboclean/runner"
8
+ require "ruboclean/to_yaml_converter"
9
+ require "ruboclean/version"
7
10
 
8
11
  # Ruboclean entry point
9
12
  module Ruboclean
10
- class Error < StandardError; end
11
-
12
- def self.run(path)
13
- rubocop_configuration_path = RubocopConfigurationPath.new(path)
14
- rubocop_configuration = rubocop_configuration_path.load
15
- rubocop_configuration_path.write(rubocop_configuration.order)
13
+ def self.run_from_cli!(args)
14
+ runner = Runner.new(args)
15
+ print "Using path '#{runner.path}' ... " if runner.verbose?
16
+ runner.run!
17
+ puts "done." if runner.verbose?
16
18
  end
17
19
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruboclean
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - lxxxvi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-01-04 00:00:00.000000000 Z
11
+ date: 2024-02-11 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Cleans and orders settings in .rubocop.yml
14
14
  email:
@@ -32,10 +32,12 @@ files:
32
32
  - bin/setup
33
33
  - bin/test
34
34
  - lib/ruboclean.rb
35
+ - lib/ruboclean/cli_arguments.rb
35
36
  - lib/ruboclean/grouper.rb
36
37
  - lib/ruboclean/orderer.rb
37
- - lib/ruboclean/rubocop_configuration.rb
38
- - lib/ruboclean/rubocop_configuration_path.rb
38
+ - lib/ruboclean/path_cleanup.rb
39
+ - lib/ruboclean/runner.rb
40
+ - lib/ruboclean/to_yaml_converter.rb
39
41
  - lib/ruboclean/version.rb
40
42
  - ruboclean.gemspec
41
43
  homepage: https://github.com/lxxxvi/ruboclean
@@ -61,7 +63,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
61
63
  - !ruby/object:Gem::Version
62
64
  version: '0'
63
65
  requirements: []
64
- rubygems_version: 3.4.1
66
+ rubygems_version: 3.5.3
65
67
  signing_key:
66
68
  specification_version: 4
67
69
  summary: Cleans and orders settings in .rubocop.yml
@@ -1,14 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Ruboclean
4
- # Contains the config_hash representation of the `.rubocop.yml` file
5
- class RubocopConfiguration
6
- def initialize(config_hash)
7
- @config_hash = config_hash
8
- end
9
-
10
- def order
11
- Ruboclean::Orderer.new(@config_hash).order
12
- end
13
- end
14
- end
@@ -1,49 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "pathname"
4
- require "yaml"
5
-
6
- module Ruboclean
7
- # Interface for reading and writing the `.rubocop.yml` file
8
- class RubocopConfigurationPath
9
- PERMITTED_CLASSED = [Regexp].freeze
10
-
11
- # Thrown if given path is invalid
12
- class InvalidPathError < StandardError
13
- def initialize(path)
14
- super "path does not exist: '#{path}'"
15
- end
16
- end
17
-
18
- def initialize(path)
19
- input_path = Pathname.new(path)
20
-
21
- @rubocop_configuration_path = if input_path.directory?
22
- input_path.join(".rubocop.yml")
23
- else
24
- input_path
25
- end
26
-
27
- raise InvalidPathError, @rubocop_configuration_path unless @rubocop_configuration_path.exist?
28
- end
29
-
30
- def load
31
- Ruboclean::RubocopConfiguration.new(load_yaml)
32
- end
33
-
34
- def write(rubocop_configuration)
35
- output = sanitize_yaml(rubocop_configuration.to_yaml)
36
- @rubocop_configuration_path.write(output)
37
- end
38
-
39
- private
40
-
41
- def sanitize_yaml(data)
42
- data.gsub(/^([a-zA-Z]+)/, "\n\\1")
43
- end
44
-
45
- def load_yaml
46
- YAML.safe_load(@rubocop_configuration_path.read, permitted_classes: PERMITTED_CLASSED)
47
- end
48
- end
49
- end