From eb4dc0dad29ab269641acbdb97984fb00bf7401b Mon Sep 17 00:00:00 2001 From: Glenn Lewis <6598971+gmlewis@users.noreply.github.com> Date: Wed, 11 Jan 2023 11:55:42 -0500 Subject: [PATCH 1/2] Add NoSynopsis option to AddGoComments Signed-off-by: Glenn Lewis <6598971+gmlewis@users.noreply.github.com> --- comment_extractor.go | 29 +++++++++++++++++++++++++++-- reflect.go | 4 ++-- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/comment_extractor.go b/comment_extractor.go index 0088b41..44bdb87 100644 --- a/comment_extractor.go +++ b/comment_extractor.go @@ -13,6 +13,25 @@ import ( "go/token" ) +// ExtractGoCommentsOption represents an option that can be passed to ExtractGoComments +// in order to modify its behavior. +type ExtractGoCommentsOption func(e *extractOptions) + +// NoSynopsis prevents ExtractGoComments from calling doc.Synopsis on the comment text. +// This is used to preserve the full text of the original comment, including newlines. +// +// Example usage: +// if err := r.AddGoComments("github.com/example/wails", "./schema/", jsonschema.NoSynopsis()); err != nil { ... } +func NoSynopsis() ExtractGoCommentsOption { + return func(e *extractOptions) { + e.noSynopsis = true + } +} + +type extractOptions struct { + noSynopsis bool +} + // ExtractGoComments will read all the go files contained in the provided path, // including sub-directories, in order to generate a dictionary of comments // associated with Types and Fields. The results will be added to the `commentsMap` @@ -24,7 +43,11 @@ import ( // // When parsing type comments, we use the `go/doc`'s Synopsis method to extract the first phrase // only. Field comments, which tend to be much shorter, will include everything. -func ExtractGoComments(base, path string, commentMap map[string]string) error { +func ExtractGoComments(base, path string, commentMap map[string]string, opts ...ExtractGoCommentsOption) error { + eopts := &extractOptions{} + for _, opt := range opts { + opt(eopts) + } fset := token.NewFileSet() dict := make(map[string][]*ast.Package) err := filepath.Walk(path, func(path string, info fs.FileInfo, err error) error { @@ -64,7 +87,9 @@ func ExtractGoComments(base, path string, commentMap map[string]string) error { txt = gtxt gtxt = "" } - txt = doc.Synopsis(txt) + if !eopts.noSynopsis { + txt = doc.Synopsis(txt) + } commentMap[fmt.Sprintf("%s.%s", pkg, typ)] = strings.TrimSpace(txt) } case *ast.Field: diff --git a/reflect.go b/reflect.go index 6ebc6be..9c2e027 100644 --- a/reflect.go +++ b/reflect.go @@ -1125,9 +1125,9 @@ func fullyQualifiedTypeName(t reflect.Type) string { // AddGoComments will update the reflectors comment map with all the comments // found in the provided source directories. See the #ExtractGoComments method // for more details. -func (r *Reflector) AddGoComments(base, path string) error { +func (r *Reflector) AddGoComments(base, path string, opts ...ExtractGoCommentsOption) error { if r.CommentMap == nil { r.CommentMap = make(map[string]string) } - return ExtractGoComments(base, path, r.CommentMap) + return ExtractGoComments(base, path, r.CommentMap, opts...) } From 1ba1f9c4061647827029beb799e4e7be8e213e74 Mon Sep 17 00:00:00 2001 From: Glenn Lewis <6598971+gmlewis@users.noreply.github.com> Date: Mon, 26 Jun 2023 20:01:17 -0400 Subject: [PATCH 2/2] Add unit test for NoSynopsis Signed-off-by: Glenn Lewis <6598971+gmlewis@users.noreply.github.com> --- comment_extractor_test.go | 53 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 comment_extractor_test.go diff --git a/comment_extractor_test.go b/comment_extractor_test.go new file mode 100644 index 0000000..b5408e2 --- /dev/null +++ b/comment_extractor_test.go @@ -0,0 +1,53 @@ +package jsonschema + +import ( + "testing" +) + +const ( + baseURL = "github.com/invopop/jsonschema" +) + +// WantStruct is a test struct +// for testing reflection and +// ensuring that comment newlines +// are preserved when using +// jsonschema.NoSynopsis(). +type WantStruct struct { +} + +func TestDescription(t *testing.T) { + r := new(Reflector) + r.DoNotReference = true + if err := r.AddGoComments(baseURL, "./"); err != nil { + t.Fatal(err) + } + v := &WantStruct{} + s := r.Reflect(v) + + want := `WantStruct is a test struct for testing reflection and ensuring that comment newlines are preserved when using jsonschema.NoSynopsis().` + + if got := s.Description; got != want { + t.Errorf("s.Description =\n%v\nwant:\n%v", got, want) + } +} + +func TestDescription_NoSynopsis(t *testing.T) { + r := new(Reflector) + r.DoNotReference = true + if err := r.AddGoComments(baseURL, "./", NoSynopsis()); err != nil { + t.Fatal(err) + } + v := &WantStruct{} + s := r.Reflect(v) + + want := `WantStruct is a test struct +for testing reflection and +ensuring that comment newlines +are preserved when using +jsonschema.NoSynopsis().` + + if got := s.Description; got != want { + t.Errorf("s.Description =\n%v\nwant:\n%v", got, want) + } +}