v / cmd / tools / find_doc_comments_with_no_dots.v
77 lines · 73 sloc · 1.68 KB · 35af6a8d12b70bf59e1df5d4fb517d04a6892b49
Raw
1import os
2
3fn main() {
4 args := arguments()
5 if args.len < 2 {
6 println('Usage: v run doc_comment_checker.v <file1.v> <file2.v>...')
7 return
8 }
9 mut fpaths := []string{}
10 for filepath in args[1..] {
11 if os.is_file(filepath) {
12 fpaths << filepath
13 }
14 if os.is_dir(filepath) {
15 fpaths << os.walk_ext(filepath, '.v').filter(!it.ends_with('_test.v')
16 && !it.ends_with('_test.c.v'))
17 }
18 }
19 fpaths.sort()
20 mut ctx := Context{}
21 for filepath in fpaths {
22 ctx.process_fpath(filepath) or {
23 eprintln('error with ${filepath}: ${err}')
24 continue
25 }
26 }
27 println('> Processed ${fpaths.len} .v files, found errors: ${ctx.errors} , in ${ctx.pub_symbols} `pub` declarations, and ${ctx.pub_comment_lines} pub comment lines.')
28 if ctx.errors > 0 {
29 exit(1)
30 }
31}
32
33struct Context {
34mut:
35 errors int
36 pub_symbols int
37 pub_comment_lines int
38 comments int
39}
40
41fn (mut ctx Context) process_fpath(filepath string) ! {
42 lines := os.read_lines(filepath)!
43 mut prev := 0
44 for iline, line in lines {
45 if line.starts_with('pub ') {
46 ctx.pub_symbols++
47 mut comments := []CommentLine{}
48 mut i := 0
49 for i = int_max(0, iline - 1); i >= prev; i-- {
50 pline := lines[i]
51 if pline.starts_with('// ') {
52 comments << CommentLine{pline, i + 1}
53 } else {
54 prev = iline + 1
55 break
56 }
57 }
58 if comments.len > 0 {
59 cline := comments.last()
60 fword := cline.comment.all_after('// ').all_before(' ')
61 if !line.contains(fword) {
62 continue
63 }
64 ctx.pub_comment_lines += comments.len
65 if !cline.comment.ends_with('.') {
66 println('${filepath}:${cline.line}: ${cline.comment}')
67 ctx.errors++
68 }
69 }
70 }
71 }
72}
73
74struct CommentLine {
75 comment string
76 line int
77}
78