diff --git a/internal/convert/custom_type_primitive.go b/internal/convert/custom_type_primitive.go index bf83a01a..25d02c95 100644 --- a/internal/convert/custom_type_primitive.go +++ b/internal/convert/custom_type_primitive.go @@ -91,3 +91,13 @@ func (c CustomTypePrimitive) ValueType() string { return "" } + +// TypeString returns the custom type string (e.g., "jsontypes.NormalizedType{}") +// when a custom type is specified. Returns empty string otherwise. +func (c CustomTypePrimitive) TypeString() string { + if c.customType != nil { + return c.customType.Type + } + + return "" +} diff --git a/internal/convert/custom_type_primitive_test.go b/internal/convert/custom_type_primitive_test.go new file mode 100644 index 00000000..6667d5b8 --- /dev/null +++ b/internal/convert/custom_type_primitive_test.go @@ -0,0 +1,116 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package convert + +import ( + "testing" + + specschema "github.com/hashicorp/terraform-plugin-codegen-spec/schema" +) + +func TestCustomTypePrimitive_TypeString(t *testing.T) { + t.Parallel() + + testCases := map[string]struct { + input CustomTypePrimitive + expected string + }{ + "no-custom-type": { + input: NewCustomTypePrimitive(nil, nil, "attr"), + expected: "", + }, + "custom-type": { + input: NewCustomTypePrimitive( + &specschema.CustomType{ + Type: "jsontypes.NormalizedType{}", + ValueType: "jsontypes.Normalized", + }, + nil, + "attr", + ), + expected: "jsontypes.NormalizedType{}", + }, + "associated-external-type-only": { + input: NewCustomTypePrimitive( + nil, + &specschema.AssociatedExternalType{ + Type: "*api.ExtString", + }, + "attr", + ), + expected: "", + }, + } + + for name, testCase := range testCases { + t.Run(name, func(t *testing.T) { + t.Parallel() + + got := testCase.input.TypeString() + + if got != testCase.expected { + t.Errorf("expected %q, got %q", testCase.expected, got) + } + }) + } +} + +func TestCustomTypePrimitive_ValueType(t *testing.T) { + t.Parallel() + + testCases := map[string]struct { + input CustomTypePrimitive + expected string + }{ + "no-custom-type": { + input: NewCustomTypePrimitive(nil, nil, "attr"), + expected: "", + }, + "custom-type": { + input: NewCustomTypePrimitive( + &specschema.CustomType{ + Type: "jsontypes.NormalizedType{}", + ValueType: "jsontypes.Normalized", + }, + nil, + "attr", + ), + expected: "jsontypes.Normalized", + }, + "associated-external-type-only": { + input: NewCustomTypePrimitive( + nil, + &specschema.AssociatedExternalType{ + Type: "*api.ExtString", + }, + "attr", + ), + expected: "AttrValue", + }, + "custom-type-overrides-associated": { + input: NewCustomTypePrimitive( + &specschema.CustomType{ + ValueType: "my_custom_value", + }, + &specschema.AssociatedExternalType{ + Type: "*api.ExtString", + }, + "attr", + ), + expected: "my_custom_value", + }, + } + + for name, testCase := range testCases { + t.Run(name, func(t *testing.T) { + t.Parallel() + + got := testCase.input.ValueType() + + if got != testCase.expected { + t.Errorf("expected %q, got %q", testCase.expected, got) + } + }) + } +} diff --git a/internal/datasource/string_attribute.go b/internal/datasource/string_attribute.go index cfada81c..bc0af326 100644 --- a/internal/datasource/string_attribute.go +++ b/internal/datasource/string_attribute.go @@ -187,6 +187,10 @@ func (g GeneratorStringAttribute) ToFromFunctions(name string) ([]byte, error) { // AttrType returns a string representation of a basetypes.StringTypable type. func (g GeneratorStringAttribute) AttrType(name schema.FrameworkIdentifier) (string, error) { + if ct := g.CustomType.TypeString(); ct != "" { + return ct, nil + } + if g.AssociatedExternalType != nil { return fmt.Sprintf("%sType{}", name.ToPascalCase()), nil } @@ -196,6 +200,10 @@ func (g GeneratorStringAttribute) AttrType(name schema.FrameworkIdentifier) (str // AttrValue returns a string representation of a basetypes.StringValuable type. func (g GeneratorStringAttribute) AttrValue(name schema.FrameworkIdentifier) string { + if cv := g.CustomType.ValueType(); cv != "" { + return cv + } + if g.AssociatedExternalType != nil { return fmt.Sprintf("%sValue", name.ToPascalCase()) } diff --git a/internal/datasource/string_attribute_test.go b/internal/datasource/string_attribute_test.go index 7f39ee37..f1a3835a 100644 --- a/internal/datasource/string_attribute_test.go +++ b/internal/datasource/string_attribute_test.go @@ -14,6 +14,7 @@ import ( "github.com/doitintl/terraform-plugin-codegen-framework/internal/convert" "github.com/doitintl/terraform-plugin-codegen-framework/internal/model" + "github.com/doitintl/terraform-plugin-codegen-framework/internal/schema" ) func TestGeneratorStringAttribute_New(t *testing.T) { @@ -406,3 +407,128 @@ func TestGeneratorStringAttribute_ModelField(t *testing.T) { }) } } + +func TestGeneratorStringAttribute_AttrType(t *testing.T) { + t.Parallel() + + testCases := map[string]struct { + input GeneratorStringAttribute + expected string + }{ + "default": { + expected: "basetypes.StringType{}", + }, + "custom-type": { + input: GeneratorStringAttribute{ + CustomType: convert.NewCustomTypePrimitive( + &specschema.CustomType{ + Type: "jsontypes.NormalizedType{}", + ValueType: "jsontypes.Normalized", + }, + nil, + "string_attribute", + ), + }, + expected: "jsontypes.NormalizedType{}", + }, + "associated-external-type": { + input: GeneratorStringAttribute{ + AssociatedExternalType: &schema.AssocExtType{}, + }, + expected: "StringAttributeType{}", + }, + "custom-type-overriding-associated-external-type": { + input: GeneratorStringAttribute{ + CustomType: convert.NewCustomTypePrimitive( + &specschema.CustomType{ + Type: "jsontypes.NormalizedType{}", + ValueType: "jsontypes.Normalized", + }, + &specschema.AssociatedExternalType{ + Type: "*api.ExtString", + }, + "string_attribute", + ), + AssociatedExternalType: &schema.AssocExtType{}, + }, + expected: "jsontypes.NormalizedType{}", + }, + } + + for name, testCase := range testCases { + t.Run(name, func(t *testing.T) { + t.Parallel() + + got, err := testCase.input.AttrType("string_attribute") + + if err != nil { + t.Errorf("unexpected error: %s", err) + } + + if diff := cmp.Diff(got, testCase.expected); diff != "" { + t.Errorf("unexpected difference: %s", diff) + } + }) + } +} + +func TestGeneratorStringAttribute_AttrValue(t *testing.T) { + t.Parallel() + + testCases := map[string]struct { + input GeneratorStringAttribute + expected string + }{ + "default": { + expected: "basetypes.StringValue", + }, + "custom-type": { + input: GeneratorStringAttribute{ + CustomType: convert.NewCustomTypePrimitive( + &specschema.CustomType{ + Type: "jsontypes.NormalizedType{}", + ValueType: "jsontypes.Normalized", + }, + nil, + "string_attribute", + ), + }, + expected: "jsontypes.Normalized", + }, + "associated-external-type": { + input: GeneratorStringAttribute{ + AssociatedExternalType: &schema.AssocExtType{}, + }, + expected: "StringAttributeValue", + }, + "custom-type-overriding-associated-external-type": { + input: GeneratorStringAttribute{ + CustomType: convert.NewCustomTypePrimitive( + &specschema.CustomType{ + Type: "jsontypes.NormalizedType{}", + ValueType: "jsontypes.Normalized", + }, + &specschema.AssociatedExternalType{ + Type: "*api.ExtString", + }, + "string_attribute", + ), + AssociatedExternalType: &schema.AssocExtType{}, + }, + expected: "jsontypes.Normalized", + }, + } + + for name, testCase := range testCases { + t.Run(name, func(t *testing.T) { + t.Parallel() + + got := testCase.input.AttrValue("string_attribute") + + if diff := cmp.Diff(got, testCase.expected); diff != "" { + t.Errorf("unexpected difference: %s", diff) + } + }) + } +} + diff --git a/internal/provider/string_attribute.go b/internal/provider/string_attribute.go index 5610f71b..a4cf9b2c 100644 --- a/internal/provider/string_attribute.go +++ b/internal/provider/string_attribute.go @@ -187,6 +187,10 @@ func (g GeneratorStringAttribute) ToFromFunctions(name string) ([]byte, error) { // AttrType returns a string representation of a basetypes.StringTypable type. func (g GeneratorStringAttribute) AttrType(name schema.FrameworkIdentifier) (string, error) { + if ct := g.CustomType.TypeString(); ct != "" { + return ct, nil + } + if g.AssociatedExternalType != nil { return fmt.Sprintf("%sType{}", name.ToPascalCase()), nil } @@ -196,6 +200,10 @@ func (g GeneratorStringAttribute) AttrType(name schema.FrameworkIdentifier) (str // AttrValue returns a string representation of a basetypes.StringValuable type. func (g GeneratorStringAttribute) AttrValue(name schema.FrameworkIdentifier) string { + if cv := g.CustomType.ValueType(); cv != "" { + return cv + } + if g.AssociatedExternalType != nil { return fmt.Sprintf("%sValue", name.ToPascalCase()) } diff --git a/internal/provider/string_attribute_test.go b/internal/provider/string_attribute_test.go index 4bde8146..69263596 100644 --- a/internal/provider/string_attribute_test.go +++ b/internal/provider/string_attribute_test.go @@ -14,6 +14,7 @@ import ( "github.com/doitintl/terraform-plugin-codegen-framework/internal/convert" "github.com/doitintl/terraform-plugin-codegen-framework/internal/model" + "github.com/doitintl/terraform-plugin-codegen-framework/internal/schema" ) func TestGeneratorStringAttribute_New(t *testing.T) { @@ -377,3 +378,127 @@ func TestGeneratorStringAttribute_ModelField(t *testing.T) { }) } } + +func TestGeneratorStringAttribute_AttrType(t *testing.T) { + t.Parallel() + + testCases := map[string]struct { + input GeneratorStringAttribute + expected string + }{ + "default": { + expected: "basetypes.StringType{}", + }, + "custom-type": { + input: GeneratorStringAttribute{ + CustomType: convert.NewCustomTypePrimitive( + &specschema.CustomType{ + Type: "jsontypes.NormalizedType{}", + ValueType: "jsontypes.Normalized", + }, + nil, + "string_attribute", + ), + }, + expected: "jsontypes.NormalizedType{}", + }, + "associated-external-type": { + input: GeneratorStringAttribute{ + AssociatedExternalType: &schema.AssocExtType{}, + }, + expected: "StringAttributeType{}", + }, + "custom-type-overriding-associated-external-type": { + input: GeneratorStringAttribute{ + CustomType: convert.NewCustomTypePrimitive( + &specschema.CustomType{ + Type: "jsontypes.NormalizedType{}", + ValueType: "jsontypes.Normalized", + }, + &specschema.AssociatedExternalType{ + Type: "*api.ExtString", + }, + "string_attribute", + ), + AssociatedExternalType: &schema.AssocExtType{}, + }, + expected: "jsontypes.NormalizedType{}", + }, + } + + for name, testCase := range testCases { + t.Run(name, func(t *testing.T) { + t.Parallel() + + got, err := testCase.input.AttrType("string_attribute") + + if err != nil { + t.Errorf("unexpected error: %s", err) + } + + if diff := cmp.Diff(got, testCase.expected); diff != "" { + t.Errorf("unexpected difference: %s", diff) + } + }) + } +} + +func TestGeneratorStringAttribute_AttrValue(t *testing.T) { + t.Parallel() + + testCases := map[string]struct { + input GeneratorStringAttribute + expected string + }{ + "default": { + expected: "basetypes.StringValue", + }, + "custom-type": { + input: GeneratorStringAttribute{ + CustomType: convert.NewCustomTypePrimitive( + &specschema.CustomType{ + Type: "jsontypes.NormalizedType{}", + ValueType: "jsontypes.Normalized", + }, + nil, + "string_attribute", + ), + }, + expected: "jsontypes.Normalized", + }, + "associated-external-type": { + input: GeneratorStringAttribute{ + AssociatedExternalType: &schema.AssocExtType{}, + }, + expected: "StringAttributeValue", + }, + "custom-type-overriding-associated-external-type": { + input: GeneratorStringAttribute{ + CustomType: convert.NewCustomTypePrimitive( + &specschema.CustomType{ + Type: "jsontypes.NormalizedType{}", + ValueType: "jsontypes.Normalized", + }, + &specschema.AssociatedExternalType{ + Type: "*api.ExtString", + }, + "string_attribute", + ), + AssociatedExternalType: &schema.AssocExtType{}, + }, + expected: "jsontypes.Normalized", + }, + } + + for name, testCase := range testCases { + t.Run(name, func(t *testing.T) { + t.Parallel() + + got := testCase.input.AttrValue("string_attribute") + + if diff := cmp.Diff(got, testCase.expected); diff != "" { + t.Errorf("unexpected difference: %s", diff) + } + }) + } +} diff --git a/internal/resource/string_attribute.go b/internal/resource/string_attribute.go index a1ec3c26..48307a72 100644 --- a/internal/resource/string_attribute.go +++ b/internal/resource/string_attribute.go @@ -225,6 +225,10 @@ func (g GeneratorStringAttribute) ToFromFunctions(name string) ([]byte, error) { // AttrType returns a string representation of a basetypes.StringTypable type. func (g GeneratorStringAttribute) AttrType(name generatorschema.FrameworkIdentifier) (string, error) { + if ct := g.CustomType.TypeString(); ct != "" { + return ct, nil + } + if g.AssociatedExternalType != nil { return fmt.Sprintf("%sType{}", name.ToPascalCase()), nil } @@ -234,6 +238,10 @@ func (g GeneratorStringAttribute) AttrType(name generatorschema.FrameworkIdentif // AttrValue returns a string representation of a basetypes.StringValuable type. func (g GeneratorStringAttribute) AttrValue(name generatorschema.FrameworkIdentifier) string { + if cv := g.CustomType.ValueType(); cv != "" { + return cv + } + if g.AssociatedExternalType != nil { return fmt.Sprintf("%sValue", name.ToPascalCase()) } diff --git a/internal/resource/string_attribute_test.go b/internal/resource/string_attribute_test.go index 8ca62c35..8261e7dd 100644 --- a/internal/resource/string_attribute_test.go +++ b/internal/resource/string_attribute_test.go @@ -922,3 +922,127 @@ func TestGeneratorStringAttribute_ModelField(t *testing.T) { }) } } + +func TestGeneratorStringAttribute_AttrType(t *testing.T) { + t.Parallel() + + testCases := map[string]struct { + input GeneratorStringAttribute + expected string + }{ + "default": { + expected: "basetypes.StringType{}", + }, + "custom-type": { + input: GeneratorStringAttribute{ + CustomType: convert.NewCustomTypePrimitive( + &specschema.CustomType{ + Type: "jsontypes.NormalizedType{}", + ValueType: "jsontypes.Normalized", + }, + nil, + "string_attribute", + ), + }, + expected: "jsontypes.NormalizedType{}", + }, + "associated-external-type": { + input: GeneratorStringAttribute{ + AssociatedExternalType: &generatorschema.AssocExtType{}, + }, + expected: "StringAttributeType{}", + }, + "custom-type-overriding-associated-external-type": { + input: GeneratorStringAttribute{ + CustomType: convert.NewCustomTypePrimitive( + &specschema.CustomType{ + Type: "jsontypes.NormalizedType{}", + ValueType: "jsontypes.Normalized", + }, + &specschema.AssociatedExternalType{ + Type: "*api.ExtString", + }, + "string_attribute", + ), + AssociatedExternalType: &generatorschema.AssocExtType{}, + }, + expected: "jsontypes.NormalizedType{}", + }, + } + + for name, testCase := range testCases { + t.Run(name, func(t *testing.T) { + t.Parallel() + + got, err := testCase.input.AttrType("string_attribute") + + if err != nil { + t.Errorf("unexpected error: %s", err) + } + + if diff := cmp.Diff(got, testCase.expected); diff != "" { + t.Errorf("unexpected difference: %s", diff) + } + }) + } +} + +func TestGeneratorStringAttribute_AttrValue(t *testing.T) { + t.Parallel() + + testCases := map[string]struct { + input GeneratorStringAttribute + expected string + }{ + "default": { + expected: "basetypes.StringValue", + }, + "custom-type": { + input: GeneratorStringAttribute{ + CustomType: convert.NewCustomTypePrimitive( + &specschema.CustomType{ + Type: "jsontypes.NormalizedType{}", + ValueType: "jsontypes.Normalized", + }, + nil, + "string_attribute", + ), + }, + expected: "jsontypes.Normalized", + }, + "associated-external-type": { + input: GeneratorStringAttribute{ + AssociatedExternalType: &generatorschema.AssocExtType{}, + }, + expected: "StringAttributeValue", + }, + "custom-type-overriding-associated-external-type": { + input: GeneratorStringAttribute{ + CustomType: convert.NewCustomTypePrimitive( + &specschema.CustomType{ + Type: "jsontypes.NormalizedType{}", + ValueType: "jsontypes.Normalized", + }, + &specschema.AssociatedExternalType{ + Type: "*api.ExtString", + }, + "string_attribute", + ), + AssociatedExternalType: &generatorschema.AssocExtType{}, + }, + expected: "jsontypes.Normalized", + }, + } + + for name, testCase := range testCases { + t.Run(name, func(t *testing.T) { + t.Parallel() + + got := testCase.input.AttrValue("string_attribute") + + if diff := cmp.Diff(got, testCase.expected); diff != "" { + t.Errorf("unexpected difference: %s", diff) + } + }) + } +}