private DeclaredTypeAssignment?GetObjectPropertyType(TypeSymbol?type, ObjectSyntax?objectSyntax, string propertyName, bool useSyntax) { // local function DeclaredTypeFlags ConvertFlags(TypePropertyFlags flags) => flags.HasFlag(TypePropertyFlags.Constant) ? DeclaredTypeFlags.Constant : DeclaredTypeFlags.None; // the declared types on the declaration side of things will take advantage of properties // set on objects to resolve discriminators at all levels // to take advantage of this, we should first try looking up the property's declared type var declaringProperty = objectSyntax?.SafeGetPropertyByName(propertyName); if (useSyntax && declaringProperty != null) { // it is important to get the property value's decl type instead of the property's decl type // (the property has the unresolved discriminated object type and the value will have it resolved) var declaredPropertyAssignment = this.GetDeclaredTypeAssignment(declaringProperty.Value); if (declaredPropertyAssignment != null) { return(declaredPropertyAssignment); } } // could not get the declared type via syntax // let's use the type info instead switch (type) { case ObjectType objectType: // lookup declared property if (objectType.Properties.TryGetValue(propertyName, out var property)) { return(new DeclaredTypeAssignment(property.TypeReference.Type, declaringProperty, ConvertFlags(property.Flags))); } // if there are additional properties, try those if (objectType.AdditionalPropertiesType != null) { return(new DeclaredTypeAssignment(objectType.AdditionalPropertiesType.Type, declaringProperty, ConvertFlags(objectType.AdditionalPropertiesFlags))); } break; case DiscriminatedObjectType discriminated: if (string.Equals(propertyName, discriminated.DiscriminatorProperty.Name, LanguageConstants.IdentifierComparison)) { // the property is the discriminator property - use its type return(new DeclaredTypeAssignment(discriminated.DiscriminatorProperty.TypeReference.Type, declaringProperty)); } break; } return(null); }
private void VisitResourceOrModuleDeclaration(SyntaxBase declaringSyntax, ObjectSyntax body) { var dependsOnProperty = body.SafeGetPropertyByName(LanguageConstants.ResourceDependsOnPropertyName); if (dependsOnProperty?.Value is ArraySyntax declaredDependencies) { if (model.GetSymbolInfo(declaringSyntax) is DeclaredSymbol thisResource) { // If this resource has no implicit dependencies, than all explicit dependsOn entries must be valid, so don't bother checking if (inferredDependenciesMap.Value.TryGetValue(thisResource, out ImmutableHashSet <ResourceDependency>?inferredDependencies)) { foreach (ArrayItemSyntax declaredDependency in declaredDependencies.Items) { // Is this a simple reference to a resource collection? if (model.GetSymbolInfo(declaredDependency.Value) is ResourceSymbol referencedResource) { if (referencedResource.IsCollection) { // Ignore dependsOn entries pointing to a resource collection - dependency analyis would // be complex and user probably knows what they're doing. continue; } if (inferredDependencies.Any(d => d.Resource == referencedResource)) { this.diagnostics.Add( parent.CreateDiagnosticForSpan( declaredDependency.Span, referencedResource.Name)); } } } } } } }