standard 1.21.1 → 1.22.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7a7fc419962214950950e1f1babe8ea008c878c3309e7066a7a971fea897df23
4
- data.tar.gz: b0d510b5788332ebca799de9a665ca8df590cb5679360daca36d67dcddf2e539
3
+ metadata.gz: f79913870ce4e07e94a76c49bfdb2bdf671b72cfe28b9c8d23d3dcfe723b9093
4
+ data.tar.gz: 1fbbe5ecbb1b9b093997cf96f4102c089305ef35f5bf0523406924120cb5906e
5
5
  SHA512:
6
- metadata.gz: 59badefc6eb57920133e0f6440374e60d96211f5496fae8acc1be5b1e90852152c38f44043918818af54a7bfa59489472af47f3b41883b7ab343ee4330d02d84
7
- data.tar.gz: 44fcaabf3eeedae4935562e4cc73d90e3b6e0116be4b18a0ae9f5359f21c8bb6cce4df77a69d27f7bd680350be052161eb6d7bcc26e2e71f45a0513078a9d25c
6
+ metadata.gz: 19e734ff2ab15102430f2cd927ef9beed5c403b6e7b30804bb8baf23d83978ffdfeec3324482d957daae0bd7efbbc7ebcd9bce9bc9f9a84e81c85839c2f30eb0
7
+ data.tar.gz: a3135a540a166b292633aa3e2adb11854f09b67fa07dccbc5199de73efa5d289b4612b10917481791563105bdc815a89e7912e054a737428fb55c25c32cfe0bb
data/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.22.1
4
+
5
+ * Improve the behavior of `extend_config` to more accurately reflect how Rubocop
6
+ extensions would behave when loaded via the `rubocop` CLI (by capturing any
7
+ mutations to RuboCop's default configuration)
8
+ [#512](https://github.com/testdouble/standard/pull/512)
9
+
10
+ ## 1.22.0
11
+
12
+ * Add `extend_config` option [#506](https://github.com/testdouble/standard/pull/506)
13
+
3
14
  ## 1.21.1
4
15
 
5
16
  * Fix standard comment directives [#498](https://github.com/testdouble/standard/pull/498)
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- standard (1.21.1)
4
+ standard (1.22.1)
5
5
  language_server-protocol (~> 3.17.0.2)
6
6
  rubocop (= 1.42.0)
7
7
  rubocop-performance (= 1.15.2)
data/README.md CHANGED
@@ -215,12 +215,11 @@ inherit_gem:
215
215
 
216
216
  ## Who uses Ruby Standard Style?
217
217
 
218
- (This section will not [look very
219
- familiar](https://github.com/standard/standard#who-uses-javascript-standard-style)
220
- if you've used StandardJS.)
218
+ Here are a few examples of Ruby Standard-compliant teams & projects:
221
219
 
222
220
  * [Test Double](https://testdouble.com/agency)
223
221
  * [Amazon Web Services](https://aws.amazon.com/)
222
+ * [Arrows](https://arrows.to/)
224
223
  * [Babylist](https://www.babylist.com/)
225
224
  * [Brand New Box](https://brandnewbox.com)
226
225
  * [Brave Software](https://github.com/brave-intl/publishers)
@@ -244,9 +243,7 @@ if you've used StandardJS.)
244
243
  * [RubyCI](https://ruby.ci)
245
244
  * [thoughtbot](https://thoughtbot.com/)
246
245
 
247
- If your team starts using Standard, [send a pull
248
- request](https://github.com/testdouble/standard/edit/main/README.md) to let us
249
- know!
246
+ Does your team use Standard? [Add your name to the list](https://github.com/testdouble/standard/edit/main/README.md)!
250
247
 
251
248
  ## Is there a readme badge?
252
249
 
@@ -401,6 +398,87 @@ configurations](https://github.com/testdouble/standard/tree/main/config) and
401
398
  consider helping out by submitting a pull request if you find a rule that won't
402
399
  work for older Rubies.
403
400
 
401
+ ## How do I use Standard with RuboCop extensions or custom rules?
402
+
403
+ If you want to use Standard in conjunction with RuboCop extensions or custom
404
+ cops, you can specify them in your own [RuboCop configuration
405
+ YAML](https://docs.rubocop.org/rubocop/configuration.html) files and
406
+ `.standard.yml` using the "extend_config` setting.
407
+
408
+ For a simple example, you could include [rubocop-rails](https://github.com/rubocop/rubocop-rails)
409
+ when Standard runs by first specifying a file in `.standard.yml`:
410
+
411
+ ```yaml
412
+ # .standard.yml
413
+
414
+ extend_config:
415
+ - .standard_rubocop_extensions.yml
416
+ ```
417
+
418
+ And a minimal RuboCop configuration file:
419
+
420
+ ```yaml
421
+ # .standard_rubocop_extensions.yml
422
+
423
+ require:
424
+ - rubocop-rails
425
+ ```
426
+
427
+ That's it! Now, in addition to all of Standard's built-in rules, `standardrb`
428
+ and `rake standard` will also execute the default configuration of the
429
+ `rubocop-rails` gem without needing to invoke `rubocop` separately.
430
+
431
+ For a slightly more complex example, we could add the
432
+ [https://github.com/Betterment/betterlint] gem from our friends at
433
+ [Betterment](https://www.betterment.com), first by telling Standard where our
434
+ configuration file is:
435
+
436
+ ```yml
437
+ # .standard.yml
438
+
439
+ extend_config:
440
+ - .betterlint.yml
441
+ ```
442
+
443
+ But if we only wanted to enable a particular rule, we could configure it more
444
+ narrowly, like this:
445
+
446
+ ```yml
447
+ # .betterlint.yml
448
+
449
+ require:
450
+ - rubocop/cop/betterment.rb
451
+
452
+ AllCops:
453
+ DisabledByDefault: true
454
+
455
+ Betterment/UnscopedFind:
456
+ Enabled: true
457
+
458
+ unauthenticated_models:
459
+ - SystemConfiguration
460
+ ```
461
+
462
+ This same approach works for more than just gems! Just require a Ruby file that
463
+ defines or loads your [custom RuboCop
464
+ implementation](https://docs.rubocop.org/rubocop/development.html) and configure
465
+ it using `extend_config`.
466
+
467
+ When Standard encounters an `extend_config` property, it will merge your
468
+ configuration files with Standard's base ruleset. To prevent Standard's built-in
469
+ rules from being modified, any configuration of rules includued in the `rubocop`
470
+ or `rubocop-performance` gems will be ignored. Most settings under `AllCops:`
471
+ can be configured, however, unless they'd conflict with a setting used by
472
+ Standard (like `TargetRubyVersion`) or prevent Standard's own rules from running
473
+ (like `StyleGuideCopsOnly`). If you specify multiple YAML files under
474
+ `extend_config`, note that their resulting RuboCop configurations will be merged
475
+ in order (i.e. last-in-wins).
476
+
477
+ If you find that Standard's `extend_config` feature doesn't meet your needs,
478
+ Evil Martians also maintains [a regularly updated
479
+ guide](https://evilmartians.com/chronicles/rubocoping-with-legacy-bring-your-ruby-code-up-to-standard)
480
+ on how to configure RuboCop to load and execute Standard's ruleset.
481
+
404
482
  ## How do I change the output?
405
483
 
406
484
  Standard's built-in formatter is intentionally minimal, printing only unfixed
@@ -492,13 +570,6 @@ either:
492
570
  gem to your build, which will automatically ensure that the comment is
493
571
  prepended for every applicable file in your project
494
572
 
495
- ## How do I use Standard with RuboCop extensions?
496
-
497
- This is not officially supported by Standard. However, Evil Martians wrote up [a
498
- regularly updated
499
- guide](https://evilmartians.com/chronicles/rubocoping-with-legacy-bring-your-ruby-code-up-to-standard)
500
- on how to do so.
501
-
502
573
  ## How often is Standard updated?
503
574
 
504
575
  We aim to update Standard once a month, in the first week of the month. In between releases, we'll be considering RuboCop updates, RuboCop Performance updates, and community contributions.
data/config/base.yml CHANGED
@@ -1269,6 +1269,7 @@ Style/EmptyCaseCondition:
1269
1269
 
1270
1270
  Style/EmptyElse:
1271
1271
  Enabled: true
1272
+ AllowComments: true
1272
1273
  EnforcedStyle: both
1273
1274
 
1274
1275
  Style/EmptyHeredoc:
@@ -0,0 +1,67 @@
1
+ require_relative "../file_finder"
2
+
3
+ class Standard::CreatesConfigStore
4
+ class MergesUserConfigExtensions
5
+ DISALLOWED_ALLCOPS_KEYS = [
6
+ "Include",
7
+ "Exclude",
8
+ "StyleGuideCopsOnly",
9
+ "TargetRubyVersion",
10
+
11
+ # The AllCops[Enabled] key is an unused artifact of #merge_with_default.
12
+ # See: https://github.com/rubocop/rubocop/blob/master/lib/rubocop/config_loader_resolver.rb#L81-L85
13
+ "Enabled"
14
+ ].freeze
15
+
16
+ def call(options_config, standard_config)
17
+ return unless standard_config[:extend_config]&.any?
18
+
19
+ extended_config = load_and_merge_extended_rubocop_configs(options_config, standard_config).to_h
20
+ merge_standard_and_user_all_cops!(options_config, extended_config)
21
+ merge_extended_rules_into_standard!(options_config, extended_config)
22
+ end
23
+
24
+ private
25
+
26
+ def load_and_merge_extended_rubocop_configs(options_config, standard_config)
27
+ fake_out_rubocop_default_configuration(options_config) do |fake_config|
28
+ standard_config[:extend_config].reduce(fake_config) do |config, path|
29
+ RuboCop::ConfigLoader.instance_variable_set(:@default_configuration, config)
30
+
31
+ user_rubocop_yaml_path = Standard::FileFinder.new.call(path, Dir.pwd)
32
+ extension = RuboCop::ConfigLoader.load_file(user_rubocop_yaml_path)
33
+ RuboCop::ConfigLoader.merge_with_default(extension, path)
34
+ end
35
+ end
36
+ end
37
+
38
+ def merge_standard_and_user_all_cops!(options_config, extended_config)
39
+ options_config["AllCops"].merge!(
40
+ except(extended_config["AllCops"], DISALLOWED_ALLCOPS_KEYS)
41
+ )
42
+ end
43
+
44
+ def merge_extended_rules_into_standard!(options_config, extended_config)
45
+ except(extended_config, options_config.keys).each do |key, value|
46
+ options_config[key] = value
47
+ end
48
+ end
49
+
50
+ def fake_out_rubocop_default_configuration(options_config)
51
+ og_default_config = RuboCop::ConfigLoader.instance_variable_get(:@default_configuration)
52
+ result = yield blank_rubocop_config(options_config)
53
+ RuboCop::ConfigLoader.instance_variable_set(:@default_configuration, og_default_config)
54
+ result
55
+ end
56
+
57
+ # Blank configuration object to merge extensions into, with all known
58
+ # AllCops keys set to avoid warnings about unknown properties
59
+ def blank_rubocop_config(example_config)
60
+ RuboCop::Config.new(example_config.to_h.slice("AllCops"), "")
61
+ end
62
+
63
+ def except(hash_or_config, keys)
64
+ hash_or_config.to_h.reject { |key, _| keys.include?(key) }.to_h
65
+ end
66
+ end
67
+ end
@@ -3,6 +3,7 @@ require "rubocop"
3
3
  require_relative "creates_config_store/assigns_rubocop_yaml"
4
4
  require_relative "creates_config_store/sets_target_ruby_version"
5
5
  require_relative "creates_config_store/configures_ignored_paths"
6
+ require_relative "creates_config_store/merges_user_config_extensions"
6
7
 
7
8
  module Standard
8
9
  class CreatesConfigStore
@@ -10,6 +11,7 @@ module Standard
10
11
  @assigns_rubocop_yaml = AssignsRubocopYaml.new
11
12
  @sets_target_ruby_version = SetsTargetRubyVersion.new
12
13
  @configures_ignored_paths = ConfiguresIgnoredPaths.new
14
+ @merges_user_config_extensions = MergesUserConfigExtensions.new
13
15
  end
14
16
 
15
17
  def call(standard_config)
@@ -17,6 +19,7 @@ module Standard
17
19
  options_config = @assigns_rubocop_yaml.call(config_store, standard_config)
18
20
  @sets_target_ruby_version.call(options_config, standard_config)
19
21
  @configures_ignored_paths.call(options_config, standard_config)
22
+ @merges_user_config_extensions.call(options_config, standard_config)
20
23
  end
21
24
  end
22
25
  end
@@ -1,9 +1,23 @@
1
+ require_relative "runners/rubocop"
2
+ require_relative "runners/version"
3
+ require_relative "runners/verbose_version"
4
+ require_relative "runners/lsp"
5
+ require_relative "runners/genignore"
6
+ require_relative "runners/help"
7
+
1
8
  module Standard
2
9
  class LoadsRunner
3
- # Warning: clever metaprogramming. 99% of the time this is Runners::Rubocop
10
+ RUNNERS = {
11
+ rubocop: ::Standard::Runners::Rubocop,
12
+ version: ::Standard::Runners::Version,
13
+ verbose_version: ::Standard::Runners::VerboseVersion,
14
+ lsp: ::Standard::Runners::Lsp,
15
+ genignore: ::Standard::Runners::Genignore,
16
+ help: ::Standard::Runners::Help
17
+ }.freeze
18
+
4
19
  def call(command)
5
- require_relative "runners/#{command}"
6
- ::Standard::Runners.const_get(command.to_s.capitalize).new
20
+ RUNNERS[command].new
7
21
  end
8
22
  end
9
23
  end
@@ -32,7 +32,8 @@ module Standard
32
32
  default_ignores: standard_yaml.key?("default_ignores") ? !!standard_yaml["default_ignores"] : true,
33
33
  config_root: yaml_path ? Pathname.new(yaml_path).dirname.to_s : nil,
34
34
  todo_file: todo_path,
35
- todo_ignore_files: (todo_yaml["ignore"] || []).map { |f| (Hash === f) ? f.keys.first : f }
35
+ todo_ignore_files: Array(todo_yaml["ignore"]).map { |f| (Hash === f) ? f.keys.first : f },
36
+ extend_config: Array(standard_yaml["extend_config"])
36
37
  }
37
38
  end
38
39
 
@@ -20,7 +20,7 @@ module Standard
20
20
 
21
21
  def separate_argv(argv)
22
22
  argv.partition do |flag|
23
- ["--generate-todo", "--fix", "--no-fix", "--version", "-v", "--help", "-h", "--lsp"].include?(flag)
23
+ ["--generate-todo", "--fix", "--no-fix", "--version", "-v", "--verbose-version", "-V", "--help", "-h", "--lsp"].include?(flag)
24
24
  end
25
25
  end
26
26
 
@@ -39,6 +39,8 @@ module Standard
39
39
  :help
40
40
  elsif (argv & ["--version", "-v"]).any?
41
41
  :version
42
+ elsif (argv & ["--verbose-version", "-V"]).any?
43
+ :verbose_version
42
44
  elsif (argv & ["--generate-todo"]).any?
43
45
  :genignore
44
46
  elsif (argv & ["--lsp"]).any?
@@ -15,6 +15,7 @@ module Standard
15
15
  --generate-todo Create a .standard_todo.yml that lists all the files that contain errors
16
16
  --lsp Start a LSP server listening on STDIN
17
17
  -v, --version Print the version of Standard
18
+ -V, --verbose-version Print the version of Standard and its dependencies.
18
19
  -h, --help Print this message
19
20
  FILE Files to lint [default: ./]
20
21
 
@@ -0,0 +1,14 @@
1
+ require_relative "rubocop"
2
+
3
+ module Standard
4
+ module Runners
5
+ class VerboseVersion
6
+ def call(config)
7
+ puts <<-MSG.gsub(/^ {10}/, "")
8
+ Standard version: #{Standard::VERSION}
9
+ RuboCop version: #{RuboCop::Version.version(debug: true)}
10
+ MSG
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,3 +1,3 @@
1
1
  module Standard
2
- VERSION = Gem::Version.new("1.21.1")
2
+ VERSION = Gem::Version.new("1.22.1")
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: standard
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.21.1
4
+ version: 1.22.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Searls
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-01-04 00:00:00.000000000 Z
11
+ date: 2023-01-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubocop
@@ -95,6 +95,7 @@ files:
95
95
  - lib/standard/creates_config_store.rb
96
96
  - lib/standard/creates_config_store/assigns_rubocop_yaml.rb
97
97
  - lib/standard/creates_config_store/configures_ignored_paths.rb
98
+ - lib/standard/creates_config_store/merges_user_config_extensions.rb
98
99
  - lib/standard/creates_config_store/sets_target_ruby_version.rb
99
100
  - lib/standard/detects_fixability.rb
100
101
  - lib/standard/file_finder.rb
@@ -112,6 +113,7 @@ files:
112
113
  - lib/standard/runners/help.rb
113
114
  - lib/standard/runners/lsp.rb
114
115
  - lib/standard/runners/rubocop.rb
116
+ - lib/standard/runners/verbose_version.rb
115
117
  - lib/standard/runners/version.rb
116
118
  - lib/standard/version.rb
117
119
  - standard.gemspec
@@ -133,7 +135,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
133
135
  - !ruby/object:Gem::Version
134
136
  version: '0'
135
137
  requirements: []
136
- rubygems_version: 3.3.26
138
+ rubygems_version: 3.3.7
137
139
  signing_key:
138
140
  specification_version: 4
139
141
  summary: Ruby Style Guide, with linter & automatic code fixer