Unified · Split
| @@ -73,7 +73,7 @@ func doDir(name string) { · 72 unmodified lines | ||
| 73 | 73 | return false |
| 74 | 74 | } |
| 75 | 75 | fs := token.NewFileSet() |
| 76 | − pkgs, err := parser.ParseDir(fs, name, notests, parser.Mode(0)) | |
| 76 | + pkgs, err := parser.ParseDir(fs, name, notests, parser.ParseComments|parser.Mode(0)) | |
| 77 | 77 | if err != nil { |
| 78 | 78 | errorf("%s", err) |
| 79 | 79 | return |
| @@ -84,20 +84,23 @@ func doDir(name string) { · 4 unmodified lines | ||
| 84 | 84 | } |
| 85 | 85 | |
| 86 | 86 | type Package struct { |
| 87 | − p *ast.Package | |
| 88 | − fs *token.FileSet | |
| 89 | − decl map[string]ast.Node | |
| 90 | − used map[string]bool | |
| 87 | + p *ast.Package | |
| 88 | + fs *token.FileSet | |
| 89 | + decl map[string]ast.Node | |
| 90 | + missingcomments map[string]ast.Node | |
| 91 | + used map[string]bool | |
| 91 | 92 | } |
| 92 | 93 | |
| 93 | 94 | func doPackage(fs *token.FileSet, pkg *ast.Package) { |
| 94 | 95 | p := &Package{ |
| 95 | − p: pkg, | |
| 96 | − fs: fs, | |
| 97 | − decl: make(map[string]ast.Node), | |
| 98 | − used: make(map[string]bool), | |
| 96 | + p: pkg, | |
| 97 | + fs: fs, | |
| 98 | + decl: make(map[string]ast.Node), | |
| 99 | + missingcomments: make(map[string]ast.Node), | |
| 100 | + used: make(map[string]bool), | |
| 99 | 101 | } |
| 100 | 102 | for _, file := range pkg.Files { |
| 103 | + cmap := ast.NewCommentMap(fs, file, file.Comments) | |
| 101 | 104 | for _, decl := range file.Decls { |
| 102 | 105 | switch n := decl.(type) { |
| 103 | 106 | case *ast.GenDecl: |
| @@ -115,6 +118,20 @@ func doPackage(fs *token.FileSet, pkg *ast.Package) { · 11 unmodified lines | ||
| 115 | 118 | } |
| 116 | 119 | } |
| 117 | 120 | case *ast.FuncDecl: |
| 121 | + // Skip if function is 'main' | |
| 122 | + if n.Name.Name == "main" { | |
| 123 | + continue | |
| 124 | + } | |
| 125 | + // Skip non-exported functions | |
| 126 | + if !ast.IsExported(n.Name.Name) { | |
| 127 | + continue | |
| 128 | + } | |
| 129 | + // Check if comments are missing from exported functions | |
| 130 | + _, ok := cmap[n] | |
| 131 | + if ok == false { | |
| 132 | + p.missingcomments[n.Name.Name] = n | |
| 133 | + } | |
| 134 | + | |
| 118 | 135 | // function declarations |
| 119 | 136 | // TODO(remy): do methods |
| 120 | 137 | if n.Recv == nil { |
| @@ -140,6 +157,7 @@ func doPackage(fs *token.FileSet, pkg *ast.Package) { · 19 unmodified lines | ||
| 140 | 157 | // walk file looking for used nodes. |
| 141 | 158 | ast.Walk(p, file) |
| 142 | 159 | } |
| 160 | + | |
| 143 | 161 | // reports. |
| 144 | 162 | reports := Reports(nil) |
| 145 | 163 | for name, node := range p.decl { |
| @@ -151,6 +169,10 @@ func doPackage(fs *token.FileSet, pkg *ast.Package) { · 5 unmodified lines | ||
| 151 | 169 | for _, report := range reports { |
| 152 | 170 | errorf("%s: %s is unused", fs.Position(report.pos), report.name) |
| 153 | 171 | } |
| 172 | + | |
| 173 | + for name, node := range p.missingcomments { | |
| 174 | + errorf("%s: comment is missing for 'func %s'", fs.Position(node.Pos()), name) | |
| 175 | + } | |
| 154 | 176 | } |
| 155 | 177 | |
| 156 | 178 | type Report struct { |