API Breaking Changes: Fields

Rule ND1502 API Breaking Changes

Runs only in diff mode (baseline defined). Warns if a field publicly visible in the baseline is no longer public or has been removed: client code using it will be broken.

How to fix

Keep public fields public, now and in the future. If a public field must be removed, tag it with System.ObsoleteAttribute and a workaround message for a few releases first (obsolete-tagged removals are not matched).

Severity is High: an API Breaking change can provoke significant friction with API consumers.

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>API Breaking Changes: Fields</Name>
// <Id>ND1502:APIBreakingChangesFields</Id>

warnif count > 0 from f in codeBase.OlderVersion().Application.Fields
where f.IsPubliclyVisible

     // The field has been removed, it was not tagged as obsolete
     // and its parent type hasn't been removed …
let reason =       
   ( ( f.WasRemoved() && 
      !f.ParentType.WasRemoved() && 
      !f.IsObsolete) ?
   "was public and has been removed" :

      // … or the field is not publicly visible anymore 
      //   but the parent type is still publicly visible
      (!f.WasRemoved() && !f.NewerVersion().IsPubliclyVisible && 
        f.ParentType.NewerVersion().IsPubliclyVisible) ?
    "used to be publicly visible but not anymore" : 

      // … or the field type has changed
      (!f.WasRemoved() && f.FieldType != null && f.NewerVersion().FieldType != null
                       && f.FieldType.FullName != f.NewerVersion().FieldType.FullName)
     ? "is public and has a different field type" : null  
   )
where reason != null   
   
select new { 
   f,
   NewVisibility = 
      (f.WasRemoved() ? " " : 
       f.NewerVersion().Visibility.ToString()),
   reason,
   Debt = 10.ToMinutes().ToDebt(),
   Severity = Severity.High
}

//<Expl>The *{0}* {2}. This breaks client code using it.</Expl>

//<Desc>
// Runs only in *diff mode* (baseline defined). Warns if a field publicly
// visible in the *baseline* is no longer public or has been removed:
// client code using it will be broken.
//</Desc>

//<HowToFix>
// Keep public fields public, now and in the future. If a public field must
// be removed, tag it with *System.ObsoleteAttribute* and a *workaround
// message* for a few releases first (obsolete-tagged removals are not
// matched).
//
// Severity is **High**: an API Breaking change can provoke significant
// friction with API consumers.
//</HowToFix>

API Breaking Changes: all 9 items