standard 1.27.0 → 1.28.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.
@@ -0,0 +1,158 @@
1
+ module Standard
2
+ module Plugin
3
+ class MergesPluginsIntoRubocopConfig
4
+ # Blank configuration object to merge plugins into, with only the following spared:
5
+ # - AllCops keys set to avoid warnings about unknown properties
6
+ # - Lint/Syntax must be set to avoid a nil error when verifying inherited configs
7
+ MANDATORY_RUBOCOP_CONFIG_KEYS = ["AllCops", "Lint/Syntax"].freeze
8
+
9
+ # AllCops keys that standard does not allow to be set by plugins
10
+ DISALLOWED_ALLCOPS_KEYS = [
11
+ "Include",
12
+ "Exclude",
13
+ "StyleGuideBaseURL",
14
+ "StyleGuideCopsOnly",
15
+ "TargetRubyVersion",
16
+ "EnabledByDefault",
17
+ "DisabledByDefault",
18
+
19
+ # The AllCops[Enabled] key is an unused artifact of #merge_with_default.
20
+ # See: https://github.com/rubocop/rubocop/blob/master/lib/rubocop/config_loader_resolver.rb#L81-L85
21
+ "Enabled"
22
+ ].freeze
23
+
24
+ def initialize
25
+ @creates_runner_context = Standard::Plugin::CreatesRunnerContext.new
26
+ end
27
+
28
+ def call(options_config, standard_config, plugins, permit_merging:)
29
+ runner_context = @creates_runner_context.call(standard_config)
30
+ plugin_config = combine_rubocop_configs(options_config, runner_context, plugins).to_h
31
+ merge_config_into_all_cops!(options_config, plugin_config)
32
+ merge_config_into_standard!(options_config, plugin_config, permit_merging: permit_merging)
33
+ end
34
+
35
+ private
36
+
37
+ def combine_rubocop_configs(options_config, runner_context, plugins)
38
+ fake_out_rubocop_default_configuration(options_config) do |fake_config|
39
+ all_cop_keys_configured_by_plugins = []
40
+
41
+ plugins.reduce(fake_config) do |combined_config, plugin|
42
+ RuboCop::ConfigLoader.instance_variable_set(:@default_configuration, combined_config)
43
+ next_config, path = config_for_plugin(plugin, runner_context)
44
+
45
+ next_config["AllCops"], all_cop_keys_configured_by_plugins = merge_all_cop_settings(
46
+ combined_config["AllCops"],
47
+ next_config["AllCops"],
48
+ all_cop_keys_configured_by_plugins
49
+ )
50
+ delete_already_configured_keys!(combined_config.keys, next_config, dont_delete_keys: ["AllCops"])
51
+
52
+ RuboCop::ConfigLoader.merge_with_default(next_config, path)
53
+ end
54
+ end
55
+ end
56
+
57
+ def config_for_plugin(plugin, runner_context)
58
+ rules = plugin.rules(runner_context)
59
+
60
+ if rules.type == :path
61
+ [RuboCop::ConfigLoader.load_file(rules.value), rules.value]
62
+ elsif rules.type == :object
63
+ [RuboCop::Config.new(rules.value), nil]
64
+ elsif rules.type == :error
65
+ raise "Plugin `#{plugin.about&.name || plugin.inspect}' failed to load with error: #{rules.value.respond_to?(:message) ? rules.value.message : rules.value}"
66
+ end
67
+ end
68
+
69
+ # This is how we ensure "first-in wins": plugins can override AllCops settings that are
70
+ # set by RuboCop's default configuration, but once a plugin sets an AllCop setting, they
71
+ # have exclusive first-in-wins rights to that setting.
72
+ #
73
+ # The one exception to this are array fields, because we don't want to
74
+ # overwrite the AllCops defaults but rather munge the arrays (`existing |
75
+ # new`) to allow plugins to add to the array, for example Include and
76
+ # Exclude paths and patterns.
77
+ def merge_all_cop_settings(existing_all_cops, new_all_cops, already_configured_keys)
78
+ return [existing_all_cops, already_configured_keys] unless new_all_cops.is_a?(Hash)
79
+
80
+ combined_all_cops = existing_all_cops.dup
81
+ combined_configured_keys = already_configured_keys.dup
82
+
83
+ new_all_cops.each do |key, value|
84
+ if combined_all_cops[key].is_a?(Array) && value.is_a?(Array)
85
+ combined_all_cops[key] |= value
86
+ combined_configured_keys |= [key]
87
+ elsif !combined_configured_keys.include?(key)
88
+ combined_all_cops[key] = value
89
+ combined_configured_keys << key
90
+ end
91
+ end
92
+
93
+ [combined_all_cops, combined_configured_keys]
94
+ end
95
+
96
+ def delete_already_configured_keys!(configured_keys, next_config, dont_delete_keys: [])
97
+ duplicate_keys = configured_keys & Array(next_config&.keys)
98
+
99
+ (duplicate_keys - dont_delete_keys).each do |key|
100
+ next_config.delete(key)
101
+ end
102
+ end
103
+
104
+ def merge_config_into_all_cops!(options_config, plugin_config)
105
+ options_config["AllCops"].merge!(
106
+ except(plugin_config["AllCops"], DISALLOWED_ALLCOPS_KEYS)
107
+ )
108
+ end
109
+
110
+ def merge_config_into_standard!(options_config, plugin_config, permit_merging:)
111
+ if permit_merging
112
+ plugin_config.each do |key, value|
113
+ options_config[key] = if options_config[key].is_a?(Hash)
114
+ merge(options_config[key], value)
115
+ else
116
+ value
117
+ end
118
+ end
119
+ else
120
+ except(plugin_config, options_config.keys).each do |key, value|
121
+ options_config[key] = value
122
+ end
123
+ end
124
+ end
125
+
126
+ def fake_out_rubocop_default_configuration(options_config)
127
+ og_default_config = RuboCop::ConfigLoader.instance_variable_get(:@default_configuration)
128
+ result = yield blank_rubocop_config(options_config)
129
+ RuboCop::ConfigLoader.instance_variable_set(:@default_configuration, og_default_config)
130
+ result
131
+ end
132
+
133
+ def blank_rubocop_config(example_config)
134
+ RuboCop::Config.new(example_config.to_h.slice(*MANDATORY_RUBOCOP_CONFIG_KEYS), "")
135
+ end
136
+
137
+ def except(hash_or_config, keys)
138
+ hash_or_config.to_h.reject { |key, _| keys.include?(key) }.to_h
139
+ end
140
+
141
+ # Always deletes nil entries, always overwrites arrays
142
+ # This is a simplified version of rubocop's ConfigLoader#merge:
143
+ # https://github.com/rubocop/rubocop/blob/v1.48.1/lib/rubocop/config_loader_resolver.rb#L98
144
+ def merge(old_hash, new_hash)
145
+ result = old_hash.merge(new_hash)
146
+ keys_appearing_in_both = old_hash.keys & new_hash.keys
147
+ keys_appearing_in_both.each do |key|
148
+ if new_hash[key].nil?
149
+ result.delete(key)
150
+ elsif old_hash[key].is_a?(Hash) && new_hash[key].is_a?(Hash)
151
+ result[key] = merge(old_hash[key], new_hash[key])
152
+ end
153
+ end
154
+ result
155
+ end
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,37 @@
1
+ module Standard
2
+ module Plugin
3
+ class StandardizesConfiguredPlugins
4
+ DEFAULT_PLUGIN_CONFIG = {
5
+ "enabled" => true,
6
+ "require_path" => nil, # If not set, will be set to the plugin name
7
+ "plugin_class_name" => nil # If not set, looks for gemspec `spec.metadata["default_lint_roller_plugin"]`
8
+ }.freeze
9
+
10
+ BUILT_INS = [
11
+ {"standard-base" => {
12
+ "require_path" => "standard/base",
13
+ "plugin_class_name" => "Standard::Base::Plugin"
14
+ }},
15
+ "standard-custom",
16
+ "standard-performance"
17
+ ].freeze
18
+
19
+ def call(plugins)
20
+ normalize_config_shape(BUILT_INS + plugins)
21
+ end
22
+
23
+ private
24
+
25
+ def normalize_config_shape(plugins)
26
+ plugins.map { |plugin|
27
+ if plugin.is_a?(Hash)
28
+ plugin_name = plugin.keys.first
29
+ [plugin_name, DEFAULT_PLUGIN_CONFIG.merge({"require_path" => plugin_name}, plugin.values.first)]
30
+ else
31
+ [plugin, DEFAULT_PLUGIN_CONFIG.merge("require_path" => plugin)]
32
+ end
33
+ }.to_h
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,11 @@
1
+ module Standard
2
+ module Plugin
3
+ end
4
+ end
5
+
6
+ require_relative "plugin/creates_runner_context"
7
+ require_relative "plugin/combines_plugin_configs"
8
+ require_relative "plugin/merges_plugins_into_rubocop_config"
9
+ require_relative "plugin/standardizes_configured_plugins"
10
+ require_relative "plugin/determines_class_constant"
11
+ require_relative "plugin/initializes_plugins"
@@ -1,7 +1,7 @@
1
1
  require "pathname"
