tools: support a `v vet -p file.v` option that will warn about private functions with missing documentation
parent
8da42bfc85
commit
c0b37409d2
|
@ -20,11 +20,12 @@ mut:
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Options {
|
struct Options {
|
||||||
is_force bool
|
is_force bool
|
||||||
is_werror bool
|
is_werror bool
|
||||||
is_verbose bool
|
is_verbose bool
|
||||||
show_warnings bool
|
show_warnings bool
|
||||||
use_color bool
|
use_color bool
|
||||||
|
doc_private_fns_too bool
|
||||||
}
|
}
|
||||||
|
|
||||||
const term_colors = term.can_show_color_on_stderr()
|
const term_colors = term.can_show_color_on_stderr()
|
||||||
|
@ -38,6 +39,7 @@ fn main() {
|
||||||
is_verbose: '-verbose' in vet_options || '-v' in vet_options
|
is_verbose: '-verbose' in vet_options || '-v' in vet_options
|
||||||
show_warnings: '-hide-warnings' !in vet_options && '-w' !in vet_options
|
show_warnings: '-hide-warnings' !in vet_options && '-w' !in vet_options
|
||||||
use_color: '-color' in vet_options || (term_colors && '-nocolor' !in vet_options)
|
use_color: '-color' in vet_options || (term_colors && '-nocolor' !in vet_options)
|
||||||
|
doc_private_fns_too: '-p' in vet_options
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mut paths := cmdline.only_non_options(vet_options)
|
mut paths := cmdline.only_non_options(vet_options)
|
||||||
|
@ -110,92 +112,100 @@ fn (mut vt Vet) vet_file(path string) {
|
||||||
|
|
||||||
// vet_line vets the contents of `line` from `vet.file`.
|
// vet_line vets the contents of `line` from `vet.file`.
|
||||||
fn (mut vt Vet) vet_line(lines []string, line string, lnumber int) {
|
fn (mut vt Vet) vet_line(lines []string, line string, lnumber int) {
|
||||||
// Vet public functions
|
vt.vet_fn_documentation(lines, line, lnumber)
|
||||||
if line.starts_with('pub fn') || (line.starts_with('fn ') && !(line.starts_with('fn C.')
|
}
|
||||||
|| line.starts_with('fn main'))) {
|
|
||||||
// Scan function declarations for missing documentation
|
// vet_fn_documentation ensures that functions are documented
|
||||||
is_pub_fn := line.starts_with('pub fn')
|
fn (mut vt Vet) vet_fn_documentation(lines []string, line string, lnumber int) {
|
||||||
if lnumber > 0 {
|
if line.starts_with('fn C.') {
|
||||||
collect_tags := fn (line string) []string {
|
return
|
||||||
mut cleaned := line.all_before('/')
|
}
|
||||||
cleaned = cleaned.replace_each(['[', '', ']', '', ' ', ''])
|
is_pub_fn := line.starts_with('pub fn ')
|
||||||
return cleaned.split(',')
|
is_fn := is_pub_fn || line.starts_with('fn ')
|
||||||
}
|
if !is_fn {
|
||||||
ident_fn_name := fn (line string) string {
|
return
|
||||||
mut fn_idx := line.index(' fn ') or { return '' }
|
}
|
||||||
if line.len < fn_idx + 5 {
|
if line.starts_with('fn main') {
|
||||||
return ''
|
return
|
||||||
}
|
}
|
||||||
mut tokens := line[fn_idx + 4..].split(' ')
|
if !(is_pub_fn || vt.opt.doc_private_fns_too) {
|
||||||
// Skip struct identifier
|
return
|
||||||
if tokens.first().starts_with('(') {
|
}
|
||||||
fn_idx = line.index(')') or { return '' }
|
// Scan function declarations for missing documentation
|
||||||
tokens = line[fn_idx..].split(' ')
|
if lnumber > 0 {
|
||||||
if tokens.len > 1 {
|
collect_tags := fn (line string) []string {
|
||||||
tokens = [tokens[1]]
|
mut cleaned := line.all_before('/')
|
||||||
}
|
cleaned = cleaned.replace_each(['[', '', ']', '', ' ', ''])
|
||||||
}
|
return cleaned.split(',')
|
||||||
if tokens.len > 0 {
|
}
|
||||||
return tokens[0].all_before('(')
|
ident_fn_name := fn (line string) string {
|
||||||
}
|
mut fn_idx := line.index(' fn ') or { return '' }
|
||||||
|
if line.len < fn_idx + 5 {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
mut line_above := lines[lnumber - 1]
|
mut tokens := line[fn_idx + 4..].split(' ')
|
||||||
mut tags := []string{}
|
// Skip struct identifier
|
||||||
if !line_above.starts_with('//') {
|
if tokens.first().starts_with('(') {
|
||||||
mut grab := true
|
fn_idx = line.index(')') or { return '' }
|
||||||
for j := lnumber - 1; j >= 0; j-- {
|
tokens = line[fn_idx..].split(' ')
|
||||||
prev_line := lines[j]
|
if tokens.len > 1 {
|
||||||
if prev_line.contains('}') { // We've looked back to the above scope, stop here
|
tokens = [tokens[1]]
|
||||||
break
|
|
||||||
} else if prev_line.starts_with('[') {
|
|
||||||
tags << collect_tags(prev_line)
|
|
||||||
continue
|
|
||||||
} else if prev_line.starts_with('//') { // Single-line comment
|
|
||||||
grab = false
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if grab {
|
}
|
||||||
|
if tokens.len > 0 {
|
||||||
|
return tokens[0].all_before('(')
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
mut line_above := lines[lnumber - 1]
|
||||||
|
mut tags := []string{}
|
||||||
|
if !line_above.starts_with('//') {
|
||||||
|
mut grab := true
|
||||||
|
for j := lnumber - 1; j >= 0; j-- {
|
||||||
|
prev_line := lines[j]
|
||||||
|
if prev_line.contains('}') { // We've looked back to the above scope, stop here
|
||||||
|
break
|
||||||
|
} else if prev_line.starts_with('[') {
|
||||||
|
tags << collect_tags(prev_line)
|
||||||
|
continue
|
||||||
|
} else if prev_line.starts_with('//') { // Single-line comment
|
||||||
|
grab = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if grab {
|
||||||
|
clean_line := line.all_before_last('{').trim(' ')
|
||||||
|
vt.warn('Function documentation seems to be missing for "$clean_line".',
|
||||||
|
lnumber, .doc)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fn_name := ident_fn_name(line)
|
||||||
|
mut grab := true
|
||||||
|
for j := lnumber - 1; j >= 0; j-- {
|
||||||
|
prev_line := lines[j]
|
||||||
|
if prev_line.contains('}') { // We've looked back to the above scope, stop here
|
||||||
|
break
|
||||||
|
} else if prev_line.starts_with('// $fn_name ') {
|
||||||
|
grab = false
|
||||||
|
break
|
||||||
|
} else if prev_line.starts_with('// $fn_name') {
|
||||||
|
grab = false
|
||||||
clean_line := line.all_before_last('{').trim(' ')
|
clean_line := line.all_before_last('{').trim(' ')
|
||||||
if is_pub_fn {
|
vt.warn('The documentation for "$clean_line" seems incomplete.', lnumber,
|
||||||
vt.warn('Function documentation seems to be missing for "$clean_line".',
|
.doc)
|
||||||
lnumber, .doc)
|
break
|
||||||
}
|
} else if prev_line.starts_with('[') {
|
||||||
}
|
tags << collect_tags(prev_line)
|
||||||
} else {
|
continue
|
||||||
fn_name := ident_fn_name(line)
|
} else if prev_line.starts_with('//') { // Single-line comment
|
||||||
mut grab := true
|
continue
|
||||||
for j := lnumber - 1; j >= 0; j-- {
|
|
||||||
prev_line := lines[j]
|
|
||||||
if prev_line.contains('}') { // We've looked back to the above scope, stop here
|
|
||||||
break
|
|
||||||
} else if prev_line.starts_with('// $fn_name ') {
|
|
||||||
grab = false
|
|
||||||
break
|
|
||||||
} else if prev_line.starts_with('// $fn_name') {
|
|
||||||
grab = false
|
|
||||||
if is_pub_fn {
|
|
||||||
clean_line := line.all_before_last('{').trim(' ')
|
|
||||||
vt.warn('The documentation for "$clean_line" seems incomplete.',
|
|
||||||
lnumber, .doc)
|
|
||||||
}
|
|
||||||
break
|
|
||||||
} else if prev_line.starts_with('[') {
|
|
||||||
tags << collect_tags(prev_line)
|
|
||||||
continue
|
|
||||||
} else if prev_line.starts_with('//') { // Single-line comment
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if grab {
|
|
||||||
clean_line := line.all_before_last('{').trim(' ')
|
|
||||||
if is_pub_fn {
|
|
||||||
vt.warn('A function name is missing from the documentation of "$clean_line".',
|
|
||||||
lnumber, .doc)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if grab {
|
||||||
|
clean_line := line.all_before_last('{').trim(' ')
|
||||||
|
vt.warn('A function name is missing from the documentation of "$clean_line".',
|
||||||
|
lnumber, .doc)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,5 +14,8 @@ Options:
|
||||||
-v, -verbose
|
-v, -verbose
|
||||||
Enable verbose logging.
|
Enable verbose logging.
|
||||||
|
|
||||||
|
-p
|
||||||
|
Report private functions with missing documentation too (by default, only the `pub fn` functions will be reported).
|
||||||
|
|
||||||
-force
|
-force
|
||||||
(NB: vet development only!) Do not skip the vet regression tests.
|
(NB: vet development only!) Do not skip the vet regression tests.
|
||||||
|
|
Loading…
Reference in New Issue