class RuboCop::Cop::RSpec::FileName

my_class_spec.rb # describe MyClass
my_class_method_spec.rb # describe MyClass, ‘#method’
my_class/method_spec.rb # describe MyClass, ‘#method’
@example
snake_case (e.g. ‘RuboCop’ => ‘rubocop’ ).
specified that should not as usual be transformed from CamelCase to
With the configuration option ‘CustomTransform` modules or clases can be
described class/module and its optionally called out method.
Checks the path of the spec file and enforces that it reflects the

def camel_to_underscore(string)

def camel_to_underscore(string)
  string.dup.tap do |result|
    result.gsub!(/([^A-Z])([A-Z]+)/,          '\\1_\\2')
    result.gsub!(/([A-Z])([A-Z][^A-Z]+)/, '\\1_\\2')
    result.downcase!
  end
end

def custom_transform

def custom_transform
  cop_config['CustomTransform'] || []
end

def matcher(object, method)

def matcher(object, method)
  path = File.join(parts(object))
  path += '*' + method.children.first.gsub(/\W+/, '') if method
  "#{path}*_spec.rb"
end

def on_top_level_describe(node, args)

def on_top_level_describe(node, args)
  return unless single_top_level_describe?
  object = const_name(args.first)
  return unless object
  path_matcher = matcher(object, args[1])
  return if source_filename =~ regexp_from_glob(path_matcher)
  add_offense(node, :expression, format(MESSAGE, path_matcher))
end

def parts(object)

def parts(object)
  object.split('::').map do |p|
    custom_transform[p] || camel_to_underscore(p)
  end
end

def regexp_from_glob(glob)

def regexp_from_glob(glob)
  Regexp.new(glob.gsub('.', '\\.').gsub('*', '.*') + '$')
end

def source_filename

def source_filename
  processed_source.buffer.name
end