2
2
 
3
3
  module Standard
4
- class Railtie < Rails::Railtie
4
+ class Railtie < ::Rails::Railtie
5
5
  railtie_name :standard
6
6
 
7
7
  rake_tasks do
@@ -27,7 +27,7 @@ module Standard
27
27
  While Standard only offers a few configuration options, most can be set in
28
28
  a `.standard.yml` file. For full documentation, please visit:
29
29
 
30
- https://github.com/testdouble/standard
30
+ https://github.com/standardrb/standard
31
31
 
32
32
  Having trouble? Here's some diagnostic information:
33
33
 
@@ -39,7 +39,7 @@ module Standard
39
39
 
40
40
  Please report any problems (and include the above information) at the URL below:
41
41
 
42
- https://github.com/testdouble/standard/issues/new
42
+ https://github.com/standardrb/standard/issues/new
43
43
 
44
44
  MESSAGE
45
45
  end
@@ -19,7 +19,7 @@ module Standard
19
19
 
20
20
  # This is a workaround for an issue with how `parallel` and `stdin`
21
21
  # interact when invoked in this way. See:
22
- # https://github.com/testdouble/standard/issues/536
22
+ # https://github.com/standardrb/standard/issues/536
23
23
  def without_parallelizing_in_stdin_mode(options)
24
24
  if options[:stdin]
25
25
  options.delete(:parallel)
@@ -1,3 +1,3 @@
1
1
  module Standard
2
- VERSION = Gem::Version.new("1.27.0")
2
+ VERSION = Gem::Version.new("1.28.0")
3
3
  end
data/lib/standard.rb CHANGED
@@ -1,4 +1,8 @@
1
1
  require "rubocop"
2
+ require "lint_roller"
3
+
4
+ module Standard
5
+ end
2
6
 
3
7
  require "standard/rubocop/ext"
4
8
 
@@ -9,5 +13,4 @@ require "standard/railtie" if defined?(Rails) && defined?(Rails::Railtie)
9
13
  require "standard/formatter"
10
14
  require "standard/cop/block_single_line_braces"
11
15
 
12
- module Standard
13
- end
16
+ require "standard/plugin"
data/standard.gemspec CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
10
10
  spec.required_ruby_version = ">= 2.6.0"
11
11
 
12
12
  spec.summary = "Ruby Style Guide, with linter & automatic code fixer"
13
- spec.homepage = "https://github.com/testdouble/standard"
13
+ spec.homepage = "https://github.com/standardrb/standard"
14
14
  spec.metadata["homepage_uri"] = spec.homepage
15
15
  spec.metadata["source_code_uri"] = spec.homepage
16
16
  spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/main/CHANGELOG.md"
@@ -24,7 +24,10 @@ Gem::Specification.new do |spec|
24
24
  spec.metadata["rubygems_mfa_required"] = "true"
