Merge pull request #15883 from Homebrew/dependabot/bundler/Library/Homebrew/rubocop-sorbet-0.7.3
build(deps): bump rubocop-sorbet from 0.7.0 to 0.7.3 in /Library/Homebrew
This commit is contained in:
commit
c953076609
@ -118,7 +118,7 @@ GEM
|
|||||||
rubocop-rspec (2.20.0)
|
rubocop-rspec (2.20.0)
|
||||||
rubocop (~> 1.33)
|
rubocop (~> 1.33)
|
||||||
rubocop-capybara (~> 2.17)
|
rubocop-capybara (~> 2.17)
|
||||||
rubocop-sorbet (0.7.0)
|
rubocop-sorbet (0.7.3)
|
||||||
rubocop (>= 0.90.0)
|
rubocop (>= 0.90.0)
|
||||||
ruby-macho (4.0.0)
|
ruby-macho (4.0.0)
|
||||||
ruby-prof (1.4.3)
|
ruby-prof (1.4.3)
|
||||||
|
|||||||
@ -95,21 +95,17 @@ module OS
|
|||||||
# directory or nil if Xcode.app is not installed.
|
# directory or nil if Xcode.app is not installed.
|
||||||
sig { returns(T.nilable(Pathname)) }
|
sig { returns(T.nilable(Pathname)) }
|
||||||
def self.prefix
|
def self.prefix
|
||||||
return @prefix if defined?(@prefix)
|
@prefix ||= begin
|
||||||
|
dir = MacOS.active_developer_dir
|
||||||
|
|
||||||
@prefix = T.let(@prefix, T.nilable(Pathname))
|
if dir.empty? || dir == CLT::PKG_PATH || !File.directory?(dir)
|
||||||
@prefix ||=
|
path = bundle_path
|
||||||
begin
|
path/"Contents/Developer" if path
|
||||||
dir = MacOS.active_developer_dir
|
else
|
||||||
|
# Use cleanpath to avoid pathological trailing slash
|
||||||
if dir.empty? || dir == CLT::PKG_PATH || !File.directory?(dir)
|
Pathname.new(dir).cleanpath
|
||||||
path = bundle_path
|
|
||||||
path/"Contents/Developer" if path
|
|
||||||
else
|
|
||||||
# Use cleanpath to avoid pathological trailing slash
|
|
||||||
Pathname.new(dir).cleanpath
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { returns(Pathname) }
|
sig { returns(Pathname) }
|
||||||
|
|||||||
@ -10,31 +10,34 @@ RuboCop::Cop::IgnoredMethods = RuboCop::Cop::AllowedMethods
|
|||||||
RuboCop::Cop::IgnoredPattern = RuboCop::Cop::AllowedPattern
|
RuboCop::Cop::IgnoredPattern = RuboCop::Cop::AllowedPattern
|
||||||
module RuboCop::Cop::Sorbet; end
|
module RuboCop::Cop::Sorbet; end
|
||||||
|
|
||||||
class RuboCop::Cop::Sorbet::AllowIncompatibleOverride < ::RuboCop::Cop::Cop
|
class RuboCop::Cop::Sorbet::AllowIncompatibleOverride < ::RuboCop::Cop::Base
|
||||||
def allow_incompatible?(param0); end
|
def on_block(node); end
|
||||||
def allow_incompatible_override?(param0 = T.unsafe(nil)); end
|
def on_numblock(node); end
|
||||||
def not_nil?(node); end
|
|
||||||
def on_send(node); end
|
def on_send(node); end
|
||||||
|
def override?(param0 = T.unsafe(nil)); end
|
||||||
def sig?(param0); end
|
def sig?(param0); end
|
||||||
|
def sig_dot_override?(param0 = T.unsafe(nil)); end
|
||||||
end
|
end
|
||||||
|
|
||||||
class RuboCop::Cop::Sorbet::BindingConstantWithoutTypeAlias < ::RuboCop::Cop::Cop
|
RuboCop::Cop::Sorbet::AllowIncompatibleOverride::MSG = T.let(T.unsafe(nil), String)
|
||||||
def autocorrect(node); end
|
RuboCop::Cop::Sorbet::AllowIncompatibleOverride::RESTRICT_ON_SEND = T.let(T.unsafe(nil), Array)
|
||||||
def binding_unaliased_type?(param0 = T.unsafe(nil)); end
|
|
||||||
def dynamic_type_creation_with_block?(param0 = T.unsafe(nil)); end
|
class RuboCop::Cop::Sorbet::BindingConstantWithoutTypeAlias < ::RuboCop::Cop::Base
|
||||||
def generic_parameter_decl_block_call?(param0 = T.unsafe(nil)); end
|
extend ::RuboCop::Cop::AutoCorrector
|
||||||
def generic_parameter_decl_call?(param0 = T.unsafe(nil)); end
|
|
||||||
def method_needing_aliasing_on_t?(param0); end
|
|
||||||
def not_dynamic_type_creation_with_block?(node); end
|
|
||||||
def not_generic_parameter_decl?(node); end
|
|
||||||
def not_nil?(node); end
|
|
||||||
def not_t_let?(node); end
|
|
||||||
def on_casgn(node); end
|
def on_casgn(node); end
|
||||||
def t_let?(param0 = T.unsafe(nil)); end
|
def requires_type_alias?(param0 = T.unsafe(nil)); end
|
||||||
def using_deprecated_type_alias_syntax?(param0 = T.unsafe(nil)); end
|
def type_alias_with_block?(param0 = T.unsafe(nil)); end
|
||||||
def using_type_alias?(param0 = T.unsafe(nil)); end
|
def type_alias_without_block(param0 = T.unsafe(nil)); end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def send_leaf(node); end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
RuboCop::Cop::Sorbet::BindingConstantWithoutTypeAlias::MSG = T.let(T.unsafe(nil), String)
|
||||||
|
RuboCop::Cop::Sorbet::BindingConstantWithoutTypeAlias::WITHOUT_BLOCK_MSG = T.let(T.unsafe(nil), String)
|
||||||
|
|
||||||
class RuboCop::Cop::Sorbet::CallbackConditionalsBinding < ::RuboCop::Cop::Cop
|
class RuboCop::Cop::Sorbet::CallbackConditionalsBinding < ::RuboCop::Cop::Cop
|
||||||
def autocorrect(node); end
|
def autocorrect(node); end
|
||||||
def on_send(node); end
|
def on_send(node); end
|
||||||
@ -133,12 +136,11 @@ class RuboCop::Cop::Sorbet::FalseSigil < ::RuboCop::Cop::Sorbet::HasSigil
|
|||||||
def minimum_strictness; end
|
def minimum_strictness; end
|
||||||
end
|
end
|
||||||
|
|
||||||
class RuboCop::Cop::Sorbet::ForbidExtendTSigHelpersInShims < ::RuboCop::Cop::Cop
|
class RuboCop::Cop::Sorbet::ForbidExtendTSigHelpersInShims < ::RuboCop::Cop::Base
|
||||||
include ::RuboCop::Cop::RangeHelp
|
include ::RuboCop::Cop::RangeHelp
|
||||||
|
extend ::RuboCop::Cop::AutoCorrector
|
||||||
|
|
||||||
def autocorrect(node); end
|
def extend_t_sig_or_helpers?(param0 = T.unsafe(nil)); end
|
||||||
def extend_t_helpers?(param0 = T.unsafe(nil)); end
|
|
||||||
def extend_t_sig?(param0 = T.unsafe(nil)); end
|
|
||||||
def on_send(node); end
|
def on_send(node); end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -167,27 +169,32 @@ class RuboCop::Cop::Sorbet::ForbidRBIOutsideOfAllowedPaths < ::RuboCop::Cop::Cop
|
|||||||
def allowed_paths; end
|
def allowed_paths; end
|
||||||
end
|
end
|
||||||
|
|
||||||
class RuboCop::Cop::Sorbet::ForbidSuperclassConstLiteral < ::RuboCop::Cop::Cop
|
class RuboCop::Cop::Sorbet::ForbidSuperclassConstLiteral < ::RuboCop::Cop::Base
|
||||||
def not_lit_const_superclass?(param0 = T.unsafe(nil)); end
|
def dynamic_superclass?(param0 = T.unsafe(nil)); end
|
||||||
def on_class(node); end
|
def on_class(node); end
|
||||||
end
|
end
|
||||||
|
|
||||||
RuboCop::Cop::Sorbet::ForbidSuperclassConstLiteral::MSG = T.let(T.unsafe(nil), String)
|
RuboCop::Cop::Sorbet::ForbidSuperclassConstLiteral::MSG = T.let(T.unsafe(nil), String)
|
||||||
|
|
||||||
class RuboCop::Cop::Sorbet::ForbidTUnsafe < ::RuboCop::Cop::Cop
|
class RuboCop::Cop::Sorbet::ForbidTUnsafe < ::RuboCop::Cop::Base
|
||||||
def on_send(node); end
|
def on_send(node); end
|
||||||
def t_unsafe?(param0 = T.unsafe(nil)); end
|
def t_unsafe?(param0 = T.unsafe(nil)); end
|
||||||
end
|
end
|
||||||
|
|
||||||
class RuboCop::Cop::Sorbet::ForbidTUntyped < ::RuboCop::Cop::Cop
|
RuboCop::Cop::Sorbet::ForbidTUnsafe::MSG = T.let(T.unsafe(nil), String)
|
||||||
|
RuboCop::Cop::Sorbet::ForbidTUnsafe::RESTRICT_ON_SEND = T.let(T.unsafe(nil), Array)
|
||||||
|
|
||||||
|
class RuboCop::Cop::Sorbet::ForbidTUntyped < ::RuboCop::Cop::Base
|
||||||
def on_send(node); end
|
def on_send(node); end
|
||||||
def t_untyped?(param0 = T.unsafe(nil)); end
|
def t_untyped?(param0 = T.unsafe(nil)); end
|
||||||
end
|
end
|
||||||
|
|
||||||
class RuboCop::Cop::Sorbet::ForbidUntypedStructProps < ::RuboCop::Cop::Cop
|
RuboCop::Cop::Sorbet::ForbidTUntyped::MSG = T.let(T.unsafe(nil), String)
|
||||||
|
RuboCop::Cop::Sorbet::ForbidTUntyped::RESTRICT_ON_SEND = T.let(T.unsafe(nil), Array)
|
||||||
|
|
||||||
|
class RuboCop::Cop::Sorbet::ForbidUntypedStructProps < ::RuboCop::Cop::Base
|
||||||
def on_class(node); end
|
def on_class(node); end
|
||||||
def subclass_of_t_struct?(param0 = T.unsafe(nil)); end
|
def subclass_of_t_struct?(param0 = T.unsafe(nil)); end
|
||||||
def t_immutable_struct(param0 = T.unsafe(nil)); end
|
|
||||||
def t_nilable_untyped(param0 = T.unsafe(nil)); end
|
def t_nilable_untyped(param0 = T.unsafe(nil)); end
|
||||||
def t_struct(param0 = T.unsafe(nil)); end
|
def t_struct(param0 = T.unsafe(nil)); end
|
||||||
def t_untyped(param0 = T.unsafe(nil)); end
|
def t_untyped(param0 = T.unsafe(nil)); end
|
||||||
@ -204,6 +211,17 @@ class RuboCop::Cop::Sorbet::IgnoreSigil < ::RuboCop::Cop::Sorbet::HasSigil
|
|||||||
def minimum_strictness; end
|
def minimum_strictness; end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class RuboCop::Cop::Sorbet::ImplicitConversionMethod < ::RuboCop::Cop::Base
|
||||||
|
def on_alias(node); end
|
||||||
|
def on_def(node); end
|
||||||
|
def on_defs(node); end
|
||||||
|
def on_send(node); end
|
||||||
|
end
|
||||||
|
|
||||||
|
RuboCop::Cop::Sorbet::ImplicitConversionMethod::IMPLICIT_CONVERSION_METHODS = T.let(T.unsafe(nil), Array)
|
||||||
|
RuboCop::Cop::Sorbet::ImplicitConversionMethod::MSG = T.let(T.unsafe(nil), String)
|
||||||
|
RuboCop::Cop::Sorbet::ImplicitConversionMethod::RESTRICT_ON_SEND = T.let(T.unsafe(nil), Array)
|
||||||
|
|
||||||
class RuboCop::Cop::Sorbet::KeywordArgumentOrdering < ::RuboCop::Cop::Sorbet::SignatureCop
|
class RuboCop::Cop::Sorbet::KeywordArgumentOrdering < ::RuboCop::Cop::Sorbet::SignatureCop
|
||||||
def on_signature(node); end
|
def on_signature(node); end
|
||||||
|
|
||||||
@ -220,6 +238,22 @@ module RuboCop::Cop::Sorbet::MutableConstantSorbetAwareBehaviour
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class RuboCop::Cop::Sorbet::ObsoleteStrictMemoization < ::RuboCop::Cop::Base
|
||||||
|
include ::RuboCop::Cop::RangeHelp
|
||||||
|
include ::RuboCop::Cop::MatchRange
|
||||||
|
include ::RuboCop::Cop::Alignment
|
||||||
|
include ::RuboCop::Cop::LineLengthHelp
|
||||||
|
include ::RuboCop::Cop::Sorbet::TargetSorbetVersion
|
||||||
|
extend ::RuboCop::Cop::AutoCorrector
|
||||||
|
extend ::RuboCop::Cop::Sorbet::TargetSorbetVersion::ClassMethods
|
||||||
|
|
||||||
|
def legacy_memoization_pattern?(param0 = T.unsafe(nil)); end
|
||||||
|
def on_begin(node); end
|
||||||
|
def relevant_file?(file); end
|
||||||
|
end
|
||||||
|
|
||||||
|
RuboCop::Cop::Sorbet::ObsoleteStrictMemoization::MSG = T.let(T.unsafe(nil), String)
|
||||||
|
|
||||||
class RuboCop::Cop::Sorbet::OneAncestorPerLine < ::RuboCop::Cop::Cop
|
class RuboCop::Cop::Sorbet::OneAncestorPerLine < ::RuboCop::Cop::Cop
|
||||||
def abstract?(param0); end
|
def abstract?(param0); end
|
||||||
def autocorrect(node); end
|
def autocorrect(node); end
|
||||||
@ -236,8 +270,9 @@ end
|
|||||||
|
|
||||||
RuboCop::Cop::Sorbet::OneAncestorPerLine::MSG = T.let(T.unsafe(nil), String)
|
RuboCop::Cop::Sorbet::OneAncestorPerLine::MSG = T.let(T.unsafe(nil), String)
|
||||||
|
|
||||||
class RuboCop::Cop::Sorbet::RedundantExtendTSig < ::RuboCop::Cop::Cop
|
class RuboCop::Cop::Sorbet::RedundantExtendTSig < ::RuboCop::Cop::Base
|
||||||
def autocorrect(node); end
|
extend ::RuboCop::Cop::AutoCorrector
|
||||||
|
|
||||||
def extend_t_sig?(param0 = T.unsafe(nil)); end
|
def extend_t_sig?(param0 = T.unsafe(nil)); end
|
||||||
def on_send(node); end
|
def on_send(node); end
|
||||||
end
|
end
|
||||||
@ -262,21 +297,22 @@ RuboCop::Cop::Sorbet::SignatureBuildOrder::ORDER = T.let(T.unsafe(nil), Hash)
|
|||||||
|
|
||||||
class RuboCop::Cop::Sorbet::SignatureCop < ::RuboCop::Cop::Cop
|
class RuboCop::Cop::Sorbet::SignatureCop < ::RuboCop::Cop::Cop
|
||||||
def on_block(node); end
|
def on_block(node); end
|
||||||
|
def on_numblock(node); end
|
||||||
def on_signature(_); end
|
def on_signature(_); end
|
||||||
def signature?(param0 = T.unsafe(nil)); end
|
def signature?(param0 = T.unsafe(nil)); end
|
||||||
def with_runtime?(param0 = T.unsafe(nil)); end
|
def with_runtime?(param0 = T.unsafe(nil)); end
|
||||||
def without_runtime?(param0 = T.unsafe(nil)); end
|
def without_runtime?(param0 = T.unsafe(nil)); end
|
||||||
end
|
end
|
||||||
|
|
||||||
class RuboCop::Cop::Sorbet::SingleLineRbiClassModuleDefinitions < ::RuboCop::Cop::Cop
|
class RuboCop::Cop::Sorbet::SingleLineRbiClassModuleDefinitions < ::RuboCop::Cop::Base
|
||||||
def autocorrect(node); end
|
extend ::RuboCop::Cop::AutoCorrector
|
||||||
|
|
||||||
def on_class(node); end
|
def on_class(node); end
|
||||||
def on_module(node); end
|
def on_module(node); end
|
||||||
|
|
||||||
protected
|
private
|
||||||
|
|
||||||
def convert_newlines(source); end
|
def convert_newlines_to_semicolons(source); end
|
||||||
def process_node(node); end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
RuboCop::Cop::Sorbet::SingleLineRbiClassModuleDefinitions::MSG = T.let(T.unsafe(nil), String)
|
RuboCop::Cop::Sorbet::SingleLineRbiClassModuleDefinitions::MSG = T.let(T.unsafe(nil), String)
|
||||||
@ -289,13 +325,30 @@ class RuboCop::Cop::Sorbet::StrongSigil < ::RuboCop::Cop::Sorbet::HasSigil
|
|||||||
def minimum_strictness; end
|
def minimum_strictness; end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
module RuboCop::Cop::Sorbet::TargetSorbetVersion
|
||||||
|
mixes_in_class_methods ::RuboCop::Cop::Sorbet::TargetSorbetVersion::ClassMethods
|
||||||
|
|
||||||
|
def enabled_for_sorbet_static_version?; end
|
||||||
|
def read_sorbet_static_version_from_bundler_lock_file; end
|
||||||
|
def target_sorbet_static_version_from_bundler_lock_file; end
|
||||||
|
|
||||||
|
class << self
|
||||||
|
def included(target); end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
module RuboCop::Cop::Sorbet::TargetSorbetVersion::ClassMethods
|
||||||
|
def minimum_target_sorbet_static_version(version); end
|
||||||
|
def support_target_sorbet_static_version?(version); end
|
||||||
|
end
|
||||||
|
|
||||||
class RuboCop::Cop::Sorbet::TrueSigil < ::RuboCop::Cop::Sorbet::HasSigil
|
class RuboCop::Cop::Sorbet::TrueSigil < ::RuboCop::Cop::Sorbet::HasSigil
|
||||||
def minimum_strictness; end
|
def minimum_strictness; end
|
||||||
end
|
end
|
||||||
|
|
||||||
class RuboCop::Cop::Sorbet::TypeAliasName < ::RuboCop::Cop::Cop
|
class RuboCop::Cop::Sorbet::TypeAliasName < ::RuboCop::Cop::Base
|
||||||
def casgn_type_alias?(param0 = T.unsafe(nil)); end
|
|
||||||
def on_casgn(node); end
|
def on_casgn(node); end
|
||||||
|
def underscored_type_alias?(param0 = T.unsafe(nil)); end
|
||||||
end
|
end
|
||||||
|
|
||||||
RuboCop::Cop::Sorbet::TypeAliasName::MSG = T.let(T.unsafe(nil), String)
|
RuboCop::Cop::Sorbet::TypeAliasName::MSG = T.let(T.unsafe(nil), String)
|
||||||
@ -310,12 +363,13 @@ class RuboCop::Cop::Sorbet::ValidSigil < ::RuboCop::Cop::Cop
|
|||||||
def check_strictness_level(sigil, strictness); end
|
def check_strictness_level(sigil, strictness); end
|
||||||
def check_strictness_not_empty(sigil, strictness); end
|
def check_strictness_not_empty(sigil, strictness); end
|
||||||
def check_strictness_valid(sigil, strictness); end
|
def check_strictness_valid(sigil, strictness); end
|
||||||
|
def exact_strictness; end
|
||||||
def extract_sigil(processed_source); end
|
def extract_sigil(processed_source); end
|
||||||
def extract_strictness(sigil); end
|
def extract_strictness(sigil); end
|
||||||
def minimum_strictness; end
|
def minimum_strictness; end
|
||||||
def require_sigil_on_all_files?; end
|
def require_sigil_on_all_files?; end
|
||||||
def suggested_strictness; end
|
def suggested_strictness; end
|
||||||
def suggested_strictness_level(minimum_strictness, suggested_strictness); end
|
def suggested_strictness_level; end
|
||||||
end
|
end
|
||||||
|
|
||||||
RuboCop::Cop::Sorbet::ValidSigil::SIGIL_REGEX = T.let(T.unsafe(nil), Regexp)
|
RuboCop::Cop::Sorbet::ValidSigil::SIGIL_REGEX = T.let(T.unsafe(nil), Regexp)
|
||||||
@ -7102,6 +7102,7 @@ class RuboCop::AST::NodePattern::Parser
|
|||||||
end
|
end
|
||||||
|
|
||||||
module RuboCop::AST::NodePattern::Sets
|
module RuboCop::AST::NodePattern::Sets
|
||||||
|
SET_ALL_ANY_CLASS_OF_ETC = ::T.let(nil, ::T.untyped)
|
||||||
SET_ARM_INTEL = ::T.let(nil, ::T.untyped)
|
SET_ARM_INTEL = ::T.let(nil, ::T.untyped)
|
||||||
SET_BASH_COMPLETION_ZSH_COMPLETION_FISH_COMPLETION = ::T.let(nil, ::T.untyped)
|
SET_BASH_COMPLETION_ZSH_COMPLETION_FISH_COMPLETION = ::T.let(nil, ::T.untyped)
|
||||||
SET_BUILD_RECOMMENDED_TEST_OPTIONAL = ::T.let(nil, ::T.untyped)
|
SET_BUILD_RECOMMENDED_TEST_OPTIONAL = ::T.let(nil, ::T.untyped)
|
||||||
@ -7111,6 +7112,8 @@ module RuboCop::AST::NodePattern::Sets
|
|||||||
SET_ON_ARM_ON_INTEL_ON_SONOMA_ETC = ::T.let(nil, ::T.untyped)
|
SET_ON_ARM_ON_INTEL_ON_SONOMA_ETC = ::T.let(nil, ::T.untyped)
|
||||||
SET_ON_INTEL_ON_ARM = ::T.let(nil, ::T.untyped)
|
SET_ON_INTEL_ON_ARM = ::T.let(nil, ::T.untyped)
|
||||||
SET_OR_NEWER_OR_OLDER = ::T.let(nil, ::T.untyped)
|
SET_OR_NEWER_OR_OLDER = ::T.let(nil, ::T.untyped)
|
||||||
|
SET_SIG_HELPERS = ::T.let(nil, ::T.untyped)
|
||||||
|
SET_STRUCT_IMMUTABLESTRUCT = ::T.let(nil, ::T.untyped)
|
||||||
SET_SYSTEM_SHELL_OUTPUT_PIPE_OUTPUT = ::T.let(nil, ::T.untyped)
|
SET_SYSTEM_SHELL_OUTPUT_PIPE_OUTPUT = ::T.let(nil, ::T.untyped)
|
||||||
SET_WITH_WITHOUT = ::T.let(nil, ::T.untyped)
|
SET_WITH_WITHOUT = ::T.let(nil, ::T.untyped)
|
||||||
SET____ETC_4 = ::T.let(nil, ::T.untyped)
|
SET____ETC_4 = ::T.let(nil, ::T.untyped)
|
||||||
|
|||||||
@ -14,4 +14,6 @@ Homebrew.setup_gem_environment!(setup_path: false)
|
|||||||
|
|
||||||
$LOAD_PATH.push HOMEBREW_LIBRARY_PATH.to_s unless $LOAD_PATH.include?(HOMEBREW_LIBRARY_PATH.to_s)
|
$LOAD_PATH.push HOMEBREW_LIBRARY_PATH.to_s unless $LOAD_PATH.include?(HOMEBREW_LIBRARY_PATH.to_s)
|
||||||
require_relative "../vendor/bundle/bundler/setup"
|
require_relative "../vendor/bundle/bundler/setup"
|
||||||
|
$LOAD_PATH.unshift "#{HOMEBREW_LIBRARY_PATH}/vendor/bundle/#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/" \
|
||||||
|
"bundler-#{Homebrew::HOMEBREW_BUNDLER_VERSION}/lib"
|
||||||
$LOAD_PATH.uniq!
|
$LOAD_PATH.uniq!
|
||||||
|
|||||||
@ -99,7 +99,7 @@ $:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version
|
|||||||
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/rubocop-performance-1.17.1/lib")
|
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/rubocop-performance-1.17.1/lib")
|
||||||
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/rubocop-rails-2.19.1/lib")
|
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/rubocop-rails-2.19.1/lib")
|
||||||
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/rubocop-rspec-2.20.0/lib")
|
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/rubocop-rspec-2.20.0/lib")
|
||||||
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/rubocop-sorbet-0.7.0/lib")
|
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/rubocop-sorbet-0.7.3/lib")
|
||||||
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/ruby-macho-4.0.0/lib")
|
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/ruby-macho-4.0.0/lib")
|
||||||
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/extensions/universal-darwin-22/#{Gem.extension_api_version}/ruby-prof-1.4.3")
|
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/extensions/universal-darwin-22/#{Gem.extension_api_version}/ruby-prof-1.4.3")
|
||||||
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/ruby-prof-1.4.3/lib")
|
$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/ruby-prof-1.4.3/lib")
|
||||||
|
|||||||
@ -1,127 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require "rubocop"
|
|
||||||
|
|
||||||
module RuboCop
|
|
||||||
module Cop
|
|
||||||
module Sorbet
|
|
||||||
# This cop disallows binding the return value of `T.any`, `T.all`, `T.enum`
|
|
||||||
# to a constant directly. To bind the value, one must use `T.type_alias`.
|
|
||||||
#
|
|
||||||
# @example
|
|
||||||
#
|
|
||||||
# # bad
|
|
||||||
# FooOrBar = T.any(Foo, Bar)
|
|
||||||
#
|
|
||||||
# # good
|
|
||||||
# FooOrBar = T.type_alias { T.any(Foo, Bar) }
|
|
||||||
class BindingConstantWithoutTypeAlias < RuboCop::Cop::Cop
|
|
||||||
def_node_matcher(:binding_unaliased_type?, <<-PATTERN)
|
|
||||||
(casgn _ _ [#not_nil? #not_t_let? #not_dynamic_type_creation_with_block? #not_generic_parameter_decl? #method_needing_aliasing_on_t?])
|
|
||||||
PATTERN
|
|
||||||
|
|
||||||
def_node_matcher(:using_type_alias?, <<-PATTERN)
|
|
||||||
(block
|
|
||||||
(send
|
|
||||||
(const nil? :T) :type_alias)
|
|
||||||
_
|
|
||||||
_
|
|
||||||
)
|
|
||||||
PATTERN
|
|
||||||
|
|
||||||
def_node_matcher(:using_deprecated_type_alias_syntax?, <<-PATTERN)
|
|
||||||
(
|
|
||||||
send
|
|
||||||
(const nil? :T)
|
|
||||||
:type_alias
|
|
||||||
_
|
|
||||||
)
|
|
||||||
PATTERN
|
|
||||||
|
|
||||||
def_node_matcher(:t_let?, <<-PATTERN)
|
|
||||||
(
|
|
||||||
send
|
|
||||||
(const nil? :T)
|
|
||||||
:let
|
|
||||||
_
|
|
||||||
_
|
|
||||||
)
|
|
||||||
PATTERN
|
|
||||||
|
|
||||||
def_node_matcher(:dynamic_type_creation_with_block?, <<-PATTERN)
|
|
||||||
(block
|
|
||||||
(send
|
|
||||||
const :new ...)
|
|
||||||
_
|
|
||||||
_
|
|
||||||
)
|
|
||||||
PATTERN
|
|
||||||
|
|
||||||
def_node_matcher(:generic_parameter_decl_call?, <<-PATTERN)
|
|
||||||
(
|
|
||||||
send nil? {:type_template :type_member} ...
|
|
||||||
)
|
|
||||||
PATTERN
|
|
||||||
|
|
||||||
def_node_matcher(:generic_parameter_decl_block_call?, <<-PATTERN)
|
|
||||||
(block
|
|
||||||
(send nil? {:type_template :type_member} ...) ...
|
|
||||||
)
|
|
||||||
PATTERN
|
|
||||||
|
|
||||||
def_node_search(:method_needing_aliasing_on_t?, <<-PATTERN)
|
|
||||||
(
|
|
||||||
send
|
|
||||||
(const nil? :T)
|
|
||||||
{:any :all :noreturn :class_of :untyped :nilable :self_type :enum :proc}
|
|
||||||
...
|
|
||||||
)
|
|
||||||
PATTERN
|
|
||||||
|
|
||||||
def not_t_let?(node)
|
|
||||||
!t_let?(node)
|
|
||||||
end
|
|
||||||
|
|
||||||
def not_dynamic_type_creation_with_block?(node)
|
|
||||||
!dynamic_type_creation_with_block?(node)
|
|
||||||
end
|
|
||||||
|
|
||||||
def not_generic_parameter_decl?(node)
|
|
||||||
!generic_parameter_decl_call?(node) && !generic_parameter_decl_block_call?(node)
|
|
||||||
end
|
|
||||||
|
|
||||||
def not_nil?(node)
|
|
||||||
!node.nil?
|
|
||||||
end
|
|
||||||
|
|
||||||
def on_casgn(node)
|
|
||||||
return unless binding_unaliased_type?(node) && !using_type_alias?(node.children[2])
|
|
||||||
if using_deprecated_type_alias_syntax?(node.children[2])
|
|
||||||
add_offense(
|
|
||||||
node.children[2],
|
|
||||||
message: "It looks like you're using the old `T.type_alias` syntax. " \
|
|
||||||
"`T.type_alias` now expects a block." \
|
|
||||||
'Run Sorbet with the options "--autocorrect --error-white-list=5043" ' \
|
|
||||||
"to automatically upgrade to the new syntax."
|
|
||||||
)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
add_offense(
|
|
||||||
node.children[2],
|
|
||||||
message: "It looks like you're trying to bind a type to a constant. " \
|
|
||||||
"To do this, you must alias the type using `T.type_alias`."
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
def autocorrect(node)
|
|
||||||
lambda do |corrector|
|
|
||||||
corrector.replace(
|
|
||||||
node.source_range,
|
|
||||||
"T.type_alias { #{node.source} }"
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@ -1,45 +0,0 @@
|
|||||||
# encoding: utf-8
|
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require "rubocop"
|
|
||||||
|
|
||||||
# Correct superclass `send` expressions by constant literals.
|
|
||||||
#
|
|
||||||
# Sorbet, the static checker, is not (yet) able to support constructs on the
|
|
||||||
# following form:
|
|
||||||
#
|
|
||||||
# ```ruby
|
|
||||||
# class Foo < send_expr; end
|
|
||||||
# ```
|
|
||||||
#
|
|
||||||
# Multiple occurences of this can be found in Shopify's code base like:
|
|
||||||
#
|
|
||||||
# ```ruby
|
|
||||||
# class ShopScope < Component::TrustedIdScope[ShopIdentity::ShopId]
|
|
||||||
# ```
|
|
||||||
# or
|
|
||||||
# ```ruby
|
|
||||||
# class ApiClientEligibility < Struct.new(:api_client, :match_results, :shop)
|
|
||||||
# ```
|
|
||||||
module RuboCop
|
|
||||||
module Cop
|
|
||||||
module Sorbet
|
|
||||||
class ForbidSuperclassConstLiteral < RuboCop::Cop::Cop
|
|
||||||
MSG = "Superclasses must only contain constant literals"
|
|
||||||
|
|
||||||
def_node_matcher :not_lit_const_superclass?, <<-PATTERN
|
|
||||||
(class
|
|
||||||
(const ...)
|
|
||||||
(send ...)
|
|
||||||
...
|
|
||||||
)
|
|
||||||
PATTERN
|
|
||||||
|
|
||||||
def on_class(node)
|
|
||||||
return unless not_lit_const_superclass?(node)
|
|
||||||
add_offense(node.child_nodes[1])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@ -1,53 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module RuboCop
|
|
||||||
module Cop
|
|
||||||
module Sorbet
|
|
||||||
# This cop ensures RBI shims do not include a call to extend T::Sig
|
|
||||||
# or to extend T::Helpers
|
|
||||||
#
|
|
||||||
# @example
|
|
||||||
#
|
|
||||||
# # bad
|
|
||||||
# module SomeModule
|
|
||||||
# extend T::Sig
|
|
||||||
# extend T::Helpers
|
|
||||||
#
|
|
||||||
# sig { returns(String) }
|
|
||||||
# def foo; end
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# # good
|
|
||||||
# module SomeModule
|
|
||||||
# sig { returns(String) }
|
|
||||||
# def foo; end
|
|
||||||
# end
|
|
||||||
class ForbidExtendTSigHelpersInShims < RuboCop::Cop::Cop
|
|
||||||
include RangeHelp
|
|
||||||
|
|
||||||
MSG = "Extending T::Sig or T::Helpers in a shim is unnecessary"
|
|
||||||
RESTRICT_ON_SEND = [:extend]
|
|
||||||
|
|
||||||
def_node_matcher :extend_t_sig?, <<~PATTERN
|
|
||||||
(send nil? :extend (const (const nil? :T) :Sig))
|
|
||||||
PATTERN
|
|
||||||
|
|
||||||
def_node_matcher :extend_t_helpers?, <<~PATTERN
|
|
||||||
(send nil? :extend (const (const nil? :T) :Helpers))
|
|
||||||
PATTERN
|
|
||||||
|
|
||||||
def autocorrect(node)
|
|
||||||
-> (corrector) do
|
|
||||||
corrector.remove(
|
|
||||||
range_by_whole_lines(node.source_range, include_final_newline: true)
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def on_send(node)
|
|
||||||
add_offense(node) if extend_t_helpers?(node) || extend_t_sig?(node)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@ -1,59 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require "rubocop"
|
|
||||||
|
|
||||||
module RuboCop
|
|
||||||
module Cop
|
|
||||||
module Sorbet
|
|
||||||
# This cop disallows using `.override(allow_incompatible: true)`.
|
|
||||||
# Using `allow_incompatible` suggests a violation of the Liskov
|
|
||||||
# Substitution Principle, meaning that a subclass is not a valid
|
|
||||||
# subtype of it's superclass. This Cop prevents these design smells
|
|
||||||
# from occurring.
|
|
||||||
#
|
|
||||||
# @example
|
|
||||||
#
|
|
||||||
# # bad
|
|
||||||
# sig.override(allow_incompatible: true)
|
|
||||||
#
|
|
||||||
# # good
|
|
||||||
# sig.override
|
|
||||||
class AllowIncompatibleOverride < RuboCop::Cop::Cop
|
|
||||||
def_node_search(:sig?, <<-PATTERN)
|
|
||||||
(
|
|
||||||
send
|
|
||||||
nil?
|
|
||||||
:sig
|
|
||||||
...
|
|
||||||
)
|
|
||||||
PATTERN
|
|
||||||
|
|
||||||
def not_nil?(node)
|
|
||||||
!node.nil?
|
|
||||||
end
|
|
||||||
|
|
||||||
def_node_search(:allow_incompatible?, <<-PATTERN)
|
|
||||||
(pair (sym :allow_incompatible) (true))
|
|
||||||
PATTERN
|
|
||||||
|
|
||||||
def_node_matcher(:allow_incompatible_override?, <<-PATTERN)
|
|
||||||
(
|
|
||||||
send
|
|
||||||
[#not_nil? #sig?]
|
|
||||||
:override
|
|
||||||
[#not_nil? #allow_incompatible?]
|
|
||||||
)
|
|
||||||
PATTERN
|
|
||||||
|
|
||||||
def on_send(node)
|
|
||||||
return unless allow_incompatible_override?(node)
|
|
||||||
add_offense(
|
|
||||||
node.children[2],
|
|
||||||
message: "Usage of `allow_incompatible` suggests a violation of the Liskov Substitution Principle. "\
|
|
||||||
"Instead, strive to write interfaces which respect subtyping principles and remove `allow_incompatible`",
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@ -1,45 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require "rubocop"
|
|
||||||
|
|
||||||
module RuboCop
|
|
||||||
module Cop
|
|
||||||
module Sorbet
|
|
||||||
# This cop ensures all constants used as `T.type_alias` are using CamelCase.
|
|
||||||
#
|
|
||||||
# @example
|
|
||||||
#
|
|
||||||
# # bad
|
|
||||||
# FOO_OR_BAR = T.type_alias { T.any(Foo, Bar) }
|
|
||||||
#
|
|
||||||
# # good
|
|
||||||
# FooOrBar = T.type_alias { T.any(Foo, Bar) }
|
|
||||||
class TypeAliasName < RuboCop::Cop::Cop
|
|
||||||
MSG = "Type alias constant name should be in CamelCase"
|
|
||||||
|
|
||||||
def_node_matcher(:casgn_type_alias?, <<-PATTERN)
|
|
||||||
(casgn
|
|
||||||
_
|
|
||||||
_
|
|
||||||
(block
|
|
||||||
(send
|
|
||||||
(const nil? :T) :type_alias)
|
|
||||||
_
|
|
||||||
_
|
|
||||||
))
|
|
||||||
PATTERN
|
|
||||||
|
|
||||||
def on_casgn(node)
|
|
||||||
return unless casgn_type_alias?(node)
|
|
||||||
|
|
||||||
name = node.children[1]
|
|
||||||
|
|
||||||
# From https://github.com/rubocop/rubocop/blob/master/lib/rubocop/cop/naming/class_and_module_camel_case.rb
|
|
||||||
return unless /_/.match?(name)
|
|
||||||
|
|
||||||
add_offense(node)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@ -1,20 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
# The original code is from https://github.com/rubocop-hq/rubocop-rspec/blob/master/lib/rubocop/rspec/inject.rb
|
|
||||||
# See https://github.com/rubocop-hq/rubocop-rspec/blob/master/MIT-LICENSE.md
|
|
||||||
module RuboCop
|
|
||||||
module Sorbet
|
|
||||||
# Because RuboCop doesn't yet support plugins, we have to monkey patch in a
|
|
||||||
# bit of our configuration.
|
|
||||||
module Inject
|
|
||||||
def self.defaults!
|
|
||||||
path = CONFIG_DEFAULT.to_s
|
|
||||||
hash = ConfigLoader.send(:load_yaml_configuration, path)
|
|
||||||
config = Config.new(hash, path).tap(&:make_excludes_absolute)
|
|
||||||
puts "configuration from #{path}" if ConfigLoader.debug?
|
|
||||||
config = ConfigLoader.merge_with_default(config, path)
|
|
||||||
ConfigLoader.instance_variable_set(:@default_configuration, config)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@ -120,7 +120,8 @@ Sorbet/HasSigil:
|
|||||||
Description: 'Makes the Sorbet typed sigil mandatory in all files.'
|
Description: 'Makes the Sorbet typed sigil mandatory in all files.'
|
||||||
Enabled: false
|
Enabled: false
|
||||||
SuggestedStrictness: "false"
|
SuggestedStrictness: "false"
|
||||||
MinimumStrictness: "false"
|
MinimumStrictness: nil
|
||||||
|
ExactStrictness: nil
|
||||||
VersionAdded: 0.3.3
|
VersionAdded: 0.3.3
|
||||||
Include:
|
Include:
|
||||||
- "**/*.{rb,rbi,rake,ru}"
|
- "**/*.{rb,rbi,rake,ru}"
|
||||||
@ -141,6 +142,13 @@ Sorbet/IgnoreSigil:
|
|||||||
- db/**/*.rb
|
- db/**/*.rb
|
||||||
- script/**/*
|
- script/**/*
|
||||||
|
|
||||||
|
Sorbet/ImplicitConversionMethod:
|
||||||
|
Description: >-
|
||||||
|
This cop disallows declaring implicit conversion methods, as sorbet does
|
||||||
|
not support implicit conversion.
|
||||||
|
Enabled: false
|
||||||
|
VersionAdded: '<<next>>'
|
||||||
|
|
||||||
Sorbet/KeywordArgumentOrdering:
|
Sorbet/KeywordArgumentOrdering:
|
||||||
Description: >-
|
Description: >-
|
||||||
Enforces a compatible keyword arguments with Sorbet.
|
Enforces a compatible keyword arguments with Sorbet.
|
||||||
@ -151,6 +159,18 @@ Sorbet/KeywordArgumentOrdering:
|
|||||||
Enabled: true
|
Enabled: true
|
||||||
VersionAdded: 0.2.0
|
VersionAdded: 0.2.0
|
||||||
|
|
||||||
|
Sorbet/ObsoleteStrictMemoization:
|
||||||
|
Description: >-
|
||||||
|
This cop checks for the obsolete pattern for initializing instance variables that was required for older Sorbet
|
||||||
|
versions in `#typed: strict` files.
|
||||||
|
|
||||||
|
It's no longer required, as of Sorbet 0.5.10210
|
||||||
|
See https://sorbet.org/docs/type-assertions#put-type-assertions-behind-memoization
|
||||||
|
Enabled: true
|
||||||
|
VersionAdded: '0.7.1'
|
||||||
|
Safe: true
|
||||||
|
SafeAutoCorrect: true
|
||||||
|
|
||||||
Sorbet/OneAncestorPerLine:
|
Sorbet/OneAncestorPerLine:
|
||||||
Description: 'Enforces one ancestor per call to requires_ancestor'
|
Description: 'Enforces one ancestor per call to requires_ancestor'
|
||||||
Enabled: false
|
Enabled: false
|
||||||
@ -235,7 +255,8 @@ Sorbet/ValidSigil:
|
|||||||
Enabled: true
|
Enabled: true
|
||||||
RequireSigilOnAllFiles: false
|
RequireSigilOnAllFiles: false
|
||||||
SuggestedStrictness: "false"
|
SuggestedStrictness: "false"
|
||||||
MinimumStrictness: "false"
|
MinimumStrictness: nil
|
||||||
|
ExactStrictness: nil
|
||||||
VersionAdded: 0.3.3
|
VersionAdded: 0.3.3
|
||||||
Include:
|
Include:
|
||||||
- "**/*.{rb,rbi,rake,ru}"
|
- "**/*.{rb,rbi,rake,ru}"
|
||||||
@ -0,0 +1,105 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "rubocop"
|
||||||
|
|
||||||
|
module RuboCop
|
||||||
|
module Cop
|
||||||
|
module Sorbet
|
||||||
|
# Disallows binding the return value of `T.any`, `T.all`, `T.enum`
|
||||||
|
# to a constant directly. To bind the value, one must use `T.type_alias`.
|
||||||
|
#
|
||||||
|
# @example
|
||||||
|
#
|
||||||
|
# # bad
|
||||||
|
# FooOrBar = T.any(Foo, Bar)
|
||||||
|
#
|
||||||
|
# # good
|
||||||
|
# FooOrBar = T.type_alias { T.any(Foo, Bar) }
|
||||||
|
class BindingConstantWithoutTypeAlias < RuboCop::Cop::Base
|
||||||
|
extend AutoCorrector
|
||||||
|
|
||||||
|
MSG = "It looks like you're trying to bind a type to a constant. " \
|
||||||
|
"To do this, you must alias the type using `T.type_alias`."
|
||||||
|
WITHOUT_BLOCK_MSG = "It looks like you're using the old `T.type_alias` syntax. " \
|
||||||
|
"`T.type_alias` now expects a block." \
|
||||||
|
'Run Sorbet with the options "--autocorrect --error-white-list=5043" ' \
|
||||||
|
"to automatically upgrade to the new syntax."
|
||||||
|
|
||||||
|
# @!method type_alias_without_block(node)
|
||||||
|
def_node_matcher :type_alias_without_block, <<~PATTERN
|
||||||
|
(send
|
||||||
|
(const {nil? cbase} :T)
|
||||||
|
:type_alias
|
||||||
|
$_
|
||||||
|
)
|
||||||
|
PATTERN
|
||||||
|
|
||||||
|
# @!method type_alias_with_block?(node)
|
||||||
|
def_node_matcher :type_alias_with_block?, <<~PATTERN
|
||||||
|
(block
|
||||||
|
(send
|
||||||
|
(const {nil? cbase} :T)
|
||||||
|
:type_alias)
|
||||||
|
...
|
||||||
|
)
|
||||||
|
PATTERN
|
||||||
|
|
||||||
|
# @!method requires_type_alias?(node)
|
||||||
|
def_node_matcher :requires_type_alias?, <<~PATTERN
|
||||||
|
(send
|
||||||
|
(const {nil? cbase} :T)
|
||||||
|
{
|
||||||
|
:all
|
||||||
|
:any
|
||||||
|
:class_of
|
||||||
|
:nilable
|
||||||
|
:noreturn
|
||||||
|
:proc
|
||||||
|
:self_type
|
||||||
|
:untyped
|
||||||
|
}
|
||||||
|
...
|
||||||
|
)
|
||||||
|
PATTERN
|
||||||
|
|
||||||
|
def on_casgn(node)
|
||||||
|
expression = node.expression
|
||||||
|
return if expression.nil? # multiple assignment
|
||||||
|
|
||||||
|
type_alias_without_block(expression) do |type|
|
||||||
|
return add_offense(expression, message: WITHOUT_BLOCK_MSG) do |corrector|
|
||||||
|
corrector.replace(expression, "T.type_alias { #{type.source} }")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return if type_alias_with_block?(expression)
|
||||||
|
|
||||||
|
requires_type_alias?(send_leaf(expression)) do
|
||||||
|
return add_offense(expression) do |corrector|
|
||||||
|
corrector.replace(expression, "T.type_alias { #{expression.source} }")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# Given nested send nodes, returns the leaf with explicit receiver.
|
||||||
|
#
|
||||||
|
# i.e. in Ruby
|
||||||
|
#
|
||||||
|
# a.b.c.d.e.f
|
||||||
|
# ^^^
|
||||||
|
#
|
||||||
|
# i.e. in AST
|
||||||
|
#
|
||||||
|
# (send (send (send (send (send (send nil :a) :b) :c) :d) :e) :f)
|
||||||
|
# ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
#
|
||||||
|
def send_leaf(node)
|
||||||
|
node = node.receiver while node&.receiver&.send_type?
|
||||||
|
node
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -3,7 +3,7 @@
|
|||||||
module RuboCop
|
module RuboCop
|
||||||
module Cop
|
module Cop
|
||||||
module Sorbet
|
module Sorbet
|
||||||
# This cop ensures that callback conditionals are bound to the right type
|
# Ensures that callback conditionals are bound to the right type
|
||||||
# so that they are type checked properly.
|
# so that they are type checked properly.
|
||||||
#
|
#
|
||||||
# Auto-correction is unsafe because other libraries define similar style callbacks as Rails, but don't always need
|
# Auto-correction is unsafe because other libraries define similar style callbacks as Rails, but don't always need
|
||||||
@ -32,16 +32,44 @@ module RuboCop
|
|||||||
# true
|
# true
|
||||||
# end
|
# end
|
||||||
# end
|
# end
|
||||||
class CallbackConditionalsBinding < RuboCop::Cop::Cop
|
class CallbackConditionalsBinding < RuboCop::Cop::Cop # rubocop:todo InternalAffairs/InheritDeprecatedCopClass
|
||||||
CALLBACKS = [
|
CALLBACKS = [
|
||||||
:validate, :validates, :validates_with, :before_validation, :around_validation, :before_create,
|
:validate,
|
||||||
:before_save, :before_destroy, :before_update, :after_create, :after_save, :after_destroy,
|
:validates,
|
||||||
:after_update, :after_touch, :after_initialize, :after_find, :around_create, :around_save,
|
:validates_with,
|
||||||
:around_destroy, :around_update, :before_commit, :after_commit, :after_create_commit,
|
:before_validation,
|
||||||
:after_destroy_commit, :after_rollback, :after_save_commit, :after_update_commit,
|
:around_validation,
|
||||||
:before_action, :prepend_before_action, :append_before_action, :around_action,
|
:before_create,
|
||||||
:prepend_around_action, :append_around_action, :after_action, :prepend_after_action,
|
:before_save,
|
||||||
:append_after_action
|
:before_destroy,
|
||||||
|
:before_update,
|
||||||
|
:after_create,
|
||||||
|
:after_save,
|
||||||
|
:after_destroy,
|
||||||
|
:after_update,
|
||||||
|
:after_touch,
|
||||||
|
:after_initialize,
|
||||||
|
:after_find,
|
||||||
|
:around_create,
|
||||||
|
:around_save,
|
||||||
|
:around_destroy,
|
||||||
|
:around_update,
|
||||||
|
:before_commit,
|
||||||
|
:after_commit,
|
||||||
|
:after_create_commit,
|
||||||
|
:after_destroy_commit,
|
||||||
|
:after_rollback,
|
||||||
|
:after_save_commit,
|
||||||
|
:after_update_commit,
|
||||||
|
:before_action,
|
||||||
|
:prepend_before_action,
|
||||||
|
:append_before_action,
|
||||||
|
:around_action,
|
||||||
|
:prepend_around_action,
|
||||||
|
:append_around_action,
|
||||||
|
:after_action,
|
||||||
|
:prepend_after_action,
|
||||||
|
:append_after_action,
|
||||||
].freeze
|
].freeze
|
||||||
|
|
||||||
def autocorrect(node)
|
def autocorrect(node)
|
||||||
@ -132,7 +160,7 @@ module RuboCop
|
|||||||
unless block.source.include?("T.bind(self")
|
unless block.source.include?("T.bind(self")
|
||||||
add_offense(
|
add_offense(
|
||||||
node,
|
node,
|
||||||
message: "Callback conditionals should be bound to the right type. Use T.bind(self, #{expected_class})"
|
message: "Callback conditionals should be bound to the right type. Use T.bind(self, #{expected_class})",
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -5,7 +5,7 @@ require "rubocop"
|
|||||||
module RuboCop
|
module RuboCop
|
||||||
module Cop
|
module Cop
|
||||||
module Sorbet
|
module Sorbet
|
||||||
# This cop disallows the calls that are used to get constants fom Strings
|
# Disallows the calls that are used to get constants fom Strings
|
||||||
# such as +constantize+, +const_get+, and +constants+.
|
# such as +constantize+, +const_get+, and +constants+.
|
||||||
#
|
#
|
||||||
# The goal of this cop is to make the code easier to statically analyze,
|
# The goal of this cop is to make the code easier to statically analyze,
|
||||||
@ -33,18 +33,20 @@ module RuboCop
|
|||||||
#
|
#
|
||||||
# # good
|
# # good
|
||||||
# { "User" => User }.fetch(class_name)
|
# { "User" => User }.fetch(class_name)
|
||||||
class ConstantsFromStrings < ::RuboCop::Cop::Cop
|
class ConstantsFromStrings < ::RuboCop::Cop::Cop # rubocop:todo InternalAffairs/InheritDeprecatedCopClass
|
||||||
|
# @!method constant_from_string?(node)
|
||||||
def_node_matcher(:constant_from_string?, <<-PATTERN)
|
def_node_matcher(:constant_from_string?, <<-PATTERN)
|
||||||
(send _ {:constantize :constants :const_get} ...)
|
(send _ {:constantize :constants :const_get} ...)
|
||||||
PATTERN
|
PATTERN
|
||||||
|
|
||||||
def on_send(node)
|
def on_send(node)
|
||||||
return unless constant_from_string?(node)
|
return unless constant_from_string?(node)
|
||||||
|
|
||||||
add_offense(
|
add_offense(
|
||||||
node,
|
node,
|
||||||
location: :selector,
|
location: :selector,
|
||||||
message: "Don't use `#{node.method_name}`, it makes the code harder to understand, less editor-friendly, " \
|
message: "Don't use `#{node.method_name}`, it makes the code harder to understand, less editor-friendly, " \
|
||||||
"and impossible to analyze. Replace `#{node.method_name}` with a case/when or a hash."
|
"and impossible to analyze. Replace `#{node.method_name}` with a case/when or a hash.",
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -3,34 +3,35 @@
|
|||||||
|
|
||||||
require "rubocop"
|
require "rubocop"
|
||||||
|
|
||||||
# Correct `send` expressions in include statements by constant literals.
|
|
||||||
#
|
|
||||||
# Sorbet, the static checker, is not (yet) able to support constructs on the
|
|
||||||
# following form:
|
|
||||||
#
|
|
||||||
# ```ruby
|
|
||||||
# class MyClass
|
|
||||||
# include send_expr
|
|
||||||
# end
|
|
||||||
# ```
|
|
||||||
#
|
|
||||||
# Multiple occurences of this can be found in Shopify's code base like:
|
|
||||||
#
|
|
||||||
# ```ruby
|
|
||||||
# include Rails.application.routes.url_helpers
|
|
||||||
# ```
|
|
||||||
# or
|
|
||||||
# ```ruby
|
|
||||||
# include Polaris::Engine.helpers
|
|
||||||
# ```
|
|
||||||
module RuboCop
|
module RuboCop
|
||||||
module Cop
|
module Cop
|
||||||
module Sorbet
|
module Sorbet
|
||||||
class ForbidIncludeConstLiteral < RuboCop::Cop::Cop
|
# Correct `send` expressions in include statements by constant literals.
|
||||||
|
#
|
||||||
|
# Sorbet, the static checker, is not (yet) able to support constructs on the
|
||||||
|
# following form:
|
||||||
|
#
|
||||||
|
# ```ruby
|
||||||
|
# class MyClass
|
||||||
|
# include send_expr
|
||||||
|
# end
|
||||||
|
# ```
|
||||||
|
#
|
||||||
|
# Multiple occurences of this can be found in Shopify's code base like:
|
||||||
|
#
|
||||||
|
# ```ruby
|
||||||
|
# include Rails.application.routes.url_helpers
|
||||||
|
# ```
|
||||||
|
# or
|
||||||
|
# ```ruby
|
||||||
|
# include Polaris::Engine.helpers
|
||||||
|
# ```
|
||||||
|
class ForbidIncludeConstLiteral < RuboCop::Cop::Cop # rubocop:todo InternalAffairs/InheritDeprecatedCopClass
|
||||||
MSG = "Includes must only contain constant literals"
|
MSG = "Includes must only contain constant literals"
|
||||||
|
|
||||||
attr_accessor :used_names
|
attr_accessor :used_names
|
||||||
|
|
||||||
|
# @!method not_lit_const_include?(node)
|
||||||
def_node_matcher :not_lit_const_include?, <<-PATTERN
|
def_node_matcher :not_lit_const_include?, <<-PATTERN
|
||||||
(send nil? {:include :extend :prepend}
|
(send nil? {:include :extend :prepend}
|
||||||
$_
|
$_
|
||||||
@ -46,18 +47,21 @@ module RuboCop
|
|||||||
return unless not_lit_const_include?(node) do |send_argument|
|
return unless not_lit_const_include?(node) do |send_argument|
|
||||||
![:const, :self].include?(send_argument.type)
|
![:const, :self].include?(send_argument.type)
|
||||||
end
|
end
|
||||||
|
|
||||||
parent = node.parent
|
parent = node.parent
|
||||||
return unless parent
|
return unless parent
|
||||||
|
|
||||||
parent = parent.parent if [:begin, :block].include?(parent.type)
|
parent = parent.parent if [:begin, :block].include?(parent.type)
|
||||||
return unless [:module, :class, :sclass].include?(parent.type)
|
return unless [:module, :class, :sclass].include?(parent.type)
|
||||||
|
|
||||||
add_offense(node)
|
add_offense(node)
|
||||||
end
|
end
|
||||||
|
|
||||||
def autocorrect(node)
|
def autocorrect(node)
|
||||||
lambda do |corrector|
|
lambda do |corrector|
|
||||||
corrector.replace(
|
corrector.replace(
|
||||||
node.source_range,
|
node,
|
||||||
"T.unsafe(self).#{node.source}"
|
"T.unsafe(self).#{node.source}",
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -0,0 +1,44 @@
|
|||||||
|
# encoding: utf-8
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "rubocop"
|
||||||
|
|
||||||
|
module RuboCop
|
||||||
|
module Cop
|
||||||
|
module Sorbet
|
||||||
|
# Correct superclass `send` expressions by constant literals.
|
||||||
|
#
|
||||||
|
# Sorbet, the static checker, is not (yet) able to support constructs on the
|
||||||
|
# following form:
|
||||||
|
#
|
||||||
|
# ```ruby
|
||||||
|
# class Foo < send_expr; end
|
||||||
|
# ```
|
||||||
|
#
|
||||||
|
# Multiple occurences of this can be found in Shopify's code base like:
|
||||||
|
#
|
||||||
|
# ```ruby
|
||||||
|
# class ShopScope < Component::TrustedIdScope[ShopIdentity::ShopId]
|
||||||
|
# ```
|
||||||
|
# or
|
||||||
|
# ```ruby
|
||||||
|
# class ApiClientEligibility < Struct.new(:api_client, :match_results, :shop)
|
||||||
|
# ```
|
||||||
|
|
||||||
|
class ForbidSuperclassConstLiteral < RuboCop::Cop::Base
|
||||||
|
MSG = "Superclasses must only contain constant literals"
|
||||||
|
|
||||||
|
# @!method dynamic_superclass?(node)
|
||||||
|
def_node_matcher :dynamic_superclass?, <<-PATTERN
|
||||||
|
(class (const ...) $(send ...) ...)
|
||||||
|
PATTERN
|
||||||
|
|
||||||
|
def on_class(node)
|
||||||
|
dynamic_superclass?(node) do |superclass|
|
||||||
|
add_offense(superclass)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -5,7 +5,7 @@ require "rubocop"
|
|||||||
module RuboCop
|
module RuboCop
|
||||||
module Cop
|
module Cop
|
||||||
module Sorbet
|
module Sorbet
|
||||||
# This cop disallows using `T.unsafe` anywhere.
|
# Disallows using `T.unsafe` anywhere.
|
||||||
#
|
#
|
||||||
# @example
|
# @example
|
||||||
#
|
#
|
||||||
@ -14,11 +14,15 @@ module RuboCop
|
|||||||
#
|
#
|
||||||
# # good
|
# # good
|
||||||
# foo
|
# foo
|
||||||
class ForbidTUnsafe < RuboCop::Cop::Cop
|
class ForbidTUnsafe < RuboCop::Cop::Base
|
||||||
|
MSG = "Do not use `T.unsafe`."
|
||||||
|
RESTRICT_ON_SEND = [:unsafe].freeze
|
||||||
|
|
||||||
|
# @!method t_unsafe?(node)
|
||||||
def_node_matcher(:t_unsafe?, "(send (const nil? :T) :unsafe _)")
|
def_node_matcher(:t_unsafe?, "(send (const nil? :T) :unsafe _)")
|
||||||
|
|
||||||
def on_send(node)
|
def on_send(node)
|
||||||
add_offense(node, message: "Do not use `T.unsafe`.") if t_unsafe?(node)
|
add_offense(node) if t_unsafe?(node)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -5,7 +5,7 @@ require "rubocop"
|
|||||||
module RuboCop
|
module RuboCop
|
||||||
module Cop
|
module Cop
|
||||||
module Sorbet
|
module Sorbet
|
||||||
# This cop disallows using `T.untyped` anywhere.
|
# Disallows using `T.untyped` anywhere.
|
||||||
#
|
#
|
||||||
# @example
|
# @example
|
||||||
#
|
#
|
||||||
@ -17,11 +17,15 @@ module RuboCop
|
|||||||
# sig { params(my_argument: String).void }
|
# sig { params(my_argument: String).void }
|
||||||
# def foo(my_argument); end
|
# def foo(my_argument); end
|
||||||
#
|
#
|
||||||
class ForbidTUntyped < RuboCop::Cop::Cop
|
class ForbidTUntyped < RuboCop::Cop::Base
|
||||||
|
MSG = "Do not use `T.untyped`."
|
||||||
|
RESTRICT_ON_SEND = [:untyped].freeze
|
||||||
|
|
||||||
|
# @!method t_untyped?(node)
|
||||||
def_node_matcher(:t_untyped?, "(send (const nil? :T) :untyped)")
|
def_node_matcher(:t_untyped?, "(send (const nil? :T) :untyped)")
|
||||||
|
|
||||||
def on_send(node)
|
def on_send(node)
|
||||||
add_offense(node, message: "Do not use `T.untyped`.") if t_untyped?(node)
|
add_offense(node) if t_untyped?(node)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -6,7 +6,7 @@ require "rubocop"
|
|||||||
module RuboCop
|
module RuboCop
|
||||||
module Cop
|
module Cop
|
||||||
module Sorbet
|
module Sorbet
|
||||||
# This cop disallows use of `T.untyped` or `T.nilable(T.untyped)`
|
# Disallows use of `T.untyped` or `T.nilable(T.untyped)`
|
||||||
# as a prop type for `T::Struct` or `T::ImmutableStruct`.
|
# as a prop type for `T::Struct` or `T::ImmutableStruct`.
|
||||||
#
|
#
|
||||||
# @example
|
# @example
|
||||||
@ -22,38 +22,40 @@ module RuboCop
|
|||||||
# const :foo, Integer
|
# const :foo, Integer
|
||||||
# prop :bar, T.nilable(String)
|
# prop :bar, T.nilable(String)
|
||||||
# end
|
# end
|
||||||
class ForbidUntypedStructProps < RuboCop::Cop::Cop
|
class ForbidUntypedStructProps < RuboCop::Cop::Base
|
||||||
MSG = "Struct props cannot be T.untyped"
|
MSG = "Struct props cannot be T.untyped"
|
||||||
|
|
||||||
|
# @!method t_struct(node)
|
||||||
def_node_matcher :t_struct, <<~PATTERN
|
def_node_matcher :t_struct, <<~PATTERN
|
||||||
(const (const nil? :T) :Struct)
|
(const (const nil? :T) {:Struct :ImmutableStruct})
|
||||||
PATTERN
|
|
||||||
|
|
||||||
def_node_matcher :t_immutable_struct, <<~PATTERN
|
|
||||||
(const (const nil? :T) :ImmutableStruct)
|
|
||||||
PATTERN
|
PATTERN
|
||||||
|
|
||||||
|
# @!method t_untyped(node)
|
||||||
def_node_matcher :t_untyped, <<~PATTERN
|
def_node_matcher :t_untyped, <<~PATTERN
|
||||||
(send (const nil? :T) :untyped)
|
(send (const nil? :T) :untyped)
|
||||||
PATTERN
|
PATTERN
|
||||||
|
|
||||||
|
# @!method t_nilable_untyped(node)
|
||||||
def_node_matcher :t_nilable_untyped, <<~PATTERN
|
def_node_matcher :t_nilable_untyped, <<~PATTERN
|
||||||
(send (const nil? :T) :nilable {#t_untyped #t_nilable_untyped})
|
(send (const nil? :T) :nilable {#t_untyped #t_nilable_untyped})
|
||||||
PATTERN
|
PATTERN
|
||||||
|
|
||||||
|
# @!method subclass_of_t_struct?(node)
|
||||||
def_node_matcher :subclass_of_t_struct?, <<~PATTERN
|
def_node_matcher :subclass_of_t_struct?, <<~PATTERN
|
||||||
(class (const ...) {#t_struct #t_immutable_struct} ...)
|
(class (const ...) #t_struct ...)
|
||||||
PATTERN
|
PATTERN
|
||||||
|
|
||||||
|
# @!method untyped_props(node)
|
||||||
|
# Search for untyped prop/const declarations and capture their types
|
||||||
def_node_search :untyped_props, <<~PATTERN
|
def_node_search :untyped_props, <<~PATTERN
|
||||||
(send nil? {:prop :const} _ {#t_untyped #t_nilable_untyped} ...)
|
(send nil? {:prop :const} _ ${#t_untyped #t_nilable_untyped} ...)
|
||||||
PATTERN
|
PATTERN
|
||||||
|
|
||||||
def on_class(node)
|
def on_class(node)
|
||||||
return unless subclass_of_t_struct?(node)
|
return unless subclass_of_t_struct?(node)
|
||||||
|
|
||||||
untyped_props(node).each do |untyped_prop|
|
untyped_props(node).each do |prop_type|
|
||||||
add_offense(untyped_prop.child_nodes[1])
|
add_offense(prop_type)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -0,0 +1,56 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "rubocop"
|
||||||
|
|
||||||
|
module RuboCop
|
||||||
|
module Cop
|
||||||
|
module Sorbet
|
||||||
|
# Disallows declaring implicit conversion methods.
|
||||||
|
# Since Sorbet is a nominal (not structural) type system,
|
||||||
|
# implicit conversion is currently unsupported.
|
||||||
|
#
|
||||||
|
# @example
|
||||||
|
#
|
||||||
|
# # bad
|
||||||
|
# def to_str; end
|
||||||
|
#
|
||||||
|
# # good
|
||||||
|
# def to_str(x); end
|
||||||
|
#
|
||||||
|
# # bad
|
||||||
|
# def self.to_str; end
|
||||||
|
#
|
||||||
|
# # good
|
||||||
|
# def self.to_str(x); end
|
||||||
|
#
|
||||||
|
# # bad
|
||||||
|
# alias to_str to_s
|
||||||
|
#
|
||||||
|
# @see https://docs.ruby-lang.org/en/master/implicit_conversion_rdoc.html
|
||||||
|
# @note Since the arity of aliased methods is not checked, false positives may result.
|
||||||
|
class ImplicitConversionMethod < RuboCop::Cop::Base
|
||||||
|
IMPLICIT_CONVERSION_METHODS = [:to_ary, :to_int, :to_hash, :to_str].freeze
|
||||||
|
MSG = "Avoid implicit conversion methods, as Sorbet does not support them. " \
|
||||||
|
"Explicity convert to the desired type instead."
|
||||||
|
RESTRICT_ON_SEND = [:alias_method].freeze
|
||||||
|
|
||||||
|
def on_alias(node)
|
||||||
|
new_id = node.new_identifier
|
||||||
|
add_offense(new_id) if IMPLICIT_CONVERSION_METHODS.include?(new_id.value)
|
||||||
|
end
|
||||||
|
|
||||||
|
def on_def(node)
|
||||||
|
return unless IMPLICIT_CONVERSION_METHODS.include?(node.method_name)
|
||||||
|
return unless node.arguments.empty?
|
||||||
|
|
||||||
|
add_offense(node)
|
||||||
|
end
|
||||||
|
alias_method :on_defs, :on_def
|
||||||
|
|
||||||
|
def on_send(node)
|
||||||
|
add_offense(node.first_argument) if IMPLICIT_CONVERSION_METHODS.include?(node.first_argument.value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -0,0 +1,49 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module RuboCop
|
||||||
|
module Cop
|
||||||
|
module Sorbet
|
||||||
|
module TargetSorbetVersion
|
||||||
|
class << self
|
||||||
|
def included(target)
|
||||||
|
target.extend(ClassMethods)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
module ClassMethods
|
||||||
|
# The version of the Sorbet static type checker required by this cop
|
||||||
|
def minimum_target_sorbet_static_version(version)
|
||||||
|
@minimum_target_sorbet_static_version = Gem::Version.new(version)
|
||||||
|
end
|
||||||
|
|
||||||
|
def support_target_sorbet_static_version?(version)
|
||||||
|
@minimum_target_sorbet_static_version <= Gem::Version.new(version)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def enabled_for_sorbet_static_version?
|
||||||
|
sorbet_static_version = target_sorbet_static_version_from_bundler_lock_file
|
||||||
|
return false unless sorbet_static_version
|
||||||
|
|
||||||
|
self.class.support_target_sorbet_static_version?(sorbet_static_version)
|
||||||
|
end
|
||||||
|
|
||||||
|
def target_sorbet_static_version_from_bundler_lock_file
|
||||||
|
# Do memoization with the `defined?` pattern since sorbet-static version might be `nil`
|
||||||
|
if defined?(@target_sorbet_static_version_from_bundler_lock_file)
|
||||||
|
@target_sorbet_static_version_from_bundler_lock_file
|
||||||
|
else
|
||||||
|
@target_sorbet_static_version_from_bundler_lock_file = read_sorbet_static_version_from_bundler_lock_file
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def read_sorbet_static_version_from_bundler_lock_file
|
||||||
|
require "bundler"
|
||||||
|
::Bundler.locked_gems.specs.find { |spec| spec.name == "sorbet-static" }&.version
|
||||||
|
rescue LoadError, Bundler::GemfileNotFound
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -6,10 +6,13 @@ module RuboCop
|
|||||||
module Cop
|
module Cop
|
||||||
module Sorbet
|
module Sorbet
|
||||||
module MutableConstantSorbetAwareBehaviour
|
module MutableConstantSorbetAwareBehaviour
|
||||||
def self.prepended(base)
|
class << self
|
||||||
base.def_node_matcher(:t_let, <<~PATTERN)
|
def prepended(base)
|
||||||
(send (const nil? :T) :let $_constant _type)
|
# @!method t_let(node)
|
||||||
PATTERN
|
base.def_node_matcher(:t_let, <<~PATTERN)
|
||||||
|
(send (const nil? :T) :let $_constant _type)
|
||||||
|
PATTERN
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def on_assignment(value)
|
def on_assignment(value)
|
||||||
@ -25,5 +28,5 @@ module RuboCop
|
|||||||
end
|
end
|
||||||
|
|
||||||
RuboCop::Cop::Style::MutableConstant.prepend(
|
RuboCop::Cop::Style::MutableConstant.prepend(
|
||||||
RuboCop::Cop::Sorbet::MutableConstantSorbetAwareBehaviour
|
RuboCop::Cop::Sorbet::MutableConstantSorbetAwareBehaviour,
|
||||||
)
|
)
|
||||||
@ -0,0 +1,92 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "rubocop"
|
||||||
|
|
||||||
|
module RuboCop
|
||||||
|
module Cop
|
||||||
|
module Sorbet
|
||||||
|
# Checks for the obsolete pattern for initializing instance variables that was required for older Sorbet
|
||||||
|
# versions in `#typed: strict` files.
|
||||||
|
#
|
||||||
|
# It's no longer required, as of Sorbet 0.5.10210
|
||||||
|
# See https://sorbet.org/docs/type-assertions#put-type-assertions-behind-memoization
|
||||||
|
#
|
||||||
|
# @example
|
||||||
|
#
|
||||||
|
# # bad
|
||||||
|
# sig { returns(Foo) }
|
||||||
|
# def foo
|
||||||
|
# @foo = T.let(@foo, T.nilable(Foo))
|
||||||
|
# @foo ||= Foo.new
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # bad
|
||||||
|
# sig { returns(Foo) }
|
||||||
|
# def foo
|
||||||
|
# # This would have been a mistake, causing the memoized value to be discarded and recomputed on every call.
|
||||||
|
# @foo = T.let(nil, T.nilable(Foo))
|
||||||
|
# @foo ||= Foo.new
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # good
|
||||||
|
# sig { returns(Foo) }
|
||||||
|
# def foo
|
||||||
|
# @foo ||= T.let(Foo.new, T.nilable(Foo))
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
class ObsoleteStrictMemoization < RuboCop::Cop::Base
|
||||||
|
include RuboCop::Cop::MatchRange
|
||||||
|
include RuboCop::Cop::Alignment
|
||||||
|
include RuboCop::Cop::LineLengthHelp
|
||||||
|
include RuboCop::Cop::RangeHelp
|
||||||
|
extend AutoCorrector
|
||||||
|
|
||||||
|
include TargetSorbetVersion
|
||||||
|
minimum_target_sorbet_static_version "0.5.10210"
|
||||||
|
|
||||||
|
MSG = "This two-stage workaround for memoization in `#typed: strict` files is no longer necessary. " \
|
||||||
|
"See https://sorbet.org/docs/type-assertions#put-type-assertions-behind-memoization."
|
||||||
|
|
||||||
|
# @!method legacy_memoization_pattern?(node)
|
||||||
|
def_node_matcher :legacy_memoization_pattern?, <<~PATTERN
|
||||||
|
(begin
|
||||||
|
... # Ignore any other lines that come first.
|
||||||
|
$(ivasgn $_ivar # First line: @_ivar = ...
|
||||||
|
(send # T.let(_ivar, T.nilable(_ivar_type))
|
||||||
|
$(const {nil? cbase} :T) :let
|
||||||
|
{(ivar _ivar) nil}
|
||||||
|
(send (const {nil? cbase} :T) :nilable $_ivar_type))) # T.nilable(_ivar_type)
|
||||||
|
$(or-asgn (ivasgn _ivar) $_initialization_expr)) # Second line: @_ivar ||= _initialization_expr
|
||||||
|
PATTERN
|
||||||
|
|
||||||
|
def on_begin(node)
|
||||||
|
legacy_memoization_pattern?(node) do |first_asgn_node, ivar, t, ivar_type, second_or_asgn_node, init_expr| # rubocop:disable Metrics/ParameterLists
|
||||||
|
add_offense(first_asgn_node) do |corrector|
|
||||||
|
indent = offset(node)
|
||||||
|
correction = "#{ivar} ||= #{t.source}.let(#{init_expr.source}, #{t.source}.nilable(#{ivar_type.source}))"
|
||||||
|
|
||||||
|
# We know good places to put line breaks, if required.
|
||||||
|
if line_length(indent + correction) > max_line_length || correction.include?("\n")
|
||||||
|
correction = <<~RUBY.chomp
|
||||||
|
#{ivar} ||= #{t.source}.let(
|
||||||
|
#{indent} #{init_expr.source.gsub("\n", "\n#{indent}")},
|
||||||
|
#{indent} #{t.source}.nilable(#{ivar_type.source.gsub("\n", "\n#{indent}")}),
|
||||||
|
#{indent})
|
||||||
|
RUBY
|
||||||
|
end
|
||||||
|
|
||||||
|
corrector.replace(
|
||||||
|
range_between(first_asgn_node.source_range.begin_pos, second_or_asgn_node.source_range.end_pos),
|
||||||
|
correction,
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def relevant_file?(file)
|
||||||
|
super && enabled_for_sorbet_static_version?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -6,7 +6,7 @@ require "rubocop"
|
|||||||
module RuboCop
|
module RuboCop
|
||||||
module Cop
|
module Cop
|
||||||
module Sorbet
|
module Sorbet
|
||||||
# This cop ensures one ancestor per requires_ancestor line
|
# Ensures one ancestor per requires_ancestor line
|
||||||
# rather than chaining them as a comma-separated list.
|
# rather than chaining them as a comma-separated list.
|
||||||
#
|
#
|
||||||
# @example
|
# @example
|
||||||
@ -21,17 +21,20 @@ module RuboCop
|
|||||||
# requires_ancestor Kernel
|
# requires_ancestor Kernel
|
||||||
# requires_ancestor Minitest::Assertions
|
# requires_ancestor Minitest::Assertions
|
||||||
# end
|
# end
|
||||||
class OneAncestorPerLine < RuboCop::Cop::Cop
|
class OneAncestorPerLine < RuboCop::Cop::Cop # rubocop:todo InternalAffairs/InheritDeprecatedCopClass
|
||||||
MSG = "Cannot require more than one ancestor per line"
|
MSG = "Cannot require more than one ancestor per line"
|
||||||
|
|
||||||
|
# @!method requires_ancestors(node)
|
||||||
def_node_search :requires_ancestors, <<~PATTERN
|
def_node_search :requires_ancestors, <<~PATTERN
|
||||||
(send nil? :requires_ancestor ...)
|
(send nil? :requires_ancestor ...)
|
||||||
PATTERN
|
PATTERN
|
||||||
|
|
||||||
|
# @!method more_than_one_ancestor(node)
|
||||||
def_node_matcher :more_than_one_ancestor, <<~PATTERN
|
def_node_matcher :more_than_one_ancestor, <<~PATTERN
|
||||||
(send nil? :requires_ancestor const const+)
|
(send nil? :requires_ancestor const const+)
|
||||||
PATTERN
|
PATTERN
|
||||||
|
|
||||||
|
# @!method abstract?(node)
|
||||||
def_node_search :abstract?, <<~PATTERN
|
def_node_search :abstract?, <<~PATTERN
|
||||||
(send nil? :abstract!)
|
(send nil? :abstract!)
|
||||||
PATTERN
|
PATTERN
|
||||||
@ -39,17 +42,19 @@ module RuboCop
|
|||||||
def on_module(node)
|
def on_module(node)
|
||||||
return unless node.body
|
return unless node.body
|
||||||
return unless requires_ancestors(node)
|
return unless requires_ancestors(node)
|
||||||
|
|
||||||
process_node(node)
|
process_node(node)
|
||||||
end
|
end
|
||||||
|
|
||||||
def on_class(node)
|
def on_class(node)
|
||||||
return unless abstract?(node)
|
return unless abstract?(node)
|
||||||
return unless requires_ancestors(node)
|
return unless requires_ancestors(node)
|
||||||
|
|
||||||
process_node(node)
|
process_node(node)
|
||||||
end
|
end
|
||||||
|
|
||||||
def autocorrect(node)
|
def autocorrect(node)
|
||||||
-> (corrector) do
|
->(corrector) do
|
||||||
ra_call = node.parent
|
ra_call = node.parent
|
||||||
split_ra_calls = ra_call.source.gsub(/,\s+/, new_ra_line(ra_call.loc.column))
|
split_ra_calls = ra_call.source.gsub(/,\s+/, new_ra_line(ra_call.loc.column))
|
||||||
corrector.replace(ra_call, split_ra_calls)
|
corrector.replace(ra_call, split_ra_calls)
|
||||||
@ -0,0 +1,47 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module RuboCop
|
||||||
|
module Cop
|
||||||
|
module Sorbet
|
||||||
|
# Ensures RBI shims do not include a call to extend T::Sig
|
||||||
|
# or to extend T::Helpers
|
||||||
|
#
|
||||||
|
# @example
|
||||||
|
#
|
||||||
|
# # bad
|
||||||
|
# module SomeModule
|
||||||
|
# extend T::Sig
|
||||||
|
# extend T::Helpers
|
||||||
|
#
|
||||||
|
# sig { returns(String) }
|
||||||
|
# def foo; end
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # good
|
||||||
|
# module SomeModule
|
||||||
|
# sig { returns(String) }
|
||||||
|
# def foo; end
|
||||||
|
# end
|
||||||
|
class ForbidExtendTSigHelpersInShims < RuboCop::Cop::Base
|
||||||
|
extend AutoCorrector
|
||||||
|
include RangeHelp
|
||||||
|
|
||||||
|
MSG = "Extending T::Sig or T::Helpers in a shim is unnecessary"
|
||||||
|
RESTRICT_ON_SEND = [:extend].freeze
|
||||||
|
|
||||||
|
# @!method extend_t_sig_or_helpers?(node)
|
||||||
|
def_node_matcher :extend_t_sig_or_helpers?, <<~PATTERN
|
||||||
|
(send nil? :extend (const (const nil? :T) {:Sig :Helpers}))
|
||||||
|
PATTERN
|
||||||
|
|
||||||
|
def on_send(node)
|
||||||
|
extend_t_sig_or_helpers?(node) do
|
||||||
|
add_offense(node) do |corrector|
|
||||||
|
corrector.remove(range_by_whole_lines(node.source_range, include_final_newline: true))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -5,7 +5,7 @@ require "pathname"
|
|||||||
module RuboCop
|
module RuboCop
|
||||||
module Cop
|
module Cop
|
||||||
module Sorbet
|
module Sorbet
|
||||||
# This cop makes sure that RBI files are always located under the defined allowed paths.
|
# Makes sure that RBI files are always located under the defined allowed paths.
|
||||||
#
|
#
|
||||||
# Options:
|
# Options:
|
||||||
#
|
#
|
||||||
@ -20,7 +20,7 @@ module RuboCop
|
|||||||
# # rbi/external_interface.rbi
|
# # rbi/external_interface.rbi
|
||||||
# # sorbet/rbi/some_file.rbi
|
# # sorbet/rbi/some_file.rbi
|
||||||
# # sorbet/rbi/any/path/for/file.rbi
|
# # sorbet/rbi/any/path/for/file.rbi
|
||||||
class ForbidRBIOutsideOfAllowedPaths < RuboCop::Cop::Cop
|
class ForbidRBIOutsideOfAllowedPaths < RuboCop::Cop::Cop # rubocop:todo InternalAffairs/InheritDeprecatedCopClass
|
||||||
include RangeHelp
|
include RangeHelp
|
||||||
|
|
||||||
def investigate(processed_source)
|
def investigate(processed_source)
|
||||||
@ -30,14 +30,14 @@ module RuboCop
|
|||||||
add_offense(
|
add_offense(
|
||||||
nil,
|
nil,
|
||||||
location: source_range(processed_source.buffer, 1, 0),
|
location: source_range(processed_source.buffer, 1, 0),
|
||||||
message: "AllowedPaths expects an array"
|
message: "AllowedPaths expects an array",
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
elsif paths.empty?
|
elsif paths.empty?
|
||||||
add_offense(
|
add_offense(
|
||||||
nil,
|
nil,
|
||||||
location: source_range(processed_source.buffer, 1, 0),
|
location: source_range(processed_source.buffer, 1, 0),
|
||||||
message: "AllowedPaths cannot be empty"
|
message: "AllowedPaths cannot be empty",
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@ -49,15 +49,16 @@ module RuboCop
|
|||||||
add_offense(
|
add_offense(
|
||||||
nil,
|
nil,
|
||||||
location: source_range(processed_source.buffer, 1, 0),
|
location: source_range(processed_source.buffer, 1, 0),
|
||||||
message: "RBI file path should match one of: #{paths.join(", ")}"
|
message: "RBI file path should match one of: #{paths.join(", ")}",
|
||||||
) if paths.none? { |pattern| File.fnmatch(pattern, rel_path) }
|
) if paths.none? { |pattern| File.fnmatch(pattern, rel_path) }
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def allowed_paths
|
def allowed_paths
|
||||||
paths = cop_config["AllowedPaths"]
|
paths = cop_config["AllowedPaths"] # rubocop:todo InternalAffairs/UndefinedConfig
|
||||||
return nil unless paths.is_a?(Array)
|
return unless paths.is_a?(Array)
|
||||||
|
|
||||||
paths.compact
|
paths.compact
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -3,7 +3,7 @@
|
|||||||
module RuboCop
|
module RuboCop
|
||||||
module Cop
|
module Cop
|
||||||
module Sorbet
|
module Sorbet
|
||||||
# This cop ensures empty class/module definitions in RBI files are
|
# Ensures empty class/module definitions in RBI files are
|
||||||
# done on a single line rather than being split across multiple lines.
|
# done on a single line rather than being split across multiple lines.
|
||||||
#
|
#
|
||||||
# @example
|
# @example
|
||||||
@ -14,31 +14,25 @@ module RuboCop
|
|||||||
#
|
#
|
||||||
# # good
|
# # good
|
||||||
# module SomeModule; end
|
# module SomeModule; end
|
||||||
class SingleLineRbiClassModuleDefinitions < RuboCop::Cop::Cop
|
class SingleLineRbiClassModuleDefinitions < RuboCop::Cop::Base
|
||||||
|
extend AutoCorrector
|
||||||
|
|
||||||
MSG = "Empty class/module definitions in RBI files should be on a single line."
|
MSG = "Empty class/module definitions in RBI files should be on a single line."
|
||||||
|
|
||||||
def on_module(node)
|
def on_module(node)
|
||||||
process_node(node)
|
|
||||||
end
|
|
||||||
|
|
||||||
def on_class(node)
|
|
||||||
process_node(node)
|
|
||||||
end
|
|
||||||
|
|
||||||
def autocorrect(node)
|
|
||||||
-> (corrector) { corrector.replace(node, convert_newlines(node.source)) }
|
|
||||||
end
|
|
||||||
|
|
||||||
protected
|
|
||||||
|
|
||||||
def convert_newlines(source)
|
|
||||||
source.sub(/[\r\n]+\s*[\r\n]*/, "; ")
|
|
||||||
end
|
|
||||||
|
|
||||||
def process_node(node)
|
|
||||||
return if node.body
|
return if node.body
|
||||||
return if node.single_line?
|
return if node.single_line?
|
||||||
add_offense(node)
|
|
||||||
|
add_offense(node) do |corrector|
|
||||||
|
corrector.replace(node, convert_newlines_to_semicolons(node.source))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
alias_method :on_class, :on_module
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def convert_newlines_to_semicolons(source)
|
||||||
|
source.sub(/[\r\n]+\s*[\r\n]*/, "; ")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -25,10 +25,13 @@ module RuboCop
|
|||||||
# def no_op; end
|
# def no_op; end
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
class RedundantExtendTSig < RuboCop::Cop::Cop
|
class RedundantExtendTSig < RuboCop::Cop::Base
|
||||||
|
extend AutoCorrector
|
||||||
|
|
||||||
MSG = "Do not redundantly `extend T::Sig` when it is already included in all modules."
|
MSG = "Do not redundantly `extend T::Sig` when it is already included in all modules."
|
||||||
RESTRICT_ON_SEND = [:extend].freeze
|
RESTRICT_ON_SEND = [:extend].freeze
|
||||||
|
|
||||||
|
# @!method extend_t_sig?(node)
|
||||||
def_node_matcher :extend_t_sig?, <<~PATTERN
|
def_node_matcher :extend_t_sig?, <<~PATTERN
|
||||||
(send _ :extend (const (const {nil? | cbase} :T) :Sig))
|
(send _ :extend (const (const {nil? | cbase} :T) :Sig))
|
||||||
PATTERN
|
PATTERN
|
||||||
@ -36,11 +39,7 @@ module RuboCop
|
|||||||
def on_send(node)
|
def on_send(node)
|
||||||
return unless extend_t_sig?(node)
|
return unless extend_t_sig?(node)
|
||||||
|
|
||||||
add_offense(node)
|
add_offense(node) do |corrector|
|
||||||
end
|
|
||||||
|
|
||||||
def autocorrect(node)
|
|
||||||
lambda do |corrector|
|
|
||||||
corrector.remove(node)
|
corrector.remove(node)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -5,7 +5,7 @@ require "rubocop"
|
|||||||
module RuboCop
|
module RuboCop
|
||||||
module Cop
|
module Cop
|
||||||
module Sorbet
|
module Sorbet
|
||||||
# This cop checks that the Sorbet sigil comes as the first magic comment in the file.
|
# Checks that the Sorbet sigil comes as the first magic comment in the file.
|
||||||
#
|
#
|
||||||
# The expected order for magic comments is: (en)?coding, typed, warn_indent then frozen_string_literal.
|
# The expected order for magic comments is: (en)?coding, typed, warn_indent then frozen_string_literal.
|
||||||
#
|
#
|
||||||
@ -57,6 +57,7 @@ module RuboCop
|
|||||||
(lines.min...lines.max).each do |line|
|
(lines.min...lines.max).each do |line|
|
||||||
next if lines.include?(line)
|
next if lines.include?(line)
|
||||||
next unless processed_source[line - 1].empty?
|
next unless processed_source[line - 1].empty?
|
||||||
|
|
||||||
corrector.remove(source_range(processed_source.buffer, line, 0))
|
corrector.remove(source_range(processed_source.buffer, line, 0))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -104,7 +105,7 @@ module RuboCop
|
|||||||
add_offense(
|
add_offense(
|
||||||
token,
|
token,
|
||||||
location: token.pos,
|
location: token.pos,
|
||||||
message: "Magic comments should be in the following order: #{PREFERRED_ORDER.values.join(", ")}."
|
message: "Magic comments should be in the following order: #{PREFERRED_ORDER.values.join(", ")}.",
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -3,7 +3,7 @@
|
|||||||
module RuboCop
|
module RuboCop
|
||||||
module Cop
|
module Cop
|
||||||
module Sorbet
|
module Sorbet
|
||||||
# This cop checks that there is only one Sorbet sigil in a given file
|
# Checks that there is only one Sorbet sigil in a given file
|
||||||
#
|
#
|
||||||
# For example, the following class with two sigils
|
# For example, the following class with two sigils
|
||||||
#
|
#
|
||||||
@ -28,8 +28,9 @@ module RuboCop
|
|||||||
|
|
||||||
def investigate(processed_source)
|
def investigate(processed_source)
|
||||||
return if processed_source.tokens.empty?
|
return if processed_source.tokens.empty?
|
||||||
|
|
||||||
sigils = extract_all_sigils(processed_source)
|
sigils = extract_all_sigils(processed_source)
|
||||||
return unless sigils.size > 1
|
return if sigils.empty?
|
||||||
|
|
||||||
sigils[1..sigils.size].each do |token|
|
sigils[1..sigils.size].each do |token|
|
||||||
add_offense(token, location: token.pos, message: "Files must only contain one sigil")
|
add_offense(token, location: token.pos, message: "Files must only contain one sigil")
|
||||||
@ -37,14 +38,14 @@ module RuboCop
|
|||||||
end
|
end
|
||||||
|
|
||||||
def autocorrect(_node)
|
def autocorrect(_node)
|
||||||
-> (corrector) do
|
->(corrector) do
|
||||||
sigils = extract_all_sigils(processed_source)
|
sigils = extract_all_sigils(processed_source)
|
||||||
return unless sigils.size > 1
|
return if sigils.empty?
|
||||||
|
|
||||||
# The first sigil encountered represents the "real" strictness so remove any below
|
# The first sigil encountered represents the "real" strictness so remove any below
|
||||||
sigils[1..sigils.size].each do |token|
|
sigils[1..sigils.size].each do |token|
|
||||||
corrector.remove(
|
corrector.remove(
|
||||||
source_range(processed_source.buffer, token.line, (0..token.pos.last_column))
|
source_range(processed_source.buffer, token.line, (0..token.pos.last_column)),
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -6,7 +6,7 @@ require_relative "has_sigil"
|
|||||||
module RuboCop
|
module RuboCop
|
||||||
module Cop
|
module Cop
|
||||||
module Sorbet
|
module Sorbet
|
||||||
# This cop makes the Sorbet `false` sigil mandatory in all files.
|
# Makes the Sorbet `false` sigil mandatory in all files.
|
||||||
class FalseSigil < HasSigil
|
class FalseSigil < HasSigil
|
||||||
def minimum_strictness
|
def minimum_strictness
|
||||||
"false"
|
"false"
|
||||||
@ -6,7 +6,7 @@ require_relative "valid_sigil"
|
|||||||
module RuboCop
|
module RuboCop
|
||||||
module Cop
|
module Cop
|
||||||
module Sorbet
|
module Sorbet
|
||||||
# This cop makes the Sorbet typed sigil mandatory in all files.
|
# Makes the Sorbet typed sigil mandatory in all files.
|
||||||
#
|
#
|
||||||
# Options:
|
# Options:
|
||||||
#
|
#
|
||||||
@ -6,7 +6,7 @@ require_relative "has_sigil"
|
|||||||
module RuboCop
|
module RuboCop
|
||||||
module Cop
|
module Cop
|
||||||
module Sorbet
|
module Sorbet
|
||||||
# This cop makes the Sorbet `ignore` sigil mandatory in all files.
|
# Makes the Sorbet `ignore` sigil mandatory in all files.
|
||||||
class IgnoreSigil < HasSigil
|
class IgnoreSigil < HasSigil
|
||||||
def minimum_strictness
|
def minimum_strictness
|
||||||
"ignore"
|
"ignore"
|
||||||
@ -6,7 +6,7 @@ require_relative "has_sigil"
|
|||||||
module RuboCop
|
module RuboCop
|
||||||
module Cop
|
module Cop
|
||||||
module Sorbet
|
module Sorbet
|
||||||
# This cop makes the Sorbet `strict` sigil mandatory in all files.
|
# Makes the Sorbet `strict` sigil mandatory in all files.
|
||||||
class StrictSigil < HasSigil
|
class StrictSigil < HasSigil
|
||||||
def minimum_strictness
|
def minimum_strictness
|
||||||
"strict"
|
"strict"
|
||||||
@ -6,7 +6,7 @@ require_relative "has_sigil"
|
|||||||
module RuboCop
|
module RuboCop
|
||||||
module Cop
|
module Cop
|
||||||
module Sorbet
|
module Sorbet
|
||||||
# This cop makes the Sorbet `strong` sigil mandatory in all files.
|
# Makes the Sorbet `strong` sigil mandatory in all files.
|
||||||
class StrongSigil < HasSigil
|
class StrongSigil < HasSigil
|
||||||
def minimum_strictness
|
def minimum_strictness
|
||||||
"strong"
|
"strong"
|
||||||
@ -6,7 +6,7 @@ require_relative "has_sigil"
|
|||||||
module RuboCop
|
module RuboCop
|
||||||
module Cop
|
module Cop
|
||||||
module Sorbet
|
module Sorbet
|
||||||
# This cop makes the Sorbet `true` sigil mandatory in all files.
|
# Makes the Sorbet `true` sigil mandatory in all files.
|
||||||
class TrueSigil < HasSigil
|
class TrueSigil < HasSigil
|
||||||
def minimum_strictness
|
def minimum_strictness
|
||||||
"true"
|
"true"
|
||||||
@ -5,7 +5,7 @@ require "rubocop"
|
|||||||
module RuboCop
|
module RuboCop
|
||||||
module Cop
|
module Cop
|
||||||
module Sorbet
|
module Sorbet
|
||||||
# This cop checks that every Ruby file contains a valid Sorbet sigil.
|
# Checks that every Ruby file contains a valid Sorbet sigil.
|
||||||
# Adapted from: https://gist.github.com/clarkdave/85aca4e16f33fd52aceb6a0a29936e52
|
# Adapted from: https://gist.github.com/clarkdave/85aca4e16f33fd52aceb6a0a29936e52
|
||||||
#
|
#
|
||||||
# Options:
|
# Options:
|
||||||
@ -13,9 +13,11 @@ module RuboCop
|
|||||||
# * `RequireSigilOnAllFiles`: make offense if the Sorbet typed is not found in the file (default: false)
|
# * `RequireSigilOnAllFiles`: make offense if the Sorbet typed is not found in the file (default: false)
|
||||||
# * `SuggestedStrictness`: Sorbet strictness level suggested in offense messages (default: 'false')
|
# * `SuggestedStrictness`: Sorbet strictness level suggested in offense messages (default: 'false')
|
||||||
# * `MinimumStrictness`: If set, make offense if the strictness level in the file is below this one
|
# * `MinimumStrictness`: If set, make offense if the strictness level in the file is below this one
|
||||||
|
# * `ExactStrictness`: If set, make offense if the strictness level in the file is different than this one
|
||||||
#
|
#
|
||||||
# If a `MinimumStrictness` level is specified, it will be used in offense messages and autocorrect.
|
# If an `ExactStrictness` level is specified, it will be used in offense messages and autocorrect.
|
||||||
class ValidSigil < RuboCop::Cop::Cop
|
# Otherwise, if a `MinimumStrictness` level is specified, it will be used in offense messages and autocorrect.
|
||||||
|
class ValidSigil < RuboCop::Cop::Cop # rubocop:todo InternalAffairs/InheritDeprecatedCopClass
|
||||||
@registry = Cop.registry # So we can properly subclass this cop
|
@registry = Cop.registry # So we can properly subclass this cop
|
||||||
|
|
||||||
def investigate(processed_source)
|
def investigate(processed_source)
|
||||||
@ -36,7 +38,7 @@ module RuboCop
|
|||||||
return unless extract_sigil(processed_source).nil?
|
return unless extract_sigil(processed_source).nil?
|
||||||
|
|
||||||
token = processed_source.tokens.first
|
token = processed_source.tokens.first
|
||||||
replace_with = suggested_strictness_level(minimum_strictness, suggested_strictness)
|
replace_with = suggested_strictness_level
|
||||||
sigil = "# typed: #{replace_with}"
|
sigil = "# typed: #{replace_with}"
|
||||||
if token.text.start_with?("#!") # shebang line
|
if token.text.start_with?("#!") # shebang line
|
||||||
corrector.insert_after(token.pos, "\n#{sigil}")
|
corrector.insert_after(token.pos, "\n#{sigil}")
|
||||||
@ -49,7 +51,7 @@ module RuboCop
|
|||||||
protected
|
protected
|
||||||
|
|
||||||
STRICTNESS_LEVELS = ["ignore", "false", "true", "strict", "strong"]
|
STRICTNESS_LEVELS = ["ignore", "false", "true", "strict", "strong"]
|
||||||
SIGIL_REGEX = /^\s*#\s+typed:(?:\s+([\w]+))?/
|
SIGIL_REGEX = /^[[:blank:]]*#[[:blank:]]+typed:(?:[[:blank:]]+([\S]+))?/
|
||||||
|
|
||||||
# extraction
|
# extraction
|
||||||
|
|
||||||
@ -70,34 +72,37 @@ module RuboCop
|
|||||||
|
|
||||||
token = processed_source.tokens.first
|
token = processed_source.tokens.first
|
||||||
if require_sigil_on_all_files?
|
if require_sigil_on_all_files?
|
||||||
strictness = suggested_strictness_level(minimum_strictness, suggested_strictness)
|
strictness = suggested_strictness_level
|
||||||
add_offense(
|
add_offense(
|
||||||
token,
|
token,
|
||||||
location: token.pos,
|
location: token.pos,
|
||||||
message: "No Sorbet sigil found in file. " \
|
message: "No Sorbet sigil found in file. " \
|
||||||
"Try a `typed: #{strictness}` to start (you can also use `rubocop -a` to automatically add this)."
|
"Try a `typed: #{strictness}` to start (you can also use `rubocop -a` to automatically add this).",
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
def suggested_strictness_level(minimum_strictness, suggested_strictness)
|
def suggested_strictness_level
|
||||||
|
return exact_strictness if exact_strictness
|
||||||
# if no minimum strictness is set (eg. using Sorbet/HasSigil without config) then
|
# if no minimum strictness is set (eg. using Sorbet/HasSigil without config) then
|
||||||
# we always use the suggested strictness which defaults to `false`
|
# we always use the suggested strictness which defaults to `false`
|
||||||
return suggested_strictness unless minimum_strictness
|
return suggested_strictness unless minimum_strictness
|
||||||
|
|
||||||
# special case: if you're using Sorbet/IgnoreSigil without config, we should recommend `ignore`
|
# special case: if you're using Sorbet/IgnoreSigil without config, we should recommend `ignore`
|
||||||
return "ignore" if minimum_strictness == "ignore" && cop_config["SuggestedStrictness"].nil?
|
return "ignore" if minimum_strictness == "ignore" && cop_config["SuggestedStrictness"].nil? # rubocop:todo InternalAffairs/UndefinedConfig
|
||||||
|
|
||||||
# if a minimum strictness is set (eg. you're using Sorbet/FalseSigil)
|
# if a minimum strictness is set (eg. you're using Sorbet/FalseSigil)
|
||||||
# we want to compare the minimum strictness and suggested strictness. this is because
|
# we want to compare the minimum strictness and suggested strictness. this is because
|
||||||
# the suggested strictness might be higher than the minimum (eg. if you want all new files
|
# the suggested strictness might be higher than the minimum (eg. if you want all new files
|
||||||
# at a higher strictness level, without having to migrate existing files at lower levels).
|
# at a higher strictness level, without having to migrate existing files at lower levels).
|
||||||
|
|
||||||
suggested_level = STRICTNESS_LEVELS.index(suggested_strictness)
|
levels = [
|
||||||
minimum_level = STRICTNESS_LEVELS.index(minimum_strictness)
|
STRICTNESS_LEVELS.index(suggested_strictness),
|
||||||
|
STRICTNESS_LEVELS.index(minimum_strictness),
|
||||||
|
]
|
||||||
|
|
||||||
suggested_level > minimum_level ? suggested_strictness : minimum_strictness
|
STRICTNESS_LEVELS[levels.compact.max]
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_strictness_not_empty(sigil, strictness)
|
def check_strictness_not_empty(sigil, strictness)
|
||||||
@ -106,7 +111,7 @@ module RuboCop
|
|||||||
add_offense(
|
add_offense(
|
||||||
sigil,
|
sigil,
|
||||||
location: sigil.pos,
|
location: sigil.pos,
|
||||||
message: "Sorbet sigil should not be empty."
|
message: "Sorbet sigil should not be empty.",
|
||||||
)
|
)
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
@ -117,24 +122,38 @@ module RuboCop
|
|||||||
add_offense(
|
add_offense(
|
||||||
sigil,
|
sigil,
|
||||||
location: sigil.pos,
|
location: sigil.pos,
|
||||||
message: "Invalid Sorbet sigil `#{strictness}`."
|
message: "Invalid Sorbet sigil `#{strictness}`.",
|
||||||
)
|
)
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_strictness_level(sigil, strictness)
|
def check_strictness_level(sigil, strictness)
|
||||||
return true unless minimum_strictness
|
return true if !minimum_strictness && !exact_strictness
|
||||||
|
|
||||||
minimum_level = STRICTNESS_LEVELS.index(minimum_strictness)
|
|
||||||
current_level = STRICTNESS_LEVELS.index(strictness)
|
current_level = STRICTNESS_LEVELS.index(strictness)
|
||||||
if current_level < minimum_level
|
|
||||||
add_offense(
|
if exact_strictness
|
||||||
sigil,
|
exact_level = STRICTNESS_LEVELS.index(exact_strictness)
|
||||||
location: sigil.pos,
|
if current_level != exact_level
|
||||||
message: "Sorbet sigil should be at least `#{minimum_strictness}` got `#{strictness}`."
|
add_offense(
|
||||||
)
|
sigil,
|
||||||
return false
|
location: sigil.pos,
|
||||||
|
message: "Sorbet sigil should be `#{exact_strictness}` got `#{strictness}`.",
|
||||||
|
)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
else
|
||||||
|
minimum_level = STRICTNESS_LEVELS.index(minimum_strictness)
|
||||||
|
if current_level < minimum_level
|
||||||
|
add_offense(
|
||||||
|
sigil,
|
||||||
|
location: sigil.pos,
|
||||||
|
message: "Sorbet sigil should be at least `#{minimum_strictness}` got `#{strictness}`.",
|
||||||
|
)
|
||||||
|
return false
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -142,18 +161,24 @@ module RuboCop
|
|||||||
|
|
||||||
# Default is `false`
|
# Default is `false`
|
||||||
def require_sigil_on_all_files?
|
def require_sigil_on_all_files?
|
||||||
!!cop_config["RequireSigilOnAllFiles"]
|
!!cop_config["RequireSigilOnAllFiles"] # rubocop:todo InternalAffairs/UndefinedConfig
|
||||||
end
|
end
|
||||||
|
|
||||||
# Default is `'false'`
|
# Default is `'false'`
|
||||||
def suggested_strictness
|
def suggested_strictness
|
||||||
config = cop_config["SuggestedStrictness"].to_s
|
config = cop_config["SuggestedStrictness"].to_s # rubocop:todo InternalAffairs/UndefinedConfig
|
||||||
STRICTNESS_LEVELS.include?(config) ? config : "false"
|
STRICTNESS_LEVELS.include?(config) ? config : "false"
|
||||||
end
|
end
|
||||||
|
|
||||||
# Default is `nil`
|
# Default is `nil`
|
||||||
def minimum_strictness
|
def minimum_strictness
|
||||||
config = cop_config["MinimumStrictness"].to_s
|
config = cop_config["MinimumStrictness"].to_s # rubocop:todo InternalAffairs/UndefinedConfig
|
||||||
|
config if STRICTNESS_LEVELS.include?(config)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Default is `nil`
|
||||||
|
def exact_strictness
|
||||||
|
config = cop_config["ExactStrictness"].to_s # rubocop:todo InternalAffairs/UndefinedConfig
|
||||||
config if STRICTNESS_LEVELS.include?(config)
|
config if STRICTNESS_LEVELS.include?(config)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -0,0 +1,76 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "rubocop"
|
||||||
|
|
||||||
|
module RuboCop
|
||||||
|
module Cop
|
||||||
|
module Sorbet
|
||||||
|
# Disallows using `.override(allow_incompatible: true)`.
|
||||||
|
# Using `allow_incompatible` suggests a violation of the Liskov
|
||||||
|
# Substitution Principle, meaning that a subclass is not a valid
|
||||||
|
# subtype of its superclass. This Cop prevents these design smells
|
||||||
|
# from occurring.
|
||||||
|
#
|
||||||
|
# @example
|
||||||
|
#
|
||||||
|
# # bad
|
||||||
|
# sig.override(allow_incompatible: true)
|
||||||
|
#
|
||||||
|
# # good
|
||||||
|
# sig.override
|
||||||
|
class AllowIncompatibleOverride < RuboCop::Cop::Base
|
||||||
|
MSG = "Usage of `allow_incompatible` suggests a violation of the Liskov Substitution Principle. " \
|
||||||
|
"Instead, strive to write interfaces which respect subtyping principles and remove `allow_incompatible`"
|
||||||
|
RESTRICT_ON_SEND = [:override].freeze
|
||||||
|
|
||||||
|
# @!method sig_dot_override?(node)
|
||||||
|
def_node_matcher(:sig_dot_override?, <<~PATTERN)
|
||||||
|
(send
|
||||||
|
[!nil? #sig?]
|
||||||
|
:override
|
||||||
|
(hash <$(pair (sym :allow_incompatible) true) ...>)
|
||||||
|
)
|
||||||
|
PATTERN
|
||||||
|
|
||||||
|
# @!method sig?(node)
|
||||||
|
def_node_search(:sig?, <<~PATTERN)
|
||||||
|
(send _ :sig ...)
|
||||||
|
PATTERN
|
||||||
|
|
||||||
|
# @!method override?(node)
|
||||||
|
def_node_matcher(:override?, <<~PATTERN)
|
||||||
|
(send
|
||||||
|
_
|
||||||
|
:override
|
||||||
|
(hash <$(pair (sym :allow_incompatible) true) ...>)
|
||||||
|
)
|
||||||
|
PATTERN
|
||||||
|
|
||||||
|
def on_send(node)
|
||||||
|
sig_dot_override?(node) do |allow_incompatible_pair|
|
||||||
|
add_offense(allow_incompatible_pair)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def on_block(node)
|
||||||
|
return unless sig?(node.send_node)
|
||||||
|
|
||||||
|
block = node.children.last
|
||||||
|
return unless block.send_type?
|
||||||
|
|
||||||
|
receiver = block.receiver
|
||||||
|
while receiver
|
||||||
|
allow_incompatible_pair = override?(receiver)
|
||||||
|
if allow_incompatible_pair
|
||||||
|
add_offense(allow_incompatible_pair)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
receiver = receiver.receiver
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
alias_method :on_numblock, :on_block
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -6,7 +6,7 @@ require_relative "signature_cop"
|
|||||||
module RuboCop
|
module RuboCop
|
||||||
module Cop
|
module Cop
|
||||||
module Sorbet
|
module Sorbet
|
||||||
# This cop disallows the usage of `checked(true)`. This usage could cause
|
# Disallows the usage of `checked(true)`. This usage could cause
|
||||||
# confusion; it could lead some people to believe that a method would be checked
|
# confusion; it could lead some people to believe that a method would be checked
|
||||||
# even if runtime checks have not been enabled on the class or globally.
|
# even if runtime checks have not been enabled on the class or globally.
|
||||||
# Additionally, in the event where checks are enabled, `checked(true)` would
|
# Additionally, in the event where checks are enabled, `checked(true)` would
|
||||||
@ -22,6 +22,7 @@ module RuboCop
|
|||||||
class CheckedTrueInSignature < SignatureCop
|
class CheckedTrueInSignature < SignatureCop
|
||||||
include(RuboCop::Cop::RangeHelp)
|
include(RuboCop::Cop::RangeHelp)
|
||||||
|
|
||||||
|
# @!method offending_node(node)
|
||||||
def_node_search(:offending_node, <<~PATTERN)
|
def_node_search(:offending_node, <<~PATTERN)
|
||||||
(send _ :checked (true))
|
(send _ :checked (true))
|
||||||
PATTERN
|
PATTERN
|
||||||
@ -44,7 +45,7 @@ module RuboCop
|
|||||||
error.location.line,
|
error.location.line,
|
||||||
(error.location.selector.begin_pos)..(error.location.end.begin_pos),
|
(error.location.selector.begin_pos)..(error.location.end.begin_pos),
|
||||||
),
|
),
|
||||||
message: MESSAGE
|
message: MESSAGE,
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -5,7 +5,7 @@ require_relative "signature_cop"
|
|||||||
module RuboCop
|
module RuboCop
|
||||||
module Cop
|
module Cop
|
||||||
module Sorbet
|
module Sorbet
|
||||||
# This cop checks for blank lines after signatures.
|
# Checks for blank lines after signatures.
|
||||||
#
|
#
|
||||||
# It also suggests an autocorrect
|
# It also suggests an autocorrect
|
||||||
#
|
#
|
||||||
@ -31,10 +31,10 @@ module RuboCop
|
|||||||
end
|
end
|
||||||
|
|
||||||
def autocorrect(node)
|
def autocorrect(node)
|
||||||
-> (corrector) do
|
->(corrector) do
|
||||||
offending_range = node.source_range.with(
|
offending_range = node.source_range.with(
|
||||||
begin_pos: node.source_range.end_pos + 1,
|
begin_pos: node.source_range.end_pos + 1,
|
||||||
end_pos: processed_source.buffer.line_range(next_method(node).line).begin_pos
|
end_pos: processed_source.buffer.line_range(next_method(node).line).begin_pos,
|
||||||
)
|
)
|
||||||
corrector.remove(offending_range)
|
corrector.remove(offending_range)
|
||||||
clean_range = offending_range.source.split("\n").reject(&:empty?).join("\n")
|
clean_range = offending_range.source.split("\n").reject(&:empty?).join("\n")
|
||||||
@ -7,7 +7,7 @@ require_relative "signature_cop"
|
|||||||
module RuboCop
|
module RuboCop
|
||||||
module Cop
|
module Cop
|
||||||
module Sorbet
|
module Sorbet
|
||||||
# This cop checks that every method definition and attribute accessor has a Sorbet signature.
|
# Checks that every method definition and attribute accessor has a Sorbet signature.
|
||||||
#
|
#
|
||||||
# It also suggest an autocorrect with placeholders so the following code:
|
# It also suggest an autocorrect with placeholders so the following code:
|
||||||
#
|
#
|
||||||
@ -32,6 +32,7 @@ module RuboCop
|
|||||||
@last_sig_for_scope = {}
|
@last_sig_for_scope = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# @!method accessor?(node)
|
||||||
def_node_matcher(:accessor?, <<-PATTERN)
|
def_node_matcher(:accessor?, <<-PATTERN)
|
||||||
(send nil? {:attr_reader :attr_writer :attr_accessor} ...)
|
(send nil? {:attr_reader :attr_writer :attr_accessor} ...)
|
||||||
PATTERN
|
PATTERN
|
||||||
@ -67,13 +68,14 @@ module RuboCop
|
|||||||
suggest.returns = "void" if method == :attr_writer
|
suggest.returns = "void" if method == :attr_writer
|
||||||
end
|
end
|
||||||
|
|
||||||
corrector.insert_before(node.loc.expression, suggest.to_autocorrect)
|
corrector.insert_before(node, suggest.to_autocorrect)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def scope(node)
|
def scope(node)
|
||||||
return nil unless node.parent
|
return unless node.parent
|
||||||
return node.parent if [:begin, :block, :class, :module].include?(node.parent.type)
|
return node.parent if [:begin, :block, :class, :module].include?(node.parent.type)
|
||||||
|
|
||||||
scope(node.parent)
|
scope(node.parent)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -84,7 +86,7 @@ module RuboCop
|
|||||||
unless @last_sig_for_scope[scope]
|
unless @last_sig_for_scope[scope]
|
||||||
add_offense(
|
add_offense(
|
||||||
node,
|
node,
|
||||||
message: "Each method is required to have a signature."
|
message: "Each method is required to have a signature.",
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
@last_sig_for_scope[scope] = nil
|
@last_sig_for_scope[scope] = nil
|
||||||
@ -123,6 +125,7 @@ module RuboCop
|
|||||||
|
|
||||||
def generate_params
|
def generate_params
|
||||||
return if @params.empty?
|
return if @params.empty?
|
||||||
|
|
||||||
out = StringIO.new
|
out = StringIO.new
|
||||||
out << "params("
|
out << "params("
|
||||||
out << @params.map do |param|
|
out << @params.map do |param|
|
||||||
@ -135,6 +138,7 @@ module RuboCop
|
|||||||
def generate_return
|
def generate_return
|
||||||
return "returns(#{@return_placeholder})" if @returns.nil?
|
return "returns(#{@return_placeholder})" if @returns.nil?
|
||||||
return @returns if @returns == "void"
|
return @returns if @returns == "void"
|
||||||
|
|
||||||
"returns(#{@returns})"
|
"returns(#{@returns})"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -6,7 +6,7 @@ require_relative "signature_cop"
|
|||||||
module RuboCop
|
module RuboCop
|
||||||
module Cop
|
module Cop
|
||||||
module Sorbet
|
module Sorbet
|
||||||
# This cop checks for the ordering of keyword arguments required by
|
# Checks for the ordering of keyword arguments required by
|
||||||
# sorbet-runtime. The ordering requires that all keyword arguments
|
# sorbet-runtime. The ordering requires that all keyword arguments
|
||||||
# are at the end of the parameters list, and all keyword arguments
|
# are at the end of the parameters list, and all keyword arguments
|
||||||
# with a default value must be after those without default values.
|
# with a default value must be after those without default values.
|
||||||
@ -24,6 +24,7 @@ module RuboCop
|
|||||||
def on_signature(node)
|
def on_signature(node)
|
||||||
method_node = node.parent.children[node.sibling_index + 1]
|
method_node = node.parent.children[node.sibling_index + 1]
|
||||||
return if method_node.nil?
|
return if method_node.nil?
|
||||||
|
|
||||||
method_parameters = method_node.arguments
|
method_parameters = method_node.arguments
|
||||||
|
|
||||||
check_order_for_kwoptargs(method_parameters)
|
check_order_for_kwoptargs(method_parameters)
|
||||||
@ -35,13 +36,13 @@ module RuboCop
|
|||||||
out_of_kwoptarg = false
|
out_of_kwoptarg = false
|
||||||
|
|
||||||
parameters.reverse.each do |param|
|
parameters.reverse.each do |param|
|
||||||
out_of_kwoptarg = true unless param.type == :kwoptarg || param.type == :blockarg || param.type == :kwrestarg
|
out_of_kwoptarg = true unless param.kwoptarg_type? || param.blockarg_type? || param.kwrestarg_type?
|
||||||
|
|
||||||
next unless param.type == :kwoptarg && out_of_kwoptarg
|
next unless param.kwoptarg_type? && out_of_kwoptarg
|
||||||
|
|
||||||
add_offense(
|
add_offense(
|
||||||
param,
|
param,
|
||||||
message: "Optional keyword arguments must be at the end of the parameter list."
|
message: "Optional keyword arguments must be at the end of the parameter list.",
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -27,13 +27,18 @@ module RuboCop
|
|||||||
:on_failure,
|
:on_failure,
|
||||||
].each_with_index.to_h.freeze
|
].each_with_index.to_h.freeze
|
||||||
|
|
||||||
|
# @!method root_call(node)
|
||||||
def_node_search(:root_call, <<~PATTERN)
|
def_node_search(:root_call, <<~PATTERN)
|
||||||
(send nil? {#{ORDER.keys.map(&:inspect).join(" ")}} ...)
|
(send nil? {#{ORDER.keys.map(&:inspect).join(" ")}} ...)
|
||||||
PATTERN
|
PATTERN
|
||||||
|
|
||||||
def on_signature(node)
|
def on_signature(node)
|
||||||
calls = call_chain(node.children[2]).map(&:method_name)
|
calls = call_chain(node.children[2]).map(&:method_name)
|
||||||
return unless calls.any?
|
return if calls.empty?
|
||||||
|
|
||||||
|
# While the developer is typing, we may have an incomplete call statement, which means `ORDER[call]` will
|
||||||
|
# return `nil`. In that case, invoking `sort_by` will raise
|
||||||
|
return if calls.any? { |call| ORDER[call].nil? }
|
||||||
|
|
||||||
expected_order = calls.sort_by { |call| ORDER[call] }
|
expected_order = calls.sort_by { |call| ORDER[call] }
|
||||||
return if expected_order == calls
|
return if expected_order == calls
|
||||||
@ -52,7 +57,7 @@ module RuboCop
|
|||||||
end
|
end
|
||||||
|
|
||||||
def autocorrect(node)
|
def autocorrect(node)
|
||||||
return nil unless can_autocorrect?
|
return unless can_autocorrect?
|
||||||
|
|
||||||
lambda do |corrector|
|
lambda do |corrector|
|
||||||
tree = call_chain(node_reparsed_with_modern_features(node))
|
tree = call_chain(node_reparsed_with_modern_features(node))
|
||||||
@ -62,7 +67,7 @@ module RuboCop
|
|||||||
end
|
end
|
||||||
|
|
||||||
corrector.replace(
|
corrector.replace(
|
||||||
node.source_range,
|
node,
|
||||||
Unparser.unparse(tree),
|
Unparser.unparse(tree),
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
@ -8,9 +8,10 @@ module RuboCop
|
|||||||
# Abstract cop specific to Sorbet signatures
|
# Abstract cop specific to Sorbet signatures
|
||||||
#
|
#
|
||||||
# You can subclass it to use the `on_signature` trigger and the `signature?` node matcher.
|
# You can subclass it to use the `on_signature` trigger and the `signature?` node matcher.
|
||||||
class SignatureCop < RuboCop::Cop::Cop
|
class SignatureCop < RuboCop::Cop::Cop # rubocop:todo InternalAffairs/InheritDeprecatedCopClass
|
||||||
@registry = Cop.registry # So we can properly subclass this cop
|
@registry = Cop.registry # So we can properly subclass this cop
|
||||||
|
|
||||||
|
# @!method signature?(node)
|
||||||
def_node_matcher(:signature?, <<~PATTERN)
|
def_node_matcher(:signature?, <<~PATTERN)
|
||||||
(block (send
|
(block (send
|
||||||
{nil? #with_runtime? #without_runtime?}
|
{nil? #with_runtime? #without_runtime?}
|
||||||
@ -19,10 +20,12 @@ module RuboCop
|
|||||||
) (args) ...)
|
) (args) ...)
|
||||||
PATTERN
|
PATTERN
|
||||||
|
|
||||||
|
# @!method with_runtime?(node)
|
||||||
def_node_matcher(:with_runtime?, <<~PATTERN)
|
def_node_matcher(:with_runtime?, <<~PATTERN)
|
||||||
(const (const nil? :T) :Sig)
|
(const (const nil? :T) :Sig)
|
||||||
PATTERN
|
PATTERN
|
||||||
|
|
||||||
|
# @!method without_runtime?(node)
|
||||||
def_node_matcher(:without_runtime?, <<~PATTERN)
|
def_node_matcher(:without_runtime?, <<~PATTERN)
|
||||||
(const (const (const nil? :T) :Sig) :WithoutRuntime)
|
(const (const (const nil? :T) :Sig) :WithoutRuntime)
|
||||||
PATTERN
|
PATTERN
|
||||||
@ -31,6 +34,8 @@ module RuboCop
|
|||||||
on_signature(node) if signature?(node)
|
on_signature(node) if signature?(node)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
alias_method :on_numblock, :on_block
|
||||||
|
|
||||||
def on_signature(_)
|
def on_signature(_)
|
||||||
# To be defined in subclasses
|
# To be defined in subclasses
|
||||||
end
|
end
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "rubocop"
|
||||||
|
|
||||||
|
module RuboCop
|
||||||
|
module Cop
|
||||||
|
module Sorbet
|
||||||
|
# Ensures all constants used as `T.type_alias` are using CamelCase.
|
||||||
|
#
|
||||||
|
# @example
|
||||||
|
#
|
||||||
|
# # bad
|
||||||
|
# FOO_OR_BAR = T.type_alias { T.any(Foo, Bar) }
|
||||||
|
#
|
||||||
|
# # good
|
||||||
|
# FooOrBar = T.type_alias { T.any(Foo, Bar) }
|
||||||
|
class TypeAliasName < RuboCop::Cop::Base
|
||||||
|
MSG = "Type alias constant name should be in CamelCase"
|
||||||
|
|
||||||
|
# @!method underscored_type_alias?(node)
|
||||||
|
def_node_matcher(:underscored_type_alias?, <<-PATTERN)
|
||||||
|
(casgn
|
||||||
|
_
|
||||||
|
/_/ # Name matches underscore
|
||||||
|
(block
|
||||||
|
(send (const nil? :T) :type_alias)
|
||||||
|
...
|
||||||
|
)
|
||||||
|
)
|
||||||
|
PATTERN
|
||||||
|
|
||||||
|
def on_casgn(node)
|
||||||
|
add_offense(node) if underscored_type_alias?(node)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -1,15 +1,20 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
require_relative "sorbet/binding_constants_without_type_alias"
|
|
||||||
|
require_relative "sorbet/mixin/target_sorbet_version.rb"
|
||||||
|
|
||||||
|
require_relative "sorbet/binding_constant_without_type_alias"
|
||||||
require_relative "sorbet/constants_from_strings"
|
require_relative "sorbet/constants_from_strings"
|
||||||
require_relative "sorbet/forbid_superclass_const_literal"
|
require_relative "sorbet/forbid_superclass_const_literal"
|
||||||
require_relative "sorbet/forbid_include_const_literal"
|
require_relative "sorbet/forbid_include_const_literal"
|
||||||
require_relative "sorbet/forbid_untyped_struct_props"
|
require_relative "sorbet/forbid_untyped_struct_props"
|
||||||
|
require_relative "sorbet/implicit_conversion_method"
|
||||||
require_relative "sorbet/one_ancestor_per_line"
|
require_relative "sorbet/one_ancestor_per_line"
|
||||||
require_relative "sorbet/callback_conditionals_binding"
|
require_relative "sorbet/callback_conditionals_binding"
|
||||||
require_relative "sorbet/forbid_t_unsafe"
|
require_relative "sorbet/forbid_t_unsafe"
|
||||||
require_relative "sorbet/forbid_t_untyped"
|
require_relative "sorbet/forbid_t_untyped"
|
||||||
require_relative "sorbet/redundant_extend_t_sig"
|
require_relative "sorbet/redundant_extend_t_sig"
|
||||||
require_relative "sorbet/type_alias_name"
|
require_relative "sorbet/type_alias_name"
|
||||||
|
require_relative "sorbet/obsolete_strict_memoization"
|
||||||
|
|
||||||
require_relative "sorbet/rbi/forbid_extend_t_sig_helpers_in_shims"
|
require_relative "sorbet/rbi/forbid_extend_t_sig_helpers_in_shims"
|
||||||
require_relative "sorbet/rbi/forbid_rbi_outside_of_allowed_paths"
|
require_relative "sorbet/rbi/forbid_rbi_outside_of_allowed_paths"
|
||||||
@ -1,4 +1,5 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "rubocop/sorbet/version"
|
require "rubocop/sorbet/version"
|
||||||
require "yaml"
|
require "yaml"
|
||||||
|
|
||||||
22
Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-sorbet-0.7.3/lib/rubocop/sorbet/inject.rb
vendored
Normal file
22
Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/rubocop-sorbet-0.7.3/lib/rubocop/sorbet/inject.rb
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# The original code is from https://github.com/rubocop-hq/rubocop-rspec/blob/master/lib/rubocop/rspec/inject.rb
|
||||||
|
# See https://github.com/rubocop-hq/rubocop-rspec/blob/master/MIT-LICENSE.md
|
||||||
|
module RuboCop
|
||||||
|
module Sorbet
|
||||||
|
# Because RuboCop doesn't yet support plugins, we have to monkey patch in a
|
||||||
|
# bit of our configuration.
|
||||||
|
module Inject
|
||||||
|
class << self
|
||||||
|
def defaults!
|
||||||
|
path = CONFIG_DEFAULT.to_s
|
||||||
|
hash = ConfigLoader.send(:load_yaml_configuration, path)
|
||||||
|
config = Config.new(hash, path).tap(&:make_excludes_absolute)
|
||||||
|
puts "configuration from #{path}" if ConfigLoader.debug?
|
||||||
|
config = ConfigLoader.merge_with_default(config, path)
|
||||||
|
ConfigLoader.instance_variable_set(:@default_configuration, config)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -1,6 +1,7 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module RuboCop
|
module RuboCop
|
||||||
module Sorbet
|
module Sorbet
|
||||||
VERSION = "0.7.0"
|
VERSION = "0.7.3"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
Loading…
x
Reference in New Issue
Block a user