Discard generated Namespaces from JustMyCode

JustMyCode Definition ND3001 Defining JustMyCode

A notmycode query: matched namespaces (and their types, methods, fields) are removed from the JustMyCode code base view used by most default queries and rules.

It matches the VB.NET-generated My namespaces, and tool-generated namespaces like mshtml or Microsoft.Office.*.

notmycode queries run before other queries and rules; modifying one re-runs the queries relying on JustMyCode. Several notmycode namespaces queries cumulate. Documentation: https://www.ndepend.com/docs/cqlinq-syntax#NotMyCode

CQLinq source

This JustMyCode definition 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>Discard generated Namespaces from JustMyCode</Name>
// <Id>ND3001:DiscardGeneratedNamespacesFromJustMyCode</Id>

notmycode

// First gather assemblies written with VB.NET
let vbnetAssemblies = Application.Assemblies.Where(
   a => a.SourceDecls.Any(decl => 
      string.Equals(decl.SourceFile.FileNameExtension, ".vb", 
                    StringComparison.OrdinalIgnoreCase)))
// Then find the My namespace and its child namespaces.
let vbnetMyNamespaces = vbnetAssemblies.ChildNamespaces().Where(
   n => n.SimpleNameEquals("My") ||
   n.ParentNamespaces.Any(nParent => nParent.SimpleNameEquals("My")))


let generatedNamespace = Application.Namespaces.WithFullNameIn(
   // COM/Import mshtml namespace and all its types are not-my-code
   "mshtml",
   // Some VB.NET generated code goes into this namespace
   "Microsoft.VisualBasic",
   // Roslyn can generate types in these  namespaces, consider them as not-my-code
   "Microsoft.CodeAnalysis",
   "System.Runtime.CompilerServices",
   "AspNetCoreGeneratedDocument")

.Concat(Application.Namespaces.WithSimpleNameIn(
   // Don't match types generated by the Refit infrastructure like the class PreserveAttribute
   "RefitInternalGenerated"))

.Concat(Application.Namespaces.Where(
      // Don't match classes in namespaces generated by the Blazor and Maui infrastructure
   n => n.Name.StartsWithAny("__Blazor", "Microsoft.Maui.Controls")))

.Concat(Application.Namespaces.Where(
   // Anonymous namespaces with only types generated by the compiler are not-my-code
   n => n.Name == "" && n.ChildTypes.All(t => t.IsGeneratedByCompiler)))

.Concat(Application.Namespaces.Where(
   // Don't match namespaces generated by PostSharp
   n => n.Name.StartsWith("PostSharp.ImplementationDetails")))

.Concat(Application.Namespaces.Where(
   // Namespaces of a Roslyn source generator whose generated files are not on disk: all their types
   // are tagged with GeneratedCodeAttribute, generated by the compiler, or declared in no source file
   // of an assembly that has sources (an assembly analyzed without its PDB files is not concerned).
   n => n.ParentAssembly.SourceFileDeclAvailable &&
        n.ChildTypes.Any(t => t.HasAttribute("System.CodeDom.Compiler.GeneratedCodeAttribute".AllowNoMatch())) &&
        n.ChildTypes.All(t => t.HasAttribute("System.CodeDom.Compiler.GeneratedCodeAttribute".AllowNoMatch()) ||
                              t.IsGeneratedByCompiler ||
                             !t.SourceFileDeclAvailable)))

// Discard types generated in Microsoft.Office.* namespaces.
// Issues won't be reported on this code. Especially issues related 
// to the rule "Interface name should begin with a 'I'" broken 
// by many interfaces in these namespaces.
let microsoftOffices = Application.Namespaces.Where(n => n.Name.StartsWith("Microsoft.Office"))

from n in vbnetMyNamespaces.Concat(generatedNamespace).Concat(microsoftOffices)
select n

//<Desc>
// A **notmycode** query: matched namespaces (and their types, methods,
// fields) are removed from the *JustMyCode* code base view used by most
// default queries and rules.
//
// It matches the VB.NET-generated **My** namespaces, and tool-generated
// namespaces like **mshtml** or **Microsoft.Office.***.
//
// *notmycode* queries run before other queries and rules; modifying one
// re-runs the queries relying on *JustMyCode*. Several *notmycode*
// namespaces queries cumulate. Documentation:
// https://www.ndepend.com/docs/cqlinq-syntax#NotMyCode
//</Desc>

Defining JustMyCode: all 7 items