Mark attributes with AttributeUsageAttribute
Mark custom attributes with AttributeUsageAttribute to indicate where they can be applied, per their meaning (e.g. a type-maintainer attribute belongs on classes, enumerations and interfaces, not methods or properties). Valid targets come from the System.AttributeTargets enumeration; omitting the attribute means All targets.
Not matched: abstract attribute classes (usage can be deferred to derived classes) and classes whose base is tagged (usage is inherited).
Not matched: abstract attribute classes (usage can be deferred to derived classes) and classes whose base is tagged (usage is inherited).
How to fix
Specify targets via AttributeUsageAttribute with the proper AttributeTargets values.
CQLinq source
This rule is written in CQLinq, C# LINQ over the NDepend code model. It ships with every new NDepend project: you can read it, adapt it, or use it as a starting point for your own custom rules.
// <Name>Mark attributes with AttributeUsageAttribute</Name>
// <Id>ND2203:MarkAttributesWithAttributeUsageAttribute</Id>
warnif count > 0
from t in JustMyCode.Types where
t.DeriveFrom ("System.Attribute".AllowNoMatch())
&& !t.HasAttribute ("System.AttributeUsageAttribute".AllowNoMatch())
// AttributeUsageAttribute can be deferred to classes that derive from an abstract attribute class
&& !t.IsAbstract
// AttributeUsageAttribute can de inherited from a base attribute class (that is not System.Attribute)
&& !t.BaseClasses.Any(c =>
c.FullName != "System.Attribute" &&
c.HasAttribute ("System.AttributeUsageAttribute".AllowNoMatch()))
select new {
t,
Debt = 5.ToMinutes().ToDebt(),
Severity = Severity.High
}
//<Expl>
// The *attribute {0}* should be annotated with *AttributeUsageAttribute*
// to specify where in the source code the custom attribute can be applied.
//</Expl>
//<Desc>
// Mark custom attributes with **AttributeUsageAttribute** to indicate where
// they can be applied, per their meaning (e.g. a type-maintainer attribute
// belongs on classes, enumerations and interfaces, not methods or
// properties). Valid targets come from the **System.AttributeTargets**
// enumeration; omitting the attribute means **All** targets.
//
// Not matched: abstract attribute classes (usage can be deferred to derived
// classes) and classes whose base is tagged (usage is inherited).
//</Desc>
//<HowToFix>
// Specify targets via *AttributeUsageAttribute* with the proper
// *AttributeTargets* values.
//</HowToFix>
Open in the interactive Rules Explorer · All default rules
.NET Framework Usage / System: all 12 items
- Mark ISerializable types with SerializableAttribute ND2200
- Mark assemblies with CLSCompliant (deprecated) ND2201
- Mark assemblies with ComVisible (deprecated) ND2202
- Mark attributes with AttributeUsageAttribute ND2203
- Remove calls to GC.Collect() ND2204
- Don't call GC.Collect() without calling GC.WaitForPendingFinalizers() ND2205
- Enum Storage should be Int32 ND2206
- Do not raise too general exception types ND2207
- Do not raise reserved exception types ND2208
- Uri fields or properties should be of type System.Uri ND2209
- Types should not derive from System.ApplicationException ND2210
- Don't Implement ICloneable ND2211