From 3929a0c1ac109804ea860d1ce6e6050b3daa6fe3 Mon Sep 17 00:00:00 2001 From: Alexander Jung Date: Fri, 27 Jun 2025 16:21:13 -0400 Subject: [PATCH 1/2] feat: add top-level `comment_line_limit` config option This commit introduces a new configuration option which can be used to adjust the line width of comments. Setting a negative value will disable line wrapping. Signed-off-by: Alexander Jung --- gen/generator.go | 3 ++ gen/generator_test.go | 68 ++++++++++++++++++++++++++++++++++++ gen/ir/description.go | 33 +++++++++++++++--- gen/ir/description_test.go | 70 ++++++++++++++++++++++++++++++++++++++ gen/options.go | 3 ++ 5 files changed, 173 insertions(+), 4 deletions(-) create mode 100644 gen/generator_test.go diff --git a/gen/generator.go b/gen/generator.go index c32595413..789a50de9 100644 --- a/gen/generator.go +++ b/gen/generator.go @@ -71,6 +71,9 @@ func expandSpec(api *openapi.API, p string) (err error) { func NewGenerator(spec *ogen.Spec, opts Options) (*Generator, error) { opts.setDefaults() + // Set the comment line limit for pretty documentation. + ir.SetLineLimit(opts.Generator.CommentLineLimit) + var external jsonschema.ExternalResolver if opts.Parser.AllowRemote { external = jsonschema.NewExternalResolver(opts.Parser.Remote) diff --git a/gen/generator_test.go b/gen/generator_test.go new file mode 100644 index 000000000..d39353e5a --- /dev/null +++ b/gen/generator_test.go @@ -0,0 +1,68 @@ +package gen + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/ogen-go/ogen" + "github.com/ogen-go/ogen/gen/ir" +) + +func TestCommentLineLimitPropagation(t *testing.T) { + // Create a simple spec for testing + spec := &ogen.Spec{ + OpenAPI: "3.0.0", + Info: ogen.Info{ + Title: "Test API", + Version: "1.0.0", + }, + } + + // Test cases with different comment line limit values + tests := []struct { + name string + lineLimit int + expectLimit int + }{ + { + name: "default_value", + lineLimit: 0, + expectLimit: 100, // Should use default value + }, + { + name: "custom_value", + lineLimit: 50, + expectLimit: 50, + }, + { + name: "disable_wrapping", + lineLimit: -1, + expectLimit: -1, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Save the original line limit to restore after the test + originalLimit := ir.GetLineLimit() + defer ir.SetLineLimit(originalLimit) + + // Create options with the test case's line limit + opts := Options{ + Generator: GenerateOptions{ + CommentLineLimit: tt.lineLimit, + }, + } + + // Create a new generator + _, err := NewGenerator(spec, opts) + require.NoError(t, err) + + // Verify the line limit was set correctly + actualLimit := ir.GetLineLimit() + require.Equal(t, tt.expectLimit, actualLimit, + "Line limit should be set to %d, but got %d", tt.expectLimit, actualLimit) + }) + } +} diff --git a/gen/ir/description.go b/gen/ir/description.go index dc2226cfb..ffc56f39e 100644 --- a/gen/ir/description.go +++ b/gen/ir/description.go @@ -8,7 +8,35 @@ import ( "github.com/ogen-go/ogen/internal/naming" ) +// Global line limit, can be configured via SetLineLimit. +var lineLimit = 100 + +// SetLineLimit sets the maximum width of a comment line before it is wrapped. +// Use a negative value to disable line wrapping altogether. +func SetLineLimit(limit int) { + if limit == 0 { + // Use default value for zero. + lineLimit = 100 + return + } + lineLimit = limit +} + +// GetLineLimit returns the current line limit value. +func GetLineLimit() int { + return lineLimit +} + func splitLine(s string, limit int) (r []string) { + // If limit is negative, don't split lines. + if limit < 0 { + s = strings.TrimSpace(s) + if s == "" { + return nil + } + return []string{s} + } + s = strings.TrimSpace(s) if s == "" { return nil @@ -39,11 +67,8 @@ func splitLine(s string, limit int) (r []string) { } } -const ( - lineLimit = 100 -) - func prettyDoc(s, deprecation string) (r []string) { + // Original pretty documentation behavior // TODO(tdakkota): basic common mark rendering? for _, line := range strings.Split(s, "\n") { r = append(r, splitLine(line, lineLimit)...) diff --git a/gen/ir/description_test.go b/gen/ir/description_test.go index 9cb525345..cef1915b8 100644 --- a/gen/ir/description_test.go +++ b/gen/ir/description_test.go @@ -11,6 +11,12 @@ import ( ) func Test_prettyDoc(t *testing.T) { + // Save the original value to restore after the test + originalLimit := lineLimit + defer func() { + lineLimit = originalLimit + }() + tests := []struct { input string notice string @@ -77,3 +83,67 @@ func Test_prettyDoc(t *testing.T) { }) } } + +func TestSetLineLimit(t *testing.T) { + // Save the original value to restore after the test + originalLimit := lineLimit + defer func() { + lineLimit = originalLimit + }() + + const longText = "This is a very long description that should be split into multiple lines depending on the configured line limit" + + tests := []struct { + name string + limit int + expected int // expected number of lines (approximate) + }{ + { + name: "default_limit", + limit: 0, // Should use default 100 + expected: 2, // The long test will still need to be split in 2 with default limit + }, + { + name: "short_limit", + limit: 20, + expected: 8, // Will split into multiple lines + }, + { + name: "negative_limit_disables_wrapping", + limit: -1, + expected: 1, // Should not wrap + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + SetLineLimit(tt.limit) + result := prettyDoc(longText, "") + require.Len(t, result, tt.expected) + }) + } +} + +func TestCommentLineLimit(t *testing.T) { + // Save the original value to restore after the test + originalLimit := lineLimit + defer func() { + lineLimit = originalLimit + }() + + // Reset to default to start + SetLineLimit(0) + require.Equal(t, 100, lineLimit, "Default line limit should be 100") + + // Test with a custom line limit + SetLineLimit(50) + require.Equal(t, 50, lineLimit, "Line limit should be updated to 50") + + // Test with a negative value (disabled wrapping) + SetLineLimit(-1) + require.Equal(t, -1, lineLimit, "Negative line limit should disable wrapping") + + // Test with zero (should set to default) + SetLineLimit(0) + require.Equal(t, 100, lineLimit, "Zero line limit should reset to default (100)") +} diff --git a/gen/options.go b/gen/options.go index ec7f2b9b6..6906b9d88 100644 --- a/gen/options.go +++ b/gen/options.go @@ -161,6 +161,9 @@ type GenerateOptions struct { IgnoreNotImplemented []string `json:"ignore_not_implemented" yaml:"ignore_not_implemented"` // NotImplementedHook is hook for ErrNotImplemented errors. NotImplementedHook func(name string, err error) `json:"-" yaml:"-"` + // CommentLineLimit sets the maximum width of a comment line before it is + // wrapped. -1 disables line wrapping altogether. + CommentLineLimit int `json:"comment_line_limit" yaml:"comment_line_limit"` // ConvenientErrors control Convenient Errors feature. // From ebbc82b70f9c07dd3e60ac8b6d4045d84e7b5d63 Mon Sep 17 00:00:00 2001 From: Alexander Jung Date: Sat, 28 Jun 2025 12:53:42 -0700 Subject: [PATCH 2/2] feat: add top-level `comment_pretty_doc` config option This commit introduces a new configuration option which can be used to enable or disable post-processing of the comment/description. This is useful for providing the description as a comment verbatim. Signed-off-by: Alexander Jung --- gen/generator.go | 2 ++ gen/ir/description.go | 32 ++++++++++++++++++++++++++++++++ gen/ir/description_flag_test.go | 28 ++++++++++++++++++++++++++++ gen/options.go | 2 ++ 4 files changed, 64 insertions(+) create mode 100644 gen/ir/description_flag_test.go diff --git a/gen/generator.go b/gen/generator.go index 789a50de9..dbc15b050 100644 --- a/gen/generator.go +++ b/gen/generator.go @@ -73,6 +73,8 @@ func NewGenerator(spec *ogen.Spec, opts Options) (*Generator, error) { // Set the comment line limit for pretty documentation. ir.SetLineLimit(opts.Generator.CommentLineLimit) + // Set whether to use pretty documentation. + ir.SetPrettyDoc(opts.Generator.CommentPrettyDoc) var external jsonschema.ExternalResolver if opts.Parser.AllowRemote { diff --git a/gen/ir/description.go b/gen/ir/description.go index ffc56f39e..eb98346c7 100644 --- a/gen/ir/description.go +++ b/gen/ir/description.go @@ -11,6 +11,9 @@ import ( // Global line limit, can be configured via SetLineLimit. var lineLimit = 100 +// Global flag to enable or disable pretty documentation. +var prettyDocEnabled = true + // SetLineLimit sets the maximum width of a comment line before it is wrapped. // Use a negative value to disable line wrapping altogether. func SetLineLimit(limit int) { @@ -27,6 +30,16 @@ func GetLineLimit() int { return lineLimit } +// SetPrettyDoc enables or disables pretty documentation. +func SetPrettyDoc(enabled bool) { + prettyDocEnabled = enabled +} + +// IsPrettyDocEnabled returns whether pretty documentation is enabled. +func IsPrettyDocEnabled() bool { + return prettyDocEnabled +} + func splitLine(s string, limit int) (r []string) { // If limit is negative, don't split lines. if limit < 0 { @@ -68,6 +81,25 @@ func splitLine(s string, limit int) (r []string) { } func prettyDoc(s, deprecation string) (r []string) { + // If pretty documentation is disabled, return the comment as-is + if !prettyDocEnabled { + // Just split by newlines. + for _, line := range strings.Split(s, "\n") { + r = append(r, line) + } + + // Add deprecation notice if provided + if deprecation != "" { + if len(r) > 0 { + // Insert empty line between description and deprecated notice. + r = append(r, "") + } + r = append(r, deprecation) + } + + return r + } + // Original pretty documentation behavior // TODO(tdakkota): basic common mark rendering? for _, line := range strings.Split(s, "\n") { diff --git a/gen/ir/description_flag_test.go b/gen/ir/description_flag_test.go new file mode 100644 index 000000000..7bb48b392 --- /dev/null +++ b/gen/ir/description_flag_test.go @@ -0,0 +1,28 @@ +package ir + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestPrettyDocEnabledFlag(t *testing.T) { + // Save original state to restore later + originalState := prettyDocEnabled + + // Test with pretty documentation enabled + SetPrettyDoc(true) + require.True(t, IsPrettyDocEnabled()) + doc := " this is a test. " + prettyResult := prettyDoc(doc, "") + require.Equal(t, "This is a test.", prettyResult[0]) + + // Test with pretty documentation disabled + SetPrettyDoc(false) + require.False(t, IsPrettyDocEnabled()) + verbatimResult := prettyDoc(doc, "") + require.Equal(t, " this is a test. ", verbatimResult[0]) + + // Restore original state + SetPrettyDoc(originalState) +} diff --git a/gen/options.go b/gen/options.go index 6906b9d88..29dad7410 100644 --- a/gen/options.go +++ b/gen/options.go @@ -161,6 +161,8 @@ type GenerateOptions struct { IgnoreNotImplemented []string `json:"ignore_not_implemented" yaml:"ignore_not_implemented"` // NotImplementedHook is hook for ErrNotImplemented errors. NotImplementedHook func(name string, err error) `json:"-" yaml:"-"` + // CommentPrettyDoc enables or disables pretty documentation for comments. + CommentPrettyDoc bool `json:"comment_pretty_doc" yaml:"comment_pretty_doc"` // CommentLineLimit sets the maximum width of a comment line before it is // wrapped. -1 disables line wrapping altogether. CommentLineLimit int `json:"comment_line_limit" yaml:"comment_line_limit"`