mirror of
https://github.com/Homebrew/brew.git
synced 2025-07-14 16:09:03 +08:00
Fix violations
This commit is contained in:
parent
c354377f3e
commit
eeb31d3050
@ -10,14 +10,10 @@ class PATH
|
||||
|
||||
delegate each: :@paths
|
||||
|
||||
# FIXME: Enable cop again when https://github.com/sorbet/sorbet/issues/3532 is fixed.
|
||||
# rubocop:disable Style/MutableConstant
|
||||
Element = T.type_alias { T.nilable(T.any(Pathname, String, PATH)) }
|
||||
private_constant :Element
|
||||
Elements = T.type_alias { T.any(Element, T::Array[Element]) }
|
||||
private_constant :Elements
|
||||
# rubocop:enable Style/MutableConstant
|
||||
|
||||
sig { params(paths: Elements).void }
|
||||
def initialize(*paths)
|
||||
@paths = parse(paths)
|
||||
|
@ -10,11 +10,7 @@ module Cask
|
||||
|
||||
requires_ancestor { Kernel }
|
||||
|
||||
# FIXME: Enable cop again when https://github.com/sorbet/sorbet/issues/3532 is fixed.
|
||||
# rubocop:disable Style/MutableConstant
|
||||
Paths = T.type_alias { T.any(String, Pathname, T::Array[T.any(String, Pathname)]) }
|
||||
# rubocop:enable Style/MutableConstant
|
||||
|
||||
sig { params(paths: Paths, permissions_str: String).void }
|
||||
def set_permissions(paths, permissions_str)
|
||||
full_paths = remove_nonexistent(paths)
|
||||
|
@ -6,16 +6,12 @@ require "ostruct"
|
||||
module Homebrew
|
||||
module CLI
|
||||
class Args < OpenStruct
|
||||
# FIXME: Enable cop again when https://github.com/sorbet/sorbet/issues/3532 is fixed.
|
||||
# rubocop:disable Style/MutableConstant
|
||||
# Represents a processed option. The array elements are:
|
||||
# 0: short option name (e.g. "-d")
|
||||
# 1: long option name (e.g. "--debug")
|
||||
# 2: option description (e.g. "Print debugging information")
|
||||
# 3: whether the option is hidden
|
||||
OptionsType = T.type_alias { T::Array[[String, T.nilable(String), String, T::Boolean]] }
|
||||
# rubocop:enable Style/MutableConstant
|
||||
|
||||
sig { returns(T::Array[String]) }
|
||||
attr_reader :options_only, :flags_only
|
||||
|
||||
|
@ -13,10 +13,7 @@ require "utils/formatter"
|
||||
module Homebrew
|
||||
module CLI
|
||||
class Parser
|
||||
# FIXME: Enable cop again when https://github.com/sorbet/sorbet/issues/3532 is fixed.
|
||||
# rubocop:disable Style/MutableConstant
|
||||
ArgType = T.type_alias { T.any(NilClass, Symbol, T::Array[String], T::Array[Symbol]) }
|
||||
# rubocop:enable Style/MutableConstant
|
||||
HIDDEN_DESC_PLACEHOLDER = "@@HIDDEN@@"
|
||||
SYMBOL_TO_USAGE_MAPPING = T.let({
|
||||
text_or_regex: "<text>|`/`<regex>`/`",
|
||||
|
@ -5,8 +5,6 @@ require "test_runner_formula"
|
||||
require "github_runner"
|
||||
|
||||
class GitHubRunnerMatrix
|
||||
# FIXME: Enable cop again when https://github.com/sorbet/sorbet/issues/3532 is fixed.
|
||||
# rubocop:disable Style/MutableConstant
|
||||
RunnerSpec = T.type_alias { T.any(LinuxRunnerSpec, MacOSRunnerSpec) }
|
||||
private_constant :RunnerSpec
|
||||
|
||||
@ -36,8 +34,6 @@ class GitHubRunnerMatrix
|
||||
|
||||
RunnerSpecHash = T.type_alias { T.any(LinuxRunnerSpecHash, MacOSRunnerSpecHash) }
|
||||
private_constant :RunnerSpecHash
|
||||
# rubocop:enable Style/MutableConstant
|
||||
|
||||
sig { returns(T::Array[GitHubRunner]) }
|
||||
attr_reader :runners
|
||||
|
||||
|
@ -13,12 +13,8 @@ module Tapioca
|
||||
end.flatten.freeze, T::Array[String]
|
||||
)
|
||||
|
||||
# FIXME: Enable cop again when https://github.com/sorbet/sorbet/issues/3532 is fixed.
|
||||
# rubocop:disable Style/MutableConstant
|
||||
Parsable = T.type_alias { T.any(T.class_of(Homebrew::CLI::Args), T.class_of(Homebrew::AbstractCommand)) }
|
||||
ConstantType = type_member { { fixed: Parsable } }
|
||||
# rubocop:enable Style/MutableConstant
|
||||
|
||||
sig { override.returns(T::Enumerable[Parsable]) }
|
||||
def self.gather_constants
|
||||
# require all the commands to ensure the command subclasses are defined
|
||||
|
@ -7,10 +7,7 @@ require "env_config"
|
||||
module Tapioca
|
||||
module Compilers
|
||||
class EnvConfig < Tapioca::Dsl::Compiler
|
||||
# FIXME: Enable cop again when https://github.com/sorbet/sorbet/issues/3532 is fixed.
|
||||
# rubocop:disable Style/MutableConstant
|
||||
ConstantType = type_member { { fixed: Module } }
|
||||
# rubocop:enable Style/MutableConstant
|
||||
|
||||
sig { override.returns(T::Enumerable[Module]) }
|
||||
def self.gather_constants = [Homebrew::EnvConfig]
|
||||
|
@ -8,13 +8,9 @@ require_relative "../../../rubocops"
|
||||
module Tapioca
|
||||
module Compilers
|
||||
class RuboCop < Tapioca::Dsl::Compiler
|
||||
# FIXME: Enable cop again when https://github.com/sorbet/sorbet/issues/3532 is fixed.
|
||||
# rubocop:disable Style/MutableConstant
|
||||
# This should be a module whose singleton class contains RuboCop::AST::NodePattern::Macros,
|
||||
# but I don't know how to express that in Sorbet.
|
||||
ConstantType = type_member { { fixed: Module } }
|
||||
# rubocop:enable Style/MutableConstant
|
||||
|
||||
sig { override.returns(T::Enumerable[Module]) }
|
||||
def self.gather_constants
|
||||
all_modules.select do |klass|
|
||||
|
@ -7,10 +7,7 @@ require "utils/tty"
|
||||
module Tapioca
|
||||
module Compilers
|
||||
class Tty < Tapioca::Dsl::Compiler
|
||||
# FIXME: Enable cop again when https://github.com/sorbet/sorbet/issues/3532 is fixed.
|
||||
# rubocop:disable Style/MutableConstant
|
||||
ConstantType = type_member { { fixed: Module } }
|
||||
# rubocop:enable Style/MutableConstant
|
||||
|
||||
sig { override.returns(T::Enumerable[Module]) }
|
||||
def self.gather_constants = [::Tty]
|
||||
|
@ -1,630 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "rubocops/extend/mutable_constant_exclude_unfreezable"
|
||||
|
||||
RSpec.describe(RuboCop::Cop::Style::MutableConstant, :config) do
|
||||
let(:prefix) { nil }
|
||||
|
||||
shared_examples "mutable objects" do |o|
|
||||
context "when using T.let" do
|
||||
context "when assigning with =" do
|
||||
it "registers an offense for #{o} assigned to a constant " \
|
||||
"and corrects by adding .freeze" do
|
||||
expect_offense([prefix, <<~RUBY].compact.join("\n"), o:)
|
||||
CONST = T.let(%<o>s, Object)
|
||||
^{o} Freeze mutable objects assigned to constants.
|
||||
RUBY
|
||||
expect_correction([prefix, <<~RUBY].compact.join("\n"))
|
||||
CONST = T.let(#{o}.freeze, Object)
|
||||
RUBY
|
||||
end
|
||||
end
|
||||
|
||||
context "when assigning with ||=" do
|
||||
it "registers an offense for #{o} assigned to a constant " \
|
||||
"and corrects by adding .freeze" do
|
||||
expect_offense([prefix, <<~RUBY].compact.join("\n"), o:)
|
||||
CONST ||= T.let(%<o>s, Object)
|
||||
^{o} Freeze mutable objects assigned to constants.
|
||||
RUBY
|
||||
expect_correction([prefix, <<~RUBY].compact.join("\n"))
|
||||
CONST ||= T.let(#{o}.freeze, Object)
|
||||
RUBY
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when not using T.let" do
|
||||
context "when assigning with =" do
|
||||
it "registers an offense for #{o} assigned to a constant " \
|
||||
"and corrects by adding .freeze" do
|
||||
expect_offense([prefix, <<~RUBY].compact.join("\n"), o:)
|
||||
CONST = %<o>s
|
||||
^{o} Freeze mutable objects assigned to constants.
|
||||
RUBY
|
||||
expect_correction([prefix, <<~RUBY].compact.join("\n"))
|
||||
CONST = #{o}.freeze
|
||||
RUBY
|
||||
end
|
||||
end
|
||||
|
||||
context "when assigning with ||=" do
|
||||
it "registers an offense for #{o} assigned to a constant " \
|
||||
"and corrects by adding .freeze" do
|
||||
expect_offense([prefix, <<~RUBY].compact.join("\n"), o:)
|
||||
CONST ||= %<o>s
|
||||
^{o} Freeze mutable objects assigned to constants.
|
||||
RUBY
|
||||
expect_correction([prefix, <<~RUBY].compact.join("\n"))
|
||||
CONST ||= #{o}.freeze
|
||||
RUBY
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples "immutable objects" do |o|
|
||||
context "when using T.let" do
|
||||
it "allows #{o} to be assigned to a constant" do
|
||||
const = if o.start_with?("<<~HERE")
|
||||
heredoc = o.delete_prefix("<<~HERE")
|
||||
"CONST = T.let(<<~HERE, Object)#{heredoc}"
|
||||
else
|
||||
"CONST = T.let(#{o.chomp}, Object)"
|
||||
end
|
||||
source = [prefix, const].compact.join("\n")
|
||||
expect_no_offenses(source)
|
||||
end
|
||||
|
||||
it "allows #{o} to be ||= to a constant" do
|
||||
const = if o.start_with?("<<~HERE")
|
||||
heredoc = o.delete_prefix("<<~HERE")
|
||||
"CONST ||= T.let(<<~HERE, Object)#{heredoc}"
|
||||
else
|
||||
"CONST ||= T.let(#{o.chomp}, Object)"
|
||||
end
|
||||
source = [prefix, const].compact.join("\n")
|
||||
expect_no_offenses(source)
|
||||
end
|
||||
end
|
||||
|
||||
context "when not using T.let" do
|
||||
it "allows #{o} to be assigned to a constant" do
|
||||
source = [prefix, "CONST = #{o}"].compact.join("\n")
|
||||
expect_no_offenses(source)
|
||||
end
|
||||
|
||||
it "allows #{o} to be ||= to a constant" do
|
||||
source = [prefix, "CONST ||= #{o}"].compact.join("\n")
|
||||
expect_no_offenses(source)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples "literals that are frozen" do |o|
|
||||
let(:prefix) { o }
|
||||
|
||||
it_behaves_like "immutable objects", "[1, 2, 3]"
|
||||
it_behaves_like "immutable objects", "%w(a b c)"
|
||||
it_behaves_like "immutable objects", "{ a: 1, b: 2 }"
|
||||
it_behaves_like "immutable objects", "'str'"
|
||||
it_behaves_like "immutable objects", %Q("top#{1 + 2}")
|
||||
it_behaves_like "immutable objects", "1"
|
||||
it_behaves_like "immutable objects", "1.5"
|
||||
it_behaves_like "immutable objects", ":sym"
|
||||
it_behaves_like "immutable objects", "FOO + BAR"
|
||||
it_behaves_like "immutable objects", "FOO - BAR"
|
||||
it_behaves_like "immutable objects", "'foo' + 'bar'"
|
||||
it_behaves_like "immutable objects", "ENV['foo']"
|
||||
it_behaves_like "immutable objects", "::ENV['foo']"
|
||||
end
|
||||
|
||||
shared_examples "literals that are not frozen" do |o|
|
||||
let(:prefix) { o }
|
||||
|
||||
it_behaves_like "mutable objects", "[1, 2, 3]"
|
||||
it_behaves_like "mutable objects", "%w(a b c)"
|
||||
it_behaves_like "mutable objects", "{ a: 1, b: 2 }"
|
||||
it_behaves_like "mutable objects", "'str'"
|
||||
it_behaves_like "mutable objects", %Q("top#{1 + 2}")
|
||||
|
||||
it_behaves_like "immutable objects", "1"
|
||||
it_behaves_like "immutable objects", "1.5"
|
||||
it_behaves_like "immutable objects", ":sym"
|
||||
it_behaves_like "immutable objects", "FOO + BAR"
|
||||
it_behaves_like "immutable objects", "FOO - BAR"
|
||||
it_behaves_like "immutable objects", "'foo' + 'bar'"
|
||||
it_behaves_like "immutable objects", "ENV['foo']"
|
||||
it_behaves_like "immutable objects", "::ENV['foo']"
|
||||
end
|
||||
|
||||
shared_examples "string literal" do
|
||||
# TODO : It is not yet decided when frozen string will be the default.
|
||||
# It has been abandoned in the Ruby 3.0 period, but may default in
|
||||
# the long run. So these tests are left with a provisional value of 4.0.
|
||||
if RuboCop::TargetRuby.supported_versions.include?(4.0)
|
||||
context "when the target ruby version >= 4.0" do
|
||||
let(:ruby_version) { 4.0 }
|
||||
|
||||
context "when the frozen string literal comment is missing" do
|
||||
it_behaves_like "immutable objects", %Q("#{a}")
|
||||
end
|
||||
|
||||
context "when the frozen string literal comment is true" do
|
||||
let(:prefix) { "# frozen_string_literal: true" }
|
||||
|
||||
it_behaves_like "immutable objects", %Q("#{a}")
|
||||
end
|
||||
|
||||
context "when the frozen string literal comment is false" do
|
||||
let(:prefix) { "# frozen_string_literal: false" }
|
||||
|
||||
it_behaves_like "immutable objects", %Q("#{a}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with Ruby 3.0 or higher", :ruby30 do
|
||||
context "when the frozen string literal comment is missing" do
|
||||
it_behaves_like "mutable objects", %Q("#{a}")
|
||||
end
|
||||
|
||||
context "when the frozen string literal comment is true" do
|
||||
let(:prefix) { "# frozen_string_literal: true" }
|
||||
|
||||
it_behaves_like "mutable objects", %Q("#{a}")
|
||||
it_behaves_like "immutable objects", <<~RUBY
|
||||
<<~HERE
|
||||
foo
|
||||
bar
|
||||
HERE
|
||||
RUBY
|
||||
it "registers an offense when using interpolated heredoc constant" do
|
||||
expect_offense(<<~'RUBY')
|
||||
# frozen_string_literal: true
|
||||
|
||||
CONST = T.let(<<~HERE, Object)
|
||||
^^^^^^^ Freeze mutable objects assigned to constants.
|
||||
foo #{use_interpolation}
|
||||
bar
|
||||
HERE
|
||||
RUBY
|
||||
end
|
||||
|
||||
it "does not register an offense when using a multiline string" do
|
||||
expect_no_offenses(<<~RUBY)
|
||||
# frozen_string_literal: true
|
||||
|
||||
CONST = T.let('foo' \
|
||||
'bar', Object)
|
||||
RUBY
|
||||
end
|
||||
|
||||
it "registers an offense when using a multiline string with interpolation" do
|
||||
expect_offense(<<~'RUBY')
|
||||
# frozen_string_literal: true
|
||||
|
||||
CONST = T.let("#{foo}" \
|
||||
^^^^^^^^^^ Freeze mutable objects assigned to constants.
|
||||
'bar', Object)
|
||||
RUBY
|
||||
end
|
||||
end
|
||||
|
||||
context "when the frozen string literal comment is false" do
|
||||
let(:prefix) { "# frozen_string_literal: false" }
|
||||
|
||||
it_behaves_like "mutable objects", %Q("#{a}")
|
||||
end
|
||||
end
|
||||
|
||||
context "with Ruby 2.7 or lower", :ruby27 do
|
||||
context "when the frozen string literal comment is missing" do
|
||||
it_behaves_like "mutable objects", %Q("#{a}")
|
||||
end
|
||||
|
||||
context "when the frozen string literal comment is true" do
|
||||
let(:prefix) { "# frozen_string_literal: true" }
|
||||
|
||||
it_behaves_like "immutable objects", %Q("#{a}")
|
||||
it_behaves_like "immutable objects", <<~RUBY
|
||||
<<~HERE
|
||||
foo
|
||||
bar
|
||||
HERE
|
||||
RUBY
|
||||
it "does not register an offense when using interpolated heredoc constant" do
|
||||
expect_no_offenses(<<~'RUBY')
|
||||
# frozen_string_literal: true
|
||||
|
||||
CONST = T.let(<<~HERE, Object)
|
||||
foo #{use_interpolation}
|
||||
bar
|
||||
HERE
|
||||
RUBY
|
||||
end
|
||||
|
||||
it "does not register an offense when using a multiline string" do
|
||||
expect_no_offenses(<<~RUBY)
|
||||
# frozen_string_literal: true
|
||||
|
||||
CONST = T.let('foo' \
|
||||
'bar', Object)
|
||||
RUBY
|
||||
end
|
||||
end
|
||||
|
||||
context "when the frozen string literal comment is false" do
|
||||
let(:prefix) { "# frozen_string_literal: false" }
|
||||
|
||||
it_behaves_like "mutable objects", %Q("#{a}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with Strict: false" do
|
||||
let(:cop_config) { { "EnforcedStyle" => "literals" } }
|
||||
|
||||
it_behaves_like "mutable objects", "[1, 2, 3]"
|
||||
it_behaves_like "mutable objects", "%w(a b c)"
|
||||
it_behaves_like "mutable objects", "{ a: 1, b: 2 }"
|
||||
it_behaves_like "mutable objects", "'str'"
|
||||
it_behaves_like "mutable objects", %Q("top#{1 + 2}")
|
||||
|
||||
it_behaves_like "immutable objects", "1"
|
||||
it_behaves_like "immutable objects", "1.5"
|
||||
it_behaves_like "immutable objects", ":sym"
|
||||
it_behaves_like "immutable objects", "FOO + BAR"
|
||||
it_behaves_like "immutable objects", "FOO - BAR"
|
||||
it_behaves_like "immutable objects", "'foo' + 'bar'"
|
||||
it_behaves_like "immutable objects", "ENV['foo']"
|
||||
it_behaves_like "immutable objects", "::ENV['foo']"
|
||||
|
||||
it "allows method call assignments" do
|
||||
expect_no_offenses("TOP_TEST = Something.new")
|
||||
end
|
||||
|
||||
context "when assigning an array without brackets" do
|
||||
it "does not insert brackets for %w() arrays" do
|
||||
expect_offense(<<~RUBY)
|
||||
XXX = T.let(%w(YYY ZZZ), Object)
|
||||
^^^^^^^^^^^ Freeze mutable objects assigned to constants.
|
||||
RUBY
|
||||
|
||||
expect_correction(<<~RUBY)
|
||||
XXX = T.let(%w(YYY ZZZ).freeze, Object)
|
||||
RUBY
|
||||
end
|
||||
end
|
||||
|
||||
# Ruby 3.0's Regexp and Range literals are frozen.
|
||||
#
|
||||
# https://bugs.ruby-lang.org/issues/15504
|
||||
# https://bugs.ruby-lang.org/issues/16377
|
||||
context "with Ruby 3.0 or higher", :ruby30 do
|
||||
context "when assigning a regexp" do
|
||||
it "does not register an offense" do
|
||||
expect_no_offenses(<<~RUBY)
|
||||
XXX = T.let(/regexp/, Object)
|
||||
RUBY
|
||||
end
|
||||
end
|
||||
|
||||
context "when assigning a range (irange)" do
|
||||
it "does not register an offense when without parenthesis" do
|
||||
expect_no_offenses(<<~RUBY)
|
||||
XXX = T.let(1..99, Object)
|
||||
RUBY
|
||||
end
|
||||
|
||||
it "does not register an offense when with parenthesis" do
|
||||
expect_no_offenses(<<~RUBY)
|
||||
XXX = T.let((1..99), Object)
|
||||
RUBY
|
||||
end
|
||||
end
|
||||
|
||||
context "when assigning a range (erange)" do
|
||||
it "does not register an offense when without parenthesis" do
|
||||
expect_no_offenses(<<~RUBY)
|
||||
XXX = T.let(1...99, Object)
|
||||
RUBY
|
||||
end
|
||||
|
||||
it "does not register an offense when with parenthesis" do
|
||||
expect_no_offenses(<<~RUBY)
|
||||
XXX = T.let((1...99), Object)
|
||||
RUBY
|
||||
end
|
||||
end
|
||||
|
||||
context "when using shareable_constant_value" do
|
||||
it_behaves_like "literals that are frozen", "# shareable_constant_value: literal"
|
||||
it_behaves_like "literals that are frozen", "# shareable_constant_value: experimental_everything"
|
||||
it_behaves_like "literals that are frozen", "# shareable_constant_value: experimental_copy"
|
||||
it_behaves_like "literals that are not frozen", "# shareable_constant_value: none"
|
||||
end
|
||||
|
||||
it "raises offense when shareable_constant_value is specified as an inline comment" do
|
||||
expect_offense(<<~RUBY)
|
||||
X = T.let([1, 2, 3], Object) # shareable_constant_value: literal
|
||||
^^^^^^^^^ Freeze mutable objects assigned to constants.
|
||||
Y = T.let([4, 5, 6], Object)
|
||||
^^^^^^^^^ Freeze mutable objects assigned to constants.
|
||||
RUBY
|
||||
end
|
||||
|
||||
it "raises offense only for shareable_constant_value as none when set in the order of: " \
|
||||
"literal, none and experimental_everything" do
|
||||
expect_offense(<<~RUBY)
|
||||
# shareable_constant_value: literal
|
||||
X = T.let([1, 2, 3], Object)
|
||||
# shareable_constant_value: none
|
||||
Y = T.let([4, 5, 6], Object)
|
||||
^^^^^^^^^ Freeze mutable objects assigned to constants.
|
||||
# shareable_constant_value: experimental_everything
|
||||
Z = T.let([7, 8, 9], Object)
|
||||
RUBY
|
||||
end
|
||||
end
|
||||
|
||||
context "with Ruby 2.7 or lower", :ruby27 do
|
||||
context "when assigning a regexp" do
|
||||
it "registers an offense" do
|
||||
expect_offense(<<~RUBY)
|
||||
XXX = T.let(/regexp/, Object)
|
||||
^^^^^^^^ Freeze mutable objects assigned to constants.
|
||||
RUBY
|
||||
|
||||
expect_correction(<<~RUBY)
|
||||
XXX = T.let(/regexp/.freeze, Object)
|
||||
RUBY
|
||||
end
|
||||
end
|
||||
|
||||
context "when assigning a range (irange) without parenthesis" do
|
||||
it "adds parenthesis when auto-correcting" do
|
||||
expect_offense(<<~RUBY)
|
||||
XXX = T.let(1..99, Object)
|
||||
^^^^^ Freeze mutable objects assigned to constants.
|
||||
RUBY
|
||||
|
||||
expect_correction(<<~RUBY)
|
||||
XXX = T.let((1..99).freeze, Object)
|
||||
RUBY
|
||||
end
|
||||
|
||||
it "does not insert parenthesis to range enclosed in parentheses" do
|
||||
expect_offense(<<~RUBY)
|
||||
XXX = T.let((1..99), Object)
|
||||
^^^^^^^ Freeze mutable objects assigned to constants.
|
||||
RUBY
|
||||
|
||||
expect_correction(<<~RUBY)
|
||||
XXX = T.let((1..99).freeze, Object)
|
||||
RUBY
|
||||
end
|
||||
end
|
||||
|
||||
context "when assigning a range (erange) without parenthesis" do
|
||||
it "adds parenthesis when auto-correcting" do
|
||||
expect_offense(<<~RUBY)
|
||||
XXX = T.let(1...99, Object)
|
||||
^^^^^^ Freeze mutable objects assigned to constants.
|
||||
RUBY
|
||||
|
||||
expect_correction(<<~RUBY)
|
||||
XXX = T.let((1...99).freeze, Object)
|
||||
RUBY
|
||||
end
|
||||
|
||||
it "does not insert parenthesis to range enclosed in parentheses" do
|
||||
expect_offense(<<~RUBY)
|
||||
XXX = T.let((1...99), Object)
|
||||
^^^^^^^^ Freeze mutable objects assigned to constants.
|
||||
RUBY
|
||||
|
||||
expect_correction(<<~RUBY)
|
||||
XXX = T.let((1...99).freeze, Object)
|
||||
RUBY
|
||||
end
|
||||
end
|
||||
|
||||
context "when using shareable_constant_values" do
|
||||
it_behaves_like "literals that are not frozen", "# shareable_constant_value: literal"
|
||||
it_behaves_like "literals that are not frozen", "# shareable_constant_value: experimental_everything"
|
||||
it_behaves_like "literals that are not frozen", "# shareable_constant_value: experimental_copy"
|
||||
it_behaves_like "literals that are not frozen", "# shareable_constant_value: none"
|
||||
end
|
||||
end
|
||||
|
||||
it_behaves_like "string literal"
|
||||
end
|
||||
|
||||
context "with Strict: true" do
|
||||
let(:cop_config) { { "EnforcedStyle" => "strict" } }
|
||||
|
||||
it_behaves_like "mutable objects", "[1, 2, 3]"
|
||||
it_behaves_like "mutable objects", "%w(a b c)"
|
||||
it_behaves_like "mutable objects", "{ a: 1, b: 2 }"
|
||||
it_behaves_like "mutable objects", "'str'"
|
||||
it_behaves_like "mutable objects", %Q("top#{1 + 2}")
|
||||
it_behaves_like "mutable objects", "Something.new"
|
||||
|
||||
it_behaves_like "immutable objects", "1"
|
||||
it_behaves_like "immutable objects", "1.5"
|
||||
it_behaves_like "immutable objects", ":sym"
|
||||
it_behaves_like "immutable objects", "ENV['foo']"
|
||||
it_behaves_like "immutable objects", "::ENV['foo']"
|
||||
it_behaves_like "immutable objects", "OTHER_CONST"
|
||||
it_behaves_like "immutable objects", "::OTHER_CONST"
|
||||
it_behaves_like "immutable objects", "Namespace::OTHER_CONST"
|
||||
it_behaves_like "immutable objects", "::Namespace::OTHER_CONST"
|
||||
it_behaves_like "immutable objects", "Struct.new"
|
||||
it_behaves_like "immutable objects", "::Struct.new"
|
||||
it_behaves_like "immutable objects", "Struct.new(:a, :b)"
|
||||
it_behaves_like "immutable objects", "T.type_alias { T.nilable(T.any(Pathname, String)) }"
|
||||
it_behaves_like "immutable objects", "::T.type_alias { T.nilable(T.any(Pathname, String)) }"
|
||||
it_behaves_like "immutable objects", "type_member { { fixed: Module } }"
|
||||
it_behaves_like "immutable objects", <<~RUBY
|
||||
Struct.new(:node) do
|
||||
def assignment?
|
||||
true
|
||||
end
|
||||
end
|
||||
RUBY
|
||||
|
||||
it "allows calls to freeze" do
|
||||
expect_no_offenses(<<~RUBY)
|
||||
CONST = T.let([1].freeze, Object)
|
||||
RUBY
|
||||
end
|
||||
|
||||
context "when assigning with an operator" do
|
||||
shared_examples "operator methods" do |o|
|
||||
it "registers an offense and corrects with parens and freeze" do
|
||||
expect_offense(<<~RUBY, o:)
|
||||
CONST = T.let(FOO %<o>s BAR, Object)
|
||||
^^^^^{o}^^^^ Freeze mutable objects assigned to constants.
|
||||
RUBY
|
||||
|
||||
expect_correction(<<~RUBY)
|
||||
CONST = T.let((FOO #{o} BAR).freeze, Object)
|
||||
RUBY
|
||||
end
|
||||
end
|
||||
|
||||
it_behaves_like "operator methods", "+"
|
||||
it_behaves_like "operator methods", "-"
|
||||
it_behaves_like "operator methods", "*"
|
||||
it_behaves_like "operator methods", "/"
|
||||
it_behaves_like "operator methods", "%"
|
||||
it_behaves_like "operator methods", "**"
|
||||
end
|
||||
|
||||
context "when assigning with multiple operator calls" do
|
||||
it "registers an offense and corrects with parens and freeze" do
|
||||
expect_offense(<<~RUBY)
|
||||
FOO = [1].freeze
|
||||
BAR = [2].freeze
|
||||
BAZ = [3].freeze
|
||||
CONST = T.let(FOO + BAR + BAZ, Object)
|
||||
^^^^^^^^^^^^^^^ Freeze mutable objects assigned to constants.
|
||||
RUBY
|
||||
|
||||
expect_correction(<<~RUBY)
|
||||
FOO = [1].freeze
|
||||
BAR = [2].freeze
|
||||
BAZ = [3].freeze
|
||||
CONST = T.let((FOO + BAR + BAZ).freeze, Object)
|
||||
RUBY
|
||||
end
|
||||
end
|
||||
|
||||
context "with methods and operators that produce frozen objects" do
|
||||
it "accepts assigning to an environment variable with a fallback" do
|
||||
expect_no_offenses(<<~RUBY)
|
||||
CONST = T.let(ENV['foo'] || 'foo', Object)
|
||||
RUBY
|
||||
expect_no_offenses(<<~RUBY)
|
||||
CONST = T.let(::ENV['foo'] || 'foo', Object)
|
||||
RUBY
|
||||
end
|
||||
|
||||
it "accepts operating on a constant and an interger" do
|
||||
expect_no_offenses(<<~RUBY)
|
||||
CONST = T.let(FOO + 2, Object)
|
||||
RUBY
|
||||
end
|
||||
|
||||
it "accepts operating on multiple integers" do
|
||||
expect_no_offenses(<<~RUBY)
|
||||
CONST = T.let(1 + 2, Object)
|
||||
RUBY
|
||||
end
|
||||
|
||||
it "accepts operating on a constant and a float" do
|
||||
expect_no_offenses(<<~RUBY)
|
||||
CONST = T.let(FOO + 2.1, Object)
|
||||
RUBY
|
||||
end
|
||||
|
||||
it "accepts operating on multiple floats" do
|
||||
expect_no_offenses(<<~RUBY)
|
||||
CONST = T.let(1.2 + 2.1, Object)
|
||||
RUBY
|
||||
end
|
||||
|
||||
it "accepts comparison operators" do
|
||||
expect_no_offenses(<<~RUBY)
|
||||
CONST = T.let(FOO == BAR, Object)
|
||||
RUBY
|
||||
end
|
||||
|
||||
it "accepts checking fixed size" do
|
||||
expect_no_offenses(<<~RUBY)
|
||||
CONST = T.let('foo'.count, Object)
|
||||
CONST = T.let('foo'.count('f'), Object)
|
||||
CONST = T.let([1, 2, 3].count { |n| n > 2 }, Object)
|
||||
CONST = T.let([1, 2, 3].count(2) { |n| n > 2 }, Object)
|
||||
CONST = T.let('foo'.length, Object)
|
||||
CONST = T.let('foo'.size, Object)
|
||||
RUBY
|
||||
end
|
||||
end
|
||||
|
||||
context "with operators that produce unfrozen objects" do
|
||||
it "registers an offense when operating on a constant and a string" do
|
||||
expect_offense(<<~RUBY)
|
||||
CONST = T.let(FOO + 'bar', Object)
|
||||
^^^^^^^^^^^ Freeze mutable objects assigned to constants.
|
||||
RUBY
|
||||
|
||||
expect_correction(<<~RUBY)
|
||||
CONST = T.let((FOO + 'bar').freeze, Object)
|
||||
RUBY
|
||||
end
|
||||
|
||||
it "registers an offense when operating on multiple strings" do
|
||||
expect_offense(<<~RUBY)
|
||||
CONST = T.let('foo' + 'bar' + 'baz', Object)
|
||||
^^^^^^^^^^^^^^^^^^^^^ Freeze mutable objects assigned to constants.
|
||||
RUBY
|
||||
|
||||
expect_correction(<<~RUBY)
|
||||
CONST = T.let(('foo' + 'bar' + 'baz').freeze, Object)
|
||||
RUBY
|
||||
end
|
||||
end
|
||||
|
||||
context "when assigning an array without brackets" do
|
||||
it "does not insert brackets for %w() arrays" do
|
||||
expect_offense(<<~RUBY)
|
||||
XXX = T.let(%w(YYY ZZZ), Object)
|
||||
^^^^^^^^^^^ Freeze mutable objects assigned to constants.
|
||||
RUBY
|
||||
|
||||
expect_correction(<<~RUBY)
|
||||
XXX = T.let(%w(YYY ZZZ).freeze, Object)
|
||||
RUBY
|
||||
end
|
||||
end
|
||||
|
||||
it "freezes a heredoc" do
|
||||
expect_offense(<<~RUBY)
|
||||
FOO = T.let(<<-HERE, Object)
|
||||
^^^^^^^ Freeze mutable objects assigned to constants.
|
||||
SOMETHING
|
||||
HERE
|
||||
RUBY
|
||||
|
||||
expect_correction(<<~RUBY)
|
||||
FOO = T.let(<<-HERE.freeze, Object)
|
||||
SOMETHING
|
||||
HERE
|
||||
RUBY
|
||||
end
|
||||
|
||||
it_behaves_like "string literal"
|
||||
end
|
||||
end
|
@ -11,10 +11,7 @@ module UnpackStrategy
|
||||
|
||||
requires_ancestor { Kernel }
|
||||
|
||||
# FIXME: Enable cop again when https://github.com/sorbet/sorbet/issues/3532 is fixed.
|
||||
# rubocop:disable Style/MutableConstant
|
||||
UnpackStrategyType = T.type_alias { T.all(T::Class[UnpackStrategy], UnpackStrategy::ClassMethods) }
|
||||
# rubocop:enable Style/MutableConstant
|
||||
|
||||
module ClassMethods
|
||||
extend T::Helpers
|
||||
|
Loading…
x
Reference in New Issue
Block a user