struct-guard

command
v1.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 29, 2024 License: MIT Imports: 13 Imported by: 0

README

Struct-Guard Code Generator

The struct-guard tool, part of the devtoolkit library, generates wrapper structs in Go for tracking changes to the fields of the original struct. This tool simplifies the process of managing changes, appending values to slices, managing maps, and handling pointers within the structs.

Features

  • Generates wrapper structs with change tracking functionality.
  • Supports slices, maps, and pointers within structs.
  • Provides builder pattern for easy struct initialization.
  • Resets change tracking for the fields.

Installation

To install the devtoolkit library, you can use the following command:

go get github.com/rendis/devtoolkit

Usage

To run the struct-guard code generator, use the following command:

go run github.com/rendis/devtoolkit/generator/struct-guard

Configuration

The configuration for the struct-guard generator is provided in the devtoolkit.yml file. Below is the structure of the configuration file:

generators:
  struct-guard:
    generated-file-name: gen                 # The name of the generated file (optional, defaults to 'codegen.go')
    generated-struct-prefix: ''              # Prefix to be added to the generated struct name (optional, defaults to '')
    generated-struct-postfix: ''             # Postfix to be added to the generated struct name (optional, defaults to 'Wrapper')
    force-export: true                       # Flag to force export of the generated struct (optional, defaults to false)
    to-scan:                                 # List of directories or files to scan for structs
      - internal/core/domain/application_domain.go
      - internal/core/domain/process_order_domain.go
    exclude-files-to-scan:                   # List of files to exclude from scanning (optional)
      - internal/core/domain/excluded_file.go

Generated Code

The struct-guard tool generates a Go file based on the provided configuration. The generated file includes:

  • Wrapper Struct: A wrapper struct that embeds the original struct and tracks changes to its fields.
  • Change Tracking Struct: A struct to track changes for each field in the original struct.
  • Getter Methods: Methods to get the value of each field, with or without a change flag.
    • Get<FieldName>(): Returns the value of the field.
    • Get<FieldName>WithChange(): Returns the value of the field and a boolean indicating if the value has changed.
  • Setter Methods: Methods to set the value of each field and mark it as changed.
    • Set<FieldName>(value): Sets the value of the field and marks it as changed.
  • Slice Methods: Methods to append to a slice, get the last element, and check if it has changed.
    • GetLast<FieldName>(): Returns the last element of the slice.
    • GetLast<FieldName>WithChange(): Returns the last element of the slice and a boolean indicating if it has changed.
    • AppendTo<FieldName>(value): Appends a value to the slice and marks it as changed.
  • Map Methods: Methods to initialize, add to, remove from, and get values from a map, with change tracking.
    • Init<FieldName>(): Initializes the map if it is nil.
    • AddTo<FieldName>(key, value): Adds a key-value pair to the map and marks it as changed.
    • RemoveFrom<FieldName>(key): Removes a key from the map and marks it as changed.
    • Get<FieldName>Value(key): Returns the value for a given key in the map.
  • Pointer Methods: Methods to check if a pointer is nil, get the value if not nil, and get the value or zero if nil.
    • Is<FieldName>Nil(): Returns true if the pointer is nil.
    • Get<FieldName>Value(): Returns the value of the pointer and a boolean indicating if the value is not nil.
    • Get<FieldName>OrZeroValue(): Returns the value of the pointer or a zero value if the pointer is nil.
  • Builder Pattern: A builder struct and methods to initialize the wrapper struct with a fluent API.
    • ToBuilder(): Returns a builder for the wrapper struct.
    • New<WrapperName>Builder(): Returns a new builder for the wrapper struct.
    • Build(): Returns the built wrapper struct.
    • With<FieldName>(value): Sets the value of the field in the builder.

Example

Given the following structure and configuration:

example/example.go

type exampleStruct struct {
	intValue   int
	strValue   string
	ptrValue   *string
	sliceValue []string
	mapValue   map[string]string
}

devtoolkit.yml

generators:
  struct-guard:
    generated-file-name: gen
    generated-struct-postfix: ''
    force-export: true
    to-scan:
      - example/example.go

The result is the following generated code:

