This is an automated email from the git hooks/post-receive script.
git pushed a commit to branch main
in repository ego.
View the commit online.
commit 23181f96cfbbdbdef8c38161af6fe1bac7c5c8b5
Author: [email protected] <[email protected]>
AuthorDate: Sun Mar 29 22:00:53 2026 -0600
feat(ego-gen): add indexed property template with accessor pattern
Generate unexported accessor structs for indexed properties.
Each accessor captures the Eo object pointer and key values,
exposing Get() and/or Set() methods.
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
---
cmd/ego-gen/generator_test.go | 77 ++++++++++++++++++++++++++
cmd/ego-gen/templates/class.go.tmpl | 105 ++++++++++++++++++++++++++++++++++++
2 files changed, 182 insertions(+)
diff --git a/cmd/ego-gen/generator_test.go b/cmd/ego-gen/generator_test.go
index 5daff44..76da170 100644
--- a/cmd/ego-gen/generator_test.go
+++ b/cmd/ego-gen/generator_test.go
@@ -456,6 +456,83 @@ func TestGenerateClass_IndexedProperty(t *testing.T) {
}
}
+func TestGenerateClass_IndexedPropertyMultiValue(t *testing.T) {
+ g, outDir := newTestGenerator(t)
+
+ data := ClassData{
+ PackageName: "gfx",
+ GoName: "ColorClass",
+ EolianName: "Efl.Gfx.Color_Class",
+ CClassName: "EFL_GFX_COLOR_CLASS_CLASS",
+ CClassGetFunc: "efl_gfx_color_class_class_get",
+ CPrefix: "efl_gfx_color_class",
+ EOHeaderFile: "efl_gfx_color_class.eo.h",
+ IsAbstract: true,
+ IndexedProperties: []IndexedPropertyData{
+ {
+ GoAccessorMethod: "ColorClass",
+ AccessorTypeName: "colorClassProperty",
+ CGetName: "efl_gfx_color_class_get",
+ CSetName: "efl_gfx_color_class_set",
+ HasGet: true,
+ HasSet: true,
+ Keys: []ParamData{
+ {GoName: "colorClass", GoType: "string", CType: "const char *"},
+ {GoName: "layer", GoType: "int", CType: "int"},
+ },
+ IsMultiValue: true,
+ MultiGetValues: []MultiValueData{
+ {GoName: "R", LowerGoName: "r", GoType: "int", CType: "int"},
+ {GoName: "G", LowerGoName: "g", GoType: "int", CType: "int"},
+ {GoName: "B", LowerGoName: "b", GoType: "int", CType: "int"},
+ {GoName: "A", LowerGoName: "a", GoType: "int", CType: "int"},
+ },
+ MultiSetValues: []MultiValueData{
+ {GoName: "R", LowerGoName: "r", GoType: "int", CType: "int"},
+ {GoName: "G", LowerGoName: "g", GoType: "int", CType: "int"},
+ {GoName: "B", LowerGoName: "b", GoType: "int", CType: "int"},
+ {GoName: "A", LowerGoName: "a", GoType: "int", CType: "int"},
+ },
+ },
+ },
+ }
+
+ if err := g.GenerateClass(data); err != nil {
+ t.Fatalf("GenerateClass: %v", err)
+ }
+
+ outFile := filepath.Join(outDir, "gfx", "color_class.go")
+ content, err := os.ReadFile(outFile)
+ if err != nil {
+ t.Fatalf("output file not found at %s: %v", outFile, err)
+ }
+
+ src := string(content)
+
+ mustContain := []string{
+ // Accessor struct with two keys.
+ "type colorClassProperty struct",
+ "colorClass string",
+ "layer int",
+ // Accessor method with two key params.
+ "func (o *ColorClass) ColorClass(colorClass string, layer int) colorClassProperty",
+ // Multi-value getter.
+ "func (p colorClassProperty) Get() (r int, g int, b int, a int)",
+ "efl_gfx_color_class_get",
+ // Multi-value setter.
+ "func (p colorClassProperty) Set(r int, g int, b int, a int)",
+ "efl_gfx_color_class_set",
+ // String key conversion in Get/Set.
+ "C.CString(p.colorClass)",
+ }
+
+ for _, want := range mustContain {
+ if !strings.Contains(src, want) {
+ t.Errorf("output missing expected pattern %q\nfile content:\n%s", want, src)
+ }
+ }
+}
+
func TestToSnake(t *testing.T) {
tests := []struct {
input string
diff --git a/cmd/ego-gen/templates/class.go.tmpl b/cmd/ego-gen/templates/class.go.tmpl
index 326db32..0392bca 100644
--- a/cmd/ego-gen/templates/class.go.tmpl
+++ b/cmd/ego-gen/templates/class.go.tmpl
@@ -330,6 +330,103 @@ func (o *{{$.GoName}}) {{.GoName}}({{range $i, $p := .Params}}{{if $i}}, {{end}}
C.{{.CName}}((*C.Eo)(o.Eo()){{range .Params}}, {{template "paramArg" .}}{{end}})
{{- end}}
}
+{{- end}}
+{{- range $ip := .IndexedProperties}}
+
+type {{$ip.AccessorTypeName}} struct {
+ obj *C.Eo
+{{- range $ip.Keys}}
+ {{.GoName}} {{if needsStringConversion .CType}}string{{else if isBoolType .CType}}bool{{else if .IsEo}}efl.Objecter{{else if isPointerType .GoType}}unsafe.Pointer{{else}}{{.GoType}}{{end}}
+{{- end}}
+}
+
+// {{$ip.GoAccessorMethod}} returns an accessor for the {{$ip.GoAccessorMethod}} indexed property.
+func (o *{{$.GoName}}) {{$ip.GoAccessorMethod}}({{range $i, $k := $ip.Keys}}{{if $i}}, {{end}}{{$k.GoName}} {{if needsStringConversion $k.CType}}string{{else if isBoolType $k.CType}}bool{{else if $k.IsEo}}efl.Objecter{{else if isPointerType $k.GoType}}unsafe.Pointer{{else}}{{$k.GoType}}{{end}}{{end}}) {{$ip.AccessorTypeName}} {
+ return {{$ip.AccessorTypeName}}{
+ obj: (*C.Eo)(o.Eo()),
+{{- range $ip.Keys}}
+ {{.GoName}}: {{.GoName}},
+{{- end}}
+ }
+}
+
+{{- if $ip.HasGet}}
+{{- if $ip.IsMultiValue}}
+// Get returns the values for the captured key(s).
+func (p {{$ip.AccessorTypeName}}) Get() ({{range $i, $v := $ip.MultiGetValues}}{{if $i}}, {{end}}{{$v.LowerGoName}} {{$v.GoType}}{{end}}) {
+{{- range $ip.Keys}}
+{{- if needsStringConversion .CType}}
+ c{{.GoName}} := C.CString(p.{{.GoName}})
+ defer C.free(unsafe.Pointer(c{{.GoName}}))
+{{- end}}
+{{- end}}
+{{- range $v := $ip.MultiGetValues}}
+ var c{{$v.GoName}} C.{{cTypeToCgo $v.CType}}
+{{- end}}
+ C.{{$ip.CGetName}}(p.obj{{range $ip.Keys}}, {{template "indexedKeyArg" .}}{{end}}{{range $ip.MultiGetValues}}, &c{{.GoName}}{{end}})
+ return {{range $i, $v := $ip.MultiGetValues}}{{if $i}}, {{end}}{{- if isBoolType $v.CType}}c{{$v.GoName}} != 0{{else}}{{$v.GoType}}(c{{$v.GoName}}){{end}}{{end}}
+}
+{{- else}}
+// Get returns the value for the captured key(s).
+func (p {{$ip.AccessorTypeName}}) Get() {{if $ip.IsEo}}unsafe.Pointer{{else}}{{$ip.GoType}}{{end}} {
+{{- range $ip.Keys}}
+{{- if needsStringConversion .CType}}
+ c{{.GoName}} := C.CString(p.{{.GoName}})
+ defer C.free(unsafe.Pointer(c{{.GoName}}))
+{{- end}}
+{{- end}}
+{{- if needsStringConversion $ip.CType}}
+ cResult := C.{{$ip.CGetName}}(p.obj{{range $ip.Keys}}, {{template "indexedKeyArg" .}}{{end}})
+ return C.GoString(cResult)
+{{- else if isBoolType $ip.CType}}
+ return C.{{$ip.CGetName}}(p.obj{{range $ip.Keys}}, {{template "indexedKeyArg" .}}{{end}}) != 0
+{{- else if isPointerType $ip.GoType}}
+ return unsafe.Pointer(C.{{$ip.CGetName}}(p.obj{{range $ip.Keys}}, {{template "indexedKeyArg" .}}{{end}}))
+{{- else}}
+ return {{$ip.GoType}}(C.{{$ip.CGetName}}(p.obj{{range $ip.Keys}}, {{template "indexedKeyArg" .}}{{end}}))
+{{- end}}
+}
+{{- end}}
+{{- end}}
+
+{{- if $ip.HasSet}}
+{{- if $ip.IsMultiValue}}
+// Set sets the values for the captured key(s).
+func (p {{$ip.AccessorTypeName}}) Set({{range $i, $v := $ip.MultiSetValues}}{{if $i}}, {{end}}{{$v.LowerGoName}} {{$v.GoType}}{{end}}) {
+{{- range $ip.Keys}}
+{{- if needsStringConversion .CType}}
+ c{{.GoName}} := C.CString(p.{{.GoName}})
+ defer C.free(unsafe.Pointer(c{{.GoName}}))
+{{- end}}
+{{- end}}
+ C.{{$ip.CSetName}}(p.obj{{range $ip.Keys}}, {{template "indexedKeyArg" .}}{{end}}{{range $ip.MultiSetValues}}{{- if isBoolType .CType}}, func() C.{{cTypeToCgo .CType}} { if {{.LowerGoName}} { return 1 }; return 0 }(){{else}}, C.{{cTypeToCgo .CType}}({{.LowerGoName}}){{end}}{{end}})
+}
+{{- else}}
+// Set sets the value for the captured key(s).
+func (p {{$ip.AccessorTypeName}}) Set(val {{if $ip.IsEo}}efl.Objecter{{else}}{{$ip.GoType}}{{end}}) {
+{{- range $ip.Keys}}
+{{- if needsStringConversion .CType}}
+ c{{.GoName}} := C.CString(p.{{.GoName}})
+ defer C.free(unsafe.Pointer(c{{.GoName}}))
+{{- end}}
+{{- end}}
+{{- if needsStringConversion $ip.CType}}
+ cVal := C.CString(val)
+ defer C.free(unsafe.Pointer(cVal))
+ C.{{$ip.CSetName}}(p.obj{{range $ip.Keys}}, {{template "indexedKeyArg" .}}{{end}}, cVal)
+{{- else if isBoolType $ip.CType}}
+ var cVal C.{{cTypeToCgo $ip.CType}}
+ if val { cVal = 1 }
+ C.{{$ip.CSetName}}(p.obj{{range $ip.Keys}}, {{template "indexedKeyArg" .}}{{end}}, cVal)
+{{- else if isPointerType $ip.GoType}}
+ C.{{$ip.CSetName}}(p.obj{{range $ip.Keys}}, {{template "indexedKeyArg" .}}{{end}}, val)
+{{- else}}
+ C.{{$ip.CSetName}}(p.obj{{range $ip.Keys}}, {{template "indexedKeyArg" .}}{{end}}, C.{{cTypeToCgo $ip.CType}}(val))
+{{- end}}
+}
+{{- end}}
+{{- end}}
+
{{- end}}
{{- range .Events}}
@@ -364,3 +461,11 @@ func (o *{{$.GoName}}) {{.GoName}}(fn func({{if and .PayloadGoType (not (isPoint
{{- else}}C.{{cTypeToCgo .CType}}({{.GoName}})
{{- end}}
{{- end}}
+{{- define "indexedKeyArg"}}
+{{- if needsStringConversion .CType}}c{{.GoName}}
+{{- else if isBoolType .CType}}func() C.{{cTypeToCgo .CType}} { if p.{{.GoName}} { return 1 }; return 0 }()
+{{- else if .IsEo}}(*C.Eo)(p.{{.GoName}}.Eo())
+{{- else if isPointerType .GoType}}p.{{.GoName}}
+{{- else}}C.{{cTypeToCgo .CType}}(p.{{.GoName}})
+{{- end}}
+{{- end}}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.