diff --git a/README.md b/README.md index 3ae5177..0567c24 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Flags: -tab tab width for column calculations (default 2) -w overwrite modified files -wrap column to wrap at (default 100) - -wrapfndoc column to wrap function doc strings at (default 80, ignores multiline comments) + -wrapdoc column at which to wrap doc strings for functions, variables, constants, and types. ignores multiline comments denoted by /* ``` ## Examples diff --git a/internal/parser/parser.go b/internal/parser/parser.go index 19934e4..0abc863 100644 --- a/internal/parser/parser.go +++ b/internal/parser/parser.go @@ -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}) } } @@ -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() {} diff --git a/internal/render/render.go b/internal/render/render.go index fdcabc2..e481093 100644 --- a/internal/render/render.go +++ b/internal/render/render.go @@ -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 @@ -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())) } @@ -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 { @@ -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'}) } } @@ -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)) } diff --git a/main.go b/main.go index f4edd87..5aa9b1f 100644 --- a/main.go +++ b/main.go @@ -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") @@ -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 diff --git a/main_test.go b/main_test.go index 0f95303..c08dd33 100644 --- a/main_test.go +++ b/main_test.go @@ -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) diff --git a/testdata/comments.in.go b/testdata/comments.in.go index 37f7210..537b179 100644 --- a/testdata/comments.in.go +++ b/testdata/comments.in.go @@ -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 @@ -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) diff --git a/testdata/comments.out.go b/testdata/comments.out.go index 31caecf..7243c6d 100644 --- a/testdata/comments.out.go +++ b/testdata/comments.out.go @@ -4,6 +4,9 @@ package test // 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 @@ -29,3 +32,110 @@ multiline comments are unchanged multiline comments are unchanged multiline co multiline comments are unchanged multiline comments are unchanged multiline comments are unchanged */ func multilineComment() 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 +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 +*/ +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)