diff --git a/cmd/generate-bindings/solana/anchor-go/generator/types.go b/cmd/generate-bindings/solana/anchor-go/generator/types.go index d3822fb1..23e5386d 100644 --- a/cmd/generate-bindings/solana/anchor-go/generator/types.go +++ b/cmd/generate-bindings/solana/anchor-go/generator/types.go @@ -171,7 +171,10 @@ func (g *Generator) gen_complexEnum(name string, docs []string, typ idl.IdlTypeD argBody.Switch(Id("tmp").Dot("Enum")). BlockFunc(func(switchGroup *Group) { - interfaceType := g.idl.Types.ByName(enumName) + interfaceType := g.idl.Types.ByName(name) + if interfaceType == nil { + panic(fmt.Errorf("complex enum type %q not found in IDL types", name)) + } for variantIndex, variant := range interfaceType.Ty.(*idl.IdlTypeDefTyEnum).Variants { variantTypeNameComplex := formatComplexEnumVariantTypeName(enumName, variant.Name) @@ -226,8 +229,10 @@ func (g *Generator) gen_complexEnum(name string, docs []string, typ idl.IdlTypeD argBody.List(Id("tmp")).Op(":=").Id(formatEnumContainerName(enumTypeName)).Block() argBody.Switch(Id("realvalue").Op(":=").Id("value").Op(".").Parens(Type())). BlockFunc(func(switchGroup *Group) { - // TODO: maybe it's from idl.Accounts ??? - interfaceType := g.idl.Types.ByName(enumTypeName) + interfaceType := g.idl.Types.ByName(name) + if interfaceType == nil { + panic(fmt.Errorf("complex enum type %q not found in IDL types", name)) + } for variantIndex, variant := range interfaceType.Ty.(*idl.IdlTypeDefTyEnum).Variants { variantTypeNameStruct := formatComplexEnumVariantTypeName(enumTypeName, variant.Name) diff --git a/cmd/generate-bindings/solana/anchor-go/generator/types_test.go b/cmd/generate-bindings/solana/anchor-go/generator/types_test.go new file mode 100644 index 00000000..fbd4083d --- /dev/null +++ b/cmd/generate-bindings/solana/anchor-go/generator/types_test.go @@ -0,0 +1,100 @@ +//nolint:all // Forked from anchor-go generator, maintaining original code structure +package generator + +import ( + "testing" + + "github.com/gagliardetto/anchor-go/idl" + "github.com/gagliardetto/anchor-go/idl/idltype" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func makeComplexEnumIDL(enumName string) *idl.Idl { + enumType := &idl.IdlTypeDefTyEnum{ + Kind: "enum", + Variants: idl.VariantSlice{ + {Name: "Simple"}, + { + Name: "WithFields", + Fields: idl.Some[idl.IdlDefinedFields](idl.IdlDefinedFieldsNamed{ + {Name: "value", Ty: &idltype.U64{}}, + }), + }, + }, + } + + return &idl.Idl{ + Types: idl.IdTypeDef_slice{ + { + Name: enumName, + Ty: enumType, + }, + }, + } +} + +func TestGenComplexEnum_ConsecutiveUppercase(t *testing.T) { + // "HTTPStatus" is stored in the IDL as-is. ToCamelUpper converts it to + // "HttpStatus" (via snake_case intermediary), so ByName("HttpStatus") + // won't find the original "HTTPStatus" entry and returns nil. + idlData := makeComplexEnumIDL("HTTPStatus") + gen := &Generator{ + idl: idlData, + options: &GeneratorOptions{Package: "test"}, + } + + // Register the complex enum as the generator normally would. + for _, typ := range gen.idl.Types { + registerComplexEnums(typ) + } + + outputFile, err := gen.genfile_types() + require.NoError(t, err, "genfile_types should not panic or error for enum named HTTPStatus") + require.NotNil(t, outputFile) + + generatedCode := outputFile.File.GoString() + assert.Contains(t, generatedCode, "HttpStatus") +} + +func TestGenComplexEnum_SnakeCaseName(t *testing.T) { + // "my_status" is stored in the IDL. ToCamelUpper converts it to + // "MyStatus", so ByName("MyStatus") won't find "my_status". + idlData := makeComplexEnumIDL("my_status") + gen := &Generator{ + idl: idlData, + options: &GeneratorOptions{Package: "test"}, + } + + for _, typ := range gen.idl.Types { + registerComplexEnums(typ) + } + + outputFile, err := gen.genfile_types() + require.NoError(t, err, "genfile_types should not panic or error for enum named my_status") + require.NotNil(t, outputFile) + + generatedCode := outputFile.File.GoString() + assert.Contains(t, generatedCode, "MyStatus") +} + +func TestGenComplexEnum_AlreadyCamelCase(t *testing.T) { + // "MyStatus" is already CamelCase. ToCamelUpper("MyStatus") == "MyStatus", + // so ByName should find it. This should always work. + idlData := makeComplexEnumIDL("MyStatus") + gen := &Generator{ + idl: idlData, + options: &GeneratorOptions{Package: "test"}, + } + + for _, typ := range gen.idl.Types { + registerComplexEnums(typ) + } + + outputFile, err := gen.genfile_types() + require.NoError(t, err, "genfile_types should not panic or error for enum named MyStatus") + require.NotNil(t, outputFile) + + generatedCode := outputFile.File.GoString() + assert.Contains(t, generatedCode, "MyStatus") +}