public ResourceType GetType(ResourceTypeReference reference, ResourceTypeGenerationFlags flags) { var bodyType = new ObjectType(reference.FormatName(), TypeSymbolValidationFlags.Default, LanguageConstants.CreateResourceProperties(reference), null); var resourceType = new ResourceType(reference, ResourceScope.Tenant | ResourceScope.ManagementGroup | ResourceScope.Subscription | ResourceScope.ResourceGroup | ResourceScope.Resource, bodyType); return(AzResourceTypeProvider.SetBicepResourceProperties(resourceType, flags)); }
public ResourceType?TryGetResourceType(ResourceTypeReference typeReference, ResourceTypeGenerationFlags flags) { // TODO should we return an array of matching types here? var definedTypes = namespaceTypes.Values .Select(type => type.ResourceTypeProvider.TryGetDefinedType(type, typeReference, flags)) .WhereNotNull(); if (definedTypes.FirstOrDefault() is { } definedType) { return(definedType); } var generatedTypes = namespaceTypes.Values .Select(type => type.ResourceTypeProvider.TryGenerateFallbackType(type, typeReference, flags)) .WhereNotNull(); return(generatedTypes.FirstOrDefault()); }
public ResourceType GetResourceType(ResourceTypeReference reference, ResourceTypeGenerationFlags flags) { var definedTypes = namespaceTypes.Values .Select(type => type.ResourceTypeProvider.TryGetDefinedType(type, reference, flags)) .WhereNotNull(); if (definedTypes.FirstOrDefault() is {} definedType) { return(definedType); } var generatedTypes = namespaceTypes.Values .Select(type => type.ResourceTypeProvider.TryGenerateDefaultType(type, reference, flags)) .WhereNotNull(); // Here we are assuming that one of the namespaces will always return at least one result with TryGenerateDefaultType. // This is a fair assumption at present, because the "az" namespace is always imported. return(generatedTypes.First()); }
public void AzResourceTypeProvider_can_deserialize_all_types_without_throwing(ResourceTypeGenerationFlags flags) { var resourceTypeProvider = AzResourceTypeProvider.CreateWithAzTypes(); var availableTypes = resourceTypeProvider.GetAvailableTypes(); // sanity check - we know there should be a lot of types available var expectedTypeCount = 3000; availableTypes.Should().HaveCountGreaterThan(expectedTypeCount); foreach (var availableType in availableTypes) { resourceTypeProvider.HasType(availableType).Should().BeTrue(); var resourceType = resourceTypeProvider.GetType(availableType, flags); try { var visited = new HashSet <TypeSymbol>(); VisitAllReachableTypes(resourceType, visited); } catch (Exception exception) { throw new InvalidOperationException($"Deserializing type {availableType.FormatName()} failed", exception); } } }
public ResourceType?TryGetDefinedType(NamespaceType declaringNamespace, ResourceTypeReference reference, ResourceTypeGenerationFlags flags) { if (resourceTypes.TryGetValue(reference) is not { } resourceType) { return(null); } return(new(declaringNamespace, resourceType.TypeReference, resourceType.ValidParentScopes, resourceType.Body, UniqueIdentifierProperties)); }
public ResourceType?TryGenerateFallbackType(NamespaceType declaringNamespace, ResourceTypeReference reference, ResourceTypeGenerationFlags flags) => null;
public ResourceType?TryGetDefinedType(NamespaceType declaringNamespace, ResourceTypeReference reference, ResourceTypeGenerationFlags flags) => null;
public void AzResourceTypeProvider_can_deserialize_all_types_without_throwing(ResourceTypeGenerationFlags flags) { var resourceTypeProvider = AzResourceTypeProvider.CreateWithAzTypes(); var availableTypes = resourceTypeProvider.GetAvailableTypes(); // sanity check - we know there should be a lot of types available var expectedTypeCount = 3000; availableTypes.Should().HaveCountGreaterThan(expectedTypeCount); foreach (var availableType in availableTypes) { resourceTypeProvider.HasType(availableType).Should().BeTrue(); var resourceType = resourceTypeProvider.GetType(availableType, flags); try { var visited = new HashSet <TypeSymbol>(); VisitAllReachableTypes(resourceType, visited); } catch (Exception exception) { throw new InvalidOperationException($"Deserializing type {availableType.FormatName()} failed", exception); } bool IsSymbolicProperty(TypeProperty property) { var type = property.TypeReference.Type; return(type is IScopeReference || type == LanguageConstants.ResourceOrResourceCollectionRefItem || type == LanguageConstants.ResourceOrResourceCollectionRefArray); } /* * This test is the most expensive one because it deserializes all the types. * Creating a separate test to add a bit of extra validation would basically double the runtime of the Az provider tests. */ { // some types include a top-level scope property that is different than our own scope property // so we need to filter by type var topLevelProperties = GetTopLevelProperties(resourceType); var symbolicProperties = topLevelProperties.Where(property => IsSymbolicProperty(property)); symbolicProperties.Should().NotBeEmpty(); symbolicProperties.Should().OnlyContain(property => property.Flags.HasFlag(TypePropertyFlags.DisallowAny), $"because all symbolic properties in type '{availableType.FullyQualifiedType}' and api version '{availableType.ApiVersion}' should have the {nameof(TypePropertyFlags.DisallowAny)} flag."); var loopVariantProperties = topLevelProperties.Where(property => ExpectedLoopVariantProperties.Contains(property.Name) && (!string.Equals(property.Name, LanguageConstants.ResourceScopePropertyName, LanguageConstants.IdentifierComparison) || IsSymbolicProperty(property))); loopVariantProperties.Should().NotBeEmpty(); loopVariantProperties.Should().OnlyContain(property => property.Flags.HasFlag(TypePropertyFlags.LoopVariant), $"because all loop variant properties in type '{availableType.FullyQualifiedType}' and api version '{availableType.ApiVersion}' should have the {nameof(TypePropertyFlags.LoopVariant)} flag."); if (flags.HasFlag(ResourceTypeGenerationFlags.NestedResource)) { // syntactically nested resources should not have the parent property topLevelProperties.Should().NotContain(property => string.Equals(property.Name, LanguageConstants.ResourceParentPropertyName, LanguageConstants.IdentifierComparison)); } } } }
public void AzResourceTypeProvider_can_deserialize_all_types_without_throwing(ResourceTypeGenerationFlags flags) { var resourceTypeProvider = AzResourceTypeProvider.CreateWithAzTypes(); var availableTypes = resourceTypeProvider.GetAvailableTypes(); // sanity check - we know there should be a lot of types available var expectedTypeCount = 3000; availableTypes.Should().HaveCountGreaterThan(expectedTypeCount); foreach (var availableType in availableTypes) { resourceTypeProvider.HasType(availableType).Should().BeTrue(); var resourceType = resourceTypeProvider.GetType(availableType, flags); try { var visited = new HashSet <TypeSymbol>(); VisitAllReachableTypes(resourceType, visited); } catch (Exception exception) { throw new InvalidOperationException($"Deserializing type {availableType.FormatName()} failed", exception); } bool IsSymbolicProperty(TypeProperty property) { var type = property.TypeReference.Type; return(type is IScopeReference || type == LanguageConstants.ResourceOrResourceCollectionRefItem || type == LanguageConstants.ResourceOrResourceCollectionRefArray); } /* * This test is the most expensive one because it deserializes all the types. * Creating a separate test to add a bit of extra validation would basically double the runtime of the Az provider tests. */ { // some types include a top-level scope property that is different than our own scope property // so we need to filter by type var topLevelProperties = GetTopLevelProperties(resourceType); var symbolicProperties = topLevelProperties.Where(property => IsSymbolicProperty(property)); symbolicProperties.Should().NotBeEmpty(); symbolicProperties.Should().OnlyContain(property => property.Flags.HasFlag(TypePropertyFlags.DisallowAny)); } } }
public ResourceType GetType(ResourceTypeReference reference, ResourceTypeGenerationFlags flags) => AzResourceTypeProvider.SetBicepResourceProperties(typeDictionary[reference], flags);