/// <summary> /// Validate attribute usage target and duplicate attributes. /// </summary> /// <param name="attribute">Bound attribute</param> /// <param name="node">Syntax node for attribute specification</param> /// <param name="compilation">Compilation</param> /// <param name="symbolPart">Symbol part to which the attribute has been applied.</param> /// <param name="diagnostics">Diagnostics</param> /// <param name="uniqueAttributeTypes">Set of unique attribute types applied to the symbol</param> private bool ValidateAttributeUsage( CSharpAttributeData attribute, AttributeSyntax node, CSharpCompilation compilation, AttributeLocation symbolPart, DiagnosticBag diagnostics, HashSet <NamedTypeSymbol> uniqueAttributeTypes) { Debug.Assert(!attribute.HasErrors); NamedTypeSymbol attributeType = attribute.AttributeClass; AttributeUsageInfo attributeUsageInfo = attributeType.GetAttributeUsageInfo(); // Given attribute can't be specified more than once if AllowMultiple is false. if (!uniqueAttributeTypes.Add(attributeType) && !attributeUsageInfo.AllowMultiple) { diagnostics.Add(ErrorCode.ERR_DuplicateAttribute, node.Name.Location, node.GetErrorDisplayName()); return(false); } // Verify if the attribute type can be applied to given owner symbol. StarkAttributeTargets attributeTarget; if (symbolPart == AttributeLocation.Return) { // attribute on return type Debug.Assert(this.Kind == SymbolKind.Method); attributeTarget = StarkAttributeTargets.ReturnValue; } else { attributeTarget = this.GetAttributeTarget(); } if ((attributeTarget & attributeUsageInfo.ValidTargets) == 0) { // generate error diagnostics.Add(ErrorCode.ERR_AttributeOnBadSymbolType, node.Name.Location, node.GetErrorDisplayName(), attributeUsageInfo.GetValidTargetsErrorArgument()); return(false); } if (attribute.IsSecurityAttribute(compilation)) { switch (this.Kind) { case SymbolKind.Assembly: case SymbolKind.NamedType: case SymbolKind.Method: break; default: // CS7070: Security attribute '{0}' is not valid on this declaration type. Security attributes are only valid on assembly, type and method declarations. diagnostics.Add(ErrorCode.ERR_SecurityAttributeInvalidTarget, node.Name.Location, node.GetErrorDisplayName()); return(false); } } return(true); }
/// <summary> /// Validate attribute usage target and duplicate attributes. /// </summary> /// <param name="attribute">Bound attribute</param> /// <param name="node">Syntax node for attribute specification</param> /// <param name="compilation">Compilation</param> /// <param name="symbolPart">Symbol part to which the attribute has been applied.</param> /// <param name="diagnostics">Diagnostics</param> /// <param name="uniqueAttributeTypes">Set of unique attribute types applied to the symbol</param> private bool ValidateAttributeUsage( CSharpAttributeData attribute, AttributeSyntax node, CSharpCompilation compilation, AttributeLocation symbolPart, DiagnosticBag diagnostics, HashSet <NamedTypeSymbol> uniqueAttributeTypes) { Debug.Assert(!attribute.HasErrors); NamedTypeSymbol attributeType = attribute.AttributeClass; AttributeUsageInfo attributeUsageInfo = attributeType.GetAttributeUsageInfo(); // Given attribute can't be specified more than once if AllowMultiple is false. if (!uniqueAttributeTypes.Add(attributeType) && !attributeUsageInfo.AllowMultiple) { diagnostics.Add(ErrorCode.ERR_DuplicateAttribute, node.Name.Location, node.GetErrorDisplayName()); return(false); } // Verify if the attribute type can be applied to given owner symbol. AttributeTargets attributeTarget; if (symbolPart == AttributeLocation.Return) { // attribute on return type Debug.Assert(this.Kind == SymbolKind.Method); attributeTarget = AttributeTargets.ReturnValue; } else { attributeTarget = this.GetAttributeTarget(); } if ((attributeTarget & attributeUsageInfo.ValidTargets) == 0) { #if XSHARP // The ClipperCallingConvention Attribute in VulcanRT has incorrect Targets (Method, but should also be allowed on Constructors) if (node.Name.ToString().ToLower().IndexOf(OurTypeNames.ClipperCallingConventionAttribute, XSharpString.Comparison) == -1) { #endif // generate error diagnostics.Add(ErrorCode.ERR_AttributeOnBadSymbolType, node.Name.Location, node.GetErrorDisplayName(), attributeUsageInfo.GetValidTargetsErrorArgument()); return(false); #if XSHARP } #endif } if (attribute.IsSecurityAttribute(compilation)) { switch (this.Kind) { case SymbolKind.Assembly: case SymbolKind.NamedType: case SymbolKind.Method: break; default: // CS7070: Security attribute '{0}' is not valid on this declaration type. Security attributes are only valid on assembly, type and method declarations. diagnostics.Add(ErrorCode.ERR_SecurityAttributeInvalidTarget, node.Name.Location, node.GetErrorDisplayName()); return(false); } } return(true); }