class RuboCop::Cop::Style::ClassAndModuleChildren
The compact style is only forced for classes/modules with one child.
end
class Foo::Bar
# combine definitions as much as possible
# good
@example EnforcedStyle: compact
end
end
class Bar
class Foo
# have each child on its own line
# good
@example EnforcedStyle: nested (default)
modules. Basically there are two different styles:
This cop checks the style of children definitions at classes and
def add_trailing_end(corrector, node, padding)
def add_trailing_end(corrector, node, padding) replacement = "#{padding}end\n#{leading_spaces(node)}end".freeze corrector.replace(node.loc.end, replacement) end
def autocorrect(node)
def autocorrect(node) lambda do |corrector| return if node.class_type? && node.parent_class && style != :nested nest_or_compact(corrector, node) end end
def check_compact_style(node, body)
def check_compact_style(node, body) return unless one_child?(body) && !compact_node_name?(node) add_offense(node, location: :name, message: COMPACT_MSG) end
def check_nested_style(node)
def check_nested_style(node) return unless compact_node_name?(node) add_offense(node, location: :name, message: NESTED_MSG) end
def check_style(node, body)
def check_style(node, body) if style == :nested check_nested_style(node) else check_compact_style(node, body) end end
def compact_definition(corrector, node)
def compact_definition(corrector, node) compact_node(corrector, node) remove_end(corrector, node.body) end
def compact_identifier_name(node)
def compact_identifier_name(node) "#{node.identifier.const_name}::" \ "#{node.body.children.first.const_name}" end
def compact_node(corrector, node)
def compact_node(corrector, node) replacement = "#{node.body.type} #{compact_identifier_name(node)}" range = range_between(node.loc.keyword.begin_pos, node.body.loc.name.end_pos) corrector.replace(range, replacement) end
def compact_node_name?(node)
def compact_node_name?(node) node.loc.name.source =~ /::/ end
def indent_width
def indent_width @config.for_cop('IndentationWidth')['Width'] || 2 end
def leading_spaces(node)
def leading_spaces(node) node.source_range.source_line[/\A\s*/] end
def nest_definition(corrector, node)
def nest_definition(corrector, node) padding = ((' ' * indent_width) + leading_spaces(node)).to_s padding_for_trailing_end = padding.sub(' ' * node.loc.end.column, '') replace_keyword_with_module(corrector, node) split_on_double_colon(corrector, node, padding) add_trailing_end(corrector, node, padding_for_trailing_end) end
def nest_or_compact(corrector, node)
def nest_or_compact(corrector, node) if style == :nested nest_definition(corrector, node) else compact_definition(corrector, node) end end
def on_class(node)
def on_class(node) return if node.parent_class && style != :nested check_style(node, node.body) end
def on_module(node)
def on_module(node) check_style(node, node.body) end
def one_child?(body)
def one_child?(body) body && %i[module class].include?(body.type) end
def remove_end(corrector, body)
def remove_end(corrector, body) range = range_between( body.loc.end.begin_pos - leading_spaces(body).size, body.loc.end.end_pos + 1 ) corrector.remove(range) end
def replace_keyword_with_module(corrector, node)
def replace_keyword_with_module(corrector, node) corrector.replace(node.loc.keyword, 'module'.freeze) end
def split_on_double_colon(corrector, node, padding)
def split_on_double_colon(corrector, node, padding) children_definition = node.children.first range = range_between(children_definition.loc.double_colon.begin_pos, children_definition.loc.double_colon.end_pos) replacement = "\n#{padding}#{node.loc.keyword.source} ".freeze corrector.replace(range, replacement) end