Skip to content

Commit

Permalink
Merge pull request #45 from cockroachdb/doc-str
Browse files Browse the repository at this point in the history
add flag to wrap docstrings for const, var, and type
  • Loading branch information
jayshrivastava authored May 5, 2023
2 parents d513405 + 4067d8f commit 461e866
Show file tree
Hide file tree
Showing 7 changed files with 279 additions and 18 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Flags:
-tab <int> tab width for column calculations (default 2)
-w overwrite modified files
-wrap <int> column to wrap at (default 100)
-wrapfndoc <int> column to wrap function doc strings at (default 80, ignores multiline comments)
-wrapdoc <int> column at which to wrap doc strings for functions, variables, constants, and types. ignores multiline comments denoted by /*
```

## Examples
Expand Down
21 changes: 21 additions & 0 deletions internal/parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,12 @@ func ParseFile(name string, src []byte) (*File, error) {
assocFieldListComments(&cr, f.Type.Results)
}
}
} else if g, ok := d.(*ast.GenDecl); ok && g.Tok == token.CONST {
decls = append(decls, &ConstDecl{*g})
} else if g, ok := d.(*ast.GenDecl); ok && g.Tok == token.VAR {
decls = append(decls, &VarDecl{*g})
} else if g, ok := d.(*ast.GenDecl); ok && g.Tok == token.TYPE {
decls = append(decls, &TypeDecl{*g})
}
}

Expand Down Expand Up @@ -179,5 +185,20 @@ type Decl interface {
decl()
}

type TypeDecl struct {
ast.GenDecl
}

type VarDecl struct {
ast.GenDecl
}

type ConstDecl struct {
ast.GenDecl
}

func (i *ImportDecl) decl() {}
func (f *FuncDecl) decl() {}
func (f *ConstDecl) decl() {}
func (f *VarDecl) decl() {}
func (f *TypeDecl) decl() {}
34 changes: 23 additions & 11 deletions internal/render/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ import (
// sort.Interface to sort imports by path.
type ImportGroup []parser.ImportSpec

func (ig ImportGroup) Len() int { return len(ig) }
func (ig ImportGroup) Len() int { return len(ig) }
func (ig ImportGroup) Less(i, j int) bool { return ig[i].Path() < ig[j].Path() }
func (ig ImportGroup) Swap(i, j int) { ig[i], ig[j] = ig[j], ig[i] }
func (ig ImportGroup) Swap(i, j int) { ig[i], ig[j] = ig[j], ig[i] }

// An ImportBlock is a collectino of ImportGroups.
type ImportBlock []ImportGroup
Expand Down Expand Up @@ -138,7 +138,7 @@ func Func(w io.Writer, f *parser.File, fn *parser.FuncDecl, tabSize, wrapBody, w
results := fn.Type.Results

if fn.Doc != nil {
FuncDocString(w, f, fn, wrapDocString, lastPos)
DocString(w, f, fn.Doc, wrapDocString, lastPos, fn.Type.Pos())
} else {
w.Write(f.Slice(lastPos, fn.Type.Pos()))
}
Expand Down Expand Up @@ -245,13 +245,25 @@ func Func(w io.Writer, f *parser.File, fn *parser.FuncDecl, tabSize, wrapBody, w
w.Write(f.Slice(fn.Type.End(), closing))
}

func FuncDocString(w io.Writer, f *parser.File, fn *parser.FuncDecl, wrapDocString int, lastPos token.Pos) {
w.Write(f.Slice(lastPos, fn.Doc.Pos()))
if strings.Fields(fn.Doc.List[0].Text)[0] != "/*" {
for i, c := range fn.Doc.List {
func GenDecl(w io.Writer, f *parser.File, decl ast.GenDecl, wrapDocString int, lastPos token.Pos) {
if decl.Doc != nil {
DocString(w, f, decl.Doc, wrapDocString, lastPos, decl.TokPos)
w.Write(f.Slice(decl.TokPos, decl.End()))
} else {
w.Write(f.Slice(lastPos, decl.End()))
}
}

// DocString renders a docstring from lastPos to nextPos where lastPos is
// the end of the previous Decl and next pos is the start of the Decl
// corresponding to this doc string.
func DocString(w io.Writer, f *parser.File, doc *ast.CommentGroup, wrapDocString int, lastPos, nextPos token.Pos) {
w.Write(f.Slice(lastPos, doc.Pos()))
if strings.Fields(doc.List[0].Text)[0] != "/*" {
for i, c := range doc.List {
if len(c.Text) <= wrapDocString {
w.Write(f.Slice(c.Pos(), c.End()))
if i < len(fn.Doc.List)-1 {
if i < len(doc.List)-1 {
w.Write([]byte{'\n'})
}
} else {
Expand All @@ -278,7 +290,7 @@ func FuncDocString(w io.Writer, f *parser.File, fn *parser.FuncDecl, wrapDocStri
}
}
w.Write(commentLine.Bytes())
if tokenIdx < len(tokens) || i < len(fn.Doc.List)-1 {
if tokenIdx < len(tokens) || i < len(doc.List)-1 {
w.Write([]byte{'\n'})
}
}
Expand All @@ -287,8 +299,8 @@ func FuncDocString(w io.Writer, f *parser.File, fn *parser.FuncDecl, wrapDocStri

} else {
// Multiline comments are unchanged for now.
w.Write(f.Slice(fn.Doc.Pos(), fn.Doc.End()))
w.Write(f.Slice(doc.Pos(), doc.End()))
}

w.Write(f.Slice(fn.Doc.End(), fn.Type.Pos()))
w.Write(f.Slice(doc.End(), nextPos))
}
23 changes: 21 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ import (
)

var (
wrapfndoc = flag.Int("wrapfndoc", 80, "column to wrap function docstrings at")
// TODO: wrap doc strings for imports and floating comments.
wrapdoc = flag.Int("wrapdoc", 160, "column at which to wrap doc strings for functions, variables, constants, and types. ignores multiline comments denoted by /*")
wrap = flag.Int("wrap", 100, "column to wrap at")
tab = flag.Int("tab", 2, "tab width for column calculations")
overwrite = flag.Bool("w", false, "overwrite modified files")
Expand Down Expand Up @@ -250,10 +251,28 @@ func checkBuf(path string, src []byte) ([]byte, error) {
}
if fn, ok := d.(*parser.FuncDecl); ok {
var curFunc bytes.Buffer
render.Func(&curFunc, file, fn, *tab, *wrap, *wrapfndoc, lastPos)
render.Func(&curFunc, file, fn, *tab, *wrap, *wrapdoc, lastPos)
output.Write(curFunc.Bytes())
lastPos = fn.BodyEnd()
}
if cnst, ok := d.(*parser.ConstDecl); ok {
var declBuf bytes.Buffer
render.GenDecl(&declBuf, file, cnst.GenDecl, *wrapdoc, lastPos)
output.Write(declBuf.Bytes())
lastPos = cnst.End()
}
if vr, ok := d.(*parser.VarDecl); ok {
var declBuf bytes.Buffer
render.GenDecl(&declBuf, file, vr.GenDecl, *wrapdoc, lastPos)
output.Write(declBuf.Bytes())
lastPos = vr.End()
}
if typ, ok := d.(*parser.TypeDecl); ok {
var declBuf bytes.Buffer
render.GenDecl(&declBuf, file, typ.GenDecl, *wrapdoc, lastPos)
output.Write(declBuf.Bytes())
lastPos = typ.End()
}
}
output.Write(src[file.Offset(lastPos):])
return output.Bytes(), nil
Expand Down
1 change: 1 addition & 0 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ func TestCheckPath(t *testing.T) {
*printDiff = false
*tab = 8
*groupImports = false
*wrapdoc = 80
files, err := filepath.Glob("testdata/*.in.go")
if err != nil {
t.Fatal(err)
Expand Down
106 changes: 102 additions & 4 deletions testdata/comments.in.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package test

// docstring should wrap to 80 chars test1 test2 test3 test4 test5 test6 test7 test8 test9 test1 test2
// test3 test4 test5 test6 test7 test3 test4 test5 test6 test7 test8 test9 test1 test2 test3 test4 test5
//
// test3 test4 test5 test6 test7 test3 test4 test5 test6 test7 test8 test9 test1 test2 test3 test4 test5
func docstring() string

// docstring with a word over 80 chars cannot be wrapped
Expand All @@ -21,10 +23,106 @@ func docstringWith80CharComments() string
func docstringWithBullets() string

/*
multiline comments are unchanged multiline comments are unchanged multiline comments are unchanged
multiline comments are unchanged multiline comments are unchanged multiline comments are unchanged
multiline comments are unchanged multiline comments are unchanged multiline comments are unchanged
*/
func multilineComment() string

multiline comments are unchanged multiline comments are unchanged multiline comments are unchanged
multiline comments are unchanged multiline comments are unchanged multiline comments are unchanged
multiline comments are unchanged multiline comments are unchanged multiline comments are unchanged
// docstring should wrap to 80 chars test1 test2 test3 test4 test5 test6 test7 test8 test9 test1 test2
// test3 test4 test5 test6 test7 test3 test4 test5 test6 test7 test8 test9 test1 test2 test3 test4 test5
type docstring string

// docstring with a word over 80 chars cannot be wrapped
// verylongwordverylongwordverylongwordverylongwordverylongwordverylongwordverylongwordverylongwordverylongwordverylongwordverylongwordverylongword
// test1 test2 test3 test4 test5 test6 test7 test8 test9 test1 test2 verylongwordverylongwordverylongwordverylongwordverylongwordverylongwordverylongwordverylongwordverylongwordverylongwordverylongwordverylongword
// test1 test2
type longWords struct {
s string
}

// test1 test2 test3 test4 test5 test6 test7 test8 test9 test1 test2 test3 aaaaa
// test1 test2 test3 test4 test5 test6 test7 test8 test9 test1 test2 test3 bbbbb
// test1 test2 test3 test4 test5 test6 test7 test8 test9 test1 test2 test3 ccccc
type eightyCharLines struct {
s string
}

// This is an explanation
// - foo
// - bar
type bullets struct {
s string
}

/*
multiline comments are unchanged multiline comments are unchanged multiline comments are unchanged
multiline comments are unchanged multiline comments are unchanged multiline comments are unchanged
multiline comments are unchanged multiline comments are unchanged multiline comments are unchanged
*/
func multilineComment() string
type multiline struct {
s string
}

// docstring should wrap to 80 chars test1 test2 test3 test4 test5 test6 test7 test8 test9 test1 test2
// test3 test4 test5 test6 test7 test3 test4 test5 test6 test7 test8 test9 test1 test2 test3 test4 test5
const docstring = ""

// docstring with a word over 80 chars cannot be wrapped
// verylongwordverylongwordverylongwordverylongwordverylongwordverylongwordverylongwordverylongwordverylongwordverylongwordverylongwordverylongword
// test1 test2 test3 test4 test5 test6 test7 test8 test9 test1 test2 verylongwordverylongwordverylongwordverylongwordverylongwordverylongwordverylongwordverylongwordverylongwordverylongwordverylongwordverylongword
// test1 test2
const longWords = "asdf"

// test1 test2 test3 test4 test5 test6 test7 test8 test9 test1 test2 test3 aaaaa
// test1 test2 test3 test4 test5 test6 test7 test8 test9 test1 test2 test3 bbbbb
// test1 test2 test3 test4 test5 test6 test7 test8 test9 test1 test2 test3 ccccc
const eightyCharLines = 80

// This is an explanation
// - foo
// - bar
const bullets = `foo
bar
baz
`

/*
multiline comments are unchanged multiline comments are unchanged multiline comments are unchanged
multiline comments are unchanged multiline comments are unchanged multiline comments are unchanged
multiline comments are unchanged multiline comments are unchanged multiline comments are unchanged
*/
const multiline = `foo
bar
baz
`

// docstring should wrap to 80 chars test1 test2 test3 test4 test5 test6 test7 test8 test9 test1 test2
// test3 test4 test5 test6 test7 test3 test4 test5 test6 test7 test8 test9 test1 test2 test3 test4 test5
var docstring = struct{ string }{}

// docstring with a word over 80 chars cannot be wrapped
// verylongwordverylongwordverylongwordverylongwordverylongwordverylongwordverylongwordverylongwordverylongwordverylongwordverylongwordverylongword
// test1 test2 test3 test4 test5 test6 test7 test8 test9 test1 test2 verylongwordverylongwordverylongwordverylongwordverylongwordverylongwordverylongwordverylongwordverylongwordverylongwordverylongwordverylongword
// test1 test2
var longWords = [10]int{}

// test1 test2 test3 test4 test5 test6 test7 test8 test9 test1 test2 test3 aaaaa
// test1 test2 test3 test4 test5 test6 test7 test8 test9 test1 test2 test3 bbbbb
// test1 test2 test3 test4 test5 test6 test7 test8 test9 test1 test2 test3 ccccc
var eightyCharLines = 80

// This is an explanation
// - foo
// - bar
var bullets = `foo
bar
baz
`

/*
multiline comments are unchanged multiline comments are unchanged multiline comments are unchanged
multiline comments are unchanged multiline comments are unchanged multiline comments are unchanged
multiline comments are unchanged multiline comments are unchanged multiline comments are unchanged
*/
var multiline = make(map[string]int)
Loading

0 comments on commit 461e866

Please sign in to comment.