Example #1
0
        /// <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);
        }