lib/rubocop/rspec/description_extractor.rb in rubocop-rspec-1.8.0 vs lib/rubocop/rspec/description_extractor.rb in rubocop-rspec-1.9.0
- old
+ new
@@ -1,35 +1,72 @@
module RuboCop
module RSpec
# Extracts cop descriptions from YARD docstrings
class DescriptionExtractor
- COP_NAMESPACE = 'RuboCop::Cop::RSpec'.freeze
- COP_FORMAT = 'RSpec/%s'.freeze
-
def initialize(yardocs)
- @yardocs = yardocs
+ @code_objects = yardocs.map(&CodeObject.public_method(:new))
end
def to_h
- cop_documentation.each_with_object({}) do |(name, docstring), config|
- config[format(COP_FORMAT, name)] = {
- 'Description' => docstring.split("\n\n").first.to_s
- }
- end
+ code_objects
+ .select(&:rspec_cop?)
+ .map(&:configuration)
+ .reduce(:merge)
end
private
- def cop_documentation
- yardocs
- .select(&method(:cop?))
- .map { |doc| [doc.name, doc.docstring] }
- end
+ attr_reader :code_objects
- def cop?(doc)
- doc.type.equal?(:class) && doc.to_s.start_with?(COP_NAMESPACE)
- end
+ # Decorator of a YARD code object for working with documented rspec cops
+ class CodeObject
+ COP_NAMESPACE = 'RuboCop::Cop::RSpec'.freeze
- attr_reader :yardocs
+ def initialize(yardoc)
+ @yardoc = yardoc
+ end
+
+ # Test if the YARD code object documents a concrete rspec cop class
+ #
+ # @return [Boolean]
+ def rspec_cop?
+ class_documentation? && rspec_cop_namespace? && !abstract?
+ end
+
+ # Configuration for the documented cop that would live in default.yml
+ #
+ # @return [Hash]
+ def configuration
+ { cop_name => { 'Description' => description } }
+ end
+
+ private
+
+ def cop_name
+ Object.const_get(documented_constant).cop_name
+ end
+
+ def description
+ yardoc.docstring.split("\n\n").first.to_s
+ end
+
+ def class_documentation?
+ yardoc.type.equal?(:class)
+ end
+
+ def rspec_cop_namespace?
+ documented_constant.start_with?(COP_NAMESPACE)
+ end
+
+ def documented_constant
+ yardoc.to_s
+ end
+
+ def abstract?
+ yardoc.tags.any? { |tag| tag.tag_name.eql?('abstract') }
+ end
+
+ attr_reader :yardoc
+ end
end
end
end