lib/rubocop/cop/rspec/file_path.rb in rubocop-rspec-1.12.0 vs lib/rubocop/cop/rspec/file_path.rb in rubocop-rspec-1.13.0
- old
+ new
@@ -42,69 +42,70 @@
# my_class_spec.rb # describe MyClass, '#method'
#
class FilePath < Cop
include RuboCop::RSpec::TopLevelDescribe
- MESSAGE = 'Spec path should end with `%s`'.freeze
- ROUTING_PAIR = s(:pair, s(:sym, :type), s(:sym, :routing))
+ MSG = 'Spec path should end with `%s`.'.freeze
+ def_node_search :const_described?, '(send _ :describe (const ...) ...)'
+ def_node_search :routing_metadata?, '(pair (sym :type) (sym :routing))'
+
def on_top_level_describe(node, args)
+ return unless const_described?(node) && single_top_level_describe?
return if routing_spec?(args)
- return unless single_top_level_describe?
- object = args.first.const_name
- return unless object
+ glob = glob_for(args)
- path_matcher = matcher(object, args.at(1))
- return if source_filename =~ regexp_from_glob(path_matcher)
+ return if filename_ends_with?(glob)
- add_offense(node, :expression, format(MESSAGE, path_matcher))
+ add_offense(node, :expression, format(MSG, glob))
end
private
def routing_spec?(args)
- args.any? do |arg|
- arg.children.include?(ROUTING_PAIR)
- end
+ args.any?(&method(:routing_metadata?))
end
- def matcher(object, method)
- path = File.join(parts(object))
- if method && method.type.equal?(:str) && !ignore_methods?
- path += '*' + method.str_content.gsub(/\W+/, '')
- end
-
- "#{path}*_spec.rb"
+ def glob_for((described_class, method_name))
+ "#{expected_path(described_class)}#{name_glob(method_name)}*_spec.rb"
end
- def parts(object)
- object.split('::').map do |p|
- custom_transform[p] || camel_to_underscore(p)
- end
+ def name_glob(name)
+ return unless name && name.str_type?
+
+ "*#{name.str_content.gsub(/\W/, '')}" unless ignore_methods?
end
- def source_filename
- processed_source.buffer.name
+ def expected_path(constant)
+ File.join(
+ constant.const_name.split('::').map do |name|
+ custom_transform.fetch(name) { camel_to_snake_case(name) }
+ end
+ )
end
- def camel_to_underscore(string)
+ def camel_to_snake_case(string)
string
.gsub(/([^A-Z])([A-Z]+)/, '\1_\2')
.gsub(/([A-Z])([A-Z][^A-Z\d]+)/, '\1_\2')
.downcase
end
- def regexp_from_glob(glob)
- Regexp.new(glob.sub('.', '\\.').gsub('*', '.*') + '$')
+ def custom_transform
+ cop_config.fetch('CustomTransform', {})
end
def ignore_methods?
cop_config['IgnoreMethods']
end
- def custom_transform
- cop_config['CustomTransform'] || {}
+ def filename_ends_with?(glob)
+ File.fnmatch?("*#{glob}", processed_source.buffer.name)
+ end
+
+ def relevant_rubocop_rspec_file?(_)
+ true
end
end
end
end
end