standard 1.21.1 → 1.22.1

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: 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