Skip to content

Commit

Permalink
Support a generator for composite literals
Browse files Browse the repository at this point in the history
  • Loading branch information
moznion committed Jan 19, 2019
1 parent de042fc commit a37fc26
Show file tree
Hide file tree
Showing 2 changed files with 143 additions and 0 deletions.
82 changes: 82 additions & 0 deletions generator/composite_literal.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package generator

import (
"fmt"
"strings"
)

type compositeLiteralField struct {
key string
value Statement
}

// CompositeLiteral represents a code generator for composite literal.
// Please see also: https://golang.org/doc/effective_go.html#composite_literals
type CompositeLiteral struct {
typ string
fields []*compositeLiteralField
}

// NewCompositeLiteral returns a new `CompositeLiteral`.
func NewCompositeLiteral(typ string) *CompositeLiteral {
return &CompositeLiteral{
typ: typ,
}
}

// AddField adds a field as `Statement` to `ComposeLiteral`.
// This method returns a *new* `Struct`; it means this method acts as immutable.
func (c *CompositeLiteral) AddField(key string, value Statement) *CompositeLiteral {
return &CompositeLiteral{
typ: c.typ,
fields: append(c.fields, &compositeLiteralField{
key: key,
value: value,
}),
}
}

// AddFieldStr adds a field as string to `ComposeLiteral`.
// This method returns a *new* `Struct`; it means this method acts as immutable.
func (c *CompositeLiteral) AddFieldStr(key string, value string) *CompositeLiteral {
return &CompositeLiteral{
typ: c.typ,
fields: append(c.fields, &compositeLiteralField{
key: key,
value: NewRawStatement(fmt.Sprintf(`"%s"`, value)),
}),
}
}

// AddFieldRaw adds a field as raw text to `ComposeLiteral`.
// This method returns a *new* `Struct`; it means this method acts as immutable.
func (c *CompositeLiteral) AddFieldRaw(key string, value interface{}) *CompositeLiteral {
return &CompositeLiteral{
typ: c.typ,
fields: append(c.fields, &compositeLiteralField{
key: key,
value: NewRawStatement(fmt.Sprintf("%v", value)),
}),
}
}

// Generate generates composite literal block as golang code.
func (c *CompositeLiteral) Generate(indentLevel int) (string, error) {
indent := buildIndent(indentLevel)
nextLevelIndent := buildIndent(indentLevel + 1)

stmt := fmt.Sprintf("%s%s{\n", indent, c.typ)
for _, field := range c.fields {
genValue, err := field.value.Generate(indentLevel + 1)
if err != nil {
return "", err
}

genValue = strings.TrimSpace(genValue)

stmt += fmt.Sprintf("%s%s: %s,\n", nextLevelIndent, field.key, genValue)
}
stmt += fmt.Sprintf("%s}\n", indent)

return stmt, nil
}
61 changes: 61 additions & 0 deletions generator/composite_literal_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package generator

import (
"testing"

"github.com/moznion/gowrtr/internal/errmsg"

"github.com/stretchr/testify/assert"
)

func TestShouldGenerateCompositeLiteralBeSuccess(t *testing.T) {
composeGenerator := NewCompositeLiteral("&Struct").
AddField("foo", NewRawStatement(`"foo-value"`)).
AddFieldStr("bar", "bar-value").
AddField("buz", NewAnonymousFunc(
false,
NewAnonymousFuncSignature().ReturnTypes("bool"),
NewReturnStatement("true"),
).Invocation(NewFuncInvocation())).
AddFieldRaw("qux", 12345).
AddFieldRaw("foobar", false)

{
gen, err := composeGenerator.Generate(0)

assert.NoError(t, err)
expected := `&Struct{
foo: "foo-value",
bar: "bar-value",
buz: func() bool {
return true
}(),
qux: 12345,
foobar: false,
}
`
assert.Equal(t, expected, gen)
}

{
gen, err := composeGenerator.Generate(2)

assert.NoError(t, err)
expected := ` &Struct{
foo: "foo-value",
bar: "bar-value",
buz: func() bool {
return true
}(),
qux: 12345,
foobar: false,
}
`
assert.Equal(t, expected, gen)
}
}

func TestShouldGenerateCompositeLiteralRaiseError(t *testing.T) {
_, err := NewCompositeLiteral("").AddField("foo", NewIf("")).Generate(0)
assert.EqualError(t, err, errmsg.IfConditionIsEmptyError().Error())
}

0 comments on commit a37fc26

Please sign in to comment.