25
25
 
26
26
  spec.add_dependency "rubocop", "~> 1.50.2"
27
- spec.add_dependency "rubocop-performance", "~> 1.16.0"
27
+
28
+ spec.add_dependency "lint_roller", "~> 1.0"
29
+ spec.add_dependency "standard-custom", "~> 1.0.0"
30
+ spec.add_dependency "standard-performance", "~> 1.0.1"
28
31
 
29
32
  # not semver: first three are lsp protocol version, last is patch
30
33
  spec.add_dependency "language_server-protocol", "~> 3.17.0.2"
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.27.0
4
+ version: 1.28.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Searls
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-04-19 00:00:00.000000000 Z
11
+ date: 2023-04-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubocop
@@ -25,19 +25,47 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: 1.50.2
27
27
  - !ruby/object:Gem::Dependency
28
- name: rubocop-performance
28
+ name: lint_roller
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 1.16.0
33
+ version: '1.0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 1.16.0
40
+ version: '1.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: standard-custom
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 1.0.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 1.0.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: standard-performance
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 1.0.1
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 1.0.1
41
69
  - !ruby/object:Gem::Dependency
42
70
  name: language_server-protocol
43
71
  requirement: !ruby/object:Gem::Requirement
@@ -52,7 +80,7 @@ dependencies:
52
80
  - - "~>"
53
81
  - !ruby/object:Gem::Version
54
82
  version: 3.17.0.2
55
- description:
83
+ description:
56
84
  email:
57
85
  - searls@gmail.com
58
86
  executables:
@@ -72,8 +100,10 @@ files:
72
100
  - README.md
73
101
  - Rakefile
74
102
  - bin/console
103
+ - bin/run
75
104
  - bin/setup
76
105
  - config/base.yml
106
+ - config/default.yml
77
107
  - config/ruby-1.8.yml
78
108
  - config/ruby-1.9.yml
79
109
  - config/ruby-2.0.yml
@@ -86,13 +116,15 @@ files:
86
116
  - config/ruby-2.7.yml
87
117
  - config/ruby-3.0.yml
88
118
  - config/ruby-3.1.yml
119
+ - docs/ARCHITECTURE.md
89
120
  - docs/NEW_RUBIES.md
90
121
  - docs/RELEASE.md
91
122
  - exe/standardrb
92
123
  - lib/standard.rb
124
+ - lib/standard/base.rb
125
+ - lib/standard/base/plugin.rb
93
126
  - lib/standard/builds_config.rb
94
127
  - lib/standard/cli.rb
95
- - lib/standard/cop/block_single_line_braces.rb
96
128
  - lib/standard/creates_config_store.rb
97
129
  - lib/standard/creates_config_store/assigns_rubocop_yaml.rb
98
130
  - lib/standard/creates_config_store/configures_ignored_paths.rb
@@ -108,6 +140,13 @@ files:
108
140
  - lib/standard/lsp/server.rb
109
141
  - lib/standard/lsp/standardizer.rb
110
142
  - lib/standard/merges_settings.rb
143
+ - lib/standard/plugin.rb
144
+ - lib/standard/plugin/combines_plugin_configs.rb
145
+ - lib/standard/plugin/creates_runner_context.rb
146
+ - lib/standard/plugin/determines_class_constant.rb
147
+ - lib/standard/plugin/initializes_plugins.rb
148
+ - lib/standard/plugin/merges_plugins_into_rubocop_config.rb
149
+ - lib/standard/plugin/standardizes_configured_plugins.rb
111
150
  - lib/standard/railtie.rb
112
151
  - lib/standard/rake.rb
113
152
  - lib/standard/resolves_yaml_option.rb
@@ -120,14 +159,14 @@ files:
120
159
  - lib/standard/runners/version.rb
121
160
  - lib/standard/version.rb
122
161
  - standard.gemspec
123
- homepage: https://github.com/testdouble/standard
162
+ homepage: https://github.com/standardrb/standard
124
163
  licenses: []
125
164
  metadata:
