Skip to content

Commit f002872

Browse files
Merge pull request #4 from MartinSimango/feat/add-examples
Refactor task logic and fix some bugs
2 parents 5a35962 + eff4f35 commit f002872

30 files changed

Lines changed: 886 additions & 311 deletions

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@ main/
1717

1818
dist/
1919
.DS_Store
20-
examples/
20+
future_ideas.txt
21+

builder.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,10 @@ type Builder interface {
1010
// Build returns a DynamicStructModifier instance.
1111
Build() DynamicStructModifier
1212

13-
// GetField returns a builder instance of the subfield of the struct that is currently being built.
13+
// GetField returns a builder instance of the subfield of the struct that is currently being built. It will panic if the
14+
// field is not a struct or does not fully dereference to a struct value. It returns nil if field does not exist.
1415
GetField(name string) Builder
1516

16-
// GetFieldCopy returns a copy of a builder instance of the subfield of the struct that is currently being built.
17-
//
18-
// Deprecated: this method will be removed use NewBuilderFromField instead.
19-
GetFieldCopy(name string) Builder
20-
2117
// GetNewBuilderFromField returns a new builder instance where the subfield of the struct "field" is the root of the struct.
2218
NewBuilderFromField(field string) Builder
2319

dreflect/dreflect.go

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// package dreflect adds more advanced reflection functionality to the standard reflect package by providing additional functions to convert between different types.
2+
13
package dreflect
24

35
import (
@@ -34,7 +36,13 @@ func ConvertToType[T any](val any) T {
3436
func Convert(val reflect.Value, typ reflect.Type) reflect.Value {
3537
defer func() {
3638
if r := recover(); r != nil {
37-
panic(fmt.Sprintf("dreflect.Convert: value of type %v cannot be converted to type %v", val.Type(), typ))
39+
panic(
40+
fmt.Sprintf(
41+
"dreflect.Convert: value of type %v cannot be converted to type %v",
42+
val.Type(),
43+
typ,
44+
),
45+
)
3846
}
3947
}()
4048
dst := reflect.New(typ).Elem()
@@ -45,7 +53,6 @@ func Convert(val reflect.Value, typ reflect.Type) reflect.Value {
4553
}
4654

4755
func convertibleTo(src, dst reflect.Type) bool {
48-
4956
return !src.ConvertibleTo(dst) &&
5057
src.Kind() != reflect.Struct &&
5158
src.Kind() != reflect.Slice &&
@@ -54,9 +61,14 @@ func convertibleTo(src, dst reflect.Type) bool {
5461
}
5562

5663
func convert(src reflect.Value, dst reflect.Value) reflect.Value {
57-
5864
if convertibleTo(src.Type(), dst.Type()) {
59-
panic(fmt.Sprintf("dreflect.Convert: value of type %s cannot be converted to type %s", src.Type(), dst.Type()))
65+
panic(
66+
fmt.Sprintf(
67+
"dreflect.Convert: value of type %s cannot be converted to type %s",
68+
src.Type(),
69+
dst.Type(),
70+
),
71+
)
6072
}
6173

6274
switch src.Kind() {
@@ -67,13 +79,26 @@ func convert(src reflect.Value, dst reflect.Value) reflect.Value {
6779
sNum := srcStruct.NumField()
6880

6981
if dNum != sNum {
70-
panic(fmt.Sprintf("dreflect.Convert: Number of struct fields differ %s has %d subfield(s) and %s has %d subfield(s)", src.Type(), sNum, dst.Type(), dNum))
71-
82+
panic(
83+
fmt.Sprintf(
84+
"dreflect.Convert: Number of struct fields differ %s has %d subfield(s) and %s has %d subfield(s)",
85+
src.Type(),
86+
sNum,
87+
dst.Type(),
88+
dNum,
89+
),
90+
)
7291
}
7392
for i := 0; i < newStruct.NumField(); i++ {
7493
f := srcStruct.Field(i)
7594
if srcStruct.Type().Field(i).Name != newStruct.Type().Field(i).Name {
76-
panic(fmt.Sprintf("dreflect.Convert: value of type %s cannot be converted to type %s", src.Type(), dst.Type()))
95+
panic(
96+
fmt.Sprintf(
97+
"dreflect.Convert: value of type %s cannot be converted to type %s",
98+
src.Type(),
99+
dst.Type(),
100+
),
101+
)
77102
}
78103
fieldValue := reflect.NewAt(f.Type(), unsafe.Pointer(f.UnsafeAddr())).Elem()
79104
newField := convert(fieldValue, dst.Field(i))
@@ -100,7 +125,13 @@ func convert(src reflect.Value, dst reflect.Value) reflect.Value {
100125
return newSlice
101126
case reflect.Array:
102127
if src.Len() != dst.Len() {
103-
panic(fmt.Sprintf("dreflect.Convert: value of type %s cannot be converted to type %s", src.Type(), dst.Type()))
128+
panic(
129+
fmt.Sprintf(
130+
"dreflect.Convert: value of type %s cannot be converted to type %s",
131+
src.Type(),
132+
dst.Type(),
133+
),
134+
)
104135
}
105136
dstSliceType := GetSliceType(dst.Interface())
106137

@@ -118,17 +149,26 @@ func convert(src reflect.Value, dst reflect.Value) reflect.Value {
118149
dstPointerValueType := dst.Type().Elem()
119150
srcPointerValue := reflect.ValueOf(GetUnderlyingPointerValue(src.Interface()))
120151

121-
if src.Type().Elem().Kind() != dst.Type().Elem().Kind() && src.Elem().Kind() >= 1 && src.Elem().Kind() <= 14 {
122-
panic(fmt.Sprintf("dreflect.Convert: value of type %s cannot be converted to type %s", src.Type(), dst.Type()))
152+
if src.Type().Elem().Kind() != dst.Type().Elem().Kind() && src.Elem().Kind() >= 1 &&
153+
src.Elem().Kind() <= 14 {
154+
panic(
155+
fmt.Sprintf(
156+
"dreflect.Convert: value of type %s cannot be converted to type %s",
157+
src.Type(),
158+
dst.Type(),
159+
),
160+
)
123161
}
124162

125163
retPointer := reflect.New(dst.Type())
126-
//ensure that new pointer uses same memory address as src pointer
164+
// ensure that new pointer uses same memory address as src pointer
127165
reflect.NewAt(src.Type(), unsafe.Pointer(retPointer.Elem().UnsafeAddr())).Elem().
128166
Set(src)
129167

130168
// now copy over the values from the src
131-
retPointer.Elem().Elem().Set(convert(srcPointerValue, reflect.New(dstPointerValueType).Elem()))
169+
retPointer.Elem().
170+
Elem().
171+
Set(convert(srcPointerValue, reflect.New(dstPointerValueType).Elem()))
132172

133173
return retPointer.Elem()
134174

dstruct.generated.struct.go

Lines changed: 53 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ type DStructGeneratedStruct[T any] struct {
2525
fieldContexts GeneratedFieldContexts
2626
structConfig core.GeneratedFieldConfig
2727
instance T
28-
customTypes map[reflect.Type]core.FunctionHolder
28+
customTypes map[string]core.FunctionHolder
2929
}
3030

3131
var _ GeneratedStruct = &DStructGeneratedStruct[int]{}
@@ -50,11 +50,11 @@ func NewGeneratedStructWithConfig[T any](val T,
5050
cfg,
5151
settings,
5252
),
53-
customTypes: make(map[reflect.Type]core.FunctionHolder),
53+
customTypes: make(map[string]core.FunctionHolder),
5454
}
5555

5656
for _, v := range customTypes {
57-
generatedStruct.addCustomType(v)
57+
generatedStruct.AddCustomType(v)
5858
}
5959
generatedStruct.addCustomTypes()
6060
generatedStruct.populateGeneratedFields(generatedStruct.root)
@@ -74,6 +74,11 @@ func (gs *DStructGeneratedStruct[T]) NewT() *T {
7474

7575
// Generate implements GeneratedStruct.Generate.
7676
func (gs *DStructGeneratedStruct[T]) Generate() {
77+
// TODO: should only be called if new struct fields are generated
78+
// an idea is to have generatedFields return a bool to indicate if new fields were generated
79+
// also make this method private
80+
81+
// gs.populateGeneratedFields(gs.root) // in case new fields are added /
7782
gs.generateFields()
7883

7984
switch any(*new(T)).(type) {
@@ -83,10 +88,14 @@ func (gs *DStructGeneratedStruct[T]) Generate() {
8388
}
8489

8590
gs.instance = toType[T](gs.DynamicStructModifierImpl)
91+
}
8692

87-
// TODO: should only be called if new struct fields are generated
88-
// an idea is to have generatedFields return a bool to indicate if new fields were generated
89-
gs.Update()
93+
func (gs *DStructGeneratedStruct[T]) Set(field string, value any) error {
94+
if err := gs.DynamicStructModifierImpl.Set(field, value); err != nil {
95+
return err
96+
}
97+
gs.populateGeneratedFields(gs.fieldNodeMap[field].parent)
98+
return nil
9099
}
91100

92101
// SetFieldGenerationSettings implements GeneratedStruct.SetFieldGenerationSettings
@@ -148,7 +157,7 @@ func (gs *DStructGeneratedStruct[T]) SetFieldGenerationConfig(
148157
return err
149158
}
150159

151-
if gs.fieldContexts[field] == nil {
160+
if gs.fieldContexts[field] == nil { // if field has children
152161
gs.propagateConfig(gs.fieldNodeMap[field], cfg)
153162
} else {
154163
// this will be fields that are either custom types or fields that have no children
@@ -257,24 +266,18 @@ func (gs *DStructGeneratedStruct[T]) SetGenerationFunctions(
257266
gs.propagateGenerationFunctions(gs.root, functions)
258267
}
259268

260-
// SetFieldFromTask implements GeneratedStruct.SetFieldFromTask
261-
func (gs *DStructGeneratedStruct[T]) SetFieldFromTask(
269+
// SetFieldFromTaskInstance implements GeneratedStruct.SetFieldFromTaskInstanc
270+
func (gs *DStructGeneratedStruct[T]) SetFieldFromTaskInstance(
262271
field string,
263-
task generator.Task,
264-
params ...any,
272+
taskInstance generator.TaskInstance,
265273
) error {
266-
taskProperties, err := generator.CreateTaskProperties(
267-
field,
268-
generator.GetTagForTask(generator.TaskName(task.Name()), params...),
269-
)
270-
if err != nil {
271-
return err
272-
}
273-
274274
gs.SetFieldGenerationFunction(
275275
field,
276-
core.NewFunctionHolderNoArgs(task.GenerationFunction(*taskProperties)),
276+
core.NewFunctionHolderNoArgs(
277+
taskInstance.GenerationFunction(),
278+
),
277279
)
280+
278281
return nil
279282
}
280283

@@ -311,35 +314,41 @@ func toPointerType[T any](gs DynamicStructModifier) *T {
311314
}
312315

313316
func (gs *DStructGeneratedStruct[T]) generateFields() {
317+
// wg := sync.WaitGroup{}
314318
for k, genFunc := range gs.fieldContexts {
319+
// wg.Add(1)
320+
// go func(k string, genFunc *core.GeneratedFieldContext) {
315321
if err := gs.Set(k, genFunc.Generate()); err != nil {
316322
fmt.Println(err)
317323
}
324+
// wg.Done()
325+
// }(k, genFunc)
318326
}
327+
// wg.Wait()
319328
}
320329

321330
func (gs *DStructGeneratedStruct[T]) addCustomTypes() {
322-
gs.addCustomType(
331+
gs.AddCustomType(
323332
CustomType{
324333
time.Time{},
325334
core.DefaultDateFunctionHolder(gs.structConfig.GenerationConfig.Date()),
326335
},
327336
)
328337
}
329338

330-
func (gs *DStructGeneratedStruct[T]) addCustomType(customType CustomType) {
339+
func (gs *DStructGeneratedStruct[T]) AddCustomType(customType CustomType) {
331340
// TODO: restrict some types from being added such as nil, ints etc
332-
gs.customTypes[reflect.TypeOf(customType.Value)] = customType.FunctionHolder
341+
gs.customTypes[reflect.TypeOf(customType.Value).String()] = customType.FunctionHolder
333342
// the function holder kind is the find that the function retrusn which could either be an existing kind or a new kind i.ie time.Time would be a new kind
334343
// TODO:idea: GenerationsFunction key should be type of CustomKind and not reflect.Kind
335344
gs.structConfig.GenerationFunctions[customType.FunctionHolder.Kind()] = customType.FunctionHolder
336345
}
337346

338347
func (gs *DStructGeneratedStruct[T]) createGeneratedField(
339-
field *Node[structField],
348+
field *Node[StructField],
340349
kind reflect.Kind,
341350
) *core.GeneratedField {
342-
v := core.NewGeneratedField(field.data.fullyQualifiedName,
351+
v := core.NewGeneratedField(field.data.qualifiedName,
343352
field.data.value,
344353
field.data.tag,
345354
gs.structConfig.Copy(kind),
@@ -348,75 +357,77 @@ func (gs *DStructGeneratedStruct[T]) createGeneratedField(
348357
return v
349358
}
350359

351-
func (gs *DStructGeneratedStruct[T]) populateGeneratedFields(node *Node[structField]) {
360+
func (gs *DStructGeneratedStruct[T]) populateGeneratedFields(node *Node[StructField]) {
352361
for _, field := range node.children {
362+
if gs.fieldContexts[field.data.qualifiedName] != nil {
363+
continue
364+
}
365+
353366
if customType := gs.customTypes[field.data.goType]; customType != nil {
354-
gs.fieldContexts[field.data.fullyQualifiedName] = core.NewGeneratedFieldContext(
367+
gs.fieldContexts[field.data.qualifiedName] = core.NewGeneratedFieldContext(
355368
gs.createGeneratedField(field, customType.Kind()),
356369
)
357370
} else if field.HasChildren() {
358371
gs.populateGeneratedFields(field)
359372
} else {
360-
gs.fieldContexts[field.data.fullyQualifiedName] = core.NewGeneratedFieldContext(
373+
gs.fieldContexts[field.data.qualifiedName] = core.NewGeneratedFieldContext(
361374
gs.createGeneratedField(field, field.data.value.Kind()),
362375
)
363376
}
364377
}
365378
}
366379

367380
func (gs *DStructGeneratedStruct[T]) propagateConfig(
368-
node *Node[structField],
381+
node *Node[StructField],
369382
cfg config.Config,
370383
) {
371384
for _, field := range node.children {
372385
// Don't propagate changes to children nodes if the field is a custom type
373-
if field.HasChildren() &&
374-
!gs.fieldContexts[field.data.fullyQualifiedName].GeneratedField.IsCustomType() {
386+
if field.HasChildren() && gs.customTypes[field.data.goType] == nil {
375387
gs.propagateConfig(field, cfg)
376388
} else {
377-
gs.fieldContexts[field.data.fullyQualifiedName].GeneratedField.SetConfig(cfg)
389+
gs.fieldContexts[field.data.qualifiedName].GeneratedField.SetConfig(cfg)
378390
}
379391
}
380392
}
381393

382394
func (gs *DStructGeneratedStruct[T]) propagateSettings(
383-
node *Node[structField],
395+
node *Node[StructField],
384396
settings config.GenerationSettings,
385397
) {
386398
for _, field := range node.children {
387-
if field.HasChildren() &&
388-
!gs.fieldContexts[field.data.fullyQualifiedName].GeneratedField.IsCustomType() {
399+
if field.HasChildren() && gs.customTypes[field.data.goType] == nil {
389400
gs.propagateSettings(field, settings)
390401
} else {
391-
gs.fieldContexts[field.data.fullyQualifiedName].GeneratedField.SetGenerationSettings(settings)
402+
gs.fieldContexts[field.data.qualifiedName].GeneratedField.SetGenerationSettings(settings)
392403
}
393404
}
394405
}
395406

396407
func (gs *DStructGeneratedStruct[T]) propagateGenerationFunctions(
397-
node *Node[structField],
408+
node *Node[StructField],
398409
functions core.DefaultGenerationFunctions,
399410
) {
400411
for _, field := range node.children {
401412
if field.HasChildren() &&
402-
!gs.fieldContexts[field.data.fullyQualifiedName].GeneratedField.IsCustomType() {
413+
!gs.fieldContexts[field.data.qualifiedName].GeneratedField.IsCustomType() {
403414
gs.propagateGenerationFunctions(field, functions)
404415
} else {
405-
gs.fieldContexts[field.data.fullyQualifiedName].GeneratedField.SetGenerationFunctions(functions)
416+
gs.fieldContexts[field.data.qualifiedName].GeneratedField.SetGenerationFunctions(functions)
406417
}
407418
}
408419
}
409420

410421
func (gs *DStructGeneratedStruct[T]) propagateGenerationFunction(
411-
node *Node[structField],
422+
node *Node[StructField],
412423
functionHolder core.FunctionHolder,
413424
) {
414425
for _, field := range node.children {
415426
if field.HasChildren() &&
416-
!gs.fieldContexts[field.data.fullyQualifiedName].GeneratedField.IsCustomType() {
427+
!gs.fieldContexts[field.data.qualifiedName].GeneratedField.IsCustomType() {
417428
gs.propagateGenerationFunction(field, functionHolder)
418429
} else {
419-
gs.fieldContexts[field.data.fullyQualifiedName].GeneratedField.SetGenerationFunction(functionHolder)
430+
gs.fieldContexts[field.data.qualifiedName].GeneratedField.SetGenerationFunction(functionHolder)
420431
}
421432
}
422433
}

0 commit comments

Comments
 (0)