Skip to content

Commit

Permalink
Use refinements to support Ruby <= 2.6 Range#minmax
Browse files Browse the repository at this point in the history
  • Loading branch information
marcandre authored and mergify[bot] committed Nov 13, 2020
1 parent e27b768 commit f5c6354
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 18 deletions.
1 change: 1 addition & 0 deletions lib/rubocop/ast.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
require 'set'

require_relative 'ast/ext/range'
require_relative 'ast/ext/range_min_max'
require_relative 'ast/ext/set'
require_relative 'ast/node_pattern/method_definer'
require_relative 'ast/node_pattern'
Expand Down
18 changes: 18 additions & 0 deletions lib/rubocop/ast/ext/range_min_max.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# frozen_string_literal: true

module RuboCop
module AST
module Ext
# Refinement to circumvent broken `Range#minmax` for infinity ranges in 2.6-
module RangeMinMax
if ::Range.instance_method(:minmax).owner != ::Range
refine ::Range do
def minmax
[min, max]
end
end
end
end
end
end
end
21 changes: 3 additions & 18 deletions lib/rubocop/ast/node_pattern/node.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ class NodePattern
class Node < ::Parser::AST::Node
extend Forwardable
include ::RuboCop::AST::Descendence
using Ext::RangeMinMax

MATCHES_WITHIN_SET = %i[symbol number string].to_set.freeze
private_constant :MATCHES_WITHIN_SET
Expand Down Expand Up @@ -197,26 +198,12 @@ def arity
end
end

# Circumvent broken `Range#minmax` for infinity ranges in 2.6-
module MapMinMax
if RUBY_VERSION >= '2.7'
def map_min_max(enum)
enum.map(&:minmax)
end
else
def map_min_max(enum)
enum.map { |r| [r.min, r.max] } # rubocop:disable Style/MinMax
end
end
end

# A list (potentially empty) of nodes; part of a Union
class Subsequence < Node
include ForbidInSeqHead
include MapMinMax

def arity
min, max = map_min_max(children.map(&:arity_range)).transpose.map(&:sum)
min, max = children.map(&:arity_range).map(&:minmax).transpose.map(&:sum)
min == max ? min || 0 : min..max # NOTE: || 0 for empty case, where min == max == nil.
end

Expand All @@ -231,10 +218,8 @@ def in_sequence_head

# Node class for `{ ... }`
class Union < Node
include MapMinMax

def arity
minima, maxima = map_min_max(children.map(&:arity_range)).transpose
minima, maxima = children.map(&:arity_range).map(&:minmax).transpose
min = minima.min
max = maxima.max
min == max ? min : min..max
Expand Down

0 comments on commit f5c6354

Please sign in to comment.