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.
data/bin/console CHANGED
@@ -6,9 +6,5 @@ require "standard"
6
6
  # You can add fixtures and/or initialization code here to make experimenting
7
7
  # with your gem easier. You can also use a different console, if you like.
8
8
 
9
- # (If you use this, don't forget to add pry to your Gemfile!)
10
- # require "pry"
11
- # Pry.start
12
-
13
9
  require "irb"
14
10
  IRB.start(__FILE__)
data/bin/run ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "standard"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ Standard::Cli.new(ARGV).run
data/config/base.yml CHANGED
@@ -1,11 +1,3 @@
1
- require:
2
- - rubocop-performance
3
-
4
- AllCops:
5
- # Prevent RuboCop from exploding when it finds an older-than-2.6 .ruby-version
6
- TargetRubyVersion: 2.6
7
- Exclude: []
8
-
9
1
  Bundler/DuplicatedGem:
10
2
  Enabled: true
11
3
  Include:
@@ -936,156 +928,6 @@ Naming/VariableName:
936
928
  Naming/VariableNumber:
937
929
  Enabled: false
938
930
 
939
- Performance/AncestorsInclude:
940
- Enabled: false
941
-
942
- Performance/ArraySemiInfiniteRangeSlice:
943
- Enabled: false
944
-
945
- Performance/BigDecimalWithNumericArgument:
946
- Enabled: true
947
-
948
- Performance/BindCall:
949
- Enabled: true
950
-
951
- Performance/BlockGivenWithExplicitBlock:
952
- Enabled: true
953
-
954
- Performance/Caller:
955
- Enabled: true
956
-
957
- Performance/CaseWhenSplat:
958
- Enabled: false
959
-
960
- Performance/Casecmp:
961
- Enabled: false
962
-
963
- Performance/ChainArrayAllocation:
964
- Enabled: false
965
-
966
- Performance/CollectionLiteralInLoop:
967
- Enabled: false
968
-
969
- Performance/CompareWithBlock:
970
- Enabled: true
971
-
972
- Performance/ConcurrentMonotonicTime:
973
- Enabled: true
974
-
975
- Performance/ConstantRegexp:
976
- Enabled: true
977
-
978
- Performance/Count:
979
- Enabled: true
980
-
981
- Performance/DeletePrefix:
982
- Enabled: false
983
-
984
- Performance/DeleteSuffix:
985
- Enabled: false
986
-
987
- Performance/Detect:
988
- Enabled: true
989
-
990
- Performance/DoubleStartEndWith:
991
- Enabled: true
992
- IncludeActiveSupportAliases: false
993
-
994
- Performance/EndWith:
995
- Enabled: true
996
-
997
- Performance/FixedSize:
998
- Enabled: true
999
-
1000
- Performance/FlatMap:
1001
- Enabled: true
1002
- EnabledForFlattenWithoutParams: false
1003
-
1004
- Performance/InefficientHashSearch:
1005
- Enabled: true
1006
-
1007
- Performance/IoReadlines:
1008
- Enabled: false
1009
-
1010
- Performance/MapCompact:
1011
- Enabled: false
1012
-
1013
- Performance/MethodObjectAsBlock:
1014
- Enabled: false
1015
-
1016
- Performance/OpenStruct:
1017
- Enabled: false
1018
-
1019
- Performance/RangeInclude:
1020
- Enabled: true
1021
-
1022
- Performance/RedundantBlockCall:
1023
- Enabled: false
1024
-
1025
- Performance/RedundantEqualityComparisonBlock:
1026
- Enabled: false
1027
-
1028
- Performance/RedundantMatch:
1029
- Enabled: true
1030
-
1031
- Performance/RedundantMerge:
1032
- Enabled: true
1033
- MaxKeyValuePairs: 2
1034
-
1035
- Performance/RedundantSortBlock:
1036
- Enabled: true
1037
-
1038
- Performance/RedundantSplitRegexpArgument:
1039
- Enabled: true
1040
-
1041
- Performance/RedundantStringChars:
1042
- Enabled: true
1043
-
1044
- Performance/RegexpMatch:
1045
- Enabled: true
1046
-
1047
- Performance/ReverseEach:
1048
- Enabled: true
1049
-
1050
- Performance/ReverseFirst:
1051
- Enabled: true
1052
-
1053
- Performance/SelectMap:
1054
- Enabled: false
1055
-
1056
- Performance/Size:
1057
- Enabled: true
1058
-
1059
- Performance/SortReverse:
1060
- Enabled: true
1061
-
1062
- Performance/Squeeze:
1063
- Enabled: true
1064
-
1065
- Performance/StartWith:
1066
- Enabled: true
1067
-
1068
- Performance/StringIdentifierArgument:
1069
- Enabled: true
1070
-
1071
- Performance/StringInclude:
1072
- Enabled: false
1073
-
1074
- Performance/StringReplacement:
1075
- Enabled: true
1076
-
1077
- Performance/Sum:
1078
- Enabled: false
1079
-
1080
- Performance/TimesMap:
1081
- Enabled: false
1082
-
1083
- Performance/UnfreezeString:
1084
- Enabled: true
1085
-
1086
- Performance/UriDefaultParser:
1087
- Enabled: true
1088
-
1089
931
  Security/CompoundHash:
1090
932
  Enabled: true
1091
933
 
@@ -1107,9 +949,6 @@ Security/Open:
1107
949
  Security/YAMLLoad:
1108
950
  Enabled: true
1109
951
 
1110
- Standard/BlockSingleLineBraces:
1111
- Enabled: true
1112
-
1113
952
  Style/AccessModifierDeclarations:
1114
953
  Enabled: false
1115
954
 
@@ -0,0 +1,9 @@
1
+ AllCops:
2
+ # Prevent RuboCop from exploding when it finds an older-than-2.6 .ruby-version
3
+ TargetRubyVersion: 2.6
4
+ Exclude: []
5
+ DisabledByDefault: true
6
+ StyleGuideBaseURL: https://github.com/standardrb/standard
7
+
8
+ Lint/Syntax:
9
+ Enabled: true
data/config/ruby-2.2.yml CHANGED
@@ -9,8 +9,5 @@ AllCops:
9
9
  Layout/HeredocIndentation:
10
10
  Enabled: false
11
11
 
12
- Performance/ConcurrentMonotonicTime:
13
- Enabled: false
14
-
15
12
  Style/SafeNavigation:
16
13
  Enabled: false
@@ -0,0 +1,31 @@
1
+ # Standard Ruby's Architecture
2
+
3
+ Architecture is not a 4-letter word (but the silly abbreviation 'a10e' is!), so
4
+ as Standard's internal structure has introduced more moving parts, it's
5
+ important to plant a stake in the ground and explain where all the cops are
6
+ buried.
7
+
8
+ Starting with version 1.28.0, Standard Ruby introduced plugin support and
9
+ refactored how it loads its own rules from one large YAML file into several
10
+ plugins. As a result, what was a single `standard` gem is now spread across 3
11
+ gems. Here's how it's all organized:
12
+
13
+ * [standard](https://github.com/standardrb/standard) - The main gem. The one
14
+ people install and think of. Because `standard` has a hard dependency on `rubocop`,
15
+ the base configuration of RuboCop's built-in rules is bundled into the gem, even
16
+ though it's now [defined as a plugin](lib/standard/base/plugin.rb)
17
+ * [standard-performance](https://github.com/standardrb/standard-performance) - A
18
+ plugin that depends on and configures
19
+ [rubocop-performance](https://github.com/rubocop/rubocop-performance)
20
+ * [standard-custom](https://github.com/standardrb/standard-custom) - A plugin
21
+ that implements and configures any custom rules that the Standard team writes
22
+ and maintains itself with the intention that they be part of the default
23
+ Standard Ruby experience (there's only one of these rules so far)
24
+
25
+ To glue these things together, yet another gem was created (gems are free,
26
+ right?) to define a very simple plugin API. That gem is called
27
+ [lint_roller](https://github.com/standardrb/lint_roller) and it can be used by
28
+ any gem that provides or consumes linting and formatting rules. Because Standard
29
+ Ruby is built on RuboCop's configuration and runner, RuboCop could adopt
30
+ `lint_roller` as its plugin system and plugins could support both `rubocop`
31
+ and `standard` out of the box.
@@ -0,0 +1,65 @@
1
+ module Standard::Base
2
+ class Plugin < LintRoller::Plugin
3
+ def initialize(config)
4
+ @config = config
5
+ end
6
+
7
+ def about
8
+ LintRoller::About.new(
9
+ name: "standard-base",
10
+ version: VERSION,
11
+ homepage: "https://github.com/standardrb/standard",
12
+ description: "Configuration for RuboCop's built-in rules"
13
+ )
14
+ end
15
+
16
+ def supported?(context)
17
+ true
18
+ end
19
+
20
+ def rules(context)
21
+ LintRoller::Rules.new(
22
+ type: :path,
23
+ config_format: :rubocop,
24
+ value: determine_yaml_path(context.target_ruby_version)
25
+ )
26
+ end
27
+
28
+ private
29
+
30
+ def determine_yaml_path(desired_version)
31
+ desired_version = Gem::Version.new(desired_version) unless desired_version.is_a?(Gem::Version)
32
+ default = "base.yml"
33
+
34
+ file_name = if !Gem::Version.correct?(desired_version)
35
+ default
36
+ elsif desired_version < Gem::Version.new("1.9")
37
+ "ruby-1.8.yml"
38
+ elsif desired_version < Gem::Version.new("2.0")
39
+ "ruby-1.9.yml"
40
+ elsif desired_version < Gem::Version.new("2.1")
41
+ "ruby-2.0.yml"
42
+ elsif desired_version < Gem::Version.new("2.2")
43
+ "ruby-2.1.yml"
44
+ elsif desired_version < Gem::Version.new("2.3")
45
+ "ruby-2.2.yml"
46
+ elsif desired_version < Gem::Version.new("2.4")
47
+ "ruby-2.3.yml"
48
+ elsif desired_version < Gem::Version.new("2.5")
49
+ "ruby-2.4.yml"
50
+ elsif desired_version < Gem::Version.new("2.6")
51
+ "ruby-2.5.yml"
52
+ elsif desired_version < Gem::Version.new("3.0")
53
+ "ruby-2.7.yml"
54
+ elsif desired_version < Gem::Version.new("3.1")
55
+ "ruby-3.0.yml"
56
+ elsif desired_version < Gem::Version.new("3.2")
57
+ "ruby-3.1.yml"
58
+ else
59
+ default
60
+ end
61
+
62
+ Pathname.new(__dir__).join("../../../config/#{file_name}")
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,8 @@
1
+ require "lint_roller"
2
+
3
+ require_relative "base/plugin"
4
+
5
+ module Standard
6
+ module Base
7
+ end
8
+ end
@@ -3,42 +3,8 @@ require "pathname"
3
3
  class Standard::CreatesConfigStore
4
4
  class AssignsRubocopYaml
5
5
  def call(config_store, standard_config)
6
- config_store.options_config = rubocop_yaml_path(standard_config[:ruby_version])
6
+ config_store.options_config = Pathname.new(__dir__).join("../../../config/default.yml")
7
7
  config_store.instance_variable_get(:@options_config)
8
8
  end
9
-
10
- private
11
-
12
- def rubocop_yaml_path(desired_version)
13
- default = "base.yml"
14
-
15
- file_name = if !Gem::Version.correct?(desired_version)
16
- default
17
- elsif desired_version < Gem::Version.new("1.9")
18
- "ruby-1.8.yml"
19
- elsif desired_version < Gem::Version.new("2.0")
20
- "ruby-1.9.yml"
21
- elsif desired_version < Gem::Version.new("2.1")
22
- "ruby-2.0.yml"
23
- elsif desired_version < Gem::Version.new("2.2")
24
- "ruby-2.1.yml"
25
- elsif desired_version < Gem::Version.new("2.3")
26
- "ruby-2.2.yml"
27
- elsif desired_version < Gem::Version.new("2.4")
28
- "ruby-2.3.yml"
29
- elsif desired_version < Gem::Version.new("2.5")
30
- "ruby-2.4.yml"
31
- elsif desired_version < Gem::Version.new("2.6")
32
- "ruby-2.5.yml"
33
- elsif desired_version < Gem::Version.new("3.0")
34
- "ruby-2.7.yml"
35
- elsif desired_version < Gem::Version.new("3.1")
36
- "ruby-3.0.yml"
37
- else
38
- default
39
- end
40
-
41
- Pathname.new(__dir__).join("../../../config/#{file_name}")
42
- end
43
9
  end
44
10
  end
@@ -1,67 +1,37 @@
1
1
  require_relative "../file_finder"
2
+ require_relative "../plugin"
2
3
 
3
4
  class Standard::CreatesConfigStore
4
5
  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
6
+ class ExtendConfigPlugin < LintRoller::Plugin
7
+ def initialize(path)
8
+ @yaml_path = Standard::FileFinder.new.call(path, Dir.pwd)
35
9
  end
36
- end
37
10
 
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
11
+ def about
12
+ About.new("Pseudo-plugin wrapping the `extend_config' path: #{@yaml_path}")
13
+ end
43
14
 
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
15
+ def rules(context)
16
+ LintRoller::Rules.new(
17
+ type: :path,
18
+ config_format: :rubocop,
19
+ value: @yaml_path
20
+ )
47
21
  end
48
22
  end
49
23
 
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
24
+ def initialize
25
+ @merges_plugins_into_rubocop_config = Standard::Plugin::MergesPluginsIntoRubocopConfig.new
55
26
  end
56
27
 
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
28
+ def call(options_config, standard_config)
29
+ return unless standard_config[:extend_config]&.any?
62
30
 
63
- def except(hash_or_config, keys)
64
- hash_or_config.to_h.reject { |key, _| keys.include?(key) }.to_h
31
+ plugins = standard_config[:extend_config].map { |path|
32
+ ExtendConfigPlugin.new(path)
33
+ }
34
+ @merges_plugins_into_rubocop_config.call(options_config, standard_config, plugins, permit_merging: false)
65
35
  end
66
36
  end
67
37
  end
@@ -11,6 +11,7 @@ module Standard
11
11
  @assigns_rubocop_yaml = AssignsRubocopYaml.new
12
12
  @sets_target_ruby_version = SetsTargetRubyVersion.new
13
13
  @configures_ignored_paths = ConfiguresIgnoredPaths.new
14
+ @combines_plugin_configs = Plugin::CombinesPluginConfigs.new
14
15
  @merges_user_config_extensions = MergesUserConfigExtensions.new
15
16
  end
16
17
 
@@ -19,6 +20,7 @@ module Standard
19
20
  options_config = @assigns_rubocop_yaml.call(config_store, standard_config)
20
21
  @sets_target_ruby_version.call(options_config, standard_config)
21
22
  @configures_ignored_paths.call(options_config, standard_config)
23
+ @combines_plugin_configs.call(options_config, standard_config)
22
24
  @merges_user_config_extensions.call(options_config, standard_config)
23
25
  end
24
26
  end
@@ -4,7 +4,7 @@ require "rubocop"
4
4
  module Standard
5
5
  class Formatter < RuboCop::Formatter::BaseFormatter
6
6
  STANDARD_GREETING = <<~MSG
7
- standard: Use Ruby Standard Style (https://github.com/testdouble/standard)
7
+ standard: Use Ruby Standard Style (https://github.com/standardrb/standard)
8
8
  MSG
9
9
 
10
10
  def started(_target_files)
@@ -33,6 +33,7 @@ module Standard
33
33
  config_root: yaml_path ? Pathname.new(yaml_path).dirname.to_s : nil,
34
34
  todo_file: todo_path,
35
35
  todo_ignore_files: Array(todo_yaml["ignore"]).map { |f| (Hash === f) ? f.keys.first : f },
36
+ plugins: Array(standard_yaml["plugins"]),
36
37
  extend_config: Array(standard_yaml["extend_config"])
37
38
  }
38
39
  end
@@ -0,0 +1,15 @@
1
+ module Standard
2
+ module Plugin
3
+ class CombinesPluginConfigs
4
+ def initialize
5
+ @initializes_plugins = InitializesPlugins.new
6
+ @merges_plugins_into_rubocop_config = MergesPluginsIntoRubocopConfig.new
7
+ end
8
+
9
+ def call(options_config, standard_config)
10
+ plugins = @initializes_plugins.call(standard_config[:plugins])
11
+ @merges_plugins_into_rubocop_config.call(options_config, standard_config, plugins, permit_merging: true)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module Standard
2
+ module Plugin
3
+ class CreatesRunnerContext
4
+ def call(standard_config)
5
+ LintRoller::Context.new(
6
+ runner: :standard,
7
+ runner_version: Standard::VERSION,
8
+ engine: :rubocop,
9
+ engine_version: RuboCop::Version.version,
10
+ target_ruby_version: standard_config[:ruby_version]
11
+ )
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,56 @@
1
+ module Standard
2
+ module Plugin
3
+ class DeterminesClassConstant
4
+ def call(plugin_name, user_config)
5
+ require_plugin(user_config["require_path"])
6
+
7
+ if (constant_name = user_config["plugin_class_name"])
8
+ begin
9
+ Kernel.const_get(constant_name)
10
+ rescue
11
+ raise "Failed while configuring plugin `#{plugin_name}': no constant with name `#{constant_name}' was found"
12
+ end
13
+ else
14
+ begin
15
+ Kernel.const_get(Gem.loaded_specs[plugin_name].metadata["default_lint_roller_plugin"])
16
+ rescue LoadError, StandardError
17
+ raise <<~MSG
18
+ Failed loading plugin `#{plugin_name}' because we couldn't determine
19
+ the corresponding plugin class to instantiate.
20
+
21
+ Standard plugin class names must either be:
22
+
23
+ - If the plugin is a gem, defined in the gemspec as `default_lint_roller_plugin'
24
+
25
+ spec.metadata["default_lint_roller_plugin"] = "MyModule::Plugin"
26
+
27
+ - Set in YAML as `plugin_class_name'; example:
28
+
29
+ plugins:
30
+ - incomplete:
31
+ require_path: my_module/plugin
32
+ plugin_class_name: "MyModule::Plugin"
33
+ MSG
34
+ end
35
+
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ def require_plugin(require_path)
42
+ return if require_path.nil?
43
+
44
+ begin
45
+ require require_path
46
+ rescue LoadError
47
+ # If require_path isn't on the load_path (and it may be hard to get it
48
+ # on there since standardrb is a cli), let's give folks a break and
49
+ # also try to load it via the current working directory. This is
50
+ # tested in test/standardrb_test.rb #test_plugins_options
51
+ require Pathname.new(Dir.pwd).join(require_path)
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,23 @@
1
+ module Standard
2
+ module Plugin
3
+ class InitializesPlugins
4
+ def initialize
5
+ @standardizes_configured_plugins = StandardizesConfiguredPlugins.new
6
+ @determines_class_constants = DeterminesClassConstant.new
7
+ end
8
+
9
+ def call(plugins)
10
+ plugin_configs = @standardizes_configured_plugins.call(plugins)
11
+ plugin_configs.map { |name_or_class, user_config|
12
+ if user_config["enabled"]
13
+ if name_or_class.is_a?(String) || name_or_class.is_a?(Symbol)
14
+ @determines_class_constants.call(name_or_class, user_config).new(user_config)
15
+ else
16
+ name_or_class.new(user_config)
17
+ end
18
+ end
19
+ }
20
+ end
21
+ end
22
+ end
23
+ end