Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consider only generating one custom type per associated external type #86

Open
bendbennett opened this issue Nov 10, 2023 · 0 comments
Open
Labels
enhancement New feature or request

Comments

@bendbennett
Copy link
Contributor

Currently, the code generator iterates over the spec and generates custom type and value types for each attribute that has an associated_external_type. This could result in the generation of many custom types that provide the same functionality.

For example, given the following spec:

{
  "version": "0.1",
  "datasources": [
    {
      "name": "example",
      "schema": {
        "attributes": [
          {
            "name": "bool_attribute",
            "bool": {
              "associated_external_type": {
                "import": {
                  "path": "github.com/hashicorp/api"
                },
                "type": "*api.ExternalBool"
              },
              "computed_optional_required": "required"
            }
          },
          {
            "name": "another_bool_attribute",
            "bool": {
              "associated_external_type": {
                "import": {
                  "path": "github.com/hashicorp/api"
                },
                "type": "*api.ExternalBool"
              },
              "computed_optional_required": "required"
            }
          }
        ]
      }
    }
  ],
  "provider": {
    "name": "provider"
  }
}

The code generator will produce the following:

	return schema.Schema{
		Attributes: map[string]schema.Attribute{
			"another_bool_attribute": schema.BoolAttribute{
				CustomType: AnotherBoolAttributeType{},
				Required:   true,
			},
			"bool_attribute": schema.BoolAttribute{
				CustomType: BoolAttributeType{},
				Required:   true,
			},
		},
	}
}

type ExampleModel struct {
	AnotherBoolAttribute AnotherBoolAttributeValue `tfsdk:"another_bool_attribute"`
	BoolAttribute        BoolAttributeValue        `tfsdk:"bool_attribute"`
}

func (v AnotherBoolAttributeValue) ToApiExternalBool(ctx context.Context) (*api.ExternalBool, diag.Diagnostics) {
	var diags diag.Diagnostics

	if v.IsNull() {
		return nil, diags
	}

	if v.IsUnknown() {
		diags.Append(diag.NewErrorDiagnostic(
			"AnotherBoolAttributeValue Value Is Unknown",
			`"AnotherBoolAttributeValue" is unknown.`,
		))

		return nil, diags
	}

	a := api.ExternalBool(v.ValueBoolPointer())

	return &a, diags
}

func (v BoolAttributeValue) ToApiExternalBool(ctx context.Context) (*api.ExternalBool, diag.Diagnostics) {
	var diags diag.Diagnostics

	if v.IsNull() {
		return nil, diags
	}

	if v.IsUnknown() {
		diags.Append(diag.NewErrorDiagnostic(
			"BoolAttributeValue Value Is Unknown",
			`"BoolAttributeValue" is unknown.`,
		))

		return nil, diags
	}

	a := api.ExternalBool(v.ValueBoolPointer())

	return &a, diags
}

Consideration should be given to consolidating the generation of custom type and value types in instances where the code contained in the generated functions is essentially identical. For example:

func ExampleDataSourceSchema(ctx context.Context) schema.Schema {
	return schema.Schema{
		Attributes: map[string]schema.Attribute{
			"another_bool_attribute": schema.BoolAttribute{
				CustomType: BoolAttributeType{},
				Required:   true,
			},
			"bool_attribute": schema.BoolAttribute{
				CustomType: BoolAttributeType{},
				Required:   true,
			},
		},
	}
}

type ExampleModel struct {
	AnotherBoolAttribute BoolAttributeValue `tfsdk:"another_bool_attribute"`
	BoolAttribute        BoolAttributeValue `tfsdk:"bool_attribute"`
}

func (v BoolAttributeValue) ToApiExternalBool(ctx context.Context) (*api.ExternalBool, diag.Diagnostics) {
	var diags diag.Diagnostics

	if v.IsNull() {
		return nil, diags
	}

	if v.IsUnknown() {
		diags.Append(diag.NewErrorDiagnostic(
			"BoolAttributeValue Value Is Unknown",
			`"BoolAttributeValue" is unknown.`,
		))

		return nil, diags
	}

	a := api.ExternalBool(v.ValueBoolPointer())

	return &a, diags
}

Handling of the generation of attribute-specific diagnostics would require further consideration under these circumstances, for example:

	if v.IsUnknown() {
		diags.Append(diag.NewErrorDiagnostic(
			"BoolAttributeValue Value Is Unknown",
			`"BoolAttributeValue" is unknown.`,
		))

		return nil, diags
	}
@bendbennett bendbennett added the enhancement New feature or request label Nov 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant