From 6e26bddc6b297f310ce34ebddeb95c9814332f6b Mon Sep 17 00:00:00 2001 From: Mario Toffia Date: Wed, 21 Oct 2020 23:53:18 +0200 Subject: [PATCH] Exported / NonExported support. Breaking changes! New default is to *only* include Exported symbols. Added option --nonexported to render private symbols. --- asciidoc/defaults.go | 52 +-- asciidoc/producer.go | 10 + asciidoc/renderer.go | 1 + asciidoc/template_test.go | 38 ++ asciidoc/templatecontext.go | 13 + docs.adoc | 736 +++++------------------------------- goparser/gomethod.go | 1 + goparser/internal_parser.go | 78 ++-- goparser/types.go | 32 +- main.go | 5 + main_test.go | 6 + 11 files changed, 266 insertions(+), 706 deletions(-) diff --git a/asciidoc/defaults.go b/asciidoc/defaults.go index 9440904..0cccdf5 100644 --- a/asciidoc/defaults.go +++ b/asciidoc/defaults.go @@ -29,7 +29,7 @@ var templateImports = `=== Imports var templateFunctions = `== Functions {{range .File.StructMethods}} -{{- if notreceiver $ .}}{{render $ .}}{{end}} +{{- if notreceiver $ .}}{{if or .Exported $.Config.Private }}{{render $ .}}{{end}}{{end}} {{end}} ` @@ -47,23 +47,23 @@ var templateInterface = `=== {{ .Interface.Name }} [source, go] ---- {{.Interface.Decl}} { -{{- range .Interface.Methods}} - {{tabifylast .Decl}} +{{- range .Interface.Methods}}{{if or .Exported $.Config.Private }} + {{tabifylast .Decl}}{{end}} {{- end}} } ---- {{.Interface.Doc}} -{{range .Interface.Methods}} +{{range .Interface.Methods}}{{if or .Exported $.Config.Private }} ==== {{.Decl}} {{.Doc}} -{{end}} +{{end}}{{end}} ` var templateInterfaces = `== Interfaces -{{range .File.Interfaces}} -{{- render $ .}} +{{range .File.Interfaces}}{{if or .Exported $.Config.Private }} +{{- render $ .}}{{end}} {{end}} ` @@ -71,31 +71,31 @@ var templateStruct = `=== {{.Struct.Name}} [source, go] ---- {{.Struct.Decl}} { -{{- range .Struct.Fields}} - {{if .Nested}}{{.Nested.Name}}{{"\t"}}struct{{else}}{{tabify .Decl}}{{end}} +{{- range .Struct.Fields}}{{if or .Exported $.Config.Private }} + {{if .Nested}}{{.Nested.Name}}{{"\t"}}struct{{else}}{{tabify .Decl}}{{end}}{{end}} {{- end}} } ---- {{.Struct.Doc}} -{{range .Struct.Fields}}{{if not .Nested}} +{{range .Struct.Fields}}{{if not .Nested}}{{if or .Exported $.Config.Private }} ==== {{.Decl}} {{.Doc}} {{- end}} -{{end}} -{{range .Struct.Fields}}{{if .Nested}}{{render $ .Nested}}{{end}}{{end}} +{{end}}{{end}} +{{range .Struct.Fields}}{{if or .Exported $.Config.Private }}{{if .Nested}}{{render $ .Nested}}{{end}}{{end}}{{end}} {{if hasReceivers . .Struct.Name}}{{renderReceivers . .Struct.Name}}{{end}} ` var templateStructs = `== Structs -{{range .File.Structs}} -{{- render $ .}} +{{range .File.Structs}}{{if or .Exported $.Config.Private }} +{{- render $ .}}{{end}} {{end}} ` var templateReceivers = `==== Receivers -{{range .Receiver}} +{{range .Receiver}}{{if or .Exported $.Config.Private }} ===== {{.Name}} [source, go] ---- @@ -103,7 +103,7 @@ var templateReceivers = `==== Receivers ---- {{.Doc}} -{{end}} +{{end}}{{end}} ` var templateCustomTypeDefintion = `=== {{.TypeDefVar.Name}} @@ -119,8 +119,8 @@ var templateCustomTypeDefintion = `=== {{.TypeDefVar.Name}} var templateCustomTypeDefintions = `== Variable Typedefinitions -{{range .File.CustomTypes}} -{{- render $ .}} +{{range .File.CustomTypes}}{{if or .Exported $.Config.Private }} +{{- render $ .}}{{end}} {{end}} ` @@ -133,8 +133,8 @@ var templateVarAssignment = `=== {{.VarAssignment.Name}} ` var templateVarAssignments = `== Variables -{{range .File.VarAssignments}} -{{render $ .}} +{{range .File.VarAssignments}}{{if or .Exported $.Config.Private }} +{{render $ .}}{{end}} {{end}} ` @@ -150,13 +150,13 @@ var templateConstAssignments = `=== Constants [source, go] ---- const ( - {{- range .File.ConstAssignments}} - {{tabify .Decl}} + {{- range .File.ConstAssignments}}{{if or .Exported $.Config.Private }} + {{tabify .Decl}}{{end}} {{- end}} ) ---- -{{range .File.ConstAssignments}} -{{render $ .}} +{{range .File.ConstAssignments}}{{if or .Exported $.Config.Private }} +{{render $ .}}{{end}} {{end}} ` @@ -170,7 +170,7 @@ var templateCustomFuncDefintion = `=== {{.TypeDefFunc.Name}} var templateCustomFuncDefintions = `== Function Definitions -{{range .File.CustomFuncs}} -{{render $ .}} +{{range .File.CustomFuncs}}{{if or .Exported $.Config.Private }} +{{render $ .}}{{end}} {{end}} ` diff --git a/asciidoc/producer.go b/asciidoc/producer.go index d18c68d..79cb9c8 100644 --- a/asciidoc/producer.go +++ b/asciidoc/producer.go @@ -36,6 +36,8 @@ type Producer struct { // overviewpaths is which paths to search for overview ascii doc document. // It defaults to overview.adoc, _design/overview.adoc. overviewpaths []string + // private when set to true all symbols are rendered. + private bool } // NewProducer creates a new instance of a producer. @@ -52,6 +54,14 @@ func (p *Producer) StdOut() *Producer { return p } +// NonExported will set renderer to render all Symobols both +// exported and non exported. By default only exported symbols +// are rendered. +func (p *Producer) NonExported() *Producer { + p.private = true + return p +} + // Writer sets a custom writer where *everything* gets written to. func (p *Producer) Writer(w io.Writer) *Producer { p.writer = w diff --git a/asciidoc/renderer.go b/asciidoc/renderer.go index 48c7242..9245a41 100644 --- a/asciidoc/renderer.go +++ b/asciidoc/renderer.go @@ -36,6 +36,7 @@ func (p *Producer) Generate() { tc := t.NewContextWithConfig(&pkg.GoFile, pkg, &TemplateContextConfig{ IncludeMethodCode: false, PackageOverviewPaths: overviewpaths, + Private: p.private, }) if !indexdone { diff --git a/asciidoc/template_test.go b/asciidoc/template_test.go index be552bf..ff3dd06 100644 --- a/asciidoc/template_test.go +++ b/asciidoc/template_test.go @@ -132,6 +132,44 @@ func TestRenderSingleFunction(t *testing.T) { assert.Equal(t, "=== Bar\n[source, go]\n----\nfunc Bar() int\n----\n\t\t\nBar is a public function that outputs\ncurrent time and return zero.", buf.String()) } +func TestIncludePrivateFunctions(t *testing.T) { + src := ` + package mypkg + + import ( + "fmt" + "time" + ) + + type Kalle struct { + private int + Public string + } + // bar is a private function that outputs + // current time and return zero. + func bar() int { + fmt.Println(time.Now()) + return 0 + } + + // This is always exported. + func ExportedFunc() {}` + + m := dummyModule() + f, err := goparser.ParseInlineFile(m, m.Base+"/mypkg/file.go", src) + assert.NoError(t, err) + + var buf bytes.Buffer + + x := NewTemplateWithOverrides(nil).NewContext(f) //.RenderPrivate() + + //x.RenderFunction(&buf, f.StructMethods[0]) + //x.RenderFunction(&buf, f.StructMethods[1]) + x.RenderStructs(&buf) + + fmt.Println(buf.String()) +} + func TestRenderSingleFunctionWithCode(t *testing.T) { src := ` package mypkg diff --git a/asciidoc/templatecontext.go b/asciidoc/templatecontext.go index 2c3e78f..ad02ad6 100644 --- a/asciidoc/templatecontext.go +++ b/asciidoc/templatecontext.go @@ -82,6 +82,8 @@ type TemplateContextConfig struct { // // |=== PackageOverviewPaths []string + // Private indicates if it shall include private as well. By default only Exported is rendered. + Private bool } // IndexConfig is configuration to use when generating index template @@ -186,6 +188,17 @@ func (t *TemplateContext) Creator() *Template { return t.creator } +// RenderPrivate will enable non exported to be rendered. +func (t *TemplateContext) RenderPrivate() *TemplateContext { + + if nil == t.Config { + panic("Config is nil while trying to configure it!") + } + + t.Config.Private = true + return t +} + // RenderPackage will render the package defintion onto the provided writer. // // Depending on if a package overview asciidoc document is found it will prioritize that before diff --git a/docs.adoc b/docs.adoc index 77368ae..e827db8 100644 --- a/docs.adoc +++ b/docs.adoc @@ -31,110 +31,26 @@ import ( == Structs -=== args -[source, go] ----- -type args struct { - Out string - StdOut bool - Module string - Internal bool - Private bool - Test bool - NoIndex bool - NoToc bool - IndexConfig string - Overrides []string - Paths []string - ListTemplates bool - OutputTemplate string - PackageDoc []string -} ----- - - - -==== Out string - - -==== StdOut bool - - -==== Module string - - -==== Internal bool - - -==== Private bool - - -==== Test bool - - -==== NoIndex bool - - -==== NoToc bool - - -==== IndexConfig string - - -==== Overrides []string - - -==== Paths []string - - -==== ListTemplates bool - - -==== OutputTemplate string - - -==== PackageDoc []string - - - -==== Receivers - -===== Version -[source, go] ----- -func (args) Version() string ----- - - - - == Functions -=== main -[source, go] ----- -func main() ----- - - -=== runner +=== TestOverridePackageTemplate [source, go] ---- -func runner(args args) +func TestOverridePackageTemplate(t *testing.T) ---- -=== TestOverridePackageTemplate +=== TestNonExported [source, go] ---- -func TestOverridePackageTemplate(t *testing.T) +func TestNonExported(t *testing.T) ---- @@ -172,52 +88,20 @@ import ( [source, go] ---- type Producer struct { - parseconfig goparser.ParseConfig - paths []string - outfile string - index bool - indexconfig string - overrides map[string]string - writer io.Writer - toc bool - overviewpaths []string } ---- Producer parses go code and produces asciidoc documentation. -==== parseconfig goparser.ParseConfig -parseconfig is the configuration that it uses to invoke -the parser with. -==== paths []string -paths is files and directories to include. -==== outfile string -outfile is the file to write the generated documentation onto -==== index bool -index determines if it will render index as header for all -rendered documents. If inclusion, this might be a good idea -not to render index. Default is true. -==== indexconfig string -indexconfig is a JSON document to override the default IndexConfig -when rendering the index template -==== overrides map[string]string -overrides is the template overrides that is passed to the template engine. -==== writer io.Writer -writer is a fixed custom writer that *all* gets written to. -==== toc bool -toc enables or disables the table of contents if index is set to true -default is true -==== overviewpaths []string -overviewpaths is which paths to search for overview ascii doc document. -It defaults to overview.adoc, _design/overview.adoc. + ==== Receivers @@ -230,6 +114,16 @@ func (p *Producer) StdOut() *Producer StdOut writes to stdout instead onto filesystem. +===== NonExported +[source, go] +---- +func (p *Producer) NonExported() *Producer +---- + +NonExported will set renderer to render all Symobols both +exported and non exported. By default only exported symbols +are rendered. + ===== Writer [source, go] ---- @@ -369,29 +263,6 @@ func (p *Producer) Generate() Generate will execute the generation of the documentation -===== createWriter -[source, go] ----- -func (p *Producer) createWriter() io.Writer ----- - - - - - -=== writer -[source, go] ----- -type writer struct { - w io.Writer -} ----- - - - -==== w io.Writer - - @@ -461,7 +332,6 @@ If configuration is nil, it will use default configuration. [source, go] ---- type TemplateContext struct { - creator *Template File *goparser.GoFile Package *goparser.GoPackage Module *goparser.GoModule @@ -483,8 +353,6 @@ TemplateContext is a context that may be used to render a GoFile. Depending on the template, different fields are populated in this struct. -==== creator *Template -creator is the template created this context. ==== File *goparser.GoFile File is the complete file. This property is always present. @@ -573,6 +441,14 @@ func (t *TemplateContext) Creator() *Template Creator returns the template created this context. +===== RenderPrivate +[source, go] +---- +func (t *TemplateContext) RenderPrivate() *TemplateContext +---- + +RenderPrivate will enable non exported to be rendered. + ===== RenderPackage [source, go] ---- @@ -723,17 +599,6 @@ RenderIndex will render the complete index page for all GoFiles/GoPackages onto If nil is provided as IndexConfig it will use the default config. -===== resolvePackageOverview -[source, go] ----- -func (t *TemplateContext) resolvePackageOverview() string ----- - -resolvePackageOverview will search the list of inclusion try to resolve any file and return the filepath. - -If it fails, an empty string is returned. This uses the _TemplateConfig.PackageOverviewPaths_ -list to resolve the data. The first hit of the absolute filepath will be returned. - === TemplateContextConfig @@ -742,6 +607,7 @@ list to resolve the data. The first hit of the absolute filepath will be returne type TemplateContextConfig struct { IncludeMethodCode bool PackageOverviewPaths []string + Private bool } ---- @@ -770,6 +636,9 @@ not possible to have two _*.adoc_ inclusions. |=== +==== Private bool +Private indicates if it shall include private as well. By default only Exported is rendered. + @@ -834,8 +703,21 @@ DocType determines the document type, default is book ---- type TemplateType string ---- + TemplateType specifies the template type +==== Receivers + +===== String +[source, go] +---- +func (tt TemplateType) String() string +---- + + + + + === Constants [source, go] @@ -1009,283 +891,21 @@ ReceiversTemplate is a template that renders receivers functions == Variables -=== templateIndex -[source, go] ----- -var templateIndex = `= {{ .Index.Title }} -{{- if .Index.AuthorName}}{{"\n"}}:author_name: {{.Index.AuthorName}}{{"\n"}}:author: {author_name}{{end}} -{{- if .Index.AuthorEmail}}{{"\n"}}:author_email: {{.Index.AuthorEmail}}{{"\n"}}:email: {author_email}{{end}} -:source-highlighter: {{ .Index.Highlighter }} -{{- if .Index.TocTitle}}{{"\n"}}:toc:{{"\n"}}:toc-title: {{ .Index.TocTitle }}{{"\n"}}:toclevels: {{ .Index.TocLevels }}{{end}} -:icons: font -{{- if .Index.ImageDir}}{{"\n"}}:imagesdir: {{.Index.ImageDir}}{{end}} -{{- if .Index.HomePage}}{{"\n"}}:homepage: {{.Index.HomePage}}{{end}} -:kroki-default-format: svg -:doctype: {{.Index.DocType}} - -` ----- - - - -=== templatePackage -[source, go] ----- -var templatePackage = `== {{if .File.FqPackage}}Package {{.File.FqPackage}}{{else}}{{.File.Decl}}{{end}} - -{{if (index .Docs "package-overview")}}include::{{index .Docs "package-overview"}}[leveloffset=+1]{{"\n"}}{{else}}{{ .File.Doc }}{{end}} -` ----- - - - -=== templateImports -[source, go] ----- -var templateImports = `=== Imports -[source, go] ----- -{{ render . }} ----- -{{range .File.Imports}}{{if .Doc }}{{"\n"}}==== Import _{{ .Path }}_{{"\n"}}{{ .Doc }}{{"\n"}}{{end}}{{end}} -` ----- - - - -=== templateFunctions -[source, go] ----- -var templateFunctions = `== Functions - -{{range .File.StructMethods}} -{{- if notreceiver $ .}}{{render $ .}}{{end}} -{{end}} -` ----- -=== templateFunction -[source, go] ----- -var templateFunction = `=== {{ .Function.Name }} -[source, go] ----- -{{ .Function.Decl }} ----- -{{ .Function.Doc }} -{{ if .Config.IncludeMethodCode }}{{"\n"}}[source, go]{{"\n"}}----{{"\n"}}{{ .Function.FullDecl }}{{"\n"}}----{{end}} -` ----- -=== templateInterface -[source, go] ----- -var templateInterface = `=== {{ .Interface.Name }} -[source, go] ----- -{{.Interface.Decl}} { -{{- range .Interface.Methods}} - {{tabifylast .Decl}} -{{- end}} -} ----- - -{{.Interface.Doc}} -{{range .Interface.Methods}} -==== {{.Decl}} -{{.Doc}} -{{end}} -` ----- -=== templateInterfaces -[source, go] ----- -var templateInterfaces = `== Interfaces -{{range .File.Interfaces}} -{{- render $ .}} -{{end}} -` ----- -=== templateStruct -[source, go] ----- -var templateStruct = `=== {{.Struct.Name}} -[source, go] ----- -{{.Struct.Decl}} { -{{- range .Struct.Fields}} - {{if .Nested}}{{.Nested.Name}}{{"\t"}}struct{{else}}{{tabify .Decl}}{{end}} -{{- end}} -} ----- -{{.Struct.Doc}} -{{range .Struct.Fields}}{{if not .Nested}} -==== {{.Decl}} -{{.Doc}} -{{- end}} -{{end}} -{{range .Struct.Fields}}{{if .Nested}}{{render $ .Nested}}{{end}}{{end}} -{{if hasReceivers . .Struct.Name}}{{renderReceivers . .Struct.Name}}{{end}} -` ----- - - - -=== templateStructs -[source, go] ----- -var templateStructs = `== Structs - -{{range .File.Structs}} -{{- render $ .}} -{{end}} -` ----- - - - -=== templateReceivers -[source, go] ----- -var templateReceivers = `==== Receivers -{{range .Receiver}} -===== {{.Name}} -[source, go] ----- -{{ .Decl }} ----- - -{{.Doc}} -{{end}} -` ----- - - - -=== templateCustomTypeDefintion -[source, go] ----- -var templateCustomTypeDefintion = `=== {{.TypeDefVar.Name}} -[source, go] ----- -{{.TypeDefVar.Decl}} ----- -{{.TypeDefVar.Doc}} -` ----- - - - -=== templateCustomTypeDefintions -[source, go] ----- -var templateCustomTypeDefintions = `== Variable Typedefinitions - -{{range .File.CustomTypes}} -{{- render $ .}} -{{end}} -` ----- - - - -=== templateVarAssignment -[source, go] ----- -var templateVarAssignment = `=== {{.VarAssignment.Name}} -[source, go] ----- -{{.VarAssignment.FullDecl}} ----- -{{.VarAssignment.Doc}} -` ----- - - - -=== templateVarAssignments -[source, go] ----- -var templateVarAssignments = `== Variables -{{range .File.VarAssignments}} -{{render $ .}} -{{end}} -` ----- - - - -=== templateConstAssignment -[source, go] ----- -var templateConstAssignment = `=== {{.ConstAssignment.Name}} -[source, go] ----- -{{.ConstAssignment.Decl}} ----- -{{.ConstAssignment.Doc}} -` ----- - - - -=== templateConstAssignments -[source, go] ----- -var templateConstAssignments = `=== Constants -[source, go] ----- -const ( - {{- range .File.ConstAssignments}} - {{tabify .Decl}} - {{- end}} -) ----- -{{range .File.ConstAssignments}} -{{render $ .}} -{{end}} -` ----- - - - -=== templateCustomFuncDefintion -[source, go] ----- -var templateCustomFuncDefintion = `=== {{.TypeDefFunc.Name}} -[source, go] ----- -{{.TypeDefFunc.Decl}} ----- -{{.TypeDefFunc.Doc}} -` ----- - - - -=== templateCustomFuncDefintions -[source, go] ----- -var templateCustomFuncDefintions = `== Function Definitions - -{{range .File.CustomFuncs}} -{{render $ .}} -{{end}} -` ----- @@ -1314,6 +934,7 @@ NewProducer creates a new instance of a producer. + === TestGenerateWorkspaceToString [source, go] ---- @@ -1348,26 +969,6 @@ override defaults. -=== createTemplate -[source, go] ----- -func createTemplate(name TemplateType, str string, overrides map[string]string, fm template.FuncMap) *TemplateAndText ----- - -createTemplate will create a template named name and parses the str -as template. If fails it will panic with the parse error. - -If name is found in override map it will use that string to parse the template -instead of the provided str. - - -=== dummyModule -[source, go] ----- -func dummyModule() *goparser.GoModule ----- - - === TestRenderPackageWithModule @@ -1406,6 +1007,15 @@ func TestRenderSingleFunction(t *testing.T) +=== TestIncludePrivateFunctions +[source, go] +---- +func TestIncludePrivateFunctions(t *testing.T) +---- + + + + === TestRenderSingleFunctionWithCode [source, go] ---- @@ -1577,6 +1187,11 @@ func TestStructReceiverFunction(t *testing.T) +=== TestCustomTypeReceiverFunction +[source, go] +---- +func TestCustomTypeReceiverFunction(t *testing.T) +---- @@ -1599,21 +1214,10 @@ func TestStructReceiverFunction(t *testing.T) -=== dirExists -[source, go] ----- -func dirExists(dir string) bool ----- -=== fileExists -[source, go] ----- -func fileExists(filepath string) bool ----- - @@ -1633,6 +1237,7 @@ import ( "sort" "strings" "testing" + "unicode" "github.com/stretchr/testify/assert" "go/ast" "go/parser" @@ -1833,6 +1438,7 @@ type GoMethod struct { Doc string Decl string FullDecl string + Exported bool Params []*GoType Results []*GoType } @@ -1855,6 +1461,9 @@ GoMethod is a method on a struct, custom type, interface or just plain function ==== FullDecl string +==== Exported bool + + ==== Params []*GoType @@ -2005,50 +1614,19 @@ Optional module to resolve fully qualified package paths [source, go] ---- type ResolverImpl struct { - module *GoModule - resolvers map[string] /*module name*/ Resolver - config ParseConfig - filepath string } ---- ResolverImpl is the implementation of a `Resolver` where it operarates on a `GoModule` level. -==== module *GoModule -module is the resolvers workspace. - -It may have sub-modules through contained `Resolver` instances. -==== resolvers map[string] /*module name*/ Resolver -resolvers is a map containing `Resolver` for each `GoModule` that this _module_ -references and makes use of. -==== config ParseConfig -config is the configuration that this `Resolver` adheres to. -==== filepath string -Fully qualified filepath to this module (where _go.mod_ resides). ==== Receivers -===== resolveModule -[source, go] ----- -func (r *ResolverImpl) resolveModule(fp string) Resolver ----- - - - -===== loadAll -[source, go] ----- -func (r *ResolverImpl) loadAll() error ----- - - - === GoAssignment @@ -2060,6 +1638,7 @@ type GoAssignment struct { Doc string Decl string FullDecl string + Exported bool } ---- @@ -2081,6 +1660,9 @@ then both pelle and list will have 'var pelle, lisa = 10, 19' as Decl ==== FullDecl string +==== Exported bool + + @@ -2088,11 +1670,12 @@ then both pelle and list will have 'var pelle, lisa = 10, 19' as Decl [source, go] ---- type GoCustomType struct { - File *GoFile - Name string - Doc string - Type string - Decl string + File *GoFile + Name string + Doc string + Type string + Decl string + Exported bool } ---- @@ -2113,6 +1696,9 @@ GoCustomType is a custom type definition ==== Decl string +==== Exported bool + + @@ -2125,6 +1711,7 @@ type GoInterface struct { Decl string FullDecl string Name string + Exported bool Methods []*GoMethod } ---- @@ -2146,6 +1733,9 @@ GoInterface specifies a interface definition ==== Name string +==== Exported bool + + ==== Methods []*GoMethod @@ -2160,6 +1750,7 @@ type GoType struct { Name string Type string Underlying string + Exported bool Inner []*GoType } ---- @@ -2178,6 +1769,9 @@ GoType represents a go type such as a array, map, custom type etc. ==== Underlying string +==== Exported bool + + ==== Inner []*GoType @@ -2193,6 +1787,7 @@ type GoStruct struct { Decl string FullDecl string Name string + Exported bool Fields []*GoField } ---- @@ -2214,6 +1809,9 @@ GoStruct represents a struct ==== Name string +==== Exported bool + + ==== Fields []*GoField @@ -2224,14 +1822,15 @@ GoStruct represents a struct [source, go] ---- type GoField struct { - File *GoFile - Struct *GoStruct - Doc string - Decl string - Name string - Type string - Tag *GoTag - Nested *GoStruct + File *GoFile + Struct *GoStruct + Doc string + Decl string + Name string + Type string + Exported bool + Tag *GoTag + Nested *GoStruct } ---- @@ -2255,6 +1854,9 @@ GoField is a field in a file or struct ==== Type string +==== Exported bool + + ==== Tag *GoTag @@ -2293,15 +1895,6 @@ and the error is returned. == Functions -=== contains -[source, go] ----- -func contains(name string, arr []string) bool ----- - -contains checks if any in the _arr_ matches the _name_. If found -`true` is returned, otherwise `false` is returned. - @@ -2336,14 +1929,6 @@ NewModuleFromBuff creates a new module from the buff specified in the buff parameter and states that the buff is read from path. -=== getPwd -[source, go] ----- -func getPwd() string ----- - - - === TestModuleBasePathIsTakenFromPathParam [source, go] @@ -2382,140 +1967,21 @@ func TestParseModuleNameGoVersionAndRequires(t *testing.T) -=== parseFile -[source, go] ----- -func parseFile(mod *GoModule, path string, source []byte, file *ast.File, fset *token.FileSet, files []*ast.File) (*GoFile, error) ----- - - - - -=== buildVarAssignment -[source, go] ----- -func buildVarAssignment(file *GoFile, genDecl *ast.GenDecl, valueSpec *ast.ValueSpec, source []byte) []*GoAssignment ----- - - - - -=== extractDocs -[source, go] ----- -func extractDocs(doc *ast.CommentGroup) string ----- - - - - -=== buildGoImport -[source, go] ----- -func buildGoImport(spec *ast.ImportSpec, file *GoFile) *GoImport ----- - - - - -=== buildGoInterface -[source, go] ----- -func buildGoInterface(source []byte, file *GoFile, info *types.Info, typeSpec *ast.TypeSpec, interfaceType *ast.InterfaceType) *GoInterface ----- - -=== buildMethodList -[source, go] ----- -func buildMethodList(file *GoFile, info *types.Info, fieldList []*ast.Field, source []byte) []*GoMethod ----- -=== buildStructMethod -[source, go] ----- -func buildStructMethod(file *GoFile, info *types.Info, funcDecl *ast.FuncDecl, source []byte) *GoStructMethod ----- -=== buildReceiverList -[source, go] ----- -func buildReceiverList(info *types.Info, fieldList *ast.FieldList, source []byte) []string ----- -=== buildTypeList -[source, go] ----- -func buildTypeList(file *GoFile, info *types.Info, fieldList *ast.FieldList, source []byte) []*GoType ----- - - - - -=== getNames -[source, go] ----- -func getNames(field *ast.Field) []string ----- - - - - -=== getTypeString -[source, go] ----- -func getTypeString(expr ast.Expr, source []byte) string ----- - - - - -=== getUnderlyingTypeString -[source, go] ----- -func getUnderlyingTypeString(info *types.Info, expr ast.Expr) string ----- - - - - -=== copyType -[source, go] ----- -func copyType(goType *GoType) *GoType ----- - - - - -=== buildType -[source, go] ----- -func buildType(file *GoFile, info *types.Info, expr ast.Expr, source []byte) *GoType ----- - - - - -=== buildGoStruct -[source, go] ----- -func buildGoStruct(source []byte, file *GoFile, info *types.Info, structName string, structType *ast.StructType) *GoStruct ----- - - - === ParseSingleFile [source, go] @@ -2613,14 +2079,6 @@ or directory and do accordingly. If file it will ignore configuration and blindl accept the file. -=== dummyModule -[source, go] ----- -func dummyModule() *GoModule ----- - - - === TestParsePackageDoc [source, go] diff --git a/goparser/gomethod.go b/goparser/gomethod.go index de0c1ad..9f3ff28 100644 --- a/goparser/gomethod.go +++ b/goparser/gomethod.go @@ -13,6 +13,7 @@ type GoMethod struct { Doc string Decl string FullDecl string + Exported bool Params []*GoType Results []*GoType } diff --git a/goparser/internal_parser.go b/goparser/internal_parser.go index c095d46..96f1f91 100644 --- a/goparser/internal_parser.go +++ b/goparser/internal_parser.go @@ -8,6 +8,7 @@ import ( "go/token" "go/types" "io/ioutil" + "unicode" ) func parseFile(mod *GoModule, path string, source []byte, file *ast.File, fset *token.FileSet, files []*ast.File) (*GoFile, error) { @@ -84,11 +85,12 @@ func parseFile(mod *GoModule, path string, source []byte, file *ast.File, fset * // Custom Type declaration case (*ast.Ident): goCustomType := &GoCustomType{ - File: goFile, - Name: genSpecType.Name.Name, - Type: typeSpecType.Name, - Doc: extractDocs(declType.Doc), - Decl: string(source[decl.Pos()-1 : decl.End()-1]), + File: goFile, + Name: genSpecType.Name.Name, + Exported: isExported(genSpecType.Name.Name), + Type: typeSpecType.Name, + Doc: extractDocs(declType.Doc), + Decl: string(source[decl.Pos()-1 : decl.End()-1]), } goFile.CustomTypes = append(goFile.CustomTypes, goCustomType) @@ -98,6 +100,7 @@ func parseFile(mod *GoModule, path string, source []byte, file *ast.File, fset * goMethod := &GoMethod{ File: goFile, Name: genSpecType.Name.Name, + Exported: isExported(genSpecType.Name.Name), Decl: string(source[decl.Pos()-1 : decl.End()-1]), FullDecl: string(source[decl.Pos()-1 : decl.End()-1]), Params: buildTypeList(goFile, info, funcType.Params, source), @@ -110,11 +113,12 @@ func parseFile(mod *GoModule, path string, source []byte, file *ast.File, fset * selectType := typeSpecType goCustomType := &GoCustomType{ - File: goFile, - Name: genSpecType.Name.Name, - Type: selectType.X.(*ast.Ident).Name + "." + selectType.Sel.Name, - Doc: extractDocs(declType.Doc), - Decl: string(source[decl.Pos()-1 : decl.End()-1]), + File: goFile, + Name: genSpecType.Name.Name, + Exported: isExported(genSpecType.Name.Name), + Type: selectType.X.(*ast.Ident).Name + "." + selectType.Sel.Name, + Doc: extractDocs(declType.Doc), + Decl: string(source[decl.Pos()-1 : decl.End()-1]), } goFile.CustomTypes = append(goFile.CustomTypes, goCustomType) @@ -136,6 +140,7 @@ func parseFile(mod *GoModule, path string, source []byte, file *ast.File, fset * case token.VAR: goFile.VarAssignments = append(goFile.VarAssignments, buildVarAssignment(goFile, genDecl, valueSpec, source)...) case token.CONST: + goFile.ConstAssignments = append(goFile.ConstAssignments, buildVarAssignment(goFile, genDecl, valueSpec, source)...) } default: @@ -157,6 +162,13 @@ func parseFile(mod *GoModule, path string, source []byte, file *ast.File, fset * return goFile, nil } +// isExported returns true if name starts with a upper-case letter +func isExported(name string) bool { + + r := rune(name[0]) + return unicode.IsUpper(r) && unicode.IsLetter(r) + +} func buildVarAssignment(file *GoFile, genDecl *ast.GenDecl, valueSpec *ast.ValueSpec, source []byte) []*GoAssignment { list := []*GoAssignment{} @@ -166,6 +178,7 @@ func buildVarAssignment(file *GoFile, genDecl *ast.GenDecl, valueSpec *ast.Value File: file, Name: valueSpec.Names[i].Name, FullDecl: string(source[genDecl.Pos()-1 : genDecl.End()-1]), + Exported: isExported(valueSpec.Names[i].Name), } if genDecl.Doc != nil { @@ -215,9 +228,10 @@ func buildGoImport(spec *ast.ImportSpec, file *GoFile) *GoImport { func buildGoInterface(source []byte, file *GoFile, info *types.Info, typeSpec *ast.TypeSpec, interfaceType *ast.InterfaceType) *GoInterface { return &GoInterface{ - File: file, - Name: typeSpec.Name.Name, - Methods: buildMethodList(file, info, interfaceType.Methods.List, source), + File: file, + Name: typeSpec.Name.Name, + Exported: isExported(typeSpec.Name.Name), + Methods: buildMethodList(file, info, interfaceType.Methods.List, source), } } @@ -237,6 +251,7 @@ func buildMethodList(file *GoFile, info *types.Info, fieldList []*ast.Field, sou goMethod := &GoMethod{ Name: name, File: file, + Exported: isExported(name), Params: buildTypeList(file, info, fType.Params, source), Results: buildTypeList(file, info, fType.Results, source), Decl: name + string(source[fType.Pos()-1:fType.End()-1]), @@ -255,11 +270,12 @@ func buildStructMethod(file *GoFile, info *types.Info, funcDecl *ast.FuncDecl, s return &GoStructMethod{ Receivers: buildReceiverList(info, funcDecl.Recv, source), GoMethod: GoMethod{ - File: file, - Name: funcDecl.Name.Name, - Params: buildTypeList(file, info, funcDecl.Type.Params, source), - Results: buildTypeList(file, info, funcDecl.Type.Results, source), - Doc: extractDocs(funcDecl.Doc), + File: file, + Name: funcDecl.Name.Name, + Exported: isExported(funcDecl.Name.Name), + Params: buildTypeList(file, info, funcDecl.Type.Params, source), + Results: buildTypeList(file, info, funcDecl.Type.Results, source), + Doc: extractDocs(funcDecl.Doc), }, } @@ -326,6 +342,7 @@ func copyType(goType *GoType) *GoType { return &GoType{ Type: goType.Type, + Exported: goType.Exported, Inner: goType.Inner, Name: goType.Name, Underlying: goType.Underlying, @@ -372,6 +389,7 @@ func buildType(file *GoFile, info *types.Info, expr ast.Expr, source []byte) *Go return &GoType{ File: file, Type: typeString, + Exported: isExported(typeString), Underlying: underlyingString, Inner: innerTypes, } @@ -379,9 +397,10 @@ func buildType(file *GoFile, info *types.Info, expr ast.Expr, source []byte) *Go func buildGoStruct(source []byte, file *GoFile, info *types.Info, structName string, structType *ast.StructType) *GoStruct { goStruct := &GoStruct{ - File: file, - Name: structName, - Fields: []*GoField{}, + File: file, + Name: structName, + Exported: isExported(structName), + Fields: []*GoField{}, } // Field: A Field declaration list in a struct type, a method list in an interface type, @@ -399,6 +418,8 @@ func buildGoStruct(source []byte, file *GoFile, info *types.Info, structName str Doc: extractDocs(field.Doc), } + goField.Exported = isExported(goField.Type) + if field.Tag != nil { goTag := &GoTag{ File: file, @@ -424,13 +445,14 @@ func buildGoStruct(source []byte, file *GoFile, info *types.Info, structName str } goField := &GoField{ - Struct: goStruct, - File: file, - Name: name.String(), - Type: string(source[field.Type.Pos()-1 : field.Type.End()-1]), - Decl: name.Name + " " + string(source[field.Type.Pos()-1:field.Type.End()-1]), - Doc: extractDocs(field.Doc), - Nested: nested, + Struct: goStruct, + File: file, + Name: name.String(), + Exported: isExported(name.String()), + Type: string(source[field.Type.Pos()-1 : field.Type.End()-1]), + Decl: name.Name + " " + string(source[field.Type.Pos()-1:field.Type.End()-1]), + Doc: extractDocs(field.Doc), + Nested: nested, } if field.Tag != nil { diff --git a/goparser/types.go b/goparser/types.go index fbdcd27..0c84f98 100644 --- a/goparser/types.go +++ b/goparser/types.go @@ -9,15 +9,17 @@ type GoAssignment struct { // then both pelle and list will have 'var pelle, lisa = 10, 19' as Decl Decl string FullDecl string + Exported bool } // GoCustomType is a custom type definition type GoCustomType struct { - File *GoFile - Name string - Doc string - Type string - Decl string + File *GoFile + Name string + Doc string + Type string + Decl string + Exported bool } // GoInterface specifies a interface definition @@ -27,6 +29,7 @@ type GoInterface struct { Decl string FullDecl string Name string + Exported bool Methods []*GoMethod } @@ -36,6 +39,7 @@ type GoType struct { Name string Type string Underlying string + Exported bool Inner []*GoType } @@ -46,17 +50,19 @@ type GoStruct struct { Decl string FullDecl string Name string + Exported bool Fields []*GoField } // GoField is a field in a file or struct type GoField struct { - File *GoFile - Struct *GoStruct - Doc string - Decl string - Name string - Type string - Tag *GoTag - Nested *GoStruct + File *GoFile + Struct *GoStruct + Doc string + Decl string + Name string + Type string + Exported bool + Tag *GoTag + Nested *GoStruct } diff --git a/main.go b/main.go index 6624386..9779933 100644 --- a/main.go +++ b/main.go @@ -16,6 +16,7 @@ type args struct { Module string `arg:"-m" help:"an optional folder or file path to module, otherwise current directory" placeholder:"PATH"` Internal bool `arg:"-i" help:"If internal go code shall be rendered as well"` Private bool `arg:"-p" help:"If files beneath directories starting with an underscore shall be included"` + NonExported bool `help:"Renders Non exported as well as the exported. Default only Exported is rendered."` Test bool `arg:"-t" help:"If test code should be included"` NoIndex bool `arg:"-n" help:"If no index header shall be generated"` NoToc bool `help:"Removes the table of contents if index document"` @@ -112,5 +113,9 @@ func runner(args args) { return } + if args.NonExported { + p.NonExported() + } + p.Generate() } diff --git a/main_test.go b/main_test.go index 1530d95..2eb31ee 100644 --- a/main_test.go +++ b/main_test.go @@ -23,3 +23,9 @@ func TestOverridePackageTemplate(t *testing.T) { runner(arg) } + +func TestNonExported(t *testing.T) { + + arg := args{NonExported: true, StdOut: true} + runner(arg) +}