Class: SugarCane::DocCheck
- Inherits:
-
Struct
- Object
- Struct
- SugarCane::DocCheck
- Defined in:
- lib/sugarcane/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/sugarcane/doc_check.rb', line 8 def opts @opts end |
Class Method Details
.key ⇒ Object
21 |
# File 'lib/sugarcane/doc_check.rb', line 21 def self.key; :doc; end |
.name ⇒ Object
22 |
# File 'lib/sugarcane/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/sugarcane/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
98 99 100 101 102 103 104 105 |
# File 'lib/sugarcane/doc_check.rb', line 98 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
126 127 128 |
# File 'lib/sugarcane/doc_check.rb', line 126 def class_definition?(line) line =~ CLASS_REGEX && $1.index('<<') != 0 end |
#class_definitions_in(file_name) ⇒ Object
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/sugarcane/doc_check.rb', line 75 def class_definitions_in(file_name) closed_classes = [] open_classes = [] last_line = "" SugarCane::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
134 135 136 |
# File 'lib/sugarcane/doc_check.rb', line 134 def comment?(line) line =~ /^\s*#/ && !(MAGIC_COMMENT_REGEX =~ line) end |
#excluded?(file) ⇒ Boolean
148 149 150 |
# File 'lib/sugarcane/doc_check.rb', line 148 def excluded?(file) exclusions.include?(file) end |
#exclusions ⇒ Object
142 143 144 145 146 |
# File 'lib/sugarcane/doc_check.rb', line 142 def exclusions @exclusions ||= opts.fetch(:doc_exclude, []).flatten.map do |i| Dir[i] end.flatten.to_set end |
#extract_class_name(line) ⇒ Object
138 139 140 |
# File 'lib/sugarcane/doc_check.rb', line 138 def extract_class_name(line) line.match(CLASS_REGEX)[1] end |
#file_names ⇒ Object
118 119 120 |
# File 'lib/sugarcane/doc_check.rb', line 118 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 72 73 |
# File 'lib/sugarcane/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, menu_description: "#{class_definition.label} requires explanatory "\ "comments on the previous line" } end end.compact end |
#method_definition?(line) ⇒ Boolean
122 123 124 |
# File 'lib/sugarcane/doc_check.rb', line 122 def method_definition?(line) line =~ METHOD_REGEX end |
#missing_file_violations ⇒ Object
107 108 109 110 111 112 113 114 115 116 |
# File 'lib/sugarcane/doc_check.rb', line 107 def missing_file_violations result = [] return result if opts[:no_readme] if SugarCane::File.case_insensitive_glob("README*").none? result << { description: 'Missing documentation', label: 'No README found' } end result end |
#single_line_class_definition?(line) ⇒ Boolean
130 131 132 |
# File 'lib/sugarcane/doc_check.rb', line 130 def single_line_class_definition?(line) line =~ SINGLE_LINE_CLASS_REGEX end |
#violations ⇒ Object
52 53 54 55 56 57 58 |
# File 'lib/sugarcane/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
152 153 154 |
# File 'lib/sugarcane/doc_check.rb', line 152 def worker SugarCane.task_runner(opts) end |