126
- homepage_uri: https://github.com/testdouble/standard
127
- source_code_uri: https://github.com/testdouble/standard
128
- changelog_uri: https://github.com/testdouble/standard/blob/main/CHANGELOG.md
165
+ homepage_uri: https://github.com/standardrb/standard
166
+ source_code_uri: https://github.com/standardrb/standard
167
+ changelog_uri: https://github.com/standardrb/standard/blob/main/CHANGELOG.md
129
168
  rubygems_mfa_required: 'true'
130
- post_install_message:
169
+ post_install_message:
131
170
  rdoc_options: []
132
171
  require_paths:
133
172
  - lib
@@ -142,8 +181,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
142
181
  - !ruby/object:Gem::Version
143
182
  version: '0'
144
183
  requirements: []
145
- rubygems_version: 3.1.6
146
- signing_key:
184
+ rubygems_version: 3.4.10
185
+ signing_key:
147
186
  specification_version: 4
148
187
  summary: Ruby Style Guide, with linter & automatic code fixer
149
188
  test_files: []
@@ -1,96 +0,0 @@
1
- module RuboCop::Cop
2
- module Standard
3
- # Check for uses of braces around single line blocks, but allows either
4
- # braces or do/end for multi-line blocks.
5
- #
6
- # @example
7
- # # bad - single line block
8
- # items.each do |item| item / 5 end
9
- #
10
- # # good - single line block
11
- # items.each { |item| item / 5 }
12
- #
13
- class BlockSingleLineBraces < RuboCop::Cop::Base
14
- extend RuboCop::Cop::AutoCorrector
15
-
16
- def on_send(node)
17
- return unless node.arguments?
18
- return if node.parenthesized?
19
- return if node.operator_method? || node.assignment_method?
20
-
21
- node.arguments.each do |arg|
22
- get_blocks(arg) do |block|
23
- # If there are no parentheses around the arguments, then braces
24
- # and do-end have different meaning due to how they bind, so we
25
- # allow either.
26
- ignore_node(block)
27
- end
28
- end
29
- end
30
-
31
- def on_block(node)
32
- return if ignored_node?(node)
33
- return if proper_block_style?(node)
34
-
35
- message = message(node)
36
- add_offense(node.loc.begin, message: message) do |corrector|
37
- autocorrect(corrector, node)
38
- end
39
- end
40
-
41
- private
42
-
43
- def get_blocks(node, &block)
44
- case node.type
45
- when :block
46
- yield node
47
- when :send
48
- get_blocks(node.receiver, &block) if node.receiver
49
- when :hash
50
- # A hash which is passed as method argument may have no braces
51
- # In that case, one of the K/V pairs could contain a block node
52
- # which could change in meaning if do...end replaced {...}
53
- return if node.braces?
54
-
55
- node.each_child_node { |child| get_blocks(child, &block) }
56
- when :pair
57
- node.each_child_node { |child| get_blocks(child, &block) }
58
- end
59
- end
60
-
61
- def proper_block_style?(node)
62
- node.multiline? || node.braces?
63
- end
64
-
65
- def message(node)
66
- "Prefer `{...}` over `do...end` for single-line blocks."
67
- end
68
-
69
- def autocorrect(corrector, node)
70
- return if correction_would_break_code?(node)
71
-
72
- replace_do_end_with_braces(corrector, node.loc)
73
- end
74
-
75
- def correction_would_break_code?(node)
76
- return unless node.keywords?
77
-
78
- node.send_node.arguments? && !node.send_node.parenthesized?
79
- end
80
-
81
- def replace_do_end_with_braces(corrector, loc)
82
- b = loc.begin
83
- e = loc.end
84
-
85
- corrector.insert_after(b, " ") unless whitespace_after?(b, 2)
86
-
87
- corrector.replace(b, "{")
88
- corrector.replace(e, "}")
89
- end
90
-
91
- def whitespace_after?(range, length = 1)
92
- /\s/.match?(range.source_buffer.source[range.begin_pos + length, 1])
93
- end
94
- end
95
- end
96
- end