Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tools.vet: reduce nesting in vet_fn_documentation, skip vetting empty lines #21465

Merged
merged 4 commits into from
May 8, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
155 changes: 79 additions & 76 deletions cmd/tools/vvet/vvet.v
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@ fn (mut vt Vet) vet_file(path string) {

// vet_line vets the contents of `line` from `vet.file`.
fn (mut vt Vet) vet_line(lines []string, line string, lnumber int) {
if line == '' {
return
}
vt.vet_fn_documentation(lines, line, lnumber)
vt.vet_space_usage(line, lnumber)
}
Expand All @@ -143,6 +146,33 @@ fn (mut vt Vet) vet_space_usage(line string, lnumber int) {
}
}

fn collect_tags(line string) []string {
mut cleaned := line.all_before('/')
cleaned = cleaned.replace_each(clean_seq)
return cleaned.split(',')
}

fn ident_fn_name(line string) string {
mut fn_idx := line.index(' fn ') or { return '' }
if line.len < fn_idx + 5 {
return ''
}
mut tokens := line[fn_idx + 4..].split(' ')
// Skip struct identifier
if tokens.first().starts_with('(') {
fn_idx = line.index(')') or { return '' }
tokens = line[fn_idx..].split(' ')
if tokens.len > 1 {
tokens = [tokens[1]]
}
}
if tokens.len > 0 {
function_name_with_generic_parameters := tokens[0].all_before('(')
return function_name_with_generic_parameters.all_before('[')
}
return ''
}

// vet_fn_documentation ensures that functions are documented
fn (mut vt Vet) vet_fn_documentation(lines []string, line string, lnumber int) {
if line.starts_with('fn C.') {
Expand All @@ -160,92 +190,65 @@ fn (mut vt Vet) vet_fn_documentation(lines []string, line string, lnumber int) {
return
}
// Scan function declarations for missing documentation
if lnumber > 0 {
collect_tags := fn (line string) []string {
mut cleaned := line.all_before('/')
cleaned = cleaned.replace_each(clean_seq)
return cleaned.split(',')
}
ident_fn_name := fn (line string) string {
mut fn_idx := line.index(' fn ') or { return '' }
if line.len < fn_idx + 5 {
return ''
mut line_above := lines[lnumber - 1] or { return }
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
}
mut tokens := line[fn_idx + 4..].split(' ')
// Skip struct identifier
if tokens.first().starts_with('(') {
fn_idx = line.index(')') or { return '' }
tokens = line[fn_idx..].split(' ')
if tokens.len > 1 {
tokens = [tokens[1]]
}
}
if tokens.len > 0 {
function_name_with_generic_parameters := tokens[0].all_before('(')
return function_name_with_generic_parameters.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
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-- {
mut prev_prev_line := ''
if j - 1 >= 0 {
prev_prev_line = lines[j - 1]
}
prev_line := lines[j]

if prev_line.starts_with('//') {
if prev_line.starts_with('// ${fn_name} ') {
grab = false
break
} else if prev_line.starts_with('[') {
tags << collect_tags(prev_line)
continue
} else if prev_line.starts_with('//') { // Single-line comment
} else if prev_line.starts_with('// ${fn_name}')
&& !prev_prev_line.starts_with('//') {
grab = false
clean_line := line.all_before_last('{').trim(' ')
vt.warn('The documentation for "${clean_line}" seems incomplete.',
lnumber, .doc)
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-- {
mut prev_prev_line := ''
if j - 1 >= 0 {
prev_prev_line = lines[j - 1]
}
prev_line := lines[j]

if prev_line.starts_with('//') {
if prev_line.starts_with('// ${fn_name} ') {
grab = false
break
} else if prev_line.starts_with('// ${fn_name}')
&& !prev_prev_line.starts_with('//') {
grab = false
clean_line := line.all_before_last('{').trim(' ')
vt.warn('The documentation for "${clean_line}" seems incomplete.',
lnumber, .doc)
break
}

continue
}

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
}
continue
}
if grab {
clean_line := line.all_before_last('{').trim(' ')
vt.warn('A function name is missing from the documentation of "${clean_line}".',
lnumber, .doc)

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
}
}
if grab {
clean_line := line.all_before_last('{').trim(' ')
vt.warn('A function name is missing from the documentation of "${clean_line}".',
lnumber, .doc)
}
}
}

Expand Down