class Cane::DocCheck

Creates violations for class definitions that do not have an explantory comment immediately preceding.

Constants

CLASS_REGEX
ClassDefinition
DESCRIPTION
MAGIC_COMMENT_REGEX

Stolen from ERB source, amended to be slightly stricter to work around some known false positives.

METHOD_REGEX
SINGLE_LINE_CLASS_REGEX

rubular.com/r/53BapkefdD

Public Class Methods

key() click to toggle source
# File lib/cane/doc_check.rb, line 21
def self.key; :doc; end
name() click to toggle source
# File lib/cane/doc_check.rb, line 22
def self.name; "documentation checking"; end
options() click to toggle source
# File lib/cane/doc_check.rb, line 23
def self.options
  {
    doc_glob:    ['Glob to run doc checks over',
                    default:  '{app,lib}/**/*.rb',
                    variable: 'GLOB',
                    clobber:  :no_doc],
    doc_exclude: ['Exclude file or glob from documentation checking',
                    variable: 'GLOB',
                    type: Array,
                    default: [],
                    clobber: :no_doc],
    no_readme:   ['Disable readme checking', cast: ->(x) { !x }],
    no_doc:      ['Disable documentation checking', cast: ->(x) { !x }]
  }
end

Public Instance Methods

class_definition(number, line, last_line) click to toggle source
# File lib/cane/doc_check.rb, line 96
def class_definition(number, line, last_line)
  ClassDefinition.new({
    line: (number + 1),
    label: extract_class_name(line),
    has_doc: comment?(last_line),
    requires_doc: method_definition?(line)
  })
end
class_definition?(line) click to toggle source
# File lib/cane/doc_check.rb, line 124
def class_definition?(line)
  line =~ CLASS_REGEX && $1.index('<<') != 0
end
class_definitions_in(file_name) click to toggle source
# File lib/cane/doc_check.rb, line 73
def class_definitions_in(file_name)
  closed_classes = []
  open_classes = []
  last_line = ""

  Cane::File.iterator(file_name).each_with_index do |line, number|
    if class_definition? line
      if single_line_class_definition? line
        closed_classes
      else
        open_classes
      end.push class_definition(number, line, last_line)

    elsif method_definition?(line) && !open_classes.empty?
      open_classes.last.requires_doc = true
    end

    last_line = line
  end

  (closed_classes + open_classes).sort_by(&:line)
end
comment?(line) click to toggle source
# File lib/cane/doc_check.rb, line 132
def comment?(line)
  line =~ /^\s*#/ && !(MAGIC_COMMENT_REGEX =~ line)
end
excluded?(file) click to toggle source
# File lib/cane/doc_check.rb, line 146
def excluded?(file)
  exclusions.include?(file)
end
exclusions() click to toggle source
# File lib/cane/doc_check.rb, line 140
def exclusions
  @exclusions ||= opts.fetch(:doc_exclude, []).flatten.map do |i|
    Dir.glob(i)
  end.flatten.to_set
end
extract_class_name(line) click to toggle source
# File lib/cane/doc_check.rb, line 136
def extract_class_name(line)
  line.match(CLASS_REGEX)[1]
end
file_names() click to toggle source
# File lib/cane/doc_check.rb, line 116
def file_names
  Dir.glob(opts.fetch(:doc_glob)).reject { |file| excluded?(file) }
end
find_violations(file_name) click to toggle source
# File lib/cane/doc_check.rb, line 60
def find_violations(file_name)
  class_definitions_in(file_name).map do |class_definition|
    if class_definition.requires_doc? && class_definition.missing_doc?
      {
        file:        file_name,
        line:        class_definition.line,
        label:       class_definition.label,
        description: DESCRIPTION
      }
    end
  end.compact
end
method_definition?(line) click to toggle source
# File lib/cane/doc_check.rb, line 120
def method_definition?(line)
  !comment?(line) && line =~ METHOD_REGEX
end
missing_file_violations() click to toggle source
# File lib/cane/doc_check.rb, line 105
def missing_file_violations
  result = []
  return result if opts[:no_readme]

  if Cane::File.case_insensitive_glob("README*").none?
    result << { description: 'Missing documentation',
                label: 'No README found' }
  end
  result
end
single_line_class_definition?(line) click to toggle source
# File lib/cane/doc_check.rb, line 128
def single_line_class_definition?(line)
  line =~ SINGLE_LINE_CLASS_REGEX
end
violations() click to toggle source
# File lib/cane/doc_check.rb, line 52
def violations
  return [] if opts[:no_doc]

  missing_file_violations + worker.map(file_names) {|file_name|
    find_violations(file_name)
  }.flatten
end
worker() click to toggle source
# File lib/cane/doc_check.rb, line 150
def worker
  Cane.task_runner(opts)
end