Esempio n. 1
0
        public static void Validate(SemanticModel semanticModel, IDiagnosticWriter diagnosticWriter)
        {
            // Collect all sytnaxes that require DTCs (a.k.a. DTC containers).
            var containers = DeployTimeConstantContainerVisitor.CollectDeployTimeConstantContainers(semanticModel);

            foreach (var container in containers)
            {
                // Only visit child nodes of the DTC container to avoid flagging the DTC container itself.
                foreach (var childContainer in GetChildrenOfDeployTimeConstantContainer(semanticModel, container))
                {
                    // Validate property accesses, array accesses, resource accesses and function calls.
                    new DeployTimeConstantDirectViolationVisitor(container, semanticModel, diagnosticWriter)
                    .Visit(childContainer);

                    // Validate variable dependencies.
                    foreach (var variableDependency in VariableDependencyVisitor.GetVariableDependencies(semanticModel, childContainer))
                    {
                        new DeployTimeConstantIndirectViolationVisitor(container, variableDependency, semanticModel, diagnosticWriter)
                        .Visit(variableDependency);
                    }
                }
            }
        }
Esempio n. 2
0
        public static void Validate(SemanticModel semanticModel, IDiagnosticWriter diagnosticWriter)
        {
            var existingResourceBodyObjectTypeOverrides = new Dictionary <DeclaredSymbol, ObjectType>();

            // grab all existing resources
            var existingResourceSymbols = semanticModel.DeclaredResources
                                          .Select(x => x.Symbol)
                                          .Where(x => x.DeclaringResource.IsExistingResource())
                                          .ToArray();

            // compare existing resources to all other existing resources to find dependencies and see if it has a non-DTC value
            // and needs to remove the ReadableAtDeployTime flag from the "name" property -> O(n^2) time complexity with some optimizations
            for (int i = 0; i < existingResourceSymbols.Length; i++)
            {
                int count = existingResourceBodyObjectTypeOverrides.Count;

                foreach (var existingResourceSymbol in existingResourceSymbols)
                {
                    // skip if the existing resource symbol is already in the dictionary because there is no need to check the DTC value again
                    if (existingResourceBodyObjectTypeOverrides.TryGetValue(existingResourceSymbol, out var value))
                    {
                        continue;
                    }

                    // grab the "name" property to check if it has a DTC value or not
                    var nameObjectPropertySyntax = existingResourceSymbol.DeclaringResource.TryGetBody()?.TryGetPropertyByName(AzResourceTypeProvider.ResourceNamePropertyName);

                    var diagnosticWriterForExistingResources = SimpleDiagnosticWriter.Create();

                    // if "name" property has a non-DTC value, then make an entry for the corresponding existing ResourceSymbol to a modified ObjectType in the dictionary
                    if (nameObjectPropertySyntax != null)
                    {
                        CheckDeployTimeConstantViolations(nameObjectPropertySyntax, nameObjectPropertySyntax.Value, semanticModel, diagnosticWriterForExistingResources, existingResourceBodyObjectTypeOverrides);

                        // if a DTC diagnostic was thrown, map the resource symbol to the new modified ObjectType with the ReadableAtDeployTime flag removed
                        if (diagnosticWriterForExistingResources.HasDiagnostics())
                        {
                            RemoveReadableAtDeployTimeFlagForExistingResource(existingResourceBodyObjectTypeOverrides, existingResourceSymbol);
                        }
                    }
                }

                // if no new entries have been added to existingResourceBodyObjectTypeOverrides, that means there are no further DTC checks needed
                if (count == existingResourceBodyObjectTypeOverrides.Count)
                {
                    break;
                }
            }

            // now map every resourceSymbol in the dictionary to the same ObjectType but with the DeployTimeConstant flag removed this time
            foreach (var existingResourceSymbol in existingResourceSymbols)
            {
                if (existingResourceBodyObjectTypeOverrides.TryGetValue(existingResourceSymbol, out var value))
                {
                    if (value is { } objectType&& value.Properties.TryGetValue(AzResourceTypeProvider.ResourceNamePropertyName, out var nameProperty))
                    {
                        existingResourceBodyObjectTypeOverrides[existingResourceSymbol] = new ObjectType(
                            value.Name,
                            value.ValidationFlags,
                            value.Properties.SetItem(AzResourceTypeProvider.ResourceNamePropertyName, new TypeProperty(nameProperty.Name, LanguageConstants.String, nameProperty.Flags & ~TypePropertyFlags.DeployTimeConstant)).Values,
                            value.AdditionalPropertiesType,
                            value.AdditionalPropertiesFlags,
                            value.MethodResolver.CopyToObject);
                    }
                }
            }

            // Collect all syntaxes that require DTCs (a.k.a. DTC containers).
            var containers = DeployTimeConstantContainerVisitor.CollectDeployTimeConstantContainers(semanticModel);

            foreach (var container in containers)
            {
                // Only visit child nodes of the DTC container to avoid flagging the DTC container itself.
                foreach (var childContainer in GetChildrenOfDeployTimeConstantContainer(semanticModel, container))
                {
                    CheckDeployTimeConstantViolations(container, childContainer, semanticModel, diagnosticWriter, existingResourceBodyObjectTypeOverrides);
                }
            }
        }