v2/tools/generator/internal/astbuilder/composite_literals.go (42 lines of code) (raw):
/*
* Copyright (c) Microsoft Corporation.
* Licensed under the MIT license.
*/
package astbuilder
import (
"github.com/dave/dst"
)
// CompositeLiteralBuilder captures the information required to generate code for an inline struct initialization
type CompositeLiteralBuilder struct {
structType dst.Expr
elts []dst.Expr
newLines bool
}
// NewCompositeLiteralBuilder creates a new instance for initialization of the specified struct
// structType is an expression to handle both structs from the current package and imported ones requiring qualification
func NewCompositeLiteralBuilder(structType dst.Expr) *CompositeLiteralBuilder {
return &CompositeLiteralBuilder{
structType: structType,
newLines: true,
}
}
// WithoutNewLines returns the CompositeLiteralBuilder without NewLines enabled
func (b *CompositeLiteralBuilder) WithoutNewLines() *CompositeLiteralBuilder {
b.newLines = false
return b
}
// AddField adds initialization of another field
// Returns the receiver to allow method chaining when desired
func (b *CompositeLiteralBuilder) AddField(name string, value dst.Expr) *CompositeLiteralBuilder {
expr := &dst.KeyValueExpr{
Key: dst.NewIdent(name),
Value: dst.Clone(value).(dst.Expr),
}
expr.Decs.Before = dst.NewLine
expr.Decs.After = dst.NewLine
b.elts = append(b.elts, expr)
return b
}
// Build constructs the actual dst.CompositeLit that's required
func (b *CompositeLiteralBuilder) Build() *dst.CompositeLit {
// If we only have a single element, remove the NewLine directives to force it onto a single line.
// While there are places where this doesn't look amazing, on balance it is cleaner than having them
// on multiple lines. This is especially true when the CompositeLit is used in a deeply nested context.
if len(b.elts) == 1 {
for _, elt := range b.elts {
kvExpr := elt.(*dst.KeyValueExpr) // This is safe because it's the only type we put into elts
kvExpr.Decs.Before = dst.None
kvExpr.Decs.After = dst.None
}
}
return &dst.CompositeLit{
Type: b.structType,
Elts: b.elts,
}
}