diff --git a/pkg/codegen/hcl2/binder.go b/pkg/codegen/hcl2/binder.go index 7c6132f89..3998517de 100644 --- a/pkg/codegen/hcl2/binder.go +++ b/pkg/codegen/hcl2/binder.go @@ -47,7 +47,7 @@ type binder struct { options bindOptions referencedPackages map[string]*schema.Package - typeSchemas map[model.Type]schema.Type + schemaTypes map[schema.Type]model.Type tokens syntax.TokenMap nodes []Node @@ -117,7 +117,7 @@ func BindProgram(files []*syntax.File, opts ...BindOption) (*Program, hcl.Diagno options: options, tokens: syntax.NewTokenMapForFiles(files), referencedPackages: map[string]*schema.Package{}, - typeSchemas: map[model.Type]schema.Type{}, + schemaTypes: map[schema.Type]model.Type{}, root: model.NewRootScope(syntax.None), } diff --git a/pkg/codegen/hcl2/binder_schema.go b/pkg/codegen/hcl2/binder_schema.go index 1f679f491..3418d5c11 100644 --- a/pkg/codegen/hcl2/binder_schema.go +++ b/pkg/codegen/hcl2/binder_schema.go @@ -146,34 +146,29 @@ func (b *binder) loadReferencedPackageSchemas(n Node) error { // schemaTypeToType converts a schema.Type to a model Type. func (b *binder) schemaTypeToType(src schema.Type) (result model.Type) { - return b.schemaTypeToTypeImpl(src, map[schema.Type]model.Type{}) -} - -func (b *binder) schemaTypeToTypeImpl(src schema.Type, seen map[schema.Type]model.Type) (result model.Type) { - defer func() { - b.typeSchemas[result] = src - }() - - if already, ok := seen[src]; ok { - return already - } - switch src := src.(type) { case *schema.ArrayType: - return model.NewListType(b.schemaTypeToTypeImpl(src.ElementType, seen)) + return model.NewListType(b.schemaTypeToType(src.ElementType)) case *schema.MapType: - return model.NewMapType(b.schemaTypeToTypeImpl(src.ElementType, seen)) + return model.NewMapType(b.schemaTypeToType(src.ElementType)) + case *schema.EnumType: + // TODO(codegen): make this a union of constant types. + return b.schemaTypeToType(src.ElementType) case *schema.ObjectType: + if t, ok := b.schemaTypes[src]; ok { + return t + } + properties := map[string]model.Type{} objType := model.NewObjectType(properties, src) - seen[src] = objType + b.schemaTypes[src] = objType for _, prop := range src.Properties { typ := prop.Type if b.options.allowMissingProperties { typ = &schema.OptionalType{ElementType: typ} } - t := b.schemaTypeToTypeImpl(typ, seen) + t := b.schemaTypeToType(typ) if prop.ConstValue != nil { var value cty.Value switch v := prop.ConstValue.(type) { @@ -200,20 +195,21 @@ func (b *binder) schemaTypeToTypeImpl(src schema.Type, seen map[schema.Type]mode } if src.UnderlyingType != nil { - underlyingType := b.schemaTypeToTypeImpl(src.UnderlyingType, seen) + underlyingType := b.schemaTypeToType(src.UnderlyingType) return model.NewUnionType(t, underlyingType) } return t case *schema.InputType: - elementType := b.schemaTypeToTypeImpl(src.ElementType, seen) - return model.NewUnionTypeAnnotated([]model.Type{elementType, model.NewOutputType(elementType)}, src) + elementType := b.schemaTypeToType(src.ElementType) + resolvedElementType := b.schemaTypeToType(codegen.ResolvedType(src.ElementType)) + return model.NewUnionTypeAnnotated([]model.Type{elementType, model.NewOutputType(resolvedElementType)}, src) case *schema.OptionalType: - elementType := b.schemaTypeToTypeImpl(src.ElementType, seen) + elementType := b.schemaTypeToType(src.ElementType) return model.NewOptionalType(elementType) case *schema.UnionType: types := make([]model.Type, len(src.ElementTypes)) for i, src := range src.ElementTypes { - types[i] = b.schemaTypeToTypeImpl(src, seen) + types[i] = b.schemaTypeToType(src) } if src.Discriminator != "" { return model.NewUnionTypeAnnotated(types, src)