Skip to content

Commit

Permalink
fix(doculint): Improve the function comment check. (#95)
Browse files Browse the repository at this point in the history
This now will require a space after the function name.
  • Loading branch information
jkinkead authored Oct 21, 2022
1 parent 5484bd9 commit ec44c58
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 2 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ This makes lintroller compatible with `go vet`, the recommended way to run lintr

- `copyright` - Checks that files start with a header that matches a regular expression.
- `doculint` - Checks that packages and various top-level items in the package have well-formed comments.
- See [the golang guide for writing comments](https://go.dev/doc/comment).
- `header` - Checks that source code files have structured headers.
- `todo` - Checks that TODO comments:
- Start the comment line.
Expand Down
5 changes: 3 additions & 2 deletions internal/doculint/doculint.go
Original file line number Diff line number Diff line change
Expand Up @@ -387,8 +387,9 @@ func validateFuncDecl(reporter nolint.Reporter, expr *ast.FuncDecl) {
return
}

if !strings.HasPrefix(strings.TrimSpace(expr.Doc.Text()), expr.Name.Name) {
reporter.Reportf(expr.Pos(), "comment for function \"%s\" should begin with \"%s\"", expr.Name.Name, expr.Name.Name)
// Enforce a space after the function name.
if !strings.HasPrefix(strings.TrimSpace(expr.Doc.Text()), expr.Name.Name+" ") {
reporter.Reportf(expr.Pos(), "comment for function \"%s\" should be a sentence that starts with \"%s \"", expr.Name.Name, expr.Name.Name)
}
}

Expand Down
81 changes: 81 additions & 0 deletions internal/doculint/doculint_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Copyright 2022 Outreach Corporation. All Rights Reserved.

package doculint

import (
"go/ast"
"go/token"
"testing"

"gotest.tools/v3/assert"
)

type MockReporter struct {
lastFormat string
}

func (r *MockReporter) Reportf(pos token.Pos, format string, args ...interface{}) {
r.lastFormat = format
}

func TestValidateFunDecl(t *testing.T) {
tt := []struct {
name string
funcName string
funcDoc string
// The expected format string for the Reportf function argument.
expectedFormat string
}{
{
name: "Ignores init function",
funcName: "init",
funcDoc: "",
expectedFormat: "",
},
{
name: "Produces an error when no doc exists",
funcName: "foo",
funcDoc: "",
expectedFormat: "function \"%s\" has no comment associated with it",
},
{
name: "Produces an error when the doc doesn't start with the function name",
funcName: "foo",
funcDoc: "This function is foo.",
expectedFormat: "comment for function \"%s\" should be a sentence that starts with \"%s \"",
},
{
name: "Produces an error when the doc is malformed",
funcName: "foo",
funcDoc: "foo: Does a foo thing.",
expectedFormat: "comment for function \"%s\" should be a sentence that starts with \"%s \"",
},
{
name: "Produces an error when the doc has a bad function name",
funcName: "foo",
funcDoc: "fooBar: Does a foobar thing.",
expectedFormat: "comment for function \"%s\" should be a sentence that starts with \"%s \"",
},
{
name: "Allows good comments",
funcName: "foo",
funcDoc: "foo sure is a function.",
expectedFormat: "",
},
}

for _, test := range tt {
t.Run(test.name, func(t *testing.T) {
reporter := &MockReporter{}
funcDecl := &ast.FuncDecl{
Name: &ast.Ident{Name: test.funcName},
Type: &ast.FuncType{},
}
if test.funcDoc != "" {
funcDecl.Doc = &ast.CommentGroup{List: []*ast.Comment{{Text: test.funcDoc}}}
}
validateFuncDecl(reporter, funcDecl)
assert.Equal(t, reporter.lastFormat, test.expectedFormat)
})
}
}

0 comments on commit ec44c58

Please sign in to comment.