<commit_before>package schema

import "github.com/jagregory/cfval/reporting"

type GetAtt struct {
	definition []interface{}
}

func NewGetAtt(definition []interface{}) GetAtt {
	return GetAtt{definition}
}

func (ga GetAtt) Validate(ctx PropertyContext) (reporting.ValidateResult, reporting.Reports) {
	if len(ga.definition) != 2 {
		return reporting.ValidateAbort, reporting.Reports{reporting.NewFailure(ctx, "GetAtt has incorrect number of arguments (expected: 2, actual: %d)", len(ga.definition))}
	}

	template := ctx.Template()
	if resourceID, ok := ga.definition[0].(string); ok {
		if resource, ok := template.Resources[resourceID]; ok {
			if attributeName, ok := ga.definition[1].(string); ok {
				definition := ctx.Definitions().Lookup(resource.Type)
				// TODO: BUG this line below should be attribute, ok
				if resource, ok := definition.Attributes[attributeName]; ok {
					// TODO: make this common, so GetAtt and others can use it
					targetType := resource.Type
					switch targetType.CoercibleTo(ctx.Property().Type) {
					case CoercionNever:
						return reporting.ValidateAbort, reporting.Reports{reporting.NewFailure(ctx, "GetAtt value of %s.%s is %s but is being assigned to a %s property", resourceID, attributeName, targetType.Describe(), ctx.Property().Type.Describe())}
					case CoercionBegrudgingly:
						return reporting.ValidateAbort, reporting.Reports{reporting.NewWarning(ctx, "GetAtt value of %s.%s is %s but is being dangerously coerced to a %s property", resourceID, attributeName, targetType.Describe(), ctx.Property().Type.Describe())}
					}

					return reporting.ValidateAbort, nil
				}
			}

			// attribute not found on resource
			return reporting.ValidateAbort, reporting.Reports{reporting.NewFailure(ctx, "GetAtt %s.%s is not an attribute", resourceID, ga.definition[1])}
		}

		// resource not found
		return reporting.ValidateAbort, reporting.Reports{reporting.NewFailure(ctx, "GetAtt '%s' is not a resource", resourceID)}
	}

	// resource not a string
	return reporting.ValidateAbort, reporting.Reports{reporting.NewFailure(ctx, "GetAtt '%s' is not a valid resource name", ga.definition[0])}
}
<commit_msg>Fix variable shadowing<commit_after>package schema

import "github.com/jagregory/cfval/reporting"

type GetAtt struct {
	definition []interface{}
}

func NewGetAtt(definition []interface{}) GetAtt {
	return GetAtt{definition}
}

func (ga GetAtt) Validate(ctx PropertyContext) (reporting.ValidateResult, reporting.Reports) {
	if len(ga.definition) != 2 {
		return reporting.ValidateAbort, reporting.Reports{reporting.NewFailure(ctx, "GetAtt has incorrect number of arguments (expected: 2, actual: %d)", len(ga.definition))}
	}

	template := ctx.Template()
	if resourceID, ok := ga.definition[0].(string); ok {
		if resource, ok := template.Resources[resourceID]; ok {
			if attributeName, ok := ga.definition[1].(string); ok {
				definition := ctx.Definitions().Lookup(resource.Type)
				if attribute, ok := definition.Attributes[attributeName]; ok {
					// TODO: make this common, so GetAtt and others can use it
					targetType := attribute.Type
					switch targetType.CoercibleTo(ctx.Property().Type) {
					case CoercionNever:
						return reporting.ValidateAbort, reporting.Reports{reporting.NewFailure(ctx, "GetAtt value of %s.%s is %s but is being assigned to a %s property", resourceID, attributeName, targetType.Describe(), ctx.Property().Type.Describe())}
					case CoercionBegrudgingly:
						return reporting.ValidateAbort, reporting.Reports{reporting.NewWarning(ctx, "GetAtt value of %s.%s is %s but is being dangerously coerced to a %s property", resourceID, attributeName, targetType.Describe(), ctx.Property().Type.Describe())}
					}

					return reporting.ValidateAbort, nil
				}
			}

			// attribute not found on resource
			return reporting.ValidateAbort, reporting.Reports{reporting.NewFailure(ctx, "GetAtt %s.%s is not an attribute", resourceID, ga.definition[1])}
		}

		// resource not found
		return reporting.ValidateAbort, reporting.Reports{reporting.NewFailure(ctx, "GetAtt '%s' is not a resource", resourceID)}
	}

	// resource not a string
	return reporting.ValidateAbort, reporting.Reports{reporting.NewFailure(ctx, "GetAtt '%s' is not a valid resource name", ga.definition[0])}
}

{'fraction_non_alphanumeric': 0.1216089803554724, 'fraction_numerical': 0.002806361085126286, 'mean_word_length': 4.7255689424364125, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5958277', 'n_tokens_mistral': 1394, 'n_tokens_neox': 1258, 'n_words': 357}