From a24c0a744c664bbe6a7cfd30cfb5c41a9799b2fe Mon Sep 17 00:00:00 2001 From: Jonny Loughlin Date: Thu, 28 Dec 2023 12:11:27 -0500 Subject: [PATCH] fix: consistent whitespace around go keywords --- .version | 2 +- generator/generator.go | 39 +- .../render_test.go | 78 ++++ .../template.templ | 66 +++ .../template_templ.go | 380 ++++++++++++++++++ 5 files changed, 546 insertions(+), 19 deletions(-) create mode 100644 generator/test-whitespace-around-go-keywords/render_test.go create mode 100644 generator/test-whitespace-around-go-keywords/template.templ create mode 100644 generator/test-whitespace-around-go-keywords/template_templ.go diff --git a/.version b/.version index 994d91615..61cca7fec 100644 --- a/.version +++ b/.version @@ -1 +1 @@ -0.2.507 \ No newline at end of file +0.2.508 \ No newline at end of file diff --git a/generator/generator.go b/generator/generator.go index cb6c35e35..bc54f7dae 100644 --- a/generator/generator.go +++ b/generator/generator.go @@ -391,7 +391,7 @@ func (g *generator) writeTemplate(nodeIdx int, t parser.HTMLTemplate) error { return err } // Nodes. - if err = g.writeNodes(indentLevel, stripWhitespace(t.Children)); err != nil { + if err = g.writeNodes(indentLevel, stripWhitespace(t.Children), nil); err != nil { return err } // Return the buffer. @@ -468,13 +468,16 @@ func stripLeadingAndTrailingWhitespace(nodes []parser.Node) []parser.Node { return stripTrailingWhitespace(stripLeadingWhitespace(nodes)) } -func (g *generator) writeNodes(indentLevel int, nodes []parser.Node) error { +func (g *generator) writeNodes(indentLevel int, nodes []parser.Node, next parser.Node) error { for i, curr := range nodes { - var next parser.Node + var nextNode parser.Node if i+1 < len(nodes) { - next = nodes[i+1] + nextNode = nodes[i+1] } - if err := g.writeNode(indentLevel, curr, next); err != nil { + if nextNode == nil { + nextNode = next + } + if err := g.writeNode(indentLevel, curr, nextNode); err != nil { return err } } @@ -494,15 +497,15 @@ func (g *generator) writeNode(indentLevel int, current parser.Node, next parser. case parser.RawElement: err = g.writeRawElement(indentLevel, n) case parser.ForExpression: - err = g.writeForExpression(indentLevel, n) + err = g.writeForExpression(indentLevel, n, next) case parser.CallTemplateExpression: err = g.writeCallTemplateExpression(indentLevel, n) case parser.TemplElementExpression: err = g.writeTemplElementExpression(indentLevel, n) case parser.IfExpression: - err = g.writeIfExpression(indentLevel, n) + err = g.writeIfExpression(indentLevel, n, next) case parser.SwitchExpression: - err = g.writeSwitchExpression(indentLevel, n) + err = g.writeSwitchExpression(indentLevel, n, next) case parser.StringExpression: err = g.writeStringExpression(indentLevel, n.Expression) case parser.Whitespace: @@ -572,7 +575,7 @@ func (g *generator) writeDocType(indentLevel int, n parser.DocType) (err error) return nil } -func (g *generator) writeIfExpression(indentLevel int, n parser.IfExpression) (err error) { +func (g *generator) writeIfExpression(indentLevel int, n parser.IfExpression, nextNode parser.Node) (err error) { var r parser.Range // if if _, err = g.w.WriteIndent(indentLevel, `if `); err != nil { @@ -589,7 +592,7 @@ func (g *generator) writeIfExpression(indentLevel int, n parser.IfExpression) (e } { indentLevel++ - if err = g.writeNodes(indentLevel, stripLeadingAndTrailingWhitespace(n.Then)); err != nil { + if err = g.writeNodes(indentLevel, stripLeadingAndTrailingWhitespace(n.Then), nextNode); err != nil { return err } indentLevel-- @@ -610,7 +613,7 @@ func (g *generator) writeIfExpression(indentLevel int, n parser.IfExpression) (e } { indentLevel++ - if err = g.writeNodes(indentLevel, stripLeadingAndTrailingWhitespace(elseIf.Then)); err != nil { + if err = g.writeNodes(indentLevel, stripLeadingAndTrailingWhitespace(elseIf.Then), nextNode); err != nil { return err } indentLevel-- @@ -623,7 +626,7 @@ func (g *generator) writeIfExpression(indentLevel int, n parser.IfExpression) (e } { indentLevel++ - if err = g.writeNodes(indentLevel, stripLeadingAndTrailingWhitespace(n.Else)); err != nil { + if err = g.writeNodes(indentLevel, stripLeadingAndTrailingWhitespace(n.Else), nextNode); err != nil { return err } indentLevel-- @@ -636,7 +639,7 @@ func (g *generator) writeIfExpression(indentLevel int, n parser.IfExpression) (e return nil } -func (g *generator) writeSwitchExpression(indentLevel int, n parser.SwitchExpression) (err error) { +func (g *generator) writeSwitchExpression(indentLevel int, n parser.SwitchExpression, next parser.Node) (err error) { var r parser.Range // switch if _, err = g.w.WriteIndent(indentLevel, `switch `); err != nil { @@ -661,7 +664,7 @@ func (g *generator) writeSwitchExpression(indentLevel int, n parser.SwitchExpres } g.sourceMap.Add(c.Expression, r) indentLevel++ - if err = g.writeNodes(indentLevel, stripLeadingAndTrailingWhitespace(c.Children)); err != nil { + if err = g.writeNodes(indentLevel, stripLeadingAndTrailingWhitespace(c.Children), next); err != nil { return err } indentLevel-- @@ -701,7 +704,7 @@ func (g *generator) writeBlockTemplElementExpression(indentLevel int, n parser.T if err := g.writeTemplBuffer(indentLevel); err != nil { return err } - if err = g.writeNodes(indentLevel, stripLeadingAndTrailingWhitespace(n.Children)); err != nil { + if err = g.writeNodes(indentLevel, stripLeadingAndTrailingWhitespace(n.Children), nil); err != nil { return err } // Return the buffer. @@ -784,7 +787,7 @@ func (g *generator) writeCallTemplateExpression(indentLevel int, n parser.CallTe return nil } -func (g *generator) writeForExpression(indentLevel int, n parser.ForExpression) (err error) { +func (g *generator) writeForExpression(indentLevel int, n parser.ForExpression, next parser.Node) (err error) { var r parser.Range // for if _, err = g.w.WriteIndent(indentLevel, `for `); err != nil { @@ -801,7 +804,7 @@ func (g *generator) writeForExpression(indentLevel int, n parser.ForExpression) } // Children. indentLevel++ - if err = g.writeNodes(indentLevel, stripLeadingAndTrailingWhitespace(n.Children)); err != nil { + if err = g.writeNodes(indentLevel, stripLeadingAndTrailingWhitespace(n.Children), next); err != nil { return err } indentLevel-- @@ -898,7 +901,7 @@ func (g *generator) writeStandardElement(indentLevel int, n parser.Element) (err } } // Children. - if err = g.writeNodes(indentLevel, stripWhitespace(n.Children)); err != nil { + if err = g.writeNodes(indentLevel, stripWhitespace(n.Children), nil); err != nil { return err } // diff --git a/generator/test-whitespace-around-go-keywords/render_test.go b/generator/test-whitespace-around-go-keywords/render_test.go new file mode 100644 index 000000000..0628fdf5a --- /dev/null +++ b/generator/test-whitespace-around-go-keywords/render_test.go @@ -0,0 +1,78 @@ +package testwhitespacearoundgokeywords + +import ( + "context" + "strings" + "testing" + + "github.com/a-h/templ" + "github.com/google/go-cmp/cmp" +) + +func TestTextWhitespace(t *testing.T) { + for _, test := range []struct { + name string + input templ.Component + expected string + }{ + { + name: "whitespace is consistent in a true evaluated if statement", + input: WhitespaceIsConsistentInIf(true, false), + expected: WhitespaceIsConsistentInTrueIfExpected, + }, + { + name: "whitespace is consistent in a true evaluated else if statement", + input: WhitespaceIsConsistentInIf(false, true), + expected: WhitespaceIsConsistentInTrueElseIfExpected, + }, + { + name: "whitespace is consistent in a true evaluated else statement", + input: WhitespaceIsConsistentInIf(false, false), + expected: WhitespaceIsConsistentInTrueElseExpected, + }, + { + name: "whitespace is consistent in a false evaluated if statement", + input: WhitespaceIsConsistentInFalseIf(), + expected: WhitespaceIsConsistentInFalseIfExpected, + }, + { + name: "whitespace is consistent in a switch statment with a true case", + input: WhitespaceIsConsistentInSwitch(1), + expected: WhitespaceIsConsistentInOneSwitchExpected, + }, + { + name: "whitespace is consistent in a switch statment with a default case", + input: WhitespaceIsConsistentInSwitch(2), + expected: WhitespaceIsConsistentInDefaultSwitchExpected, + }, + { + name: "whitespace is consistent in a switch statment with no default case and no true cases", + input: WhitespaceIsConsistentInSwitchNoDefault(), + expected: WhitespaceIsConsistentInSwitchNoDefaultExpected, + }, + { + name: "whitespace is consistent in a for statment that runs 0 times", + input: WhitespaceIsConsistentInFor(0), + expected: WhitespaceIsConsistentInForZeroExpected, + }, + { + name: "whitespace is consistent in a for statment that runs 1 times", + input: WhitespaceIsConsistentInFor(1), + expected: WhitespaceIsConsistentInForOneExpected, + }, + { + name: "whitespace is consistent in a for statment that runs 3 times", + input: WhitespaceIsConsistentInFor(3), + expected: WhitespaceIsConsistentInForThreeExpected, + }, + } { + w := new(strings.Builder) + err := test.input.Render(context.Background(), w) + if err != nil { + t.Errorf("failed to render: %v", err) + } + if diff := cmp.Diff(test.expected, w.String()); diff != "" { + t.Error(diff) + } + } +} diff --git a/generator/test-whitespace-around-go-keywords/template.templ b/generator/test-whitespace-around-go-keywords/template.templ new file mode 100644 index 000000000..91e137667 --- /dev/null +++ b/generator/test-whitespace-around-go-keywords/template.templ @@ -0,0 +1,66 @@ +package testwhitespacearoundgokeywords + +import "fmt" + +templ WhitespaceIsConsistentInIf(firstIf, secondIf bool) { + + if firstIf { + + } else if secondIf { + + } else { + + } + +} + +const WhitespaceIsConsistentInTrueIfExpected = ` ` +const WhitespaceIsConsistentInTrueElseIfExpected = ` ` +const WhitespaceIsConsistentInTrueElseExpected = ` ` + +templ WhitespaceIsConsistentInFalseIf() { + + if false { + + } + +} + +const WhitespaceIsConsistentInFalseIfExpected = ` ` + +templ WhitespaceIsConsistentInSwitch(i int) { + + switch i { + case 1: + + default: + + } + +} + +const WhitespaceIsConsistentInOneSwitchExpected = ` ` +const WhitespaceIsConsistentInDefaultSwitchExpected = ` ` + +templ WhitespaceIsConsistentInSwitchNoDefault() { + + switch false { + case true: + + } + +} + +const WhitespaceIsConsistentInSwitchNoDefaultExpected = ` ` + +templ WhitespaceIsConsistentInFor(i int) { + + for j := 0; j < i; j++ { + + } + +} + +const WhitespaceIsConsistentInForZeroExpected = ` ` +const WhitespaceIsConsistentInForOneExpected = ` ` +const WhitespaceIsConsistentInForThreeExpected = ` ` diff --git a/generator/test-whitespace-around-go-keywords/template_templ.go b/generator/test-whitespace-around-go-keywords/template_templ.go new file mode 100644 index 000000000..5ce5d1075 --- /dev/null +++ b/generator/test-whitespace-around-go-keywords/template_templ.go @@ -0,0 +1,380 @@ +// Code generated by templ - DO NOT EDIT. + +package testwhitespacearoundgokeywords + +//lint:file-ignore SA4006 This context is only used if a nested component is present. + +import "github.com/a-h/templ" +import "context" +import "io" +import "bytes" + +import "fmt" + +func WhitespaceIsConsistentInIf(firstIf, secondIf bool) templ.Component { + return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) + if !templ_7745c5c3_IsBuffer { + templ_7745c5c3_Buffer = templ.GetBuffer() + defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var1 := templ.GetChildren(ctx) + if templ_7745c5c3_Var1 == nil { + templ_7745c5c3_Var1 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if firstIf { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } else if secondIf { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } else { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if !templ_7745c5c3_IsBuffer { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) + } + return templ_7745c5c3_Err + }) +} + +const WhitespaceIsConsistentInTrueIfExpected = ` ` +const WhitespaceIsConsistentInTrueElseIfExpected = ` ` +const WhitespaceIsConsistentInTrueElseExpected = ` ` + +func WhitespaceIsConsistentInFalseIf() templ.Component { + return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) + if !templ_7745c5c3_IsBuffer { + templ_7745c5c3_Buffer = templ.GetBuffer() + defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var7 := templ.GetChildren(ctx) + if templ_7745c5c3_Var7 == nil { + templ_7745c5c3_Var7 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if false { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if !templ_7745c5c3_IsBuffer { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) + } + return templ_7745c5c3_Err + }) +} + +const WhitespaceIsConsistentInFalseIfExpected = ` ` + +func WhitespaceIsConsistentInSwitch(i int) templ.Component { + return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) + if !templ_7745c5c3_IsBuffer { + templ_7745c5c3_Buffer = templ.GetBuffer() + defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var11 := templ.GetChildren(ctx) + if templ_7745c5c3_Var11 == nil { + templ_7745c5c3_Var11 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + switch i { + case 1: + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + default: + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if !templ_7745c5c3_IsBuffer { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) + } + return templ_7745c5c3_Err + }) +} + +const WhitespaceIsConsistentInOneSwitchExpected = ` ` +const WhitespaceIsConsistentInDefaultSwitchExpected = ` ` + +func WhitespaceIsConsistentInSwitchNoDefault() templ.Component { + return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) + if !templ_7745c5c3_IsBuffer { + templ_7745c5c3_Buffer = templ.GetBuffer() + defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var16 := templ.GetChildren(ctx) + if templ_7745c5c3_Var16 == nil { + templ_7745c5c3_Var16 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + switch false { + case true: + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if !templ_7745c5c3_IsBuffer { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) + } + return templ_7745c5c3_Err + }) +} + +const WhitespaceIsConsistentInSwitchNoDefaultExpected = ` ` + +func WhitespaceIsConsistentInFor(i int) templ.Component { + return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) + if !templ_7745c5c3_IsBuffer { + templ_7745c5c3_Buffer = templ.GetBuffer() + defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var20 := templ.GetChildren(ctx) + if templ_7745c5c3_Var20 == nil { + templ_7745c5c3_Var20 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + for j := 0; j < i; j++ { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if !templ_7745c5c3_IsBuffer { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) + } + return templ_7745c5c3_Err + }) +} + +const WhitespaceIsConsistentInForZeroExpected = ` ` +const WhitespaceIsConsistentInForOneExpected = ` ` +const WhitespaceIsConsistentInForThreeExpected = ` `