commit
b21c59f751
@ -163,6 +163,14 @@ Performance/CaseWhenSplat:
|
|||||||
Performance/Caller:
|
Performance/Caller:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
|
# Enable when https://github.com/Homebrew/homebrew-core/pull/64983 is merged.
|
||||||
|
Performance/ConstantRegexp:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
|
# Makes code less readable for minor performance increases.
|
||||||
|
Performance/MethodObjectAsBlock:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
# Don't allow cops to be disabled in casks and formulae.
|
# Don't allow cops to be disabled in casks and formulae.
|
||||||
Style/DisableCopsWithinSourceCodeDirective:
|
Style/DisableCopsWithinSourceCodeDirective:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|||||||
@ -44,7 +44,7 @@ GEM
|
|||||||
method_source (1.0.0)
|
method_source (1.0.0)
|
||||||
mime-types (3.3.1)
|
mime-types (3.3.1)
|
||||||
mime-types-data (~> 3.2015)
|
mime-types-data (~> 3.2015)
|
||||||
mime-types-data (3.2020.0512)
|
mime-types-data (3.2020.1104)
|
||||||
mini_portile2 (2.4.0)
|
mini_portile2 (2.4.0)
|
||||||
minitest (5.14.2)
|
minitest (5.14.2)
|
||||||
mustache (1.1.1)
|
mustache (1.1.1)
|
||||||
@ -98,7 +98,7 @@ GEM
|
|||||||
rspec-support (3.10.0)
|
rspec-support (3.10.0)
|
||||||
rspec-wait (0.0.9)
|
rspec-wait (0.0.9)
|
||||||
rspec (>= 3, < 4)
|
rspec (>= 3, < 4)
|
||||||
rubocop (1.3.0)
|
rubocop (1.3.1)
|
||||||
parallel (~> 1.10)
|
parallel (~> 1.10)
|
||||||
parser (>= 2.7.1.5)
|
parser (>= 2.7.1.5)
|
||||||
rainbow (>= 2.2.2, < 4.0)
|
rainbow (>= 2.2.2, < 4.0)
|
||||||
@ -109,8 +109,8 @@ GEM
|
|||||||
unicode-display_width (>= 1.4.0, < 2.0)
|
unicode-display_width (>= 1.4.0, < 2.0)
|
||||||
rubocop-ast (1.1.1)
|
rubocop-ast (1.1.1)
|
||||||
parser (>= 2.7.1.5)
|
parser (>= 2.7.1.5)
|
||||||
rubocop-performance (1.8.1)
|
rubocop-performance (1.9.0)
|
||||||
rubocop (>= 0.87.0)
|
rubocop (>= 0.90.0, < 2.0)
|
||||||
rubocop-ast (>= 0.4.0)
|
rubocop-ast (>= 0.4.0)
|
||||||
rubocop-rspec (2.0.0)
|
rubocop-rspec (2.0.0)
|
||||||
rubocop (~> 1.0)
|
rubocop (~> 1.0)
|
||||||
@ -123,11 +123,11 @@ GEM
|
|||||||
docile (~> 1.1)
|
docile (~> 1.1)
|
||||||
simplecov-html (~> 0.11)
|
simplecov-html (~> 0.11)
|
||||||
simplecov-html (0.12.3)
|
simplecov-html (0.12.3)
|
||||||
sorbet (0.5.6060)
|
sorbet (0.5.6076)
|
||||||
sorbet-static (= 0.5.6060)
|
sorbet-static (= 0.5.6076)
|
||||||
sorbet-runtime (0.5.6060)
|
sorbet-runtime (0.5.6076)
|
||||||
sorbet-runtime-stub (0.2.0)
|
sorbet-runtime-stub (0.2.0)
|
||||||
sorbet-static (0.5.6060-universal-darwin-14)
|
sorbet-static (0.5.6076-universal-darwin-14)
|
||||||
spoom (1.0.4)
|
spoom (1.0.4)
|
||||||
colorize
|
colorize
|
||||||
sorbet (~> 0.5.5)
|
sorbet (~> 0.5.5)
|
||||||
@ -142,14 +142,14 @@ GEM
|
|||||||
thor (>= 0.19.2)
|
thor (>= 0.19.2)
|
||||||
thor (1.0.1)
|
thor (1.0.1)
|
||||||
thread_safe (0.3.6)
|
thread_safe (0.3.6)
|
||||||
tzinfo (1.2.7)
|
tzinfo (1.2.8)
|
||||||
thread_safe (~> 0.1)
|
thread_safe (~> 0.1)
|
||||||
unf (0.1.4)
|
unf (0.1.4)
|
||||||
unf_ext
|
unf_ext
|
||||||
unf_ext (0.0.7.7)
|
unf_ext (0.0.7.7)
|
||||||
unicode-display_width (1.7.0)
|
unicode-display_width (1.7.0)
|
||||||
webrobots (0.1.2)
|
webrobots (0.1.2)
|
||||||
zeitwerk (2.4.0)
|
zeitwerk (2.4.1)
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
ruby
|
ruby
|
||||||
|
|||||||
@ -22,7 +22,7 @@ module Cask
|
|||||||
attr_reader :token, :sourcefile_path, :config, :default_config
|
attr_reader :token, :sourcefile_path, :config, :default_config
|
||||||
|
|
||||||
def self.each(&block)
|
def self.each(&block)
|
||||||
return to_enum unless block_given?
|
return to_enum unless block
|
||||||
|
|
||||||
Tap.flat_map(&:cask_files).each do |f|
|
Tap.flat_map(&:cask_files).each do |f|
|
||||||
block.call CaskLoader::FromTapPathLoader.new(f).load(config: nil)
|
block.call CaskLoader::FromTapPathLoader.new(f).load(config: nil)
|
||||||
|
|||||||
@ -84,7 +84,7 @@ module Cask
|
|||||||
|
|
||||||
def self.parser(&block)
|
def self.parser(&block)
|
||||||
Homebrew::CLI::Parser.new do
|
Homebrew::CLI::Parser.new do
|
||||||
if block_given?
|
if block
|
||||||
instance_eval(&block)
|
instance_eval(&block)
|
||||||
else
|
else
|
||||||
usage_banner <<~EOS
|
usage_banner <<~EOS
|
||||||
|
|||||||
@ -68,7 +68,7 @@ module Cask
|
|||||||
Cmd.parser do
|
Cmd.parser do
|
||||||
usage_banner banner
|
usage_banner banner
|
||||||
|
|
||||||
instance_eval(&block) if block_given?
|
instance_eval(&block) if block
|
||||||
|
|
||||||
OPTIONS.each do |option|
|
OPTIONS.each do |option|
|
||||||
send(*option)
|
send(*option)
|
||||||
|
|||||||
@ -34,7 +34,7 @@ module Cask
|
|||||||
send(*option)
|
send(*option)
|
||||||
end
|
end
|
||||||
|
|
||||||
instance_eval(&block) if block_given?
|
instance_eval(&block) if block
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -125,7 +125,7 @@ module Cask
|
|||||||
def language(*args, default: false, &block)
|
def language(*args, default: false, &block)
|
||||||
if args.empty?
|
if args.empty?
|
||||||
language_eval
|
language_eval
|
||||||
elsif block_given?
|
elsif block
|
||||||
@language_blocks ||= {}
|
@language_blocks ||= {}
|
||||||
@language_blocks[args] = block
|
@language_blocks[args] = block
|
||||||
|
|
||||||
@ -248,7 +248,7 @@ module Cask
|
|||||||
|
|
||||||
def caveats(*strings, &block)
|
def caveats(*strings, &block)
|
||||||
@caveats ||= DSL::Caveats.new(cask)
|
@caveats ||= DSL::Caveats.new(cask)
|
||||||
if block_given?
|
if block
|
||||||
@caveats.eval_caveats(&block)
|
@caveats.eval_caveats(&block)
|
||||||
elsif strings.any?
|
elsif strings.any?
|
||||||
strings.each do |string|
|
strings.each do |string|
|
||||||
|
|||||||
@ -136,7 +136,7 @@ module Homebrew
|
|||||||
switch short, long, description: desc, env: option_to_name(long), method: :on_tail
|
switch short, long, description: desc, env: option_to_name(long), method: :on_tail
|
||||||
end
|
end
|
||||||
|
|
||||||
instance_eval(&block) if block_given?
|
instance_eval(&block) if block
|
||||||
end
|
end
|
||||||
|
|
||||||
def switch(*names, description: nil, env: nil, required_for: nil, depends_on: nil, method: :on)
|
def switch(*names, description: nil, env: nil, required_for: nil, depends_on: nil, method: :on)
|
||||||
|
|||||||
@ -56,7 +56,7 @@ class CompilerFailure
|
|||||||
def initialize(name, version, &block)
|
def initialize(name, version, &block)
|
||||||
@name = name
|
@name = name
|
||||||
@version = Version.parse(version.to_s)
|
@version = Version.parse(version.to_s)
|
||||||
instance_eval(&block) if block_given?
|
instance_eval(&block) if block
|
||||||
end
|
end
|
||||||
|
|
||||||
def fails_with?(compiler)
|
def fails_with?(compiler)
|
||||||
|
|||||||
@ -120,9 +120,9 @@ class Dependency
|
|||||||
@expand_stack.pop
|
@expand_stack.pop
|
||||||
end
|
end
|
||||||
|
|
||||||
def action(dependent, dep, &_block)
|
def action(dependent, dep, &block)
|
||||||
catch(:action) do
|
catch(:action) do
|
||||||
if block_given?
|
if block
|
||||||
yield dependent, dep
|
yield dependent, dep
|
||||||
elsif dep.optional? || dep.recommended?
|
elsif dep.optional? || dep.recommended?
|
||||||
prune unless dependent.build.with?(dep)
|
prune unless dependent.build.with?(dep)
|
||||||
|
|||||||
@ -4,8 +4,8 @@
|
|||||||
class Formula
|
class Formula
|
||||||
undef on_linux
|
undef on_linux
|
||||||
|
|
||||||
def on_linux(&_block)
|
def on_linux(&block)
|
||||||
raise "No block content defined for on_linux block" unless block_given?
|
raise "No block content defined for on_linux block" unless block
|
||||||
|
|
||||||
yield
|
yield
|
||||||
end
|
end
|
||||||
@ -19,8 +19,8 @@ class Formula
|
|||||||
class << self
|
class << self
|
||||||
undef on_linux
|
undef on_linux
|
||||||
|
|
||||||
def on_linux(&_block)
|
def on_linux(&block)
|
||||||
raise "No block content defined for on_linux block" unless block_given?
|
raise "No block content defined for on_linux block" unless block
|
||||||
|
|
||||||
yield
|
yield
|
||||||
end
|
end
|
||||||
|
|||||||
@ -4,8 +4,8 @@
|
|||||||
class Formula
|
class Formula
|
||||||
undef on_macos
|
undef on_macos
|
||||||
|
|
||||||
def on_macos(&_block)
|
def on_macos(&block)
|
||||||
raise "No block content defined for on_macos block" unless block_given?
|
raise "No block content defined for on_macos block" unless block
|
||||||
|
|
||||||
yield
|
yield
|
||||||
end
|
end
|
||||||
@ -13,8 +13,8 @@ class Formula
|
|||||||
class << self
|
class << self
|
||||||
undef on_macos
|
undef on_macos
|
||||||
|
|
||||||
def on_macos(&_block)
|
def on_macos(&block)
|
||||||
raise "No block content defined for on_macos block" unless block_given?
|
raise "No block content defined for on_macos block" unless block
|
||||||
|
|
||||||
yield
|
yield
|
||||||
end
|
end
|
||||||
|
|||||||
@ -282,7 +282,7 @@ class Formula
|
|||||||
# and is specified to this instance.
|
# and is specified to this instance.
|
||||||
def installed_alias_path
|
def installed_alias_path
|
||||||
path = build.source["path"] if build.is_a?(Tab)
|
path = build.source["path"] if build.is_a?(Tab)
|
||||||
return unless path&.match?(%r{#{HOMEBREW_TAP_DIR_REGEX}/Aliases})
|
return unless path&.match?(%r{#{HOMEBREW_TAP_DIR_REGEX}/Aliases}o)
|
||||||
return unless File.symlink?(path)
|
return unless File.symlink?(path)
|
||||||
|
|
||||||
path
|
path
|
||||||
@ -1384,16 +1384,16 @@ class Formula
|
|||||||
# <pre>on_macos do
|
# <pre>on_macos do
|
||||||
# # Do something Mac-specific
|
# # Do something Mac-specific
|
||||||
# end</pre>
|
# end</pre>
|
||||||
def on_macos(&_block)
|
def on_macos(&block)
|
||||||
raise "No block content defined for on_macos block" unless block_given?
|
raise "No block content defined for on_macos block" unless block
|
||||||
end
|
end
|
||||||
|
|
||||||
# Block only executed on Linux. No-op on macOS.
|
# Block only executed on Linux. No-op on macOS.
|
||||||
# <pre>on_linux do
|
# <pre>on_linux do
|
||||||
# # Do something Linux-specific
|
# # Do something Linux-specific
|
||||||
# end</pre>
|
# end</pre>
|
||||||
def on_linux(&_block)
|
def on_linux(&block)
|
||||||
raise "No block content defined for on_linux block" unless block_given?
|
raise "No block content defined for on_linux block" unless block
|
||||||
end
|
end
|
||||||
|
|
||||||
# Standard parameters for cargo builds.
|
# Standard parameters for cargo builds.
|
||||||
@ -2118,7 +2118,7 @@ class Formula
|
|||||||
# a block.
|
# a block.
|
||||||
def mkdir(name, &block)
|
def mkdir(name, &block)
|
||||||
result = FileUtils.mkdir_p(name)
|
result = FileUtils.mkdir_p(name)
|
||||||
return result unless block_given?
|
return result unless block
|
||||||
|
|
||||||
FileUtils.chdir(name, &block)
|
FileUtils.chdir(name, &block)
|
||||||
end
|
end
|
||||||
@ -2458,7 +2458,7 @@ class Formula
|
|||||||
# end</pre>
|
# end</pre>
|
||||||
def stable(&block)
|
def stable(&block)
|
||||||
@stable ||= SoftwareSpec.new(flags: build_flags)
|
@stable ||= SoftwareSpec.new(flags: build_flags)
|
||||||
return @stable unless block_given?
|
return @stable unless block
|
||||||
|
|
||||||
@stable.instance_eval(&block)
|
@stable.instance_eval(&block)
|
||||||
end
|
end
|
||||||
@ -2482,7 +2482,7 @@ class Formula
|
|||||||
# <pre>head "https://hg.is.awesome.but.git.has.won.example.com/", using: :hg</pre>
|
# <pre>head "https://hg.is.awesome.but.git.has.won.example.com/", using: :hg</pre>
|
||||||
def head(val = nil, specs = {}, &block)
|
def head(val = nil, specs = {}, &block)
|
||||||
@head ||= HeadSoftwareSpec.new(flags: build_flags)
|
@head ||= HeadSoftwareSpec.new(flags: build_flags)
|
||||||
if block_given?
|
if block
|
||||||
@head.instance_eval(&block)
|
@head.instance_eval(&block)
|
||||||
elsif val
|
elsif val
|
||||||
@head.url(val, specs)
|
@head.url(val, specs)
|
||||||
@ -2553,16 +2553,16 @@ class Formula
|
|||||||
# <pre>on_macos do
|
# <pre>on_macos do
|
||||||
# depends_on "mac_only_dep"
|
# depends_on "mac_only_dep"
|
||||||
# end</pre>
|
# end</pre>
|
||||||
def on_macos(&_block)
|
def on_macos(&block)
|
||||||
raise "No block content defined for on_macos block" unless block_given?
|
raise "No block content defined for on_macos block" unless block
|
||||||
end
|
end
|
||||||
|
|
||||||
# Block only executed on Linux. No-op on macOS.
|
# Block only executed on Linux. No-op on macOS.
|
||||||
# <pre>on_linux do
|
# <pre>on_linux do
|
||||||
# depends_on "linux_only_dep"
|
# depends_on "linux_only_dep"
|
||||||
# end</pre>
|
# end</pre>
|
||||||
def on_linux(&_block)
|
def on_linux(&block)
|
||||||
raise "No block content defined for on_linux block" unless block_given?
|
raise "No block content defined for on_linux block" unless block
|
||||||
end
|
end
|
||||||
|
|
||||||
# @!attribute [w] option
|
# @!attribute [w] option
|
||||||
@ -2757,7 +2757,7 @@ class Formula
|
|||||||
# end</pre>
|
# end</pre>
|
||||||
def livecheck(&block)
|
def livecheck(&block)
|
||||||
@livecheck ||= Livecheck.new(self)
|
@livecheck ||= Livecheck.new(self)
|
||||||
return @livecheck unless block_given?
|
return @livecheck unless block
|
||||||
|
|
||||||
@livecheckable = true
|
@livecheckable = true
|
||||||
@livecheck.instance_eval(&block)
|
@livecheck.instance_eval(&block)
|
||||||
|
|||||||
@ -270,7 +270,7 @@ module Language
|
|||||||
next unless f.symlink?
|
next unless f.symlink?
|
||||||
next unless (rp = f.realpath.to_s).start_with? HOMEBREW_CELLAR
|
next unless (rp = f.realpath.to_s).start_with? HOMEBREW_CELLAR
|
||||||
|
|
||||||
version = rp.match %r{^#{HOMEBREW_CELLAR}/python@(.*?)/}
|
version = rp.match %r{^#{HOMEBREW_CELLAR}/python@(.*?)/}o
|
||||||
version = "@#{version.captures.first}" unless version.nil?
|
version = "@#{version.captures.first}" unless version.nil?
|
||||||
|
|
||||||
new_target = rp.sub %r{#{HOMEBREW_CELLAR}/python#{version}/[^/]+}, Formula["python#{version}"].opt_prefix
|
new_target = rp.sub %r{#{HOMEBREW_CELLAR}/python#{version}/[^/]+}, Formula["python#{version}"].opt_prefix
|
||||||
@ -281,7 +281,7 @@ module Language
|
|||||||
Pathname.glob(@venv_root/"lib/python*/orig-prefix.txt").each do |prefix_file|
|
Pathname.glob(@venv_root/"lib/python*/orig-prefix.txt").each do |prefix_file|
|
||||||
prefix_path = prefix_file.read
|
prefix_path = prefix_file.read
|
||||||
|
|
||||||
version = prefix_path.match %r{^#{HOMEBREW_CELLAR}/python@(.*?)/}
|
version = prefix_path.match %r{^#{HOMEBREW_CELLAR}/python@(.*?)/}o
|
||||||
version = "@#{version.captures.first}" unless version.nil?
|
version = "@#{version.captures.first}" unless version.nil?
|
||||||
|
|
||||||
prefix_path.sub! %r{^#{HOMEBREW_CELLAR}/python#{version}/[^/]+}, Formula["python#{version}"].opt_prefix
|
prefix_path.sub! %r{^#{HOMEBREW_CELLAR}/python#{version}/[^/]+}, Formula["python#{version}"].opt_prefix
|
||||||
|
|||||||
@ -129,7 +129,7 @@ class LinkageChecker
|
|||||||
private
|
private
|
||||||
|
|
||||||
def dylib_to_dep(dylib)
|
def dylib_to_dep(dylib)
|
||||||
dylib =~ %r{#{Regexp.escape(HOMEBREW_PREFIX)}/(opt|Cellar)/([\w+-.@]+)/}
|
dylib =~ %r{#{Regexp.escape(HOMEBREW_PREFIX)}/(opt|Cellar)/([\w+-.@]+)/}o
|
||||||
Regexp.last_match(2)
|
Regexp.last_match(2)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -82,7 +82,7 @@ class Requirement
|
|||||||
return unless @satisfied_result.is_a?(Pathname)
|
return unless @satisfied_result.is_a?(Pathname)
|
||||||
|
|
||||||
parent = @satisfied_result.resolved_path.parent
|
parent = @satisfied_result.resolved_path.parent
|
||||||
if parent.to_s =~ %r{^#{Regexp.escape(HOMEBREW_CELLAR)}/([\w+-.@]+)/[^/]+/(s?bin)/?$}
|
if parent.to_s =~ %r{^#{Regexp.escape(HOMEBREW_CELLAR)}/([\w+-.@]+)/[^/]+/(s?bin)/?$}o
|
||||||
parent = HOMEBREW_PREFIX/"opt/#{Regexp.last_match(1)}/#{Regexp.last_match(2)}"
|
parent = HOMEBREW_PREFIX/"opt/#{Regexp.last_match(1)}/#{Regexp.last_match(2)}"
|
||||||
end
|
end
|
||||||
parent
|
parent
|
||||||
@ -168,14 +168,14 @@ class Requirement
|
|||||||
attr_rw :fatal, :cask, :download
|
attr_rw :fatal, :cask, :download
|
||||||
|
|
||||||
def satisfy(options = nil, &block)
|
def satisfy(options = nil, &block)
|
||||||
return @satisfied if options.nil? && !block_given?
|
return @satisfied if options.nil? && !block
|
||||||
|
|
||||||
options = {} if options.nil?
|
options = {} if options.nil?
|
||||||
@satisfied = Satisfier.new(options, &block)
|
@satisfied = Satisfier.new(options, &block)
|
||||||
end
|
end
|
||||||
|
|
||||||
def env(*settings, &block)
|
def env(*settings, &block)
|
||||||
if block_given?
|
if block
|
||||||
@env_proc = block
|
@env_proc = block
|
||||||
else
|
else
|
||||||
super
|
super
|
||||||
@ -236,9 +236,9 @@ class Requirement
|
|||||||
reqs
|
reqs
|
||||||
end
|
end
|
||||||
|
|
||||||
def prune?(dependent, req, &_block)
|
def prune?(dependent, req, &block)
|
||||||
catch(:prune) do
|
catch(:prune) do
|
||||||
if block_given?
|
if block
|
||||||
yield dependent, req
|
yield dependent, req
|
||||||
elsif req.optional? || req.recommended?
|
elsif req.optional? || req.recommended?
|
||||||
prune unless dependent.build.with?(req)
|
prune unless dependent.build.with?(req)
|
||||||
|
|||||||
@ -32,7 +32,7 @@ class Resource
|
|||||||
@checksum = nil
|
@checksum = nil
|
||||||
@using = nil
|
@using = nil
|
||||||
@patches = []
|
@patches = []
|
||||||
instance_eval(&block) if block_given?
|
instance_eval(&block) if block
|
||||||
end
|
end
|
||||||
|
|
||||||
def owner=(owner)
|
def owner=(owner)
|
||||||
|
|||||||
@ -107,7 +107,7 @@ class SoftwareSpec
|
|||||||
end
|
end
|
||||||
|
|
||||||
def resource(name, klass = Resource, &block)
|
def resource(name, klass = Resource, &block)
|
||||||
if block_given?
|
if block
|
||||||
raise DuplicateResourceError, name if resource_defined?(name)
|
raise DuplicateResourceError, name if resource_defined?(name)
|
||||||
|
|
||||||
res = klass.new(name, &block)
|
res = klass.new(name, &block)
|
||||||
|
|||||||
@ -586,7 +586,7 @@ class Tap
|
|||||||
def self.each(&block)
|
def self.each(&block)
|
||||||
return unless TAP_DIRECTORY.directory?
|
return unless TAP_DIRECTORY.directory?
|
||||||
|
|
||||||
return to_enum unless block_given?
|
return to_enum unless block
|
||||||
|
|
||||||
TAP_DIRECTORY.subdirs.each do |user|
|
TAP_DIRECTORY.subdirs.each do |user|
|
||||||
user.subdirs.each do |repo|
|
user.subdirs.each do |repo|
|
||||||
|
|||||||
@ -10,14 +10,14 @@ end
|
|||||||
describe "brew --cache", :integration_test do
|
describe "brew --cache", :integration_test do
|
||||||
it "prints all cache files for a given Formula" do
|
it "prints all cache files for a given Formula" do
|
||||||
expect { brew "--cache", testball }
|
expect { brew "--cache", testball }
|
||||||
.to output(%r{#{HOMEBREW_CACHE}/downloads/[\da-f]{64}--testball-}).to_stdout
|
.to output(%r{#{HOMEBREW_CACHE}/downloads/[\da-f]{64}--testball-}o).to_stdout
|
||||||
.and not_to_output.to_stderr
|
.and not_to_output.to_stderr
|
||||||
.and be_a_success
|
.and be_a_success
|
||||||
end
|
end
|
||||||
|
|
||||||
it "prints the cache files for a given Cask" do
|
it "prints the cache files for a given Cask" do
|
||||||
expect { brew "--cache", cask_path("local-caffeine") }
|
expect { brew "--cache", cask_path("local-caffeine") }
|
||||||
.to output(%r{#{HOMEBREW_CACHE}/downloads/[\da-f]{64}--caffeine\.zip}).to_stdout
|
.to output(%r{#{HOMEBREW_CACHE}/downloads/[\da-f]{64}--caffeine\.zip}o).to_stdout
|
||||||
.and not_to_output.to_stderr
|
.and not_to_output.to_stderr
|
||||||
.and be_a_success
|
.and be_a_success
|
||||||
end
|
end
|
||||||
@ -28,7 +28,7 @@ describe "brew --cache", :integration_test do
|
|||||||
%r{
|
%r{
|
||||||
#{HOMEBREW_CACHE}/downloads/[\da-f]{64}--testball-.*\n
|
#{HOMEBREW_CACHE}/downloads/[\da-f]{64}--testball-.*\n
|
||||||
#{HOMEBREW_CACHE}/downloads/[\da-f]{64}--caffeine\.zip
|
#{HOMEBREW_CACHE}/downloads/[\da-f]{64}--caffeine\.zip
|
||||||
}x,
|
}xo,
|
||||||
).to_stdout
|
).to_stdout
|
||||||
.and not_to_output.to_stderr
|
.and not_to_output.to_stderr
|
||||||
.and be_a_success
|
.and be_a_success
|
||||||
|
|||||||
@ -10,7 +10,7 @@ end
|
|||||||
describe "brew --cellar", :integration_test do
|
describe "brew --cellar", :integration_test do
|
||||||
it "returns the Cellar subdirectory for a given Formula" do
|
it "returns the Cellar subdirectory for a given Formula" do
|
||||||
expect { brew "--cellar", testball }
|
expect { brew "--cellar", testball }
|
||||||
.to output(%r{#{HOMEBREW_CELLAR}/testball}).to_stdout
|
.to output(%r{#{HOMEBREW_CELLAR}/testball}o).to_stdout
|
||||||
.and not_to_output.to_stderr
|
.and not_to_output.to_stderr
|
||||||
.and be_a_success
|
.and be_a_success
|
||||||
end
|
end
|
||||||
|
|||||||
@ -10,7 +10,7 @@ end
|
|||||||
describe "brew --prefix", :integration_test do
|
describe "brew --prefix", :integration_test do
|
||||||
it "prints a given Formula's prefix" do
|
it "prints a given Formula's prefix" do
|
||||||
expect { brew "--prefix", testball }
|
expect { brew "--prefix", testball }
|
||||||
.to output(%r{#{HOMEBREW_CELLAR}/testball}).to_stdout
|
.to output(%r{#{HOMEBREW_CELLAR}/testball}o).to_stdout
|
||||||
.and not_to_output.to_stderr
|
.and not_to_output.to_stderr
|
||||||
.and be_a_success
|
.and be_a_success
|
||||||
end
|
end
|
||||||
|
|||||||
@ -10,7 +10,7 @@ end
|
|||||||
describe "brew --version", :integration_test do
|
describe "brew --version", :integration_test do
|
||||||
it "prints the Homebrew version" do
|
it "prints the Homebrew version" do
|
||||||
expect { brew "--version" }
|
expect { brew "--version" }
|
||||||
.to output(/^Homebrew #{Regexp.escape(HOMEBREW_VERSION)}\n/).to_stdout
|
.to output(/^Homebrew #{Regexp.escape(HOMEBREW_VERSION)}\n/o).to_stdout
|
||||||
.and not_to_output.to_stderr
|
.and not_to_output.to_stderr
|
||||||
.and be_a_success
|
.and be_a_success
|
||||||
end
|
end
|
||||||
|
|||||||
@ -22,7 +22,7 @@ describe "brew cleanup", :integration_test do
|
|||||||
(HOMEBREW_CACHE/"test").write "test"
|
(HOMEBREW_CACHE/"test").write "test"
|
||||||
|
|
||||||
expect { brew "cleanup", "--prune=all" }
|
expect { brew "cleanup", "--prune=all" }
|
||||||
.to output(%r{#{Regexp.escape(HOMEBREW_CACHE)}/test}).to_stdout
|
.to output(%r{#{Regexp.escape(HOMEBREW_CACHE)}/test}o).to_stdout
|
||||||
.and not_to_output.to_stderr
|
.and not_to_output.to_stderr
|
||||||
.and be_a_success
|
.and be_a_success
|
||||||
end
|
end
|
||||||
|
|||||||
@ -10,7 +10,7 @@ end
|
|||||||
describe "brew config", :integration_test do
|
describe "brew config", :integration_test do
|
||||||
it "prints information about the current Homebrew configuration" do
|
it "prints information about the current Homebrew configuration" do
|
||||||
expect { brew "config" }
|
expect { brew "config" }
|
||||||
.to output(/HOMEBREW_VERSION: #{Regexp.escape HOMEBREW_VERSION}/).to_stdout
|
.to output(/HOMEBREW_VERSION: #{Regexp.escape HOMEBREW_VERSION}/o).to_stdout
|
||||||
.and not_to_output.to_stderr
|
.and not_to_output.to_stderr
|
||||||
.and be_a_success
|
.and be_a_success
|
||||||
end
|
end
|
||||||
|
|||||||
@ -12,7 +12,7 @@ describe "brew install", :integration_test do
|
|||||||
setup_test_formula "testball1"
|
setup_test_formula "testball1"
|
||||||
|
|
||||||
expect { brew "install", "testball1" }
|
expect { brew "install", "testball1" }
|
||||||
.to output(%r{#{HOMEBREW_CELLAR}/testball1/0\.1}).to_stdout
|
.to output(%r{#{HOMEBREW_CELLAR}/testball1/0\.1}o).to_stdout
|
||||||
.and not_to_output.to_stderr
|
.and not_to_output.to_stderr
|
||||||
.and be_a_success
|
.and be_a_success
|
||||||
expect(HOMEBREW_CELLAR/"testball1/0.1/foo/test").not_to be_a_file
|
expect(HOMEBREW_CELLAR/"testball1/0.1/foo/test").not_to be_a_file
|
||||||
@ -22,7 +22,7 @@ describe "brew install", :integration_test do
|
|||||||
setup_test_formula "testball1"
|
setup_test_formula "testball1"
|
||||||
|
|
||||||
expect { brew "install", "testball1", "--with-foo" }
|
expect { brew "install", "testball1", "--with-foo" }
|
||||||
.to output(%r{#{HOMEBREW_CELLAR}/testball1/0\.1}).to_stdout
|
.to output(%r{#{HOMEBREW_CELLAR}/testball1/0\.1}o).to_stdout
|
||||||
.and not_to_output.to_stderr
|
.and not_to_output.to_stderr
|
||||||
.and be_a_success
|
.and be_a_success
|
||||||
expect(HOMEBREW_CELLAR/"testball1/0.1/foo/test").to be_a_file
|
expect(HOMEBREW_CELLAR/"testball1/0.1/foo/test").to be_a_file
|
||||||
@ -36,7 +36,7 @@ describe "brew install", :integration_test do
|
|||||||
RUBY
|
RUBY
|
||||||
|
|
||||||
expect { brew "install", "testball1" }
|
expect { brew "install", "testball1" }
|
||||||
.to output(%r{#{HOMEBREW_CELLAR}/testball1/1\.0}).to_stdout
|
.to output(%r{#{HOMEBREW_CELLAR}/testball1/1\.0}o).to_stdout
|
||||||
.and not_to_output.to_stderr
|
.and not_to_output.to_stderr
|
||||||
.and be_a_success
|
.and be_a_success
|
||||||
expect(HOMEBREW_CELLAR/"testball1/1.0/foo/test").not_to be_a_file
|
expect(HOMEBREW_CELLAR/"testball1/1.0/foo/test").not_to be_a_file
|
||||||
@ -69,7 +69,7 @@ describe "brew install", :integration_test do
|
|||||||
# and there will be the git requirement, but we cannot instantiate git
|
# and there will be the git requirement, but we cannot instantiate git
|
||||||
# formula since we only have testball1 formula.
|
# formula since we only have testball1 formula.
|
||||||
expect { brew "install", "testball1", "--HEAD", "--ignore-dependencies" }
|
expect { brew "install", "testball1", "--HEAD", "--ignore-dependencies" }
|
||||||
.to output(%r{#{HOMEBREW_CELLAR}/testball1/HEAD-d5eb689}).to_stdout
|
.to output(%r{#{HOMEBREW_CELLAR}/testball1/HEAD-d5eb689}o).to_stdout
|
||||||
.and output(/Cloning into/).to_stderr
|
.and output(/Cloning into/).to_stderr
|
||||||
.and be_a_success
|
.and be_a_success
|
||||||
expect(HOMEBREW_CELLAR/"testball1/HEAD-d5eb689/foo/test").not_to be_a_file
|
expect(HOMEBREW_CELLAR/"testball1/HEAD-d5eb689/foo/test").not_to be_a_file
|
||||||
|
|||||||
@ -10,7 +10,7 @@ end
|
|||||||
describe "brew command", :integration_test do
|
describe "brew command", :integration_test do
|
||||||
it "returns the file for a given command" do
|
it "returns the file for a given command" do
|
||||||
expect { brew "command", "info" }
|
expect { brew "command", "info" }
|
||||||
.to output(%r{#{Regexp.escape(HOMEBREW_LIBRARY_PATH)}/cmd/info.rb}).to_stdout
|
.to output(%r{#{Regexp.escape(HOMEBREW_LIBRARY_PATH)}/cmd/info.rb}o).to_stdout
|
||||||
.and be_a_success
|
.and be_a_success
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -66,7 +66,7 @@ describe Homebrew::Diagnostic::Checks do
|
|||||||
|
|
||||||
specify "#check_user_path_2" do
|
specify "#check_user_path_2" do
|
||||||
ENV["PATH"] = ENV["PATH"].gsub \
|
ENV["PATH"] = ENV["PATH"].gsub \
|
||||||
%r{(?:^|#{File::PATH_SEPARATOR})#{HOMEBREW_PREFIX}/bin}, ""
|
%r{(?:^|#{File::PATH_SEPARATOR})#{HOMEBREW_PREFIX}/bin}o, ""
|
||||||
|
|
||||||
expect(subject.check_user_path_1).to be nil
|
expect(subject.check_user_path_1).to be nil
|
||||||
expect(subject.check_user_path_2)
|
expect(subject.check_user_path_2)
|
||||||
|
|||||||
28
Library/Homebrew/vendor/bundle/bundler/setup.rb
vendored
28
Library/Homebrew/vendor/bundle/bundler/setup.rb
vendored
@ -7,15 +7,15 @@ $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/concurrent-ruby-1.1.7
|
|||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/i18n-1.8.5/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/i18n-1.8.5/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/minitest-5.14.2/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/minitest-5.14.2/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/thread_safe-0.3.6/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/thread_safe-0.3.6/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/tzinfo-1.2.7/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/tzinfo-1.2.8/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/zeitwerk-2.4.0/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/zeitwerk-2.4.1/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/activesupport-6.0.3.4/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/activesupport-6.0.3.4/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ast-2.4.1/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ast-2.4.1/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/bindata-2.4.8/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/bindata-2.4.8/lib"
|
||||||
$:.unshift "#{path}/"
|
$:.unshift "#{path}/"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/universal-darwin-19/2.6.0/byebug-11.1.3"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/universal-darwin-20/2.6.0/byebug-11.1.3"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/byebug-11.1.3/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/byebug-11.1.3/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/universal-darwin-19/2.6.0/json-2.3.1"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/universal-darwin-20/2.6.0/json-2.3.1"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/json-2.3.1/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/json-2.3.1/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/docile-1.3.2/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/docile-1.3.2/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/simplecov-html-0.12.3/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/simplecov-html-0.12.3/lib"
|
||||||
@ -27,20 +27,20 @@ $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/highline-2.0.3/lib"
|
|||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/commander-4.5.2/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/commander-4.5.2/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/connection_pool-2.2.3/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/connection_pool-2.2.3/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/diff-lcs-1.4.4/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/diff-lcs-1.4.4/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/universal-darwin-19/2.6.0/unf_ext-0.0.7.7"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/universal-darwin-20/2.6.0/unf_ext-0.0.7.7"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/unf_ext-0.0.7.7/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/unf_ext-0.0.7.7/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/unf-0.1.4/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/unf-0.1.4/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/domain_name-0.5.20190701/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/domain_name-0.5.20190701/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/elftools-1.1.3/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/elftools-1.1.3/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/universal-darwin-19/2.6.0/hpricot-0.8.6"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/universal-darwin-20/2.6.0/hpricot-0.8.6"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/hpricot-0.8.6/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/hpricot-0.8.6/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/http-cookie-1.0.3/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/http-cookie-1.0.3/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/mime-types-data-3.2020.0512/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/mime-types-data-3.2020.1104/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/mime-types-3.3.1/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/mime-types-3.3.1/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/net-http-digest_auth-1.4.1/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/net-http-digest_auth-1.4.1/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/net-http-persistent-4.0.0/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/net-http-persistent-4.0.0/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/mini_portile2-2.4.0/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/mini_portile2-2.4.0/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/universal-darwin-19/2.6.0/nokogiri-1.10.10"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/universal-darwin-20/2.6.0/nokogiri-1.10.10"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/nokogiri-1.10.10/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/nokogiri-1.10.10/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ntlm-http-0.1.1/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ntlm-http-0.1.1/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/webrobots-0.1.2/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/webrobots-0.1.2/lib"
|
||||||
@ -51,12 +51,12 @@ $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parallel-1.20.0/lib"
|
|||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parallel_tests-3.3.0/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parallel_tests-3.3.0/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parser-2.7.2.0/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parser-2.7.2.0/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rainbow-3.0.0/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rainbow-3.0.0/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/sorbet-runtime-0.5.6040/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/sorbet-runtime-0.5.6076/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parlour-4.0.1/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parlour-4.0.1/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/patchelf-1.3.0/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/patchelf-1.3.0/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/plist-3.5.0/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/plist-3.5.0/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/pry-0.13.1/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/pry-0.13.1/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/universal-darwin-19/2.6.0/rdiscount-2.2.0.2"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/universal-darwin-20/2.6.0/rdiscount-2.2.0.2"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rdiscount-2.2.0.2/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rdiscount-2.2.0.2/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/regexp_parser-1.8.2/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/regexp_parser-1.8.2/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rexml-3.2.4/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rexml-3.2.4/lib"
|
||||||
@ -72,13 +72,13 @@ $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rspec-wait-0.0.9/lib"
|
|||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-ast-1.1.1/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-ast-1.1.1/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ruby-progressbar-1.10.1/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ruby-progressbar-1.10.1/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/unicode-display_width-1.7.0/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/unicode-display_width-1.7.0/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-1.3.0/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-1.3.1/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-performance-1.8.1/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-performance-1.9.0/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-rspec-2.0.0/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-rspec-2.0.0/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-sorbet-0.5.1/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-sorbet-0.5.1/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ruby-macho-2.5.0/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ruby-macho-2.5.0/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/sorbet-static-0.5.6042-universal-darwin-19/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/sorbet-static-0.5.6076-universal-darwin-20/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/sorbet-0.5.6042/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/sorbet-0.5.6076/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/sorbet-runtime-stub-0.2.0/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/sorbet-runtime-stub-0.2.0/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/thor-1.0.1/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/thor-1.0.1/lib"
|
||||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/spoom-1.0.4/lib"
|
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/spoom-1.0.4/lib"
|
||||||
|
|||||||
@ -1,134 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module RuboCop
|
|
||||||
module Cop
|
|
||||||
module Performance
|
|
||||||
# This cop identifies places where custom code finding the sum of elements
|
|
||||||
# in some Enumerable object can be replaced by `Enumerable#sum` method.
|
|
||||||
#
|
|
||||||
# @example
|
|
||||||
# # bad
|
|
||||||
# [1, 2, 3].inject(:+)
|
|
||||||
# [1, 2, 3].reduce(10, :+)
|
|
||||||
# [1, 2, 3].inject(&:+)
|
|
||||||
# [1, 2, 3].reduce { |acc, elem| acc + elem }
|
|
||||||
#
|
|
||||||
# # good
|
|
||||||
# [1, 2, 3].sum
|
|
||||||
# [1, 2, 3].sum(10)
|
|
||||||
# [1, 2, 3].sum
|
|
||||||
#
|
|
||||||
class Sum < Base
|
|
||||||
include RangeHelp
|
|
||||||
extend AutoCorrector
|
|
||||||
|
|
||||||
MSG = 'Use `%<good_method>s` instead of `%<bad_method>s`.'
|
|
||||||
|
|
||||||
def_node_matcher :sum_candidate?, <<~PATTERN
|
|
||||||
(send _ ${:inject :reduce} $_init ? ${(sym :+) (block_pass (sym :+))})
|
|
||||||
PATTERN
|
|
||||||
|
|
||||||
def_node_matcher :sum_with_block_candidate?, <<~PATTERN
|
|
||||||
(block
|
|
||||||
$(send _ {:inject :reduce} $_init ?)
|
|
||||||
(args (arg $_acc) (arg $_elem))
|
|
||||||
$send)
|
|
||||||
PATTERN
|
|
||||||
|
|
||||||
def_node_matcher :acc_plus_elem?, <<~PATTERN
|
|
||||||
(send (lvar %1) :+ (lvar %2))
|
|
||||||
PATTERN
|
|
||||||
alias elem_plus_acc? acc_plus_elem?
|
|
||||||
|
|
||||||
def on_send(node)
|
|
||||||
sum_candidate?(node) do |method, init, operation|
|
|
||||||
range = sum_method_range(node)
|
|
||||||
message = build_method_message(method, init, operation)
|
|
||||||
|
|
||||||
add_offense(range, message: message) do |corrector|
|
|
||||||
autocorrect(corrector, init, range)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def on_block(node)
|
|
||||||
sum_with_block_candidate?(node) do |send, init, var_acc, var_elem, body|
|
|
||||||
if acc_plus_elem?(body, var_acc, var_elem) || elem_plus_acc?(body, var_elem, var_acc)
|
|
||||||
range = sum_block_range(send, node)
|
|
||||||
message = build_block_message(send, init, var_acc, var_elem, body)
|
|
||||||
|
|
||||||
add_offense(range, message: message) do |corrector|
|
|
||||||
autocorrect(corrector, init, range)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def autocorrect(corrector, init, range)
|
|
||||||
return if init.empty?
|
|
||||||
|
|
||||||
replacement = build_good_method(init)
|
|
||||||
|
|
||||||
corrector.replace(range, replacement)
|
|
||||||
end
|
|
||||||
|
|
||||||
def sum_method_range(node)
|
|
||||||
range_between(node.loc.selector.begin_pos, node.loc.end.end_pos)
|
|
||||||
end
|
|
||||||
|
|
||||||
def sum_block_range(send, node)
|
|
||||||
range_between(send.loc.selector.begin_pos, node.loc.end.end_pos)
|
|
||||||
end
|
|
||||||
|
|
||||||
def build_method_message(method, init, operation)
|
|
||||||
good_method = build_good_method(init)
|
|
||||||
bad_method = build_method_bad_method(init, method, operation)
|
|
||||||
format(MSG, good_method: good_method, bad_method: bad_method)
|
|
||||||
end
|
|
||||||
|
|
||||||
def build_block_message(send, init, var_acc, var_elem, body)
|
|
||||||
good_method = build_good_method(init)
|
|
||||||
bad_method = build_block_bad_method(send.method_name, init, var_acc, var_elem, body)
|
|
||||||
format(MSG, good_method: good_method, bad_method: bad_method)
|
|
||||||
end
|
|
||||||
|
|
||||||
def build_good_method(init)
|
|
||||||
good_method = 'sum'
|
|
||||||
|
|
||||||
unless init.empty?
|
|
||||||
init = init.first
|
|
||||||
good_method += "(#{init.source})" unless init.int_type? && init.value.zero?
|
|
||||||
end
|
|
||||||
good_method
|
|
||||||
end
|
|
||||||
|
|
||||||
def build_method_bad_method(init, method, operation)
|
|
||||||
bad_method = "#{method}("
|
|
||||||
unless init.empty?
|
|
||||||
init = init.first
|
|
||||||
bad_method += "#{init.source}, "
|
|
||||||
end
|
|
||||||
bad_method += if operation.block_pass_type?
|
|
||||||
'&:+)'
|
|
||||||
else
|
|
||||||
':+)'
|
|
||||||
end
|
|
||||||
bad_method
|
|
||||||
end
|
|
||||||
|
|
||||||
def build_block_bad_method(method, init, var_acc, var_elem, body)
|
|
||||||
bad_method = method.to_s
|
|
||||||
|
|
||||||
unless init.empty?
|
|
||||||
init = init.first
|
|
||||||
bad_method += "(#{init.source})"
|
|
||||||
end
|
|
||||||
bad_method += " { |#{var_acc}, #{var_elem}| #{body.source} }"
|
|
||||||
bad_method
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module RuboCop
|
|
||||||
module Performance
|
|
||||||
module Version
|
|
||||||
STRING = '1.8.1'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@ -7,6 +7,11 @@ Performance/AncestorsInclude:
|
|||||||
Safe: false
|
Safe: false
|
||||||
VersionAdded: '1.7'
|
VersionAdded: '1.7'
|
||||||
|
|
||||||
|
Performance/ArraySemiInfiniteRangeSlice:
|
||||||
|
Description: 'Identifies places where slicing arrays with semi-infinite ranges can be replaced by `Array#take` and `Array#drop`.'
|
||||||
|
Enabled: pending
|
||||||
|
VersionAdded: '1.9'
|
||||||
|
|
||||||
Performance/BigDecimalWithNumericArgument:
|
Performance/BigDecimalWithNumericArgument:
|
||||||
Description: 'Convert numeric argument to string before passing to BigDecimal.'
|
Description: 'Convert numeric argument to string before passing to BigDecimal.'
|
||||||
Enabled: 'pending'
|
Enabled: 'pending'
|
||||||
@ -17,11 +22,17 @@ Performance/BindCall:
|
|||||||
Enabled: true
|
Enabled: true
|
||||||
VersionAdded: '1.6'
|
VersionAdded: '1.6'
|
||||||
|
|
||||||
|
Performance/BlockGivenWithExplicitBlock:
|
||||||
|
Description: 'Check block argument explicitly instead of using `block_given?`.'
|
||||||
|
Enabled: pending
|
||||||
|
VersionAdded: '1.9'
|
||||||
|
|
||||||
Performance/Caller:
|
Performance/Caller:
|
||||||
Description: >-
|
Description: >-
|
||||||
Use `caller(n..n)` instead of `caller`.
|
Use `caller(n..n)` instead of `caller`.
|
||||||
Enabled: true
|
Enabled: true
|
||||||
VersionAdded: '0.49'
|
VersionAdded: '0.49'
|
||||||
|
VersionChanged: '1.9'
|
||||||
|
|
||||||
Performance/CaseWhenSplat:
|
Performance/CaseWhenSplat:
|
||||||
Description: >-
|
Description: >-
|
||||||
@ -51,7 +62,7 @@ Performance/ChainArrayAllocation:
|
|||||||
|
|
||||||
Performance/CollectionLiteralInLoop:
|
Performance/CollectionLiteralInLoop:
|
||||||
Description: 'Extract Array and Hash literals outside of loops into local variables or constants.'
|
Description: 'Extract Array and Hash literals outside of loops into local variables or constants.'
|
||||||
Enabled: true
|
Enabled: 'pending'
|
||||||
VersionAdded: '1.8'
|
VersionAdded: '1.8'
|
||||||
# Min number of elements to consider an offense
|
# Min number of elements to consider an offense
|
||||||
MinSize: 1
|
MinSize: 1
|
||||||
@ -61,6 +72,11 @@ Performance/CompareWithBlock:
|
|||||||
Enabled: true
|
Enabled: true
|
||||||
VersionAdded: '0.46'
|
VersionAdded: '0.46'
|
||||||
|
|
||||||
|
Performance/ConstantRegexp:
|
||||||
|
Description: 'Finds regular expressions with dynamic components that are all constants.'
|
||||||
|
Enabled: pending
|
||||||
|
VersionAdded: '1.9'
|
||||||
|
|
||||||
Performance/Count:
|
Performance/Count:
|
||||||
Description: >-
|
Description: >-
|
||||||
Use `count` instead of `{select,find_all,filter,reject}...{size,count,length}`.
|
Use `count` instead of `{select,find_all,filter,reject}...{size,count,length}`.
|
||||||
@ -154,6 +170,12 @@ Performance/IoReadlines:
|
|||||||
Enabled: false
|
Enabled: false
|
||||||
VersionAdded: '1.7'
|
VersionAdded: '1.7'
|
||||||
|
|
||||||
|
Performance/MethodObjectAsBlock:
|
||||||
|
Description: 'Use block explicitly instead of block-passing a method object.'
|
||||||
|
Reference: 'https://github.com/JuanitoFatas/fast-ruby#normal-way-to-apply-method-vs-method-code'
|
||||||
|
Enabled: pending
|
||||||
|
VersionAdded: '1.9'
|
||||||
|
|
||||||
Performance/OpenStruct:
|
Performance/OpenStruct:
|
||||||
Description: 'Use `Struct` instead of `OpenStruct`.'
|
Description: 'Use `Struct` instead of `OpenStruct`.'
|
||||||
Enabled: false
|
Enabled: false
|
||||||
@ -283,7 +305,9 @@ Performance/TimesMap:
|
|||||||
Performance/UnfreezeString:
|
Performance/UnfreezeString:
|
||||||
Description: 'Use unary plus to get an unfrozen string literal.'
|
Description: 'Use unary plus to get an unfrozen string literal.'
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
SafeAutoCorrect: false
|
||||||
VersionAdded: '0.50'
|
VersionAdded: '0.50'
|
||||||
|
VersionChanged: '1.9'
|
||||||
|
|
||||||
Performance/UriDefaultParser:
|
Performance/UriDefaultParser:
|
||||||
Description: 'Use `URI::DEFAULT_PARSER` instead of `URI::Parser.new`.'
|
Description: 'Use `URI::DEFAULT_PARSER` instead of `URI::Parser.new`.'
|
||||||
@ -25,7 +25,7 @@ module RuboCop
|
|||||||
# (tricky: \s, \d, and so on are metacharacters, but other characters
|
# (tricky: \s, \d, and so on are metacharacters, but other characters
|
||||||
# escaped with a slash are just literals. LITERAL_REGEX takes all
|
# escaped with a slash are just literals. LITERAL_REGEX takes all
|
||||||
# that into account.)
|
# that into account.)
|
||||||
/\A\\A(?:#{Util::LITERAL_REGEX})+\z/.match?(regex_str)
|
/\A\\A(?:#{Util::LITERAL_REGEX})+\z/o.match?(regex_str)
|
||||||
end
|
end
|
||||||
|
|
||||||
def literal_at_start_with_caret?(regex_str)
|
def literal_at_start_with_caret?(regex_str)
|
||||||
@ -35,21 +35,21 @@ module RuboCop
|
|||||||
# (tricky: \s, \d, and so on are metacharacters, but other characters
|
# (tricky: \s, \d, and so on are metacharacters, but other characters
|
||||||
# escaped with a slash are just literals. LITERAL_REGEX takes all
|
# escaped with a slash are just literals. LITERAL_REGEX takes all
|
||||||
# that into account.)
|
# that into account.)
|
||||||
/\A\^(?:#{Util::LITERAL_REGEX})+\z/.match?(regex_str)
|
/\A\^(?:#{Util::LITERAL_REGEX})+\z/o.match?(regex_str)
|
||||||
end
|
end
|
||||||
|
|
||||||
def literal_at_end_with_backslash_z?(regex_str)
|
def literal_at_end_with_backslash_z?(regex_str)
|
||||||
# is this regexp 'literal' in the sense of only matching literal
|
# is this regexp 'literal' in the sense of only matching literal
|
||||||
# chars, rather than using metachars like . and * and so on?
|
# chars, rather than using metachars like . and * and so on?
|
||||||
# also, is it anchored at the end of the string?
|
# also, is it anchored at the end of the string?
|
||||||
/\A(?:#{Util::LITERAL_REGEX})+\\z\z/.match?(regex_str)
|
/\A(?:#{Util::LITERAL_REGEX})+\\z\z/o.match?(regex_str)
|
||||||
end
|
end
|
||||||
|
|
||||||
def literal_at_end_with_dollar?(regex_str)
|
def literal_at_end_with_dollar?(regex_str)
|
||||||
# is this regexp 'literal' in the sense of only matching literal
|
# is this regexp 'literal' in the sense of only matching literal
|
||||||
# chars, rather than using metachars like . and * and so on?
|
# chars, rather than using metachars like . and * and so on?
|
||||||
# also, is it anchored at the end of the string?
|
# also, is it anchored at the end of the string?
|
||||||
/\A(?:#{Util::LITERAL_REGEX})+\$\z/.match?(regex_str)
|
/\A(?:#{Util::LITERAL_REGEX})+\$\z/o.match?(regex_str)
|
||||||
end
|
end
|
||||||
|
|
||||||
def drop_start_metacharacter(regexp_string)
|
def drop_start_metacharacter(regexp_string)
|
||||||
@ -18,6 +18,7 @@ module RuboCop
|
|||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
|
||||||
MSG = 'Use `<=` instead of `ancestors.include?`.'
|
MSG = 'Use `<=` instead of `ancestors.include?`.'
|
||||||
|
RESTRICT_ON_SEND = %i[include?].freeze
|
||||||
|
|
||||||
def_node_matcher :ancestors_include_candidate?, <<~PATTERN
|
def_node_matcher :ancestors_include_candidate?, <<~PATTERN
|
||||||
(send (send $_subclass :ancestors) :include? $_superclass)
|
(send (send $_subclass :ancestors) :include? $_superclass)
|
||||||
@ -0,0 +1,74 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module RuboCop
|
||||||
|
module Cop
|
||||||
|
module Performance
|
||||||
|
# This cop identifies places where slicing arrays with semi-infinite ranges
|
||||||
|
# can be replaced by `Array#take` and `Array#drop`.
|
||||||
|
#
|
||||||
|
# @example
|
||||||
|
# # bad
|
||||||
|
# # array[..2]
|
||||||
|
# # array[...2]
|
||||||
|
# # array[2..]
|
||||||
|
# # array[2...]
|
||||||
|
# # array.slice(..2)
|
||||||
|
#
|
||||||
|
# # good
|
||||||
|
# array.take(3)
|
||||||
|
# array.take(2)
|
||||||
|
# array.drop(2)
|
||||||
|
# array.drop(2)
|
||||||
|
# array.take(3)
|
||||||
|
#
|
||||||
|
class ArraySemiInfiniteRangeSlice < Base
|
||||||
|
include RangeHelp
|
||||||
|
extend AutoCorrector
|
||||||
|
extend TargetRubyVersion
|
||||||
|
|
||||||
|
minimum_target_ruby_version 2.7
|
||||||
|
|
||||||
|
MSG = 'Use `%<prefer>s` instead of `%<current>s` with semi-infinite range.'
|
||||||
|
|
||||||
|
SLICE_METHODS = Set[:[], :slice].freeze
|
||||||
|
RESTRICT_ON_SEND = SLICE_METHODS
|
||||||
|
|
||||||
|
def_node_matcher :endless_range_slice?, <<~PATTERN
|
||||||
|
(send $_ $%SLICE_METHODS $#endless_range?)
|
||||||
|
PATTERN
|
||||||
|
|
||||||
|
def_node_matcher :endless_range?, <<~PATTERN
|
||||||
|
{
|
||||||
|
({irange erange} nil? (int positive?))
|
||||||
|
({irange erange} (int positive?) nil?)
|
||||||
|
}
|
||||||
|
PATTERN
|
||||||
|
|
||||||
|
def on_send(node)
|
||||||
|
endless_range_slice?(node) do |receiver, method_name, range_node|
|
||||||
|
prefer = range_node.begin ? :drop : :take
|
||||||
|
message = format(MSG, prefer: prefer, current: method_name)
|
||||||
|
|
||||||
|
add_offense(node, message: message) do |corrector|
|
||||||
|
corrector.replace(node, correction(receiver, range_node))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def correction(receiver, range_node)
|
||||||
|
method_call = if range_node.begin
|
||||||
|
"drop(#{range_node.begin.value})"
|
||||||
|
elsif range_node.irange_type?
|
||||||
|
"take(#{range_node.end.value + 1})"
|
||||||
|
else
|
||||||
|
"take(#{range_node.end.value})"
|
||||||
|
end
|
||||||
|
|
||||||
|
"#{receiver.source}.#{method_call}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -20,6 +20,7 @@ module RuboCop
|
|||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
|
||||||
MSG = 'Convert numeric argument to string before passing to `BigDecimal`.'
|
MSG = 'Convert numeric argument to string before passing to `BigDecimal`.'
|
||||||
|
RESTRICT_ON_SEND = %i[BigDecimal].freeze
|
||||||
|
|
||||||
def_node_matcher :big_decimal_with_numeric_argument?, <<~PATTERN
|
def_node_matcher :big_decimal_with_numeric_argument?, <<~PATTERN
|
||||||
(send nil? :BigDecimal $numeric_type? ...)
|
(send nil? :BigDecimal $numeric_type? ...)
|
||||||
@ -28,6 +28,7 @@ module RuboCop
|
|||||||
|
|
||||||
MSG = 'Use `bind_call(%<bind_arg>s%<comma>s%<call_args>s)` ' \
|
MSG = 'Use `bind_call(%<bind_arg>s%<comma>s%<call_args>s)` ' \
|
||||||
'instead of `bind(%<bind_arg>s).call(%<call_args>s)`.'
|
'instead of `bind(%<bind_arg>s).call(%<call_args>s)`.'
|
||||||
|
RESTRICT_ON_SEND = %i[call].freeze
|
||||||
|
|
||||||
def_node_matcher :bind_with_call_method?, <<~PATTERN
|
def_node_matcher :bind_with_call_method?, <<~PATTERN
|
||||||
(send
|
(send
|
||||||
@ -0,0 +1,52 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module RuboCop
|
||||||
|
module Cop
|
||||||
|
module Performance
|
||||||
|
# This cop identifies unnecessary use of a `block_given?` where explicit check
|
||||||
|
# of block argument would suffice.
|
||||||
|
#
|
||||||
|
# @example
|
||||||
|
# # bad
|
||||||
|
# def method(&block)
|
||||||
|
# do_something if block_given?
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # good
|
||||||
|
# def method(&block)
|
||||||
|
# do_something if block
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # good - block is reassigned
|
||||||
|
# def method(&block)
|
||||||
|
# block ||= -> { do_something }
|
||||||
|
# warn "Using default ..." unless block_given?
|
||||||
|
# # ...
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
class BlockGivenWithExplicitBlock < Base
|
||||||
|
extend AutoCorrector
|
||||||
|
|
||||||
|
RESTRICT_ON_SEND = %i[block_given?].freeze
|
||||||
|
MSG = 'Check block argument explicitly instead of using `block_given?`.'
|
||||||
|
|
||||||
|
def_node_matcher :reassigns_block_arg?, '`(lvasgn %1 ...)'
|
||||||
|
|
||||||
|
def on_send(node)
|
||||||
|
def_node = node.each_ancestor(:def, :defs).first
|
||||||
|
return unless def_node
|
||||||
|
|
||||||
|
block_arg = def_node.arguments.find(&:blockarg_type?)
|
||||||
|
return unless block_arg
|
||||||
|
|
||||||
|
block_arg_name = block_arg.loc.name.source.to_sym
|
||||||
|
return if reassigns_block_arg?(def_node, block_arg_name)
|
||||||
|
|
||||||
|
add_offense(node) do |corrector|
|
||||||
|
corrector.replace(node, block_arg_name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -19,10 +19,10 @@ module RuboCop
|
|||||||
# caller_locations(2..2).first
|
# caller_locations(2..2).first
|
||||||
# caller_locations(1..1).first
|
# caller_locations(1..1).first
|
||||||
class Caller < Base
|
class Caller < Base
|
||||||
MSG_BRACE = 'Use `%<method>s(%<n>d..%<n>d).first`' \
|
extend AutoCorrector
|
||||||
' instead of `%<method>s[%<m>d]`.'
|
|
||||||
MSG_FIRST = 'Use `%<method>s(%<n>d..%<n>d).first`' \
|
MSG = 'Use `%<preferred_method>s` instead of `%<current_method>s`.'
|
||||||
' instead of `%<method>s.first`.'
|
RESTRICT_ON_SEND = %i[first []].freeze
|
||||||
|
|
||||||
def_node_matcher :slow_caller?, <<~PATTERN
|
def_node_matcher :slow_caller?, <<~PATTERN
|
||||||
{
|
{
|
||||||
@ -41,26 +41,24 @@ module RuboCop
|
|||||||
def on_send(node)
|
def on_send(node)
|
||||||
return unless caller_with_scope_method?(node)
|
return unless caller_with_scope_method?(node)
|
||||||
|
|
||||||
message = message(node)
|
|
||||||
add_offense(node, message: message)
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def message(node)
|
|
||||||
method_name = node.receiver.method_name
|
method_name = node.receiver.method_name
|
||||||
caller_arg = node.receiver.first_argument
|
caller_arg = node.receiver.first_argument
|
||||||
n = caller_arg ? int_value(caller_arg) : 1
|
n = caller_arg ? int_value(caller_arg) : 1
|
||||||
|
|
||||||
if node.method?(:[])
|
if node.method?(:[])
|
||||||
m = int_value(node.first_argument)
|
m = int_value(node.first_argument)
|
||||||
n += m
|
n += m
|
||||||
format(MSG_BRACE, n: n, m: m, method: method_name)
|
end
|
||||||
else
|
|
||||||
format(MSG_FIRST, n: n, method: method_name)
|
preferred_method = "#{method_name}(#{n}..#{n}).first"
|
||||||
|
|
||||||
|
message = format(MSG, preferred_method: preferred_method, current_method: node.source)
|
||||||
|
add_offense(node, message: message) do |corrector|
|
||||||
|
corrector.replace(node, preferred_method)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
def int_value(node)
|
def int_value(node)
|
||||||
node.children[0]
|
node.children[0]
|
||||||
end
|
end
|
||||||
@ -23,6 +23,7 @@ module RuboCop
|
|||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
|
||||||
MSG = 'Use `%<good>s` instead of `%<bad>s`.'
|
MSG = 'Use `%<good>s` instead of `%<bad>s`.'
|
||||||
|
RESTRICT_ON_SEND = %i[== eql? !=].freeze
|
||||||
CASE_METHODS = %i[downcase upcase].freeze
|
CASE_METHODS = %i[downcase upcase].freeze
|
||||||
|
|
||||||
def_node_matcher :downcase_eq, <<~PATTERN
|
def_node_matcher :downcase_eq, <<~PATTERN
|
||||||
@ -0,0 +1,68 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module RuboCop
|
||||||
|
module Cop
|
||||||
|
module Performance
|
||||||
|
# This cop finds regular expressions with dynamic components that are all constants.
|
||||||
|
#
|
||||||
|
# Ruby allocates a new Regexp object every time it executes a code containing such
|
||||||
|
# a regular expression. It is more efficient to extract it into a constant
|
||||||
|
# or add an `/o` option to perform `#{}` interpolation only once and reuse that
|
||||||
|
# Regexp object.
|
||||||
|
#
|
||||||
|
# @example
|
||||||
|
#
|
||||||
|
# # bad
|
||||||
|
# def tokens(pattern)
|
||||||
|
# pattern.scan(TOKEN).reject { |token| token.match?(/\A#{SEPARATORS}\Z/) }
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # good
|
||||||
|
# ALL_SEPARATORS = /\A#{SEPARATORS}\Z/
|
||||||
|
# def tokens(pattern)
|
||||||
|
# pattern.scan(TOKEN).reject { |token| token.match?(ALL_SEPARATORS) }
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # good
|
||||||
|
# def tokens(pattern)
|
||||||
|
# pattern.scan(TOKEN).reject { |token| token.match?(/\A#{SEPARATORS}\Z/o) }
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
class ConstantRegexp < Base
|
||||||
|
extend AutoCorrector
|
||||||
|
|
||||||
|
MSG = 'Extract this regexp into a constant or append an `/o` option to its options.'
|
||||||
|
|
||||||
|
def on_regexp(node)
|
||||||
|
return if within_const_assignment?(node) ||
|
||||||
|
!include_interpolated_const?(node) ||
|
||||||
|
node.single_interpolation?
|
||||||
|
|
||||||
|
add_offense(node) do |corrector|
|
||||||
|
corrector.insert_after(node, 'o')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def within_const_assignment?(node)
|
||||||
|
node.each_ancestor(:casgn).any?
|
||||||
|
end
|
||||||
|
|
||||||
|
def_node_matcher :regexp_escape?, <<~PATTERN
|
||||||
|
(send
|
||||||
|
(const nil? :Regexp) :escape const_type?)
|
||||||
|
PATTERN
|
||||||
|
|
||||||
|
def include_interpolated_const?(node)
|
||||||
|
return false unless node.interpolation?
|
||||||
|
|
||||||
|
node.each_child_node(:begin).all? do |begin_node|
|
||||||
|
inner_node = begin_node.children.first
|
||||||
|
inner_node && (inner_node.const_type? || regexp_escape?(inner_node))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -42,6 +42,7 @@ module RuboCop
|
|||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
|
||||||
MSG = 'Use `count` instead of `%<selector>s...%<counter>s`.'
|
MSG = 'Use `count` instead of `%<selector>s...%<counter>s`.'
|
||||||
|
RESTRICT_ON_SEND = %i[count length size].freeze
|
||||||
|
|
||||||
def_node_matcher :count_candidate?, <<~PATTERN
|
def_node_matcher :count_candidate?, <<~PATTERN
|
||||||
{
|
{
|
||||||
@ -51,6 +51,7 @@ module RuboCop
|
|||||||
minimum_target_ruby_version 2.5
|
minimum_target_ruby_version 2.5
|
||||||
|
|
||||||
MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
|
MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
|
||||||
|
RESTRICT_ON_SEND = %i[gsub gsub! sub sub!].freeze
|
||||||
|
|
||||||
PREFERRED_METHODS = {
|
PREFERRED_METHODS = {
|
||||||
gsub: :delete_prefix,
|
gsub: :delete_prefix,
|
||||||
@ -51,6 +51,7 @@ module RuboCop
|
|||||||
minimum_target_ruby_version 2.5
|
minimum_target_ruby_version 2.5
|
||||||
|
|
||||||
MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
|
MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
|
||||||
|
RESTRICT_ON_SEND = %i[gsub gsub! sub sub!].freeze
|
||||||
|
|
||||||
PREFERRED_METHODS = {
|
PREFERRED_METHODS = {
|
||||||
gsub: :delete_suffix,
|
gsub: :delete_suffix,
|
||||||
@ -4,8 +4,8 @@ module RuboCop
|
|||||||
module Cop
|
module Cop
|
||||||
module Performance
|
module Performance
|
||||||
# This cop is used to identify usages of `first`, `last`, `[0]` or `[-1]`
|
# This cop is used to identify usages of `first`, `last`, `[0]` or `[-1]`
|
||||||
# chained to `select`, `find_all`, or `find_all`
|
# chained to `select`, `find_all` or `filter` and change them to use
|
||||||
# and change them to use `detect` instead.
|
# `detect` instead.
|
||||||
#
|
#
|
||||||
# @example
|
# @example
|
||||||
# # bad
|
# # bad
|
||||||
@ -39,6 +39,7 @@ module RuboCop
|
|||||||
'`%<first_method>s[%<index>i]`.'
|
'`%<first_method>s[%<index>i]`.'
|
||||||
INDEX_REVERSE_MSG = 'Use `reverse.%<prefer>s` instead of ' \
|
INDEX_REVERSE_MSG = 'Use `reverse.%<prefer>s` instead of ' \
|
||||||
'`%<first_method>s[%<index>i]`.'
|
'`%<first_method>s[%<index>i]`.'
|
||||||
|
RESTRICT_ON_SEND = %i[first last []].freeze
|
||||||
|
|
||||||
def_node_matcher :detect_candidate?, <<~PATTERN
|
def_node_matcher :detect_candidate?, <<~PATTERN
|
||||||
{
|
{
|
||||||
@ -47,6 +47,7 @@ module RuboCop
|
|||||||
|
|
||||||
MSG = 'Use `String#end_with?` instead of a regex match anchored to ' \
|
MSG = 'Use `String#end_with?` instead of a regex match anchored to ' \
|
||||||
'the end of the string.'
|
'the end of the string.'
|
||||||
|
RESTRICT_ON_SEND = %i[match =~ match?].freeze
|
||||||
|
|
||||||
def_node_matcher :redundant_regex?, <<~PATTERN
|
def_node_matcher :redundant_regex?, <<~PATTERN
|
||||||
{(send $!nil? {:match :=~ :match?} (regexp (str $#literal_at_end?) (regopt)))
|
{(send $!nil? {:match :=~ :match?} (regexp (str $#literal_at_end?) (regopt)))
|
||||||
@ -47,6 +47,7 @@ module RuboCop
|
|||||||
#
|
#
|
||||||
class FixedSize < Base
|
class FixedSize < Base
|
||||||
MSG = 'Do not compute the size of statically sized objects.'
|
MSG = 'Do not compute the size of statically sized objects.'
|
||||||
|
RESTRICT_ON_SEND = %i[count length size].freeze
|
||||||
|
|
||||||
def_node_matcher :counter, <<~MATCHER
|
def_node_matcher :counter, <<~MATCHER
|
||||||
(send ${array hash str sym} {:count :length :size} $...)
|
(send ${array hash str sym} {:count :length :size} $...)
|
||||||
@ -19,6 +19,7 @@ module RuboCop
|
|||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
|
||||||
MSG = 'Use `flat_map` instead of `%<method>s...%<flatten>s`.'
|
MSG = 'Use `flat_map` instead of `%<method>s...%<flatten>s`.'
|
||||||
|
RESTRICT_ON_SEND = %i[flatten flatten!].freeze
|
||||||
FLATTEN_MULTIPLE_LEVELS = ' Beware, `flat_map` only flattens 1 level ' \
|
FLATTEN_MULTIPLE_LEVELS = ' Beware, `flat_map` only flattens 1 level ' \
|
||||||
'and `flatten` can be used to flatten ' \
|
'and `flatten` can be used to flatten ' \
|
||||||
'multiple levels.'
|
'multiple levels.'
|
||||||
@ -39,6 +39,8 @@ module RuboCop
|
|||||||
class InefficientHashSearch < Base
|
class InefficientHashSearch < Base
|
||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
|
||||||
|
RESTRICT_ON_SEND = %i[include?].freeze
|
||||||
|
|
||||||
def_node_matcher :inefficient_include?, <<~PATTERN
|
def_node_matcher :inefficient_include?, <<~PATTERN
|
||||||
(send (send $_ {:keys :values}) :include? _)
|
(send (send $_ {:keys :values}) :include? _)
|
||||||
PATTERN
|
PATTERN
|
||||||
@ -29,14 +29,14 @@ module RuboCop
|
|||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
|
||||||
MSG = 'Use `%<good>s` instead of `%<bad>s`.'
|
MSG = 'Use `%<good>s` instead of `%<bad>s`.'
|
||||||
ENUMERABLE_METHODS = (Enumerable.instance_methods + [:each]).freeze
|
RESTRICT_ON_SEND = (Enumerable.instance_methods + [:each]).freeze
|
||||||
|
|
||||||
def_node_matcher :readlines_on_class?, <<~PATTERN
|
def_node_matcher :readlines_on_class?, <<~PATTERN
|
||||||
$(send $(send (const nil? {:IO :File}) :readlines ...) #enumerable_method?)
|
$(send $(send (const nil? {:IO :File}) :readlines ...) _)
|
||||||
PATTERN
|
PATTERN
|
||||||
|
|
||||||
def_node_matcher :readlines_on_instance?, <<~PATTERN
|
def_node_matcher :readlines_on_instance?, <<~PATTERN
|
||||||
$(send $(send ${nil? !const_type?} :readlines ...) #enumerable_method? ...)
|
$(send $(send ${nil? !const_type?} :readlines ...) _ ...)
|
||||||
PATTERN
|
PATTERN
|
||||||
|
|
||||||
def on_send(node)
|
def on_send(node)
|
||||||
@ -55,10 +55,6 @@ module RuboCop
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def enumerable_method?(node)
|
|
||||||
ENUMERABLE_METHODS.include?(node.to_sym)
|
|
||||||
end
|
|
||||||
|
|
||||||
def autocorrect(corrector, enumerable_call, readlines_call, receiver)
|
def autocorrect(corrector, enumerable_call, readlines_call, receiver)
|
||||||
# We cannot safely correct `.readlines` method called on IO/File classes
|
# We cannot safely correct `.readlines` method called on IO/File classes
|
||||||
# due to its signature and we are not sure with implicit receiver
|
# due to its signature and we are not sure with implicit receiver
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module RuboCop
|
||||||
|
module Cop
|
||||||
|
module Performance
|
||||||
|
# This cop identifies places where methods are converted to blocks, with the
|
||||||
|
# use of `&method`, and passed as arguments to method calls.
|
||||||
|
# It is faster to replace those with explicit blocks, calling those methods inside.
|
||||||
|
#
|
||||||
|
# @example
|
||||||
|
# # bad
|
||||||
|
# array.map(&method(:do_something))
|
||||||
|
# [1, 2, 3].each(&out.method(:puts))
|
||||||
|
#
|
||||||
|
# # good
|
||||||
|
# array.map { |x| do_something(x) }
|
||||||
|
# [1, 2, 3].each { |x| out.puts(x) }
|
||||||
|
#
|
||||||
|
class MethodObjectAsBlock < Base
|
||||||
|
MSG = 'Use block explicitly instead of block-passing a method object.'
|
||||||
|
|
||||||
|
def_node_matcher :method_object_as_argument?, <<~PATTERN
|
||||||
|
(^send (send _ :method sym))
|
||||||
|
PATTERN
|
||||||
|
|
||||||
|
def on_block_pass(node)
|
||||||
|
add_offense(node) if method_object_as_argument?(node)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -30,6 +30,7 @@ module RuboCop
|
|||||||
class OpenStruct < Base
|
class OpenStruct < Base
|
||||||
MSG = 'Consider using `Struct` over `OpenStruct` ' \
|
MSG = 'Consider using `Struct` over `OpenStruct` ' \
|
||||||
'to optimize the performance.'
|
'to optimize the performance.'
|
||||||
|
RESTRICT_ON_SEND = %i[new].freeze
|
||||||
|
|
||||||
def_node_matcher :open_struct, <<~PATTERN
|
def_node_matcher :open_struct, <<~PATTERN
|
||||||
(send (const {nil? cbase} :OpenStruct) :new ...)
|
(send (const {nil? cbase} :OpenStruct) :new ...)
|
||||||
@ -28,6 +28,7 @@ module RuboCop
|
|||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
|
||||||
MSG = 'Use `Range#cover?` instead of `Range#%<bad_method>s`.'
|
MSG = 'Use `Range#cover?` instead of `Range#%<bad_method>s`.'
|
||||||
|
RESTRICT_ON_SEND = %i[include? member?].freeze
|
||||||
|
|
||||||
# TODO: If we traced out assignments of variables to their uses, we
|
# TODO: If we traced out assignments of variables to their uses, we
|
||||||
# might pick up on a few more instances of this issue
|
# might pick up on a few more instances of this issue
|
||||||
@ -80,11 +80,11 @@ module RuboCop
|
|||||||
def calls_to_report(argname, body)
|
def calls_to_report(argname, body)
|
||||||
return [] if blockarg_assigned?(body, argname)
|
return [] if blockarg_assigned?(body, argname)
|
||||||
|
|
||||||
calls = to_enum(:blockarg_calls, body, argname)
|
blockarg_calls(body, argname).map do |call|
|
||||||
|
return [] if args_include_block_pass?(call)
|
||||||
|
|
||||||
return [] if calls.any? { |call| args_include_block_pass?(call) }
|
call
|
||||||
|
end
|
||||||
calls
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def args_include_block_pass?(blockcall)
|
def args_include_block_pass?(blockcall)
|
||||||
@ -22,6 +22,7 @@ module RuboCop
|
|||||||
|
|
||||||
MSG = 'Use `=~` in places where the `MatchData` returned by ' \
|
MSG = 'Use `=~` in places where the `MatchData` returned by ' \
|
||||||
'`#match` will not be used.'
|
'`#match` will not be used.'
|
||||||
|
RESTRICT_ON_SEND = %i[match].freeze
|
||||||
|
|
||||||
# 'match' is a fairly generic name, so we don't flag it unless we see
|
# 'match' is a fairly generic name, so we don't flag it unless we see
|
||||||
# a string or regexp literal on one side or the other
|
# a string or regexp literal on one side or the other
|
||||||
@ -29,6 +29,7 @@ module RuboCop
|
|||||||
|
|
||||||
AREF_ASGN = '%<receiver>s[%<key>s] = %<value>s'
|
AREF_ASGN = '%<receiver>s[%<key>s] = %<value>s'
|
||||||
MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
|
MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
|
||||||
|
RESTRICT_ON_SEND = %i[merge!].freeze
|
||||||
|
|
||||||
WITH_MODIFIER_CORRECTION = <<~RUBY
|
WITH_MODIFIER_CORRECTION = <<~RUBY
|
||||||
%<keyword>s %<condition>s
|
%<keyword>s %<condition>s
|
||||||
@ -44,10 +44,10 @@ module RuboCop
|
|||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
|
||||||
MSG = 'Use `%<good_method>s` instead of `%<bad_method>s`.'
|
MSG = 'Use `%<good_method>s` instead of `%<bad_method>s`.'
|
||||||
REPLACEABLE_METHODS = %i[[] slice first last take drop length size empty?].freeze
|
RESTRICT_ON_SEND = %i[[] slice first last take drop length size empty?].freeze
|
||||||
|
|
||||||
def_node_matcher :redundant_chars_call?, <<~PATTERN
|
def_node_matcher :redundant_chars_call?, <<~PATTERN
|
||||||
(send $(send _ :chars) $#replaceable_method? $...)
|
(send $(send _ :chars) $_ $...)
|
||||||
PATTERN
|
PATTERN
|
||||||
|
|
||||||
def on_send(node)
|
def on_send(node)
|
||||||
@ -66,10 +66,6 @@ module RuboCop
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def replaceable_method?(method_name)
|
|
||||||
REPLACEABLE_METHODS.include?(method_name)
|
|
||||||
end
|
|
||||||
|
|
||||||
def offense_range(receiver, node)
|
def offense_range(receiver, node)
|
||||||
range_between(receiver.loc.selector.begin_pos, node.loc.expression.end_pos)
|
range_between(receiver.loc.selector.begin_pos, node.loc.expression.end_pos)
|
||||||
end
|
end
|
||||||
@ -17,6 +17,7 @@ module RuboCop
|
|||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
|
||||||
MSG = 'Use `reverse_each` instead of `reverse.each`.'
|
MSG = 'Use `reverse_each` instead of `reverse.each`.'
|
||||||
|
RESTRICT_ON_SEND = %i[each].freeze
|
||||||
UNDERSCORE = '_'
|
UNDERSCORE = '_'
|
||||||
|
|
||||||
def_node_matcher :reverse_each?, <<~MATCHER
|
def_node_matcher :reverse_each?, <<~MATCHER
|
||||||
@ -21,6 +21,7 @@ module RuboCop
|
|||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
|
||||||
MSG = 'Use `%<good_method>s` instead of `%<bad_method>s`.'
|
MSG = 'Use `%<good_method>s` instead of `%<bad_method>s`.'
|
||||||
|
RESTRICT_ON_SEND = %i[first].freeze
|
||||||
|
|
||||||
def_node_matcher :reverse_first_candidate?, <<~PATTERN
|
def_node_matcher :reverse_first_candidate?, <<~PATTERN
|
||||||
(send $(send _ :reverse) :first (int _)?)
|
(send $(send _ :reverse) :first (int _)?)
|
||||||
@ -39,6 +39,7 @@ module RuboCop
|
|||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
|
||||||
MSG = 'Use `size` instead of `count`.'
|
MSG = 'Use `size` instead of `count`.'
|
||||||
|
RESTRICT_ON_SEND = %i[count].freeze
|
||||||
|
|
||||||
def_node_matcher :array?, <<~PATTERN
|
def_node_matcher :array?, <<~PATTERN
|
||||||
{
|
{
|
||||||
@ -22,6 +22,7 @@ module RuboCop
|
|||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
|
||||||
MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
|
MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
|
||||||
|
RESTRICT_ON_SEND = %i[gsub gsub!].freeze
|
||||||
|
|
||||||
PREFERRED_METHODS = {
|
PREFERRED_METHODS = {
|
||||||
gsub: :squeeze,
|
gsub: :squeeze,
|
||||||
@ -58,7 +59,7 @@ module RuboCop
|
|||||||
private
|
private
|
||||||
|
|
||||||
def repeating_literal?(regex_str)
|
def repeating_literal?(regex_str)
|
||||||
regex_str.match?(/\A(?:#{Util::LITERAL_REGEX})\+\z/)
|
regex_str.match?(/\A(?:#{Util::LITERAL_REGEX})\+\z/o)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -47,6 +47,7 @@ module RuboCop
|
|||||||
|
|
||||||
MSG = 'Use `String#start_with?` instead of a regex match anchored to ' \
|
MSG = 'Use `String#start_with?` instead of a regex match anchored to ' \
|
||||||
'the beginning of the string.'
|
'the beginning of the string.'
|
||||||
|
RESTRICT_ON_SEND = %i[match =~ match?].freeze
|
||||||
|
|
||||||
def_node_matcher :redundant_regex?, <<~PATTERN
|
def_node_matcher :redundant_regex?, <<~PATTERN
|
||||||
{(send $!nil? {:match :=~ :match?} (regexp (str $#literal_at_start?) (regopt)))
|
{(send $!nil? {:match :=~ :match?} (regexp (str $#literal_at_start?) (regopt)))
|
||||||
@ -23,6 +23,7 @@ module RuboCop
|
|||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
|
||||||
MSG = 'Use `String#include?` instead of a regex match with literal-only pattern.'
|
MSG = 'Use `String#include?` instead of a regex match with literal-only pattern.'
|
||||||
|
RESTRICT_ON_SEND = %i[match =~ match?].freeze
|
||||||
|
|
||||||
def_node_matcher :redundant_regex?, <<~PATTERN
|
def_node_matcher :redundant_regex?, <<~PATTERN
|
||||||
{(send $!nil? {:match :=~ :match?} (regexp (str $#literal?) (regopt)))
|
{(send $!nil? {:match :=~ :match?} (regexp (str $#literal?) (regopt)))
|
||||||
@ -47,7 +48,7 @@ module RuboCop
|
|||||||
private
|
private
|
||||||
|
|
||||||
def literal?(regex_str)
|
def literal?(regex_str)
|
||||||
regex_str.match?(/\A#{Util::LITERAL_REGEX}+\z/)
|
regex_str.match?(/\A#{Util::LITERAL_REGEX}+\z/o)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -23,6 +23,7 @@ module RuboCop
|
|||||||
extend AutoCorrector
|
extend AutoCorrector
|
||||||
|
|
||||||
MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
|
MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
|
||||||
|
RESTRICT_ON_SEND = %i[gsub gsub!].freeze
|
||||||
DETERMINISTIC_REGEX = /\A(?:#{LITERAL_REGEX})+\Z/.freeze
|
DETERMINISTIC_REGEX = /\A(?:#{LITERAL_REGEX})+\Z/.freeze
|
||||||
DELETE = 'delete'
|
DELETE = 'delete'
|
||||||
TR = 'tr'
|
TR = 'tr'
|
||||||
@ -0,0 +1,236 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module RuboCop
|
||||||
|
module Cop
|
||||||
|
module Performance
|
||||||
|
# This cop identifies places where custom code finding the sum of elements
|
||||||
|
# in some Enumerable object can be replaced by `Enumerable#sum` method.
|
||||||
|
#
|
||||||
|
# This cop can change auto-correction scope depending on the value of
|
||||||
|
# `SafeAutoCorrect`.
|
||||||
|
# Its auto-correction is marked as safe by default (`SafeAutoCorrect: true`)
|
||||||
|
# to prevent `TypeError` in auto-correced code when initial value is not
|
||||||
|
# specified as shown below:
|
||||||
|
#
|
||||||
|
# [source,ruby]
|
||||||
|
# ----
|
||||||
|
# ['a', 'b'].sum # => (String can't be coerced into Integer)
|
||||||
|
# ----
|
||||||
|
#
|
||||||
|
# Therefore if initial value is not specified, unsafe auto-corrected will not occur.
|
||||||
|
#
|
||||||
|
# If you always want to enable auto-correction, you can set `SafeAutoCorrect: false`.
|
||||||
|
#
|
||||||
|
# [source,yaml]
|
||||||
|
# ----
|
||||||
|
# Performance/Sum:
|
||||||
|
# SafeAutoCorrect: false
|
||||||
|
# ----
|
||||||
|
#
|
||||||
|
# Please note that the auto-correction command line option will be changed from
|
||||||
|
# `rubocop -a` to `rubocop -A`, which includes unsafe auto-correction.
|
||||||
|
#
|
||||||
|
# @example
|
||||||
|
# # bad
|
||||||
|
# [1, 2, 3].inject(:+) # These bad cases with no initial value are unsafe and
|
||||||
|
# [1, 2, 3].inject(&:+) # will not be auto-correced by default. If you want to
|
||||||
|
# [1, 2, 3].reduce { |acc, elem| acc + elem } # auto-corrected, you can set `SafeAutoCorrect: false`.
|
||||||
|
# [1, 2, 3].reduce(10, :+)
|
||||||
|
# [1, 2, 3].map { |elem| elem ** 2 }.sum
|
||||||
|
# [1, 2, 3].collect(&:count).sum(10)
|
||||||
|
#
|
||||||
|
# # good
|
||||||
|
# [1, 2, 3].sum
|
||||||
|
# [1, 2, 3].sum(10)
|
||||||
|
# [1, 2, 3].sum { |elem| elem ** 2 }
|
||||||
|
# [1, 2, 3].sum(10, &:count)
|
||||||
|
#
|
||||||
|
class Sum < Base
|
||||||
|
include RangeHelp
|
||||||
|
extend AutoCorrector
|
||||||
|
|
||||||
|
MSG = 'Use `%<good_method>s` instead of `%<bad_method>s`.'
|
||||||
|
MSG_IF_NO_INIT_VALUE =
|
||||||
|
'Use `%<good_method>s` instead of `%<bad_method>s`, unless calling `%<bad_method>s` on an empty array.'
|
||||||
|
RESTRICT_ON_SEND = %i[inject reduce sum].freeze
|
||||||
|
|
||||||
|
def_node_matcher :sum_candidate?, <<~PATTERN
|
||||||
|
(send _ ${:inject :reduce} $_init ? ${(sym :+) (block_pass (sym :+))})
|
||||||
|
PATTERN
|
||||||
|
|
||||||
|
def_node_matcher :sum_map_candidate?, <<~PATTERN
|
||||||
|
(send
|
||||||
|
{
|
||||||
|
(block $(send _ {:map :collect}) ...)
|
||||||
|
$(send _ {:map :collect} (block_pass _))
|
||||||
|
}
|
||||||
|
:sum $_init ?)
|
||||||
|
PATTERN
|
||||||
|
|
||||||
|
def_node_matcher :sum_with_block_candidate?, <<~PATTERN
|
||||||
|
(block
|
||||||
|
$(send _ {:inject :reduce} $_init ?)
|
||||||
|
(args (arg $_acc) (arg $_elem))
|
||||||
|
$send)
|
||||||
|
PATTERN
|
||||||
|
|
||||||
|
def_node_matcher :acc_plus_elem?, <<~PATTERN
|
||||||
|
(send (lvar %1) :+ (lvar %2))
|
||||||
|
PATTERN
|
||||||
|
alias elem_plus_acc? acc_plus_elem?
|
||||||
|
|
||||||
|
def on_send(node)
|
||||||
|
return if empty_array_literal?(node)
|
||||||
|
|
||||||
|
handle_sum_candidate(node)
|
||||||
|
handle_sum_map_candidate(node)
|
||||||
|
end
|
||||||
|
|
||||||
|
def on_block(node)
|
||||||
|
sum_with_block_candidate?(node) do |send, init, var_acc, var_elem, body|
|
||||||
|
if acc_plus_elem?(body, var_acc, var_elem) || elem_plus_acc?(body, var_elem, var_acc)
|
||||||
|
range = sum_block_range(send, node)
|
||||||
|
message = build_block_message(send, init, var_acc, var_elem, body)
|
||||||
|
|
||||||
|
add_offense(range, message: message) do |corrector|
|
||||||
|
autocorrect(corrector, init, range)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def handle_sum_candidate(node)
|
||||||
|
sum_candidate?(node) do |method, init, operation|
|
||||||
|
range = sum_method_range(node)
|
||||||
|
message = build_method_message(node, method, init, operation)
|
||||||
|
|
||||||
|
add_offense(range, message: message) do |corrector|
|
||||||
|
autocorrect(corrector, init, range)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_sum_map_candidate(node)
|
||||||
|
sum_map_candidate?(node) do |map, init|
|
||||||
|
next if node.block_literal? || node.block_argument?
|
||||||
|
|
||||||
|
message = build_sum_map_message(map.method_name, init)
|
||||||
|
|
||||||
|
add_offense(sum_map_range(map, node), message: message) do |corrector|
|
||||||
|
autocorrect_sum_map(corrector, node, map, init)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def empty_array_literal?(node)
|
||||||
|
receiver = node.children.first
|
||||||
|
array_literal?(node) && receiver && receiver.children.empty?
|
||||||
|
end
|
||||||
|
|
||||||
|
def array_literal?(node)
|
||||||
|
receiver = node.children.first
|
||||||
|
receiver&.literal? && receiver&.array_type?
|
||||||
|
end
|
||||||
|
|
||||||
|
def autocorrect(corrector, init, range)
|
||||||
|
return if init.empty? && safe_autocorrect?
|
||||||
|
|
||||||
|
replacement = build_good_method(init)
|
||||||
|
|
||||||
|
corrector.replace(range, replacement)
|
||||||
|
end
|
||||||
|
|
||||||
|
def autocorrect_sum_map(corrector, sum, map, init)
|
||||||
|
sum_range = method_call_with_args_range(sum)
|
||||||
|
map_range = method_call_with_args_range(map)
|
||||||
|
|
||||||
|
block_pass = map.last_argument if map.last_argument&.block_pass_type?
|
||||||
|
replacement = build_good_method(init, block_pass)
|
||||||
|
|
||||||
|
corrector.remove(sum_range)
|
||||||
|
corrector.replace(map_range, ".#{replacement}")
|
||||||
|
end
|
||||||
|
|
||||||
|
def sum_method_range(node)
|
||||||
|
range_between(node.loc.selector.begin_pos, node.loc.end.end_pos)
|
||||||
|
end
|
||||||
|
|
||||||
|
def sum_map_range(map, sum)
|
||||||
|
range_between(map.loc.selector.begin_pos, sum.source_range.end.end_pos)
|
||||||
|
end
|
||||||
|
|
||||||
|
def sum_block_range(send, node)
|
||||||
|
range_between(send.loc.selector.begin_pos, node.loc.end.end_pos)
|
||||||
|
end
|
||||||
|
|
||||||
|
def build_method_message(node, method, init, operation)
|
||||||
|
good_method = build_good_method(init)
|
||||||
|
bad_method = build_method_bad_method(init, method, operation)
|
||||||
|
msg = if init.empty? && !array_literal?(node)
|
||||||
|
MSG_IF_NO_INIT_VALUE
|
||||||
|
else
|
||||||
|
MSG
|
||||||
|
end
|
||||||
|
format(msg, good_method: good_method, bad_method: bad_method)
|
||||||
|
end
|
||||||
|
|
||||||
|
def build_sum_map_message(method, init)
|
||||||
|
sum_method = build_good_method(init)
|
||||||
|
good_method = "#{sum_method} { ... }"
|
||||||
|
bad_method = "#{method} { ... }.#{sum_method}"
|
||||||
|
format(MSG, good_method: good_method, bad_method: bad_method)
|
||||||
|
end
|
||||||
|
|
||||||
|
def build_block_message(send, init, var_acc, var_elem, body)
|
||||||
|
good_method = build_good_method(init)
|
||||||
|
bad_method = build_block_bad_method(send.method_name, init, var_acc, var_elem, body)
|
||||||
|
format(MSG, good_method: good_method, bad_method: bad_method)
|
||||||
|
end
|
||||||
|
|
||||||
|
def build_good_method(init, block_pass = nil)
|
||||||
|
good_method = 'sum'
|
||||||
|
|
||||||
|
args = []
|
||||||
|
unless init.empty?
|
||||||
|
init = init.first
|
||||||
|
args << init.source unless init.int_type? && init.value.zero?
|
||||||
|
end
|
||||||
|
args << block_pass.source if block_pass
|
||||||
|
good_method += "(#{args.join(', ')})" unless args.empty?
|
||||||
|
good_method
|
||||||
|
end
|
||||||
|
|
||||||
|
def build_method_bad_method(init, method, operation)
|
||||||
|
bad_method = "#{method}("
|
||||||
|
unless init.empty?
|
||||||
|
init = init.first
|
||||||
|
bad_method += "#{init.source}, "
|
||||||
|
end
|
||||||
|
bad_method += if operation.block_pass_type?
|
||||||
|
'&:+)'
|
||||||
|
else
|
||||||
|
':+)'
|
||||||
|
end
|
||||||
|
bad_method
|
||||||
|
end
|
||||||
|
|
||||||
|
def build_block_bad_method(method, init, var_acc, var_elem, body)
|
||||||
|
bad_method = method.to_s
|
||||||
|
|
||||||
|
unless init.empty?
|
||||||
|
init = init.first
|
||||||
|
bad_method += "(#{init.source})"
|
||||||
|
end
|
||||||
|
bad_method += " { |#{var_acc}, #{var_elem}| #{body.source} }"
|
||||||
|
bad_method
|
||||||
|
end
|
||||||
|
|
||||||
|
def method_call_with_args_range(node)
|
||||||
|
node.receiver.source_range.end.join(node.source_range.end)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -23,6 +23,7 @@ module RuboCop
|
|||||||
MESSAGE = 'Use `Array.new(%<count>s)` with a block ' \
|
MESSAGE = 'Use `Array.new(%<count>s)` with a block ' \
|
||||||
'instead of `.times.%<map_or_collect>s`'
|
'instead of `.times.%<map_or_collect>s`'
|
||||||
MESSAGE_ONLY_IF = 'only if `%<count>s` is always 0 or more'
|
MESSAGE_ONLY_IF = 'only if `%<count>s` is always 0 or more'
|
||||||
|
RESTRICT_ON_SEND = %i[map collect].freeze
|
||||||
|
|
||||||
def on_send(node)
|
def on_send(node)
|
||||||
check(node)
|
check(node)
|
||||||
@ -10,6 +10,7 @@ module RuboCop
|
|||||||
# NOTE: `String.new` (without operator) is not exactly the same as `+''`.
|
# NOTE: `String.new` (without operator) is not exactly the same as `+''`.
|
||||||
# These differ in encoding. `String.new.encoding` is always `ASCII-8BIT`.
|
# These differ in encoding. `String.new.encoding` is always `ASCII-8BIT`.
|
||||||
# However, `(+'').encoding` is the same as script encoding(e.g. `UTF-8`).
|
# However, `(+'').encoding` is the same as script encoding(e.g. `UTF-8`).
|
||||||
|
# Therefore, auto-correction is unsafe.
|
||||||
# So, if you expect `ASCII-8BIT` encoding, disable this cop.
|
# So, if you expect `ASCII-8BIT` encoding, disable this cop.
|
||||||
#
|
#
|
||||||
# @example
|
# @example
|
||||||
@ -24,7 +25,10 @@ module RuboCop
|
|||||||
# +'something'
|
# +'something'
|
||||||
# +''
|
# +''
|
||||||
class UnfreezeString < Base
|
class UnfreezeString < Base
|
||||||
|
extend AutoCorrector
|
||||||
|
|
||||||
MSG = 'Use unary plus to get an unfrozen string literal.'
|
MSG = 'Use unary plus to get an unfrozen string literal.'
|
||||||
|
RESTRICT_ON_SEND = %i[dup new].freeze
|
||||||
|
|
||||||
def_node_matcher :dup_string?, <<~PATTERN
|
def_node_matcher :dup_string?, <<~PATTERN
|
||||||
(send {str dstr} :dup)
|
(send {str dstr} :dup)
|
||||||
@ -38,7 +42,21 @@ module RuboCop
|
|||||||
PATTERN
|
PATTERN
|
||||||
|
|
||||||
def on_send(node)
|
def on_send(node)
|
||||||
add_offense(node) if dup_string?(node) || string_new?(node)
|
return unless dup_string?(node) || string_new?(node)
|
||||||
|
|
||||||
|
add_offense(node) do |corrector|
|
||||||
|
corrector.replace(node, "+#{string_value(node)}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def string_value(node)
|
||||||
|
if node.receiver.source == 'String' && node.method?(:new)
|
||||||
|
node.arguments.empty? ? "''" : node.first_argument.source
|
||||||
|
else
|
||||||
|
node.receiver.source
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -18,6 +18,7 @@ module RuboCop
|
|||||||
|
|
||||||
MSG = 'Use `%<double_colon>sURI::DEFAULT_PARSER` instead of ' \
|
MSG = 'Use `%<double_colon>sURI::DEFAULT_PARSER` instead of ' \
|
||||||
'`%<double_colon>sURI::Parser.new`.'
|
'`%<double_colon>sURI::Parser.new`.'
|
||||||
|
RESTRICT_ON_SEND = %i[new].freeze
|
||||||
|
|
||||||
def_node_matcher :uri_parser_new?, <<~PATTERN
|
def_node_matcher :uri_parser_new?, <<~PATTERN
|
||||||
(send
|
(send
|
||||||
@ -4,13 +4,16 @@ require_relative 'mixin/regexp_metacharacter'
|
|||||||
require_relative 'mixin/sort_block'
|
require_relative 'mixin/sort_block'
|
||||||
|
|
||||||
require_relative 'performance/ancestors_include'
|
require_relative 'performance/ancestors_include'
|
||||||
|
require_relative 'performance/array_semi_infinite_range_slice'
|
||||||
require_relative 'performance/big_decimal_with_numeric_argument'
|
require_relative 'performance/big_decimal_with_numeric_argument'
|
||||||
require_relative 'performance/bind_call'
|
require_relative 'performance/bind_call'
|
||||||
|
require_relative 'performance/block_given_with_explicit_block'
|
||||||
require_relative 'performance/caller'
|
require_relative 'performance/caller'
|
||||||
require_relative 'performance/case_when_splat'
|
require_relative 'performance/case_when_splat'
|
||||||
require_relative 'performance/casecmp'
|
require_relative 'performance/casecmp'
|
||||||
require_relative 'performance/collection_literal_in_loop'
|
require_relative 'performance/collection_literal_in_loop'
|
||||||
require_relative 'performance/compare_with_block'
|
require_relative 'performance/compare_with_block'
|
||||||
|
require_relative 'performance/constant_regexp'
|
||||||
require_relative 'performance/count'
|
require_relative 'performance/count'
|
||||||
require_relative 'performance/delete_prefix'
|
require_relative 'performance/delete_prefix'
|
||||||
require_relative 'performance/delete_suffix'
|
require_relative 'performance/delete_suffix'
|
||||||
@ -20,6 +23,7 @@ require_relative 'performance/end_with'
|
|||||||
require_relative 'performance/fixed_size'
|
require_relative 'performance/fixed_size'
|
||||||
require_relative 'performance/flat_map'
|
require_relative 'performance/flat_map'
|
||||||
require_relative 'performance/inefficient_hash_search'
|
require_relative 'performance/inefficient_hash_search'
|
||||||
|
require_relative 'performance/method_object_as_block'
|
||||||
require_relative 'performance/open_struct'
|
require_relative 'performance/open_struct'
|
||||||
require_relative 'performance/range_include'
|
require_relative 'performance/range_include'
|
||||||
require_relative 'performance/io_readlines'
|
require_relative 'performance/io_readlines'
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module RuboCop
|
||||||
|
module Performance
|
||||||
|
# This module holds the RuboCop Performance version information.
|
||||||
|
module Version
|
||||||
|
STRING = '1.9.0'
|
||||||
|
|
||||||
|
def self.document_version
|
||||||
|
STRING.match('\d+\.\d+').to_s
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -1,300 +0,0 @@
|
|||||||
module TZInfo
|
|
||||||
# Use send as a workaround for erroneous 'wrong number of arguments' errors
|
|
||||||
# with JRuby 9.0.5.0 when calling methods with Java implementations. See #114.
|
|
||||||
send(:using, RubyCoreSupport::UntaintExt) if RubyCoreSupport.const_defined?(:UntaintExt)
|
|
||||||
|
|
||||||
# An InvalidZoneinfoFile exception is raised if an attempt is made to load an
|
|
||||||
# invalid zoneinfo file.
|
|
||||||
class InvalidZoneinfoFile < StandardError
|
|
||||||
end
|
|
||||||
|
|
||||||
# Represents a timezone defined by a compiled zoneinfo TZif (\0, 2 or 3) file.
|
|
||||||
#
|
|
||||||
# @private
|
|
||||||
class ZoneinfoTimezoneInfo < TransitionDataTimezoneInfo #:nodoc:
|
|
||||||
|
|
||||||
# Minimum supported timestamp (inclusive).
|
|
||||||
#
|
|
||||||
# Time.utc(1700, 1, 1).to_i
|
|
||||||
MIN_TIMESTAMP = -8520336000
|
|
||||||
|
|
||||||
# Maximum supported timestamp (exclusive).
|
|
||||||
#
|
|
||||||
# Time.utc(2500, 1, 1).to_i
|
|
||||||
MAX_TIMESTAMP = 16725225600
|
|
||||||
|
|
||||||
# Constructs the new ZoneinfoTimezoneInfo with an identifier and path
|
|
||||||
# to the file.
|
|
||||||
def initialize(identifier, file_path)
|
|
||||||
super(identifier)
|
|
||||||
|
|
||||||
File.open(file_path, 'rb') do |file|
|
|
||||||
parse(file)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
# Unpack will return unsigned 32-bit integers. Translate to
|
|
||||||
# signed 32-bit.
|
|
||||||
def make_signed_int32(long)
|
|
||||||
long >= 0x80000000 ? long - 0x100000000 : long
|
|
||||||
end
|
|
||||||
|
|
||||||
# Unpack will return a 64-bit integer as two unsigned 32-bit integers
|
|
||||||
# (most significant first). Translate to signed 64-bit
|
|
||||||
def make_signed_int64(high, low)
|
|
||||||
unsigned = (high << 32) | low
|
|
||||||
unsigned >= 0x8000000000000000 ? unsigned - 0x10000000000000000 : unsigned
|
|
||||||
end
|
|
||||||
|
|
||||||
# Read bytes from file and check that the correct number of bytes could
|
|
||||||
# be read. Raises InvalidZoneinfoFile if the number of bytes didn't match
|
|
||||||
# the number requested.
|
|
||||||
def check_read(file, bytes)
|
|
||||||
result = file.read(bytes)
|
|
||||||
|
|
||||||
unless result && result.length == bytes
|
|
||||||
raise InvalidZoneinfoFile, "Expected #{bytes} bytes reading '#{file.path}', but got #{result ? result.length : 0} bytes"
|
|
||||||
end
|
|
||||||
|
|
||||||
result
|
|
||||||
end
|
|
||||||
|
|
||||||
# Zoneinfo files don't include the offset from standard time (std_offset)
|
|
||||||
# for DST periods. Derive the base offset (utc_offset) where DST is
|
|
||||||
# observed from either the previous or next non-DST period.
|
|
||||||
#
|
|
||||||
# Returns the index of the offset to be used prior to the first
|
|
||||||
# transition.
|
|
||||||
def derive_offsets(transitions, offsets)
|
|
||||||
# The first non-DST offset (if there is one) is the offset observed
|
|
||||||
# before the first transition. Fallback to the first DST offset if there
|
|
||||||
# are no non-DST offsets.
|
|
||||||
first_non_dst_offset_index = offsets.index {|o| !o[:is_dst] }
|
|
||||||
first_offset_index = first_non_dst_offset_index || 0
|
|
||||||
return first_offset_index if transitions.empty?
|
|
||||||
|
|
||||||
# Determine the utc_offset of the next non-dst offset at each transition.
|
|
||||||
utc_offset_from_next = nil
|
|
||||||
|
|
||||||
transitions.reverse_each do |transition|
|
|
||||||
offset = offsets[transition[:offset]]
|
|
||||||
if offset[:is_dst]
|
|
||||||
transition[:utc_offset_from_next] = utc_offset_from_next if utc_offset_from_next
|
|
||||||
else
|
|
||||||
utc_offset_from_next = offset[:utc_total_offset]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
utc_offset_from_previous = first_non_dst_offset_index ? offsets[first_non_dst_offset_index][:utc_total_offset] : nil
|
|
||||||
defined_offsets = {}
|
|
||||||
|
|
||||||
transitions.each do |transition|
|
|
||||||
offset_index = transition[:offset]
|
|
||||||
offset = offsets[offset_index]
|
|
||||||
utc_total_offset = offset[:utc_total_offset]
|
|
||||||
|
|
||||||
if offset[:is_dst]
|
|
||||||
utc_offset_from_next = transition[:utc_offset_from_next]
|
|
||||||
|
|
||||||
difference_to_previous = (utc_total_offset - (utc_offset_from_previous || utc_total_offset)).abs
|
|
||||||
difference_to_next = (utc_total_offset - (utc_offset_from_next || utc_total_offset)).abs
|
|
||||||
|
|
||||||
utc_offset = if difference_to_previous == 3600
|
|
||||||
utc_offset_from_previous
|
|
||||||
elsif difference_to_next == 3600
|
|
||||||
utc_offset_from_next
|
|
||||||
elsif difference_to_previous > 0 && difference_to_next > 0
|
|
||||||
difference_to_previous < difference_to_next ? utc_offset_from_previous : utc_offset_from_next
|
|
||||||
elsif difference_to_previous > 0
|
|
||||||
utc_offset_from_previous
|
|
||||||
elsif difference_to_next > 0
|
|
||||||
utc_offset_from_next
|
|
||||||
else
|
|
||||||
# No difference, assume a 1 hour offset from standard time.
|
|
||||||
utc_total_offset - 3600
|
|
||||||
end
|
|
||||||
|
|
||||||
if !offset[:utc_offset]
|
|
||||||
offset[:utc_offset] = utc_offset
|
|
||||||
defined_offsets[offset] = offset_index
|
|
||||||
elsif offset[:utc_offset] != utc_offset
|
|
||||||
# An earlier transition has already derived a different
|
|
||||||
# utc_offset. Define a new offset or reuse an existing identically
|
|
||||||
# defined offset.
|
|
||||||
new_offset = offset.dup
|
|
||||||
new_offset[:utc_offset] = utc_offset
|
|
||||||
|
|
||||||
offset_index = defined_offsets[new_offset]
|
|
||||||
|
|
||||||
unless offset_index
|
|
||||||
offsets << new_offset
|
|
||||||
offset_index = offsets.length - 1
|
|
||||||
defined_offsets[new_offset] = offset_index
|
|
||||||
end
|
|
||||||
|
|
||||||
transition[:offset] = offset_index
|
|
||||||
end
|
|
||||||
else
|
|
||||||
utc_offset_from_previous = utc_total_offset
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
first_offset_index
|
|
||||||
end
|
|
||||||
|
|
||||||
# Defines an offset for the timezone based on the given index and offset
|
|
||||||
# Hash.
|
|
||||||
def define_offset(index, offset)
|
|
||||||
utc_total_offset = offset[:utc_total_offset]
|
|
||||||
utc_offset = offset[:utc_offset]
|
|
||||||
|
|
||||||
if utc_offset
|
|
||||||
# DST offset with base utc_offset derived by derive_offsets.
|
|
||||||
std_offset = utc_total_offset - utc_offset
|
|
||||||
elsif offset[:is_dst]
|
|
||||||
# DST offset unreferenced by a transition (offset in use before the
|
|
||||||
# first transition). No derived base UTC offset, so assume 1 hour
|
|
||||||
# DST.
|
|
||||||
utc_offset = utc_total_offset - 3600
|
|
||||||
std_offset = 3600
|
|
||||||
else
|
|
||||||
# Non-DST offset.
|
|
||||||
utc_offset = utc_total_offset
|
|
||||||
std_offset = 0
|
|
||||||
end
|
|
||||||
|
|
||||||
offset index, utc_offset, std_offset, offset[:abbr].untaint.to_sym
|
|
||||||
end
|
|
||||||
|
|
||||||
# Parses a zoneinfo file and intializes the DataTimezoneInfo structures.
|
|
||||||
def parse(file)
|
|
||||||
magic, version, ttisgmtcnt, ttisstdcnt, leapcnt, timecnt, typecnt, charcnt =
|
|
||||||
check_read(file, 44).unpack('a4 a x15 NNNNNN')
|
|
||||||
|
|
||||||
if magic != 'TZif'
|
|
||||||
raise InvalidZoneinfoFile, "The file '#{file.path}' does not start with the expected header."
|
|
||||||
end
|
|
||||||
|
|
||||||
if (version == '2' || version == '3') && RubyCoreSupport.time_supports_64bit
|
|
||||||
# Skip the first 32-bit section and read the header of the second 64-bit section
|
|
||||||
file.seek(timecnt * 5 + typecnt * 6 + charcnt + leapcnt * 8 + ttisgmtcnt + ttisstdcnt, IO::SEEK_CUR)
|
|
||||||
|
|
||||||
prev_version = version
|
|
||||||
|
|
||||||
magic, version, ttisgmtcnt, ttisstdcnt, leapcnt, timecnt, typecnt, charcnt =
|
|
||||||
check_read(file, 44).unpack('a4 a x15 NNNNNN')
|
|
||||||
|
|
||||||
unless magic == 'TZif' && (version == prev_version)
|
|
||||||
raise InvalidZoneinfoFile, "The file '#{file.path}' contains an invalid 64-bit section header."
|
|
||||||
end
|
|
||||||
|
|
||||||
using_64bit = true
|
|
||||||
elsif version != '3' && version != '2' && version != "\0"
|
|
||||||
raise InvalidZoneinfoFile, "The file '#{file.path}' contains a version of the zoneinfo format that is not currently supported."
|
|
||||||
else
|
|
||||||
using_64bit = false
|
|
||||||
end
|
|
||||||
|
|
||||||
unless leapcnt == 0
|
|
||||||
raise InvalidZoneinfoFile, "The zoneinfo file '#{file.path}' contains leap second data. TZInfo requires zoneinfo files that omit leap seconds."
|
|
||||||
end
|
|
||||||
|
|
||||||
transitions = []
|
|
||||||
|
|
||||||
if using_64bit
|
|
||||||
timecnt.times do |i|
|
|
||||||
high, low = check_read(file, 8).unpack('NN'.freeze)
|
|
||||||
transition_time = make_signed_int64(high, low)
|
|
||||||
transitions << {:at => transition_time}
|
|
||||||
end
|
|
||||||
else
|
|
||||||
timecnt.times do |i|
|
|
||||||
transition_time = make_signed_int32(check_read(file, 4).unpack('N'.freeze)[0])
|
|
||||||
transitions << {:at => transition_time}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
timecnt.times do |i|
|
|
||||||
localtime_type = check_read(file, 1).unpack('C'.freeze)[0]
|
|
||||||
transitions[i][:offset] = localtime_type
|
|
||||||
end
|
|
||||||
|
|
||||||
offsets = []
|
|
||||||
|
|
||||||
typecnt.times do |i|
|
|
||||||
gmtoff, isdst, abbrind = check_read(file, 6).unpack('NCC'.freeze)
|
|
||||||
gmtoff = make_signed_int32(gmtoff)
|
|
||||||
isdst = isdst == 1
|
|
||||||
offset = {:utc_total_offset => gmtoff, :is_dst => isdst, :abbr_index => abbrind}
|
|
||||||
|
|
||||||
unless isdst
|
|
||||||
offset[:utc_offset] = gmtoff
|
|
||||||
offset[:std_offset] = 0
|
|
||||||
end
|
|
||||||
|
|
||||||
offsets << offset
|
|
||||||
end
|
|
||||||
|
|
||||||
abbrev = check_read(file, charcnt)
|
|
||||||
|
|
||||||
offsets.each do |o|
|
|
||||||
abbrev_start = o[:abbr_index]
|
|
||||||
raise InvalidZoneinfoFile, "Abbreviation index is out of range in file '#{file.path}'" unless abbrev_start < abbrev.length
|
|
||||||
|
|
||||||
abbrev_end = abbrev.index("\0", abbrev_start)
|
|
||||||
raise InvalidZoneinfoFile, "Missing abbreviation null terminator in file '#{file.path}'" unless abbrev_end
|
|
||||||
|
|
||||||
o[:abbr] = RubyCoreSupport.force_encoding(abbrev[abbrev_start...abbrev_end], 'UTF-8')
|
|
||||||
end
|
|
||||||
|
|
||||||
transitions.each do |t|
|
|
||||||
if t[:offset] < 0 || t[:offset] >= offsets.length
|
|
||||||
raise InvalidZoneinfoFile, "Invalid offset referenced by transition in file '#{file.path}'."
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Derive the offsets from standard time (std_offset).
|
|
||||||
first_offset_index = derive_offsets(transitions, offsets)
|
|
||||||
|
|
||||||
define_offset(first_offset_index, offsets[first_offset_index])
|
|
||||||
|
|
||||||
offsets.each_with_index do |o, i|
|
|
||||||
define_offset(i, o) unless i == first_offset_index
|
|
||||||
end
|
|
||||||
|
|
||||||
if !using_64bit && !RubyCoreSupport.time_supports_negative
|
|
||||||
# Filter out transitions that are not supported by Time on this
|
|
||||||
# platform.
|
|
||||||
|
|
||||||
# Move the last transition before the epoch up to the epoch. This
|
|
||||||
# allows for accurate conversions for all supported timestamps on the
|
|
||||||
# platform.
|
|
||||||
|
|
||||||
before_epoch, after_epoch = transitions.partition {|t| t[:at] < 0}
|
|
||||||
|
|
||||||
if before_epoch.length > 0 && after_epoch.length > 0 && after_epoch.first[:at] != 0
|
|
||||||
last_before = before_epoch.last
|
|
||||||
last_before[:at] = 0
|
|
||||||
transitions = [last_before] + after_epoch
|
|
||||||
else
|
|
||||||
transitions = after_epoch
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Ignore transitions that occur outside of a defined window. The
|
|
||||||
# transition index cannot handle a large range of transition times.
|
|
||||||
#
|
|
||||||
# This is primarily intended to ignore the far in the past transition
|
|
||||||
# added in zic 2014c (at timestamp -2**63 in zic 2014c and at the
|
|
||||||
# approximate time of the big bang from zic 2014d).
|
|
||||||
transitions.each do |t|
|
|
||||||
at = t[:at]
|
|
||||||
if at >= MIN_TIMESTAMP && at < MAX_TIMESTAMP
|
|
||||||
time = Time.at(at).utc
|
|
||||||
transition time.year, time.mon, t[:offset], at
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@ -10,6 +10,8 @@ require 'tzinfo/timezone_definition'
|
|||||||
|
|
||||||
require 'tzinfo/timezone_offset'
|
require 'tzinfo/timezone_offset'
|
||||||
require 'tzinfo/timezone_transition'
|
require 'tzinfo/timezone_transition'
|
||||||
|
require 'tzinfo/transition_rule'
|
||||||
|
require 'tzinfo/annual_rules'
|
||||||
require 'tzinfo/timezone_transition_definition'
|
require 'tzinfo/timezone_transition_definition'
|
||||||
|
|
||||||
require 'tzinfo/timezone_index_definition'
|
require 'tzinfo/timezone_index_definition'
|
||||||
@ -22,6 +24,7 @@ require 'tzinfo/zoneinfo_timezone_info'
|
|||||||
|
|
||||||
require 'tzinfo/data_source'
|
require 'tzinfo/data_source'
|
||||||
require 'tzinfo/ruby_data_source'
|
require 'tzinfo/ruby_data_source'
|
||||||
|
require 'tzinfo/posix_time_zone_parser'
|
||||||
require 'tzinfo/zoneinfo_data_source'
|
require 'tzinfo/zoneinfo_data_source'
|
||||||
|
|
||||||
require 'tzinfo/timezone_period'
|
require 'tzinfo/timezone_period'
|
||||||
51
Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/tzinfo-1.2.8/lib/tzinfo/annual_rules.rb
vendored
Normal file
51
Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/tzinfo-1.2.8/lib/tzinfo/annual_rules.rb
vendored
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
module TZInfo
|
||||||
|
# A set of rules that define when transitions occur in time zones with
|
||||||
|
# annually occurring daylight savings time.
|
||||||
|
#
|
||||||
|
# @private
|
||||||
|
class AnnualRules #:nodoc:
|
||||||
|
# Returned by #transitions. #offset is the TimezoneOffset that applies
|
||||||
|
# from the UTC TimeOrDateTime #at. #previous_offset is the prior
|
||||||
|
# TimezoneOffset.
|
||||||
|
Transition = Struct.new(:offset, :previous_offset, :at)
|
||||||
|
|
||||||
|
# The standard offset that applies when daylight savings time is not in
|
||||||
|
# force.
|
||||||
|
attr_reader :std_offset
|
||||||
|
|
||||||
|
# The offset that applies when daylight savings time is in force.
|
||||||
|
attr_reader :dst_offset
|
||||||
|
|
||||||
|
# The rule that determines when daylight savings time starts.
|
||||||
|
attr_reader :dst_start_rule
|
||||||
|
|
||||||
|
# The rule that determines when daylight savings time ends.
|
||||||
|
attr_reader :dst_end_rule
|
||||||
|
|
||||||
|
# Initializes a new {AnnualRules} instance.
|
||||||
|
def initialize(std_offset, dst_offset, dst_start_rule, dst_end_rule)
|
||||||
|
@std_offset = std_offset
|
||||||
|
@dst_offset = dst_offset
|
||||||
|
@dst_start_rule = dst_start_rule
|
||||||
|
@dst_end_rule = dst_end_rule
|
||||||
|
end
|
||||||
|
|
||||||
|
# Returns the transitions between standard and daylight savings time for a
|
||||||
|
# given year. The results are ordered by time of occurrence (earliest to
|
||||||
|
# latest).
|
||||||
|
def transitions(year)
|
||||||
|
start_dst = apply_rule(@dst_start_rule, @std_offset, @dst_offset, year)
|
||||||
|
end_dst = apply_rule(@dst_end_rule, @dst_offset, @std_offset, year)
|
||||||
|
|
||||||
|
end_dst.at < start_dst.at ? [end_dst, start_dst] : [start_dst, end_dst]
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# Applies a given rule between offsets on a year.
|
||||||
|
def apply_rule(rule, from_offset, to_offset, year)
|
||||||
|
at = rule.at(from_offset, year)
|
||||||
|
Transition.new(to_offset, from_offset, at)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
136
Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/tzinfo-1.2.8/lib/tzinfo/posix_time_zone_parser.rb
vendored
Normal file
136
Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/tzinfo-1.2.8/lib/tzinfo/posix_time_zone_parser.rb
vendored
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
# encoding: UTF-8
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'strscan'
|
||||||
|
|
||||||
|
module TZInfo
|
||||||
|
# An {InvalidPosixTimeZone} exception is raised if an invalid POSIX-style
|
||||||
|
# time zone string is encountered.
|
||||||
|
#
|
||||||
|
# @private
|
||||||
|
class InvalidPosixTimeZone < StandardError #:nodoc:
|
||||||
|
end
|
||||||
|
|
||||||
|
# A parser for POSIX-style TZ strings used in zoneinfo files and specified
|
||||||
|
# by tzfile.5 and tzset.3.
|
||||||
|
#
|
||||||
|
# @private
|
||||||
|
class PosixTimeZoneParser #:nodoc:
|
||||||
|
# Parses a POSIX-style TZ string, returning either a TimezoneOffset or
|
||||||
|
# an AnnualRules instance.
|
||||||
|
def parse(tz_string)
|
||||||
|
raise InvalidPosixTimeZone unless tz_string.kind_of?(String)
|
||||||
|
return nil if tz_string.empty?
|
||||||
|
|
||||||
|
s = StringScanner.new(tz_string)
|
||||||
|
check_scan(s, /([^-+,\d<][^-+,\d]*) | <([^>]+)>/x)
|
||||||
|
std_abbrev = s[1] || s[2]
|
||||||
|
check_scan(s, /([-+]?\d+)(?::(\d+)(?::(\d+))?)?/)
|
||||||
|
std_offset = get_offset_from_hms(s[1], s[2], s[3])
|
||||||
|
|
||||||
|
if s.scan(/([^-+,\d<][^-+,\d]*) | <([^>]+)>/x)
|
||||||
|
dst_abbrev = s[1] || s[2]
|
||||||
|
|
||||||
|
if s.scan(/([-+]?\d+)(?::(\d+)(?::(\d+))?)?/)
|
||||||
|
dst_offset = get_offset_from_hms(s[1], s[2], s[3])
|
||||||
|
else
|
||||||
|
# POSIX is negative for ahead of UTC.
|
||||||
|
dst_offset = std_offset - 3600
|
||||||
|
end
|
||||||
|
|
||||||
|
dst_difference = std_offset - dst_offset
|
||||||
|
|
||||||
|
start_rule = parse_rule(s, 'start')
|
||||||
|
end_rule = parse_rule(s, 'end')
|
||||||
|
|
||||||
|
raise InvalidPosixTimeZone, "Expected the end of a POSIX-style time zone string but found '#{s.rest}'." if s.rest?
|
||||||
|
|
||||||
|
if start_rule.is_always_first_day_of_year? && start_rule.transition_at == 0 &&
|
||||||
|
end_rule.is_always_last_day_of_year? && end_rule.transition_at == 86400 + dst_difference
|
||||||
|
# Constant daylight savings time.
|
||||||
|
# POSIX is negative for ahead of UTC.
|
||||||
|
TimezoneOffset.new(-std_offset, dst_difference, dst_abbrev.to_sym)
|
||||||
|
else
|
||||||
|
AnnualRules.new(
|
||||||
|
TimezoneOffset.new(-std_offset, 0, std_abbrev.to_sym),
|
||||||
|
TimezoneOffset.new(-std_offset, dst_difference, dst_abbrev.to_sym),
|
||||||
|
start_rule,
|
||||||
|
end_rule)
|
||||||
|
end
|
||||||
|
elsif !s.rest?
|
||||||
|
# Constant standard time.
|
||||||
|
# POSIX is negative for ahead of UTC.
|
||||||
|
TimezoneOffset.new(-std_offset, 0, std_abbrev.to_sym)
|
||||||
|
else
|
||||||
|
raise InvalidPosixTimeZone, "Expected the end of a POSIX-style time zone string but found '#{s.rest}'."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# Parses the rule from the TZ string, returning a TransitionRule.
|
||||||
|
def parse_rule(s, type)
|
||||||
|
check_scan(s, /,(?: (?: J(\d+) ) | (\d+) | (?: M(\d+)\.(\d)\.(\d) ) )/x)
|
||||||
|
julian_day_of_year = s[1]
|
||||||
|
absolute_day_of_year = s[2]
|
||||||
|
month = s[3]
|
||||||
|
week = s[4]
|
||||||
|
day_of_week = s[5]
|
||||||
|
|
||||||
|
if s.scan(/\//)
|
||||||
|
check_scan(s, /([-+]?\d+)(?::(\d+)(?::(\d+))?)?/)
|
||||||
|
transition_at = get_seconds_after_midnight_from_hms(s[1], s[2], s[3])
|
||||||
|
else
|
||||||
|
transition_at = 7200
|
||||||
|
end
|
||||||
|
|
||||||
|
begin
|
||||||
|
if julian_day_of_year
|
||||||
|
JulianDayOfYearTransitionRule.new(julian_day_of_year.to_i, transition_at)
|
||||||
|
elsif absolute_day_of_year
|
||||||
|
AbsoluteDayOfYearTransitionRule.new(absolute_day_of_year.to_i, transition_at)
|
||||||
|
elsif week == '5'
|
||||||
|
LastDayOfMonthTransitionRule.new(month.to_i, day_of_week.to_i, transition_at)
|
||||||
|
else
|
||||||
|
DayOfMonthTransitionRule.new(month.to_i, week.to_i, day_of_week.to_i, transition_at)
|
||||||
|
end
|
||||||
|
rescue ArgumentError => e
|
||||||
|
raise InvalidPosixTimeZone, "Invalid #{type} rule in POSIX-style time zone string: #{e}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Returns an offset in seconds from hh:mm:ss values. The value can be
|
||||||
|
# negative. -02:33:12 would represent 2 hours, 33 minutes and 12 seconds
|
||||||
|
# ahead of UTC.
|
||||||
|
def get_offset_from_hms(h, m, s)
|
||||||
|
h = h.to_i
|
||||||
|
m = m.to_i
|
||||||
|
s = s.to_i
|
||||||
|
raise InvalidPosixTimeZone, "Invalid minute #{m} in offset for POSIX-style time zone string." if m > 59
|
||||||
|
raise InvalidPosixTimeZone, "Invalid second #{s} in offset for POSIX-style time zone string." if s > 59
|
||||||
|
magnitude = (h.abs * 60 + m) * 60 + s
|
||||||
|
h < 0 ? -magnitude : magnitude
|
||||||
|
end
|
||||||
|
|
||||||
|
# Returns the seconds from midnight from hh:mm:ss values. Hours can exceed
|
||||||
|
# 24 for a time on the following day. Hours can be negative to subtract
|
||||||
|
# hours from midnight on the given day. -02:33:12 represents 22:33:12 on
|
||||||
|
# the prior day.
|
||||||
|
def get_seconds_after_midnight_from_hms(h, m, s)
|
||||||
|
h = h.to_i
|
||||||
|
m = m.to_i
|
||||||
|
s = s.to_i
|
||||||
|
raise InvalidPosixTimeZone, "Invalid minute #{m} in time for POSIX-style time zone string." if m > 59
|
||||||
|
raise InvalidPosixTimeZone, "Invalid second #{s} in time for POSIX-style time zone string." if s > 59
|
||||||
|
(h * 3600) + m * 60 + s
|
||||||
|
end
|
||||||
|
|
||||||
|
# Scans for a pattern and raises an exception if the pattern does not
|
||||||
|
# match the input.
|
||||||
|
def check_scan(s, pattern)
|
||||||
|
result = s.scan(pattern)
|
||||||
|
raise InvalidPosixTimeZone, "Expected '#{s.rest}' to match #{pattern} in POSIX-style time zone string." unless result
|
||||||
|
result
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user