class RuboCop::Cop::Highlands::ClassOrModuleDeclaredInWrongFile
This cop checks for a class or module declared in a file that does not match its name. The Rails autoloader can't find such a constant, but sometimes people “get lucky” if the file happened to be loaded before the method was defined.
@example
# bad # foo/bar.rb module Foo class Goop end module Moo end end # good # foo.rb # foo/goop.rb module Foo class Goop end end # foo/moo.rb module Foo module Moo end end
Note that autoloading works fine if classes are defined in the file that defines the module. This is common usage for things like error classes, so we'll allow it. Nested classes are also allowed:
@example
# good # foo.rb module Foo class Bar < StandardError end end # good # foo.rb class Foo class Bar # nested class end end
Constants
- CLASS_OR_MODULE_MSG
class Foo or module Foo in the wrong file
- ERROR_CLASS_MSG
class FooError < StandardError, in the wrong file
Public Instance Methods
on_class(node)
click to toggle source
class C
# File lib/rubocop/cop/highlands/class_or_module_declared_in_wrong_file.rb, line 80 def on_class(node) on_class_or_module(node) end
on_module(node)
click to toggle source
module M
# File lib/rubocop/cop/highlands/class_or_module_declared_in_wrong_file.rb, line 75 def on_module(node) on_class_or_module(node) end
Private Instance Methods
add_error(const_name, fully_qualified_const_name, node)
click to toggle source
# File lib/rubocop/cop/highlands/class_or_module_declared_in_wrong_file.rb, line 103 def add_error(const_name, fully_qualified_const_name, node) class_or_module = node.type.to_s.capitalize error_class = error_class?(node, class_or_module, const_name) if error_class parent_module_names = split_modules(node.parent_module_name) else parent_module_names = split_modules(fully_qualified_const_name) end expected_file = "#{parent_module_names.map { |name| underscore(name) }.join("/")}.rb" if error_class add_offense(node, message: ERROR_CLASS_MSG % [const_name, expected_file]) else add_offense( node, message: CLASS_OR_MODULE_MSG % [class_or_module, const_name, expected_file] ) end end
error_class?(node, class_or_module, const_name)
click to toggle source
Does this node define an Error class? (Classname or base class includes the word “Error” or “Exception”.)
# File lib/rubocop/cop/highlands/class_or_module_declared_in_wrong_file.rb, line 124 def error_class?(node, class_or_module, const_name) return false unless class_or_module == "Class" _, base_class, *_ = *node return unless base_class base_class_name = base_class.children[1].to_s if const_name =~ /Error|Exception/ || base_class_name =~ /Error|Exception/ return true end false end
on_class_or_module(node)
click to toggle source
# File lib/rubocop/cop/highlands/class_or_module_declared_in_wrong_file.rb, line 86 def on_class_or_module(node) path = node.source_range.source_buffer.name return unless run_rails_autoloading_cops?(path) const_name = node.loc.name.source parent_module_name = normalize_module_name(node.parent_module_name) fully_qualified_const_name = full_const_name(parent_module_name, const_name) expected_dir = underscore(fully_qualified_const_name) allowable_paths = allowable_paths_for(expected_dir, allow_dir: true) if allowable_paths.none? { |allowable_path| path =~ allowable_path } add_error(const_name, fully_qualified_const_name, node) end rescue => e puts e.backtrace raise end