gen.go

// Code generated by 'devtoolkit/generators/struct-guard'. DO NOT EDIT.
// Any changes made to this file will be lost when the file is regenerated

package main

// ExampleStruct wraps exampleStruct with changes tracking
type ExampleStruct struct {
	exampleStruct
	changes exampleStructChanges
}

// exampleStructChanges is a struct to track changes in exampleStruct
type exampleStructChanges struct {
	intValueChanged   bool
	strValueChanged   bool
	ptrValueChanged   bool
	sliceValueChanged bool
	mapValueChanged   bool
}

// ResetChanges resets the changes in exampleStruct
func (w *ExampleStruct) ResetChanges() {
	w.changes = exampleStructChanges{}
}

// GetIntValue returns the value of exampleStruct.intValue
func (w *ExampleStruct) GetIntValue() int {
	return w.exampleStruct.intValue
}

// GetIntValueWithChange returns the value of exampleStruct.intValue and a boolean indicating if the value has changed
func (w *ExampleStruct) GetIntValueWithChange() (int, bool) {
	return w.exampleStruct.intValue, w.changes.intValueChanged
}

// SetIntValue sets the value of exampleStruct.intValue
func (w *ExampleStruct) SetIntValue(value int) {
	w.exampleStruct.intValue = value
	w.changes.intValueChanged = true
}

// GetStrValue returns the value of exampleStruct.strValue
func (w *ExampleStruct) GetStrValue() string {
	return w.exampleStruct.strValue
}

// GetStrValueWithChange returns the value of exampleStruct.strValue and a boolean indicating if the value has changed
func (w *ExampleStruct) GetStrValueWithChange() (string, bool) {
	return w.exampleStruct.strValue, w.changes.strValueChanged
}

// SetStrValue sets the value of exampleStruct.strValue
func (w *ExampleStruct) SetStrValue(value string) {
	w.exampleStruct.strValue = value
	w.changes.strValueChanged = true
}

// GetPtrValue returns the value of exampleStruct.ptrValue
func (w *ExampleStruct) GetPtrValue() *string {
	return w.exampleStruct.ptrValue
}

// GetPtrValueWithChange returns the value of exampleStruct.ptrValue and a boolean indicating if the value has changed
func (w *ExampleStruct) GetPtrValueWithChange() (*string, bool) {
	return w.exampleStruct.ptrValue, w.changes.ptrValueChanged
}

// SetPtrValue sets the value of exampleStruct.ptrValue
func (w *ExampleStruct) SetPtrValue(value *string) {
	w.exampleStruct.ptrValue = value
	w.changes.ptrValueChanged = true
}

// IsPtrValueNil returns true if exampleStruct.ptrValue is nil
func (w *ExampleStruct) IsPtrValueNil() bool {
	return w.exampleStruct.ptrValue == nil
}

// GetPtrValueValue returns the value of exampleStruct.ptrValue and a boolean indicating if the value is not nil
func (w *ExampleStruct) GetPtrValueValue() (string, bool) {
	if w.exampleStruct.ptrValue == nil {
		var zero string
		return zero, false
	}
	return *w.exampleStruct.ptrValue, true
}

// GetPtrValueOrZeroValue returns the value of exampleStruct.ptrValue and a zero value if the value is nil
func (w *ExampleStruct) GetPtrValueOrZeroValue() string {
	if w.exampleStruct.ptrValue == nil {
		var zero string
		return zero
	}
	return *w.exampleStruct.ptrValue
}

// GetSliceValue returns the value of exampleStruct.sliceValue
func (w *ExampleStruct) GetSliceValue() []string {
	return w.exampleStruct.sliceValue
}

// GetSliceValueWithChange returns the value of exampleStruct.sliceValue and a boolean indicating if the value has changed
func (w *ExampleStruct) GetSliceValueWithChange() ([]string, bool) {
	return w.exampleStruct.sliceValue, w.changes.sliceValueChanged
}

// SetSliceValue sets the value of exampleStruct.sliceValue
func (w *ExampleStruct) SetSliceValue(value []string) {
	w.exampleStruct.sliceValue = value
	w.changes.sliceValueChanged = true
}

// GetLastSliceValue returns the last value of exampleStruct.sliceValue
func (w *ExampleStruct) GetLastSliceValue() (string, bool) {
	if len(w.exampleStruct.sliceValue) == 0 {
		var zero string
		return zero, false
	}
	return w.exampleStruct.sliceValue[len(w.exampleStruct.sliceValue)-1], true
}

// GetLastSliceValueWithChange returns the last value of exampleStruct.sliceValue and a boolean indicating if the value has changed
func (w *ExampleStruct) GetLastSliceValueWithChange() (string, bool) {
	if len(w.exampleStruct.sliceValue) == 0 {
		var zero string
		return zero, w.changes.sliceValueChanged
	}
	return w.exampleStruct.sliceValue[len(w.exampleStruct.sliceValue)-1], w.changes.sliceValueChanged
}

// AppendToSliceValue appends a value to exampleStruct.sliceValue
func (w *ExampleStruct) AppendToSliceValue(value string) {
	w.exampleStruct.sliceValue = append(w.exampleStruct.sliceValue, value)
	w.changes.sliceValueChanged = true
}

// GetMapValue returns the value of exampleStruct.mapValue
func (w *ExampleStruct) GetMapValue() map[string]string {
	return w.exampleStruct.mapValue
}

// GetMapValueWithChange returns the value of exampleStruct.mapValue and a boolean indicating if the value has changed
func (w *ExampleStruct) GetMapValueWithChange() (map[string]string, bool) {
	return w.exampleStruct.mapValue, w.changes.mapValueChanged
}

// SetMapValue sets the value of exampleStruct.mapValue
func (w *ExampleStruct) SetMapValue(value map[string]string) {
	w.exampleStruct.mapValue = value
	w.changes.mapValueChanged = true
}

// InitMapValue initializes exampleStruct.mapValue if it is nil
func (w *ExampleStruct) InitMapValue() {
	if w.exampleStruct.mapValue == nil {
		w.exampleStruct.mapValue = make(map[string]string)
	}
}

// AddToMapValue adds a value to exampleStruct.mapValue
func (w *ExampleStruct) AddToMapValue(key string, value string) {
	if w.exampleStruct.mapValue == nil {
		w.InitMapValue()
	}
	w.exampleStruct.mapValue[key] = value
	w.changes.mapValueChanged = true
}

// RemoveFromMapValue removes a value from exampleStruct.mapValue
func (w *ExampleStruct) RemoveFromMapValue(key string) {
	if w.exampleStruct.mapValue == nil {
		return
	}

	if _, ok := w.exampleStruct.mapValue[key]; ok {
		delete(w.exampleStruct.mapValue, key)
		w.changes.mapValueChanged = true
	}
}

// GetMapValueValue returns the value of exampleStruct.mapValue for the given key
func (w *ExampleStruct) GetMapValueValue(key string) (string, bool) {
	if w.exampleStruct.mapValue == nil {
		var zero string
		return zero, false
	}
	value, ok := w.exampleStruct.mapValue[key]
	return value, ok
}

// ToBuilder returns a builder for ExampleStruct
func (w *ExampleStruct) ToBuilder() *ExampleStructBuilder {
	return &ExampleStructBuilder{wrapper: w}
}

// ExampleStructBuilder is a builder for ExampleStruct
type ExampleStructBuilder struct {
	wrapper *ExampleStruct
}

// NewExampleStructBuilder returns a new ExampleStructBuilder
func NewExampleStructBuilder() *ExampleStructBuilder {
	return &ExampleStructBuilder{wrapper: NewExampleStruct()}
}

// Build returns the built ExampleStruct
func (b *ExampleStructBuilder) Build() *ExampleStruct {
	return b.wrapper
}

// WithIntValue sets the value of exampleStruct.intValue and returns the builder
// This method only sets the value of exampleStruct.intValue and does not track changes
func (b *ExampleStructBuilder) WithIntValue(value int) *ExampleStructBuilder {
	b.wrapper.exampleStruct.intValue = value
	return b
}

// WithStrValue sets the value of exampleStruct.strValue and returns the builder
// This method only sets the value of exampleStruct.strValue and does not track changes
func (b *ExampleStructBuilder) WithStrValue(value string) *ExampleStructBuilder {
	b.wrapper.exampleStruct.strValue = value
	return b
}

// WithPtrValue sets the value of exampleStruct.ptrValue and returns the builder
// This method only sets the value of exampleStruct.ptrValue and does not track changes
func (b *ExampleStructBuilder) WithPtrValue(value *string) *ExampleStructBuilder {
	b.wrapper.exampleStruct.ptrValue = value
	return b
}

// WithSliceValue sets the value of exampleStruct.sliceValue and returns the builder
// This method only sets the value of exampleStruct.sliceValue and does not track changes
func (b *ExampleStructBuilder) WithSliceValue(value []string) *ExampleStructBuilder {
	b.wrapper.exampleStruct.sliceValue = value
	return b
}

// WithMapValue sets the value of exampleStruct.mapValue and returns the builder
// This method only sets the value of exampleStruct.mapValue and does not track changes
func (b *ExampleStructBuilder) WithMapValue(value map[string]string) *ExampleStructBuilder {
	b.wrapper.exampleStruct.mapValue = value
	return b
}

// NewExampleStruct returns a new ExampleStruct
func NewExampleStruct() *ExampleStruct {
	return &ExampleStruct{}
}

// NewExampleStructFrom returns a new ExampleStruct with the given exampleStruct
func NewExampleStructFrom(exampleStruct exampleStruct) *ExampleStruct {
	return &ExampleStruct{
		exampleStruct: exampleStruct,
	}
}

Usage Example

Here is an example that demonstrates the usage of each generated functionality for ExampleStruct:

// Create a new ExampleStruct instance
wrapper := NewExampleStruct()

// Set values using setter methods
wrapper.SetIntValue(42)
wrapper.SetStrValue("Hello, World!")

// Pointer value manipulation
str := "PointerValue"
wrapper.SetPtrValue(&str)

// Get pointer value (or zero value if nil)
zeroValue := wrapper.GetPtrValueOrZeroValue()
fmt.Println("PtrValue or zero value:", zeroValue)

// Slice manipulation
wrapper.AppendToSliceValue("Value1")
wrapper.AppendToSliceValue("Value2")

// Map manipulation
wrapper.InitMapValue()
wrapper.AddToMapValue("key1", 100)
wrapper.AddToMapValue("key2", 200)

// Get values using getter methods
fmt.Println("IntValue:", wrapper.GetIntValue())
fmt.Println("StrValue:", wrapper.GetStrValue())

// Get values with change status
intValue, intValueChanged := wrapper.GetIntValueWithChange()
fmt.Println("IntValue with change status:", intValue, intValueChanged)

strValue, strValueChanged := wrapper.GetStrValueWithChange()
fmt.Println("StrValue with change status:", strValue, strValueChanged)

// Manipulate slice
lastSliceValue, lastSliceChanged := wrapper.GetLastSliceValueWithChange()
fmt.Println("Last SliceValue with change status:", lastSliceValue, lastSliceChanged)

// Manipulate map
mapValue, exists := wrapper.GetMapValueValue("key1")
fmt.Println("MapValue key1 value:", mapValue, exists)
wrapper.RemoveFromMapValue("key1")

// Check pointer field
if wrapper.IsPtrValueNil() {
    fmt.Println("PtrValue is nil")
} else {
    ptrValue, ptrExists := wrapper.GetPtrValueWithChange()
    fmt.Println("PtrValue value:", *ptrValue, ptrExists)
}

// Reset changes
wrapper.ResetChanges()

// Use builder to create a new instance
builder := NewExampleStructBuilder().
    WithIntValue(84).
    WithStrValue("BuilderValue").
    WithSliceValue([]string{"BuilderValue1", "BuilderValue2"}).
    WithMapValue(map[string]int{"builderKey1": 300}).
    WithPtrValue(&str).
    Build()

fmt.Println("Builder IntValue:", builder.GetIntValue())
fmt.Println("Builder StrValue:", builder.GetStrValue())

Documentation

The Go Gopher

There is no documentation for this package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL