lib/rubocop/cop/layout/align_hash.rb in rubocop-0.69.0 vs lib/rubocop/cop/layout/align_hash.rb in rubocop-0.70.0
- old
+ new
@@ -15,12 +15,14 @@
# can also be configured. The options are:
#
# - always_inspect
# - always_ignore
# - ignore_implicit (without curly braces)
- # - ignore_explicit (with curly braces)
#
+ # Alternatively you can specify multiple allowed styles. That's done by
+ # passing a list of styles to EnforcedStyles.
+ #
# @example EnforcedHashRocketStyle: key (default)
# # bad
# {
# :foo => bar,
# :ba => baz
@@ -196,52 +198,69 @@
def on_hash(node)
return if ignored_node?(node)
return if node.pairs.empty? || node.single_line?
- return unless alignment_for_hash_rockets.checkable_layout?(node) &&
- alignment_for_colons.checkable_layout?(node)
+ return unless alignment_for_hash_rockets
+ .any? { |a| a.checkable_layout?(node) } &&
+ alignment_for_colons
+ .any? { |a| a.checkable_layout?(node) }
check_pairs(node)
end
def autocorrect(node)
- # We can't use the instance variable inside the lambda. That would
- # just give each lambda the same reference and they would all get the
- # last value of each. A local variable fixes the problem.
- key_delta = column_deltas[:key] || 0
+ delta = column_deltas[alignment_for(node).first.class][node]
+ return if delta.nil?
- if !node.value
- correct_no_value(key_delta, node.source_range)
- else
- correct_key_value(key_delta, node.key.source_range,
- node.value.source_range,
- node.loc.operator)
- end
+ correct_node(node, delta)
end
- private
-
+ attr_accessor :offences_by
attr_accessor :column_deltas
+ private
+
def double_splat?(node)
node.children.last.is_a?(Symbol)
end
def check_pairs(node)
first_pair = node.pairs.first
- self.column_deltas = alignment_for(first_pair)
- .deltas_for_first_pair(first_pair, node)
- add_offense(first_pair) unless good_alignment?
+ self.offences_by = {}
+ self.column_deltas = Hash.new { |hash, key| hash[key] = {} }
+ alignment_for(first_pair).each do |alignment|
+ delta = alignment.deltas_for_first_pair(first_pair, node)
+ check_delta delta, node: first_pair, alignment: alignment
+ end
+
node.children.each do |current|
- self.column_deltas = alignment_for(current)
- .deltas(first_pair, current)
- add_offense(current) unless good_alignment?
+ alignment_for(current).each do |alignment|
+ delta = alignment.deltas(first_pair, current)
+ check_delta delta, node: current, alignment: alignment
+ end
end
+
+ add_offences
end
+ def add_offences
+ _format, offences = offences_by.min_by { |_, v| v.length }
+ (offences || []).each do |offence|
+ add_offense offence
+ end
+ end
+
+ def check_delta(delta, node:, alignment:)
+ offences_by[alignment.class] ||= []
+ return if good_alignment? delta
+
+ column_deltas[alignment.class][node] = delta
+ offences_by[alignment.class].push(node)
+ end
+
def ignore_hash_argument?(node)
case cop_config['EnforcedLastArgumentHashStyle']
when 'always_inspect' then false
when 'always_ignore' then true
when 'ignore_explicit' then node.braces?
@@ -265,20 +284,35 @@
def alignment_for_colons
@alignment_for_colons ||=
new_alignment('EnforcedColonStyle')
end
+ def correct_node(node, delta)
+ # We can't use the instance variable inside the lambda. That would
+ # just give each lambda the same reference and they would all get the
+ # last value of each. A local variable fixes the problem.
+
+ if !node.value
+ correct_no_value(delta[:key] || 0, node.source_range)
+ else
+ correct_key_value(delta, node.key.source_range,
+ node.value.source_range,
+ node.loc.operator)
+ end
+ end
+
def correct_no_value(key_delta, key)
->(corrector) { adjust(corrector, key_delta, key) }
end
- def correct_key_value(key_delta, key, value, separator)
+ def correct_key_value(delta, key, value, separator)
# We can't use the instance variable inside the lambda. That would
# just give each lambda the same reference and they would all get the
# last value of each. Some local variables fix the problem.
- separator_delta = column_deltas[:separator] || 0
- value_delta = column_deltas[:value] || 0
+ separator_delta = delta[:separator] || 0
+ value_delta = delta[:value] || 0
+ key_delta = delta[:key] || 0
key_column = key.column
key_delta = -key_column if key_delta < -key_column
lambda do |corrector|
@@ -287,15 +321,24 @@
adjust(corrector, value_delta, value)
end
end
def new_alignment(key)
- case cop_config[key]
- when 'key' then KeyAlignment.new
- when 'table' then TableAlignment.new
- when 'separator' then SeparatorAlignment.new
- else raise "Unknown #{key}: #{cop_config[key]}"
+ formats = cop_config[key]
+ formats = [formats] if formats.is_a? String
+
+ formats.uniq.map do |format|
+ case format
+ when 'key'
+ KeyAlignment.new
+ when 'table'
+ TableAlignment.new
+ when 'separator'
+ SeparatorAlignment.new
+ else
+ raise "Unknown #{key}: #{formats}"
+ end
end
end
def adjust(corrector, delta, range)
if delta.positive?
@@ -304,10 +347,10 @@
range = range_between(range.begin_pos - delta.abs, range.begin_pos)
corrector.remove(range)
end
end
- def good_alignment?
+ def good_alignment?(column_deltas)
column_deltas.values.all?(&:zero?)
end
end
end
end