<commit_before>package cfschema

import (
	"fmt"
)

// Expand replaces all Definition and Property JSON Pointer references with their content.
// This functionality removes the need for recursive logic when accessing Definitions and Properties.
// In unresolved form nested properties are not allowed, instead nested properties use a '$ref' JSON Pointer to reference a definition.
// See https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/resource-type-schema.html#schema-properties-properties.
func (r *Resource) Expand() error {
	if r == nil {
		return nil
	}

	err := r.ResolveProperties(r.Definitions, []string{"definitions"})

	if err != nil {
		return fmt.Errorf("error expanding Resource (%s) Definitions: %w", *r.TypeName, err)
	}

	err = r.ResolveProperties(r.Properties, []string{"properties"})

	if err != nil {
		return fmt.Errorf("error expanding Resource (%s) Properties: %w", *r.TypeName, err)
	}

	return nil
}

// ResolveProperties resolves all References in a top-level name-to-property map.
// In theory unresolved form nested properties are not allowed but in practice they do occur,
// so support arbitrarily deeply nested references.
func (r *Resource) ResolveProperties(properties map[string]*Property, path []string) error {
	for propertyName, property := range properties {
		// For example:
		// "Configuration": {
		//   "$ref": "#/definitions/ClusterConfiguration"
		// },
		resolved, err := r.ResolveProperty(property)

		if err != nil {
			return fmt.Errorf("error resolving %s: %w", propertyName, err)
		}

		if resolved {
			continue
		}

		switch property.Type.String() {
		case PropertyTypeArray:
			// For example:
			// "DefaultCapacityProviderStrategy": {
			//   "type": "array",
			//   "items": {
			//     "$ref": "#/definitions/CapacityProviderStrategyItem"
			//   }
			// },
			_, err = r.ResolveProperty(property.Items)

			if err != nil {
				return fmt.Errorf("error resolving %s Items: %w", propertyName, err)
			}

		case PropertyTypeObject:
			err = r.ResolveWrappedOneOfProperties(property, append(path, propertyName))

			if err != nil {
				return fmt.Errorf("error unwrapping %s OneOf Properties: %w", propertyName, err)
			}

			// For example:
			// "ClusterConfiguration": {
			//   "type": "object",
			//   "properties": {
			//     "ExecuteCommandConfiguration": {
			//       "$ref": "#/definitions/ExecuteCommandConfiguration"
			//     }
			//   }
			// },
			err = r.ResolveProperties(property.Properties, append(path, propertyName))

			if err != nil {
				return fmt.Errorf("error resolving %s Properties: %w", propertyName, err)
			}

			// For example:
			// "LambdaFunctionRecipeSource": {
			//   "type": "object",
			//   "properties": {
			//     "ComponentDependencies": {
			//       "type": "object",
			//       "patternProperties": {
			//         "": {
			//           "$ref": "#/definitions/ComponentDependencyRequirement"
			//         }
			//       }
			//     }
			//   }
			// },
			err = r.ResolveProperties(property.PatternProperties, append(path, propertyName))

			if err != nil {
				return fmt.Errorf("error resolving %s PatternProperties: %w", propertyName, err)
			}

		case "":
			err = r.ResolveWrappedOneOfProperties(property, append(path, propertyName))

			if err != nil {
				return fmt.Errorf("error unwrapping %s OneOf Properties: %w", propertyName, err)
			}

			if len(property.Properties) > 0 {
				// For example:
				// "PresignedUrlConfig": {
				//   "properties": {
				//     "RoleArn": {
				//       "$ref": "#/definitions/RoleArn"
				//     },
				//     "ExpiresInSec": {
				//       "$ref": "#/definitions/ExpiresInSec"
				//     }
				//   }
				// },
				err = r.ResolveProperties(property.Properties, append(path, propertyName))

				if err != nil {
					return fmt.Errorf("error resolving %s Properties: %w", propertyName, err)
				}
			}
		}
	}

	return nil
}

// ResolveProperty resolves any Reference (JSON Pointer) in a Property.
// Returns whether a Reference was resolved.
func (r *Resource) ResolveProperty(property *Property) (bool, error) {
	if property != nil && property.Ref != nil {
		defaultValue := property.Default
		description := property.Description
		ref := property.Ref
		resolution, err := r.ResolveReference(*ref)

		if err != nil {
			return false, err
		}

		*property = *resolution

		// Ensure that any default value is not lost.
		if defaultValue != nil {
			property.Default = defaultValue
		}

		// Prefer any description from the unresolved property.
		if description != nil && *description != "" {
			property.Description = description
		}

		return true, nil
	}

	return false, nil
}

// ResolveWrappedOneOfProperties resolves any Reference (JSON Pointer) in a set of properties wrapped in OneOf.
// Returns the unwrapped name-to-property map.
func (r *Resource) ResolveWrappedOneOfProperties(property *Property, path []string) error {
	if len(property.Properties) == 0 && len(property.PatternProperties) == 0 && len(property.OneOf) > 0 {
		// For example:
		// "ContentTransformation": {
		//   "type": "object",
		//   "oneOf": [
		//     {
		//       "additionalProperties": false,
		//       "properties": {
		//         "AwsLambda": {
		//           "$ref": "#/definitions/AwsLambda"
		//         }
		//       },
		//       "required": [
		//         "AwsLambda"
		//       ]
		//     }
		//   ]
		// },
		unwrappedProperties := make(map[string]*Property)

		for _, propertySubschema := range property.OneOf {
			properties := propertySubschema.Properties

			if len(properties) == 0 {
				continue
			}

			if err := r.ResolveProperties(properties, append(path, "(oneOf)")); err != nil {
				return err
			}

			for propertyName, property := range properties {<commit_msg>Revert "Add path for debugging."<commit_after>package cfschema

import (
	"fmt"
)

// Expand replaces all Definition and Property JSON Pointer references with their content.
// This functionality removes the need for recursive logic when accessing Definitions and Properties.
// In unresolved form nested properties are not allowed, instead nested properties use a '$ref' JSON Pointer to reference a definition.
// See https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/resource-type-schema.html#schema-properties-properties.
func (r *Resource) Expand() error {
	if r == nil {
		return nil
	}

	err := r.ResolveProperties(r.Definitions)

	if err != nil {
		return fmt.Errorf("error expanding Resource (%s) Definitions: %w", *r.TypeName, err)
	}

	err = r.ResolveProperties(r.Properties)

	if err != nil {
		return fmt.Errorf("error expanding Resource (%s) Properties: %w", *r.TypeName, err)
	}

	return nil
}

// ResolveProperties resolves all References in a top-level name-to-property map.
// In theory unresolved form nested properties are not allowed but in practice they do occur,
// so support arbitrarily deeply nested references.
func (r *Resource) ResolveProperties(properties map[string]*Property) error {
	for propertyName, property := range properties {
		// For example:
		// "Configuration": {
		//   "$ref": "#/definitions/ClusterConfiguration"
		// },
		resolved, err := r.ResolveProperty(property)

		if err != nil {
			return fmt.Errorf("error resolving %s: %w", propertyName, err)
		}

		if resolved {
			continue
		}

		switch property.Type.String() {
		case PropertyTypeArray:
			// For example:
			// "DefaultCapacityProviderStrategy": {
			//   "type": "array",
			//   "items": {
			//     "$ref": "#/definitions/CapacityProviderStrategyItem"
			//   }
			// },
			_, err = r.ResolveProperty(property.Items)

			if err != nil {
				return fmt.Errorf("error resolving %s Items: %w", propertyName, err)
			}

		case PropertyTypeObject:
			err = r.ResolveWrappedOneOfProperties(property)

			if err != nil {
				return fmt.Errorf("error unwrapping %s OneOf Properties: %w", propertyName, err)
			}

			// For example:
			// "ClusterConfiguration": {
			//   "type": "object",
			//   "properties": {
			//     "ExecuteCommandConfiguration": {
			//       "$ref": "#/definitions/ExecuteCommandConfiguration"
			//     }
			//   }
			// },
			err = r.ResolveProperties(property.Properties)

			if err != nil {
				return fmt.Errorf("error resolving %s Properties: %w", propertyName, err)
			}

			// For example:
			// "LambdaFunctionRecipeSource": {
			//   "type": "object",
			//   "properties": {
			//     "ComponentDependencies": {
			//       "type": "object",
			//       "patternProperties": {
			//         "": {
			//           "$ref": "#/definitions/ComponentDependencyRequirement"
			//         }
			//       }
			//     }
			//   }
			// },
			err = r.ResolveProperties(property.PatternProperties)

			if err != nil {
				return fmt.Errorf("error resolving %s PatternProperties: %w", propertyName, err)
			}

		case "":
			err = r.ResolveWrappedOneOfProperties(property)

			if err != nil {
				return fmt.Errorf("error unwrapping %s OneOf Properties: %w", propertyName, err)
			}

			if len(property.Properties) > 0 {
				// For example:
				// "PresignedUrlConfig": {
				//   "properties": {
				//     "RoleArn": {
				//       "$ref": "#/definitions/RoleArn"
				//     },
				//     "ExpiresInSec": {
				//       "$ref": "#/definitions/ExpiresInSec"
				//     }
				//   }
				// },
				err = r.ResolveProperties(property.Properties)

				if err != nil {
					return fmt.Errorf("error resolving %s Properties: %w", propertyName, err)
				}
			}
		}
	}

	return nil
}

// ResolveProperty resolves any Reference (JSON Pointer) in a Property.
// Returns whether a Reference was resolved.
func (r *Resource) ResolveProperty(property *Property) (bool, error) {
	if property != nil && property.Ref != nil {
		defaultValue := property.Default
		description := property.Description
		ref := property.Ref
		resolution, err := r.ResolveReference(*ref)

		if err != nil {
			return false, err
		}

		*property = *resolution

		// Ensure that any default value is not lost.
		if defaultValue != nil {
			property.Default = defaultValue
		}

		// Prefer any description from the unresolved property.
		if description != nil && *description != "" {
			property.Description = description
		}

		return true, nil
	}

	return false, nil
}

// ResolveWrappedOneOfProperties resolves any Reference (JSON Pointer) in a set of properties wrapped in OneOf.
// Returns the unwrapped name-to-property map.
func (r *Resource) ResolveWrappedOneOfProperties(property *Property) error {
	if len(property.Properties) == 0 && len(property.PatternProperties) == 0 && len(property.OneOf) > 0 {
		// For example:
		// "ContentTransformation": {
		//   "type": "object",
		//   "oneOf": [
		//     {
		//       "additionalProperties": false,
		//       "properties": {
		//         "AwsLambda": {
		//           "$ref": "#/definitions/AwsLambda"
		//         }
		//       },
		//       "required": [
		//         "AwsLambda"
		//       ]
		//     }
		//   ]
		// },
		unwrappedProperties := make(map[string]*Property)

		for _, propertySubschema := range property.OneOf {
			properties := propertySubschema.Properties

			if len(properties) == 0 {
				continue
			}

			if err := r.ResolveProperties(properties); err != nil {
				return err
			}

			for propertyName, property := range properties {
{'fraction_non_alphanumeric': 0.14057366130894236, 'fraction_numerical': 0.0008880206020779682, 'mean_word_length': 2.7143799472295513, 'pattern_counts': {'":': 68, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 2, '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': '1259395', 'n_tokens_mistral': 3863, 'n_tokens_neox': 3315, 'n_words': 882}