standard 1.27.0 → 1.28.0

Sign up to get free protection for your applications and to get access to all the features.
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