Class: Cane::DocCheck
- Inherits:
-
Struct
- Object
- Struct
- Cane::DocCheck
- Defined in:
- lib/cane/doc_check.rb
Overview
Creates violations for class definitions that do not have an explantory comment immediately preceding.
Defined Under Namespace
Classes: ClassDefinition
Constant Summary collapse
- DESCRIPTION =
"Class and Module definitions require explanatory comments on previous line"
- MAGIC_COMMENT_REGEX =
Stolen from ERB source, amended to be slightly stricter to work around some known false positives.
%r"#(\s+-\*-)?\s+(en)?coding\s*[=:]\s*([[:alnum:]\-_]+)"
- CLASS_REGEX =
/^\s*(?:class|module)\s+([^\s;]+)/
- SINGLE_LINE_CLASS_REGEX =
/^\s*(?:class|module).*;\s*end\s*(#.*)?\s*$/
- METHOD_REGEX =
/(?:^|\s)def\s+/
Instance Attribute Summary collapse
-
#opts ⇒ Object
Returns the value of attribute opts.
Class Method Summary collapse
Instance Method Summary collapse
- #class_definition(number, line, last_line) ⇒ Object
- #class_definition?(line) ⇒ Boolean
- #class_definitions_in(file_name) ⇒ Object
- #comment?(line) ⇒ Boolean
- #excluded?(file) ⇒ Boolean
- #exclusions ⇒ Object
- #extract_class_name(line) ⇒ Object
- #file_names ⇒ Object
- #find_violations(file_name) ⇒ Object
- #method_definition?(line) ⇒ Boolean
- #missing_file_violations ⇒ Object
- #single_line_class_definition?(line) ⇒ Boolean
- #violations ⇒ Object
- #worker ⇒ Object
Instance Attribute Details
#opts ⇒ Object
Returns the value of attribute opts
8 9 10 |
# File 'lib/cane/doc_check.rb', line 8 def opts @opts end |
Class Method Details
.key ⇒ Object
21 |
# File 'lib/cane/doc_check.rb', line 21 def self.key; :doc; end |
.name ⇒ Object
22 |
# File 'lib/cane/doc_check.rb', line 22 def self.name; "documentation checking"; end |
.options ⇒ Object
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/cane/doc_check.rb', line 23 def self. { 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 |
Instance Method Details
#class_definition(number, line, last_line) ⇒ Object
96 97 98 99 100 101 102 103 |
# 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) ⇒ Boolean
124 125 126 |
# File 'lib/cane/doc_check.rb', line 124 def class_definition?(line) line =~ CLASS_REGEX && $1.index('<<') != 0 end |
#class_definitions_in(file_name) ⇒ Object
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# 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) ⇒ Boolean
132 133 134 |
# File 'lib/cane/doc_check.rb', line 132 def comment?(line) line =~ /^\s*#/ && !(MAGIC_COMMENT_REGEX =~ line) end |
#excluded?(file) ⇒ Boolean
146 147 148 |
# File 'lib/cane/doc_check.rb', line 146 def excluded?(file) exclusions.include?(file) end |
#exclusions ⇒ Object
140 141 142 143 144 |
# File 'lib/cane/doc_check.rb', line 140 def exclusions @exclusions ||= opts.fetch(:doc_exclude, []).flatten.map do |i| Dir[i] end.flatten.to_set end |
#extract_class_name(line) ⇒ Object
136 137 138 |
# File 'lib/cane/doc_check.rb', line 136 def extract_class_name(line) line.match(CLASS_REGEX)[1] end |
#file_names ⇒ Object
116 117 118 |
# File 'lib/cane/doc_check.rb', line 116 def file_names Dir[opts.fetch(:doc_glob)].reject { |file| excluded?(file) } end |
#find_violations(file_name) ⇒ Object
60 61 62 63 64 65 66 67 68 69 70 71 |
# 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) ⇒ Boolean
120 121 122 |
# File 'lib/cane/doc_check.rb', line 120 def method_definition?(line) line =~ METHOD_REGEX end |
#missing_file_violations ⇒ Object
105 106 107 108 109 110 111 112 113 114 |
# 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) ⇒ Boolean
128 129 130 |
# File 'lib/cane/doc_check.rb', line 128 def single_line_class_definition?(line) line =~ SINGLE_LINE_CLASS_REGEX end |
#violations ⇒ Object
52 53 54 55 56 57 58 |
# 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 ⇒ Object
150 151 152 |
# File 'lib/cane/doc_check.rb', line 150 def worker Cane.task_runner(opts) end |