85 lines
1.8 KiB
Go
85 lines
1.8 KiB
Go
|
package godox
|
||
|
|
||
|
import (
|
||
|
"bufio"
|
||
|
"bytes"
|
||
|
"fmt"
|
||
|
"go/ast"
|
||
|
"go/token"
|
||
|
"path/filepath"
|
||
|
"strings"
|
||
|
)
|
||
|
|
||
|
var (
|
||
|
defaultKeywords = []string{"TODO", "BUG", "FIXME"}
|
||
|
)
|
||
|
|
||
|
// Message contains a message and position
|
||
|
type Message struct {
|
||
|
Pos token.Position
|
||
|
Message string
|
||
|
}
|
||
|
|
||
|
func getMessages(c *ast.Comment, fset *token.FileSet, keywords []string) []Message {
|
||
|
commentText := c.Text
|
||
|
switch commentText[1] {
|
||
|
case '/':
|
||
|
commentText = commentText[2:]
|
||
|
if len(commentText) > 0 && commentText[0] == ' ' {
|
||
|
commentText = commentText[1:]
|
||
|
}
|
||
|
case '*':
|
||
|
commentText = commentText[2 : len(commentText)-2]
|
||
|
}
|
||
|
|
||
|
b := bufio.NewReader(bytes.NewBufferString(commentText))
|
||
|
var comments []Message
|
||
|
|
||
|
for lineNum := 0; ; lineNum++ {
|
||
|
line, _, err := b.ReadLine()
|
||
|
if err != nil {
|
||
|
break
|
||
|
}
|
||
|
sComment := bytes.TrimSpace(line)
|
||
|
if len(sComment) < 4 {
|
||
|
continue
|
||
|
}
|
||
|
for _, kw := range keywords {
|
||
|
if bytes.EqualFold([]byte(kw), sComment[0:len(kw)]) {
|
||
|
pos := fset.Position(c.Pos())
|
||
|
// trim the comment
|
||
|
if len(sComment) > 40 {
|
||
|
sComment = []byte(fmt.Sprintf("%.40s...", sComment))
|
||
|
}
|
||
|
comments = append(comments, Message{
|
||
|
Pos: pos,
|
||
|
Message: fmt.Sprintf(
|
||
|
"%s:%d: Line contains %s: \"%s\"",
|
||
|
filepath.Join(pos.Filename),
|
||
|
pos.Line+lineNum,
|
||
|
strings.Join(keywords, "/"),
|
||
|
sComment,
|
||
|
),
|
||
|
})
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return comments
|
||
|
}
|
||
|
|
||
|
// Run runs the godox linter on given file.
|
||
|
// Godox searches for comments starting with given keywords and reports them.
|
||
|
func Run(file *ast.File, fset *token.FileSet, keywords ...string) []Message {
|
||
|
if len(keywords) == 0 {
|
||
|
keywords = defaultKeywords
|
||
|
}
|
||
|
var messages []Message
|
||
|
for _, c := range file.Comments {
|
||
|
for _, ci := range c.List {
|
||
|
messages = append(messages, getMessages(ci, fset, keywords)...)
|
||
|
}
|
||
|
}
|
||
|
return messages
|
||
|
}
|