private void ValidateIndexerNameAttribute(CSharpAttributeData attribute, AttributeSyntax node, DiagnosticBag diagnostics) { if (!this.IsIndexer || this.IsExplicitInterfaceImplementation) { diagnostics.Add(ErrorCode.ERR_BadIndexerNameAttr, node.Name.Location, node.GetErrorDisplayName()); } else { string indexerName = attribute.CommonConstructorArguments[0].DecodeValue<string>(SpecialType.System_String); if (indexerName == null || !SyntaxFacts.IsValidIdentifier(indexerName)) { diagnostics.Add(ErrorCode.ERR_BadArgumentToAttribute, node.ArgumentList.Arguments[0].Location, node.GetErrorDisplayName()); } } }
/// <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.Name); 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) { // generate error diagnostics.Add(ErrorCode.ERR_AttributeOnBadSymbolType, node.Name.Location, node.Name, 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; }
// Process the specified AttributeUsage attribute on the given ownerSymbol private AttributeUsageInfo DecodeAttributeUsageAttribute(CSharpAttributeData attribute, AttributeSyntax node, bool diagnose, DiagnosticBag diagnosticsOpt = null) { Debug.Assert(diagnose == (diagnosticsOpt != null)); Debug.Assert(!attribute.HasErrors); Debug.Assert(!this.IsErrorType()); // AttributeUsage can only be specified for attribute classes if (!this.DeclaringCompilation.IsAttributeType(this)) { if (diagnose) { diagnosticsOpt.Add(ErrorCode.ERR_AttributeUsageOnNonAttributeClass, node.Name.Location, node.GetErrorDisplayName()); } return AttributeUsageInfo.Null; } else { AttributeUsageInfo info = attribute.DecodeAttributeUsageAttribute(); // Validate first ctor argument for AtributeUsage specification is a valid AttributeTargets enum member if (!info.HasValidAttributeTargets) { if (diagnose) { // invalid attribute target CSharpSyntaxNode attributeArgumentSyntax = attribute.GetAttributeArgumentSyntax(0, node); diagnosticsOpt.Add(ErrorCode.ERR_InvalidAttributeArgument, attributeArgumentSyntax.Location, node.GetErrorDisplayName()); } return AttributeUsageInfo.Null; } return info; } }
private void ValidateConditionalAttribute(CSharpAttributeData attribute, AttributeSyntax node, DiagnosticBag diagnostics) { Debug.Assert(this.IsConditional); Debug.Assert(!attribute.HasErrors); if (!this.DeclaringCompilation.IsAttributeType(this)) { // CS1689: Attribute '{0}' is only valid on methods or attribute classes diagnostics.Add(ErrorCode.ERR_ConditionalOnNonAttributeClass, node.Location, node.GetErrorDisplayName()); } else { string name = attribute.GetConstructorArgument<string>(0, SpecialType.System_String); if (name == null || !SyntaxFacts.IsValidIdentifier(name)) { // CS0633: The argument to the '{0}' attribute must be a valid identifier CSharpSyntaxNode attributeArgumentSyntax = attribute.GetAttributeArgumentSyntax(0, node); diagnostics.Add(ErrorCode.ERR_BadArgumentToAttribute, attributeArgumentSyntax.Location, node.GetErrorDisplayName()); } } }
private void ValidateConditionalAttribute(CSharpAttributeData attribute, AttributeSyntax node, DiagnosticBag diagnostics) { Debug.Assert(this.IsConditional); if (this.IsAccessor()) { // CS1667: Attribute '{0}' is not valid on property or event accessors. It is only valid on '{1}' declarations. AttributeUsageInfo attributeUsage = attribute.AttributeClass.GetAttributeUsageInfo(); diagnostics.Add(ErrorCode.ERR_AttributeNotOnAccessor, node.Name.Location, node.GetErrorDisplayName(), attributeUsage.GetValidTargetsString()); } else if (this.ContainingType.IsInterfaceType()) { // CS0582: The Conditional attribute is not valid on interface members diagnostics.Add(ErrorCode.ERR_ConditionalOnInterfaceMethod, node.Location); } else if (this.IsOverride) { // CS0243: The Conditional attribute is not valid on '{0}' because it is an override method diagnostics.Add(ErrorCode.ERR_ConditionalOnOverride, node.Location, this); } else if (!this.CanBeReferencedByName || this.MethodKind == MethodKind.Destructor) { // CS0577: The Conditional attribute is not valid on '{0}' because it is a constructor, destructor, operator, or explicit interface implementation diagnostics.Add(ErrorCode.ERR_ConditionalOnSpecialMethod, node.Location, this); } else if (!this.ReturnsVoid) { // CS0578: The Conditional attribute is not valid on '{0}' because its return type is not void diagnostics.Add(ErrorCode.ERR_ConditionalMustReturnVoid, node.Location, this); } else if (this.HasAnyOutParameter()) { // CS0685: Conditional member '{0}' cannot have an out parameter diagnostics.Add(ErrorCode.ERR_ConditionalWithOutParam, node.Location, this); } else { string name = attribute.GetConstructorArgument<string>(0, SpecialType.System_String); if (name == null || !SyntaxFacts.IsValidIdentifier(name)) { // CS0633: The argument to the '{0}' attribute must be a valid identifier CSharpSyntaxNode attributeArgumentSyntax = attribute.GetAttributeArgumentSyntax(0, node); diagnostics.Add(ErrorCode.ERR_BadArgumentToAttribute, attributeArgumentSyntax.Location, node.GetErrorDisplayName()); } } }