Avoid public methods not publicly visible

Rule ND1807 Visibility

Warns about public methods whose parent type is not public. There public means accessible wherever my parent type is visible — elegant to some developers, misleading to others. Deactivate the rule if you disagree; the debate: http://ericlippert.com/2014/09/15/internal-or-public/

Severity is Low: more an advice than a problem.

How to fix

Declare the method internal if used outside its type, else private.

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>Avoid public methods not publicly visible</Name>
// <Id>ND1807:AvoidPublicMethodsNotPubliclyVisible</Id>

warnif count > 0
from m in JustMyCode.Methods where 
   !m.IsPubliclyVisible && m.IsPublic &&

   // Filter out virtual methods
   !m.IsVirtual &&
   
   // Filter out interface and delegate types
   !m.ParentType.IsInterface &&
   !m.ParentType.IsDelegate &&
   
   // Don't match potentially dead methods, candidate for removal
    m.MethodsCallingMe.Any() &&
   
  // Eliminate default constructor from the result.
  // Whatever the visibility of the declaring class,
  // default constructors are public and introduce noise
  // in the current rule.
  !( m.IsConstructor && m.IsPublic && m.NbParameters == 0) &&
   
   // Filter out operators that must be declared public
   !m.IsOperator &&
   
   // Filter out methods generated by compiler, except auto-property getter/setter
  (!m.IsGeneratedByCompiler || m.IsPropertyGetter || m.IsPropertySetter) &&

  // Don't advise to reduce visibility of property getters/setters 
  // of classes that implement INotifyPropertyChanged
  !((m.IsPropertyGetter || m.IsPropertySetter) &&
     m.ParentType.Implement("System.ComponentModel.INotifyPropertyChanged".AllowNoMatch())) 

let calledOutsideParentType = 
    m.MethodsCallingMe.FirstOrDefault(mCaller => mCaller.ParentType != m.ParentType) != null

// If parent type declared as public, it must be a nested type not publicly visible
let parentTypeVisibility = m.ParentType.Visibility != Visibility.Public ? 
   "declared as *" + m.ParentType.Visibility.ToString().ToLower() +"*" : 
   "not publicly visible"

select new { 
   m, 
   parentTypeVisibility,
   declareMethodAs = (Visibility) (calledOutsideParentType ? Visibility.Internal : Visibility.Private),
   methodsCaller = m.MethodsCallingMe,

   Debt = 30.ToSeconds().ToDebt(),
   Severity = Severity.Low
}

//<Expl>
// The *{0}* is declared as *public* but remains inaccessible beyond its assembly due to its parent type being {1}.
// Consider declaring this method as *{2}*, which makes its actual accessibility scope explicit.
//</Expl>

//<Desc>
// Warns about *public* methods whose parent type is not *public*. There
// *public* means *accessible wherever my parent type is visible* — elegant
// to some developers, misleading to others. Deactivate the rule if you
// disagree; the debate: http://ericlippert.com/2014/09/15/internal-or-public/
//
// Severity is **Low**: more an advice than a problem.
//</Desc>

//<HowToFix>
// Declare the method *internal* if used outside its type, else *private*.
//</HowToFix>

Visibility: all 12 items