This document assumes that you are familiar with the LINQ syntax, and exposes the CQLinq syntax peculiarities. |
CQLinq Query edition A CQLinq query can be edited live in the VBDepend UI. The query is executed automatically as soon as it compiles. Notice in the screenshot below the 13ms at the top right, that indicates the execution duration of the query. CQLinq is fast and is designed to run hundreds of queries per seconds against a large real-world code base. CQLinq edition comes also with code completion/intellisense, and also tooltip documentation on mouse hovering the query body. |
from m in Methods where m.NbLinesOfCode > 30 select m
from m in Application.Methods where m.NbLinesOfCode > 30 select m
from m in Application.Namespaces.WithNameLike("ProductName.FeatureA").ChildMethods()
where m.CyclomaticComplexity > 10 select m
from m in JustMyCode.Methods where m.NbLinesOfCode > 30 select m
notmycode from m in Methods where
m.SourceFileDeclAvailable &&
m.SourceDecls.First().SourceFile.FileName.ToLower().Contains("generated.cpp")
select m
CQLinq code rules A CQLinq query can be easily transformed into a rule by prefixing it with a condition defined with the two CQLinq keywords warnif count. The keyword count is an unsigned integer that is equal to the number of code elements matched by the query. For example the following query warns if some large methods are matched in the code base application methods: // <Name>Avoid too large methods</Name> CQLinq code rules are useful to define which bad practices the team wants to avoid in the code base. The team can see code rules violation warning in the VBDepend UI, or in the report. The team has also the possibility to define some rules as critical rules. |
Methods.Where(m => m.NbLinesOfCode > 30)
from m in Methods where m.NbLinesOfCode > 30 select m
from m in Application.Types.Where(t => t.IsNested).ChildMethods()
where m.NbLinesOfCode > 30 select m
// <Name>C.R.A.P method code metric</Name>
// Change Risk Analyzer and Predictor (i.e. CRAP) code metric
// This code metric helps in pinpointing overly complex and untested code.
// Reference: http://www.artima.com/weblogs/viewpost.jsp?thread=215899
// Formula: CRAP(m) = comp(m)^2 * (1 – cov(m)/100)^3 + comp(m)
warnif count > 0
from m in JustMyCode.Methods
// Don't match too short methods
where m.NbLinesOfCode > 10
let CC = m.CyclomaticComplexity
let uncov = (100 - m.PercentageCoverage) / 100f
let CRAP = (CC * CC * uncov * uncov * uncov) + CC
where CRAP != null && CRAP > 30
orderby CRAP descending, m.NbLinesOfCode descending
select new { m, CRAP, CC, uncoveredPercentage = uncov*100, m.NbLinesOfCode }
warnif count > 0
let base = ThirdParty.Types.WithFullName("BaseClass").FirstOrDefault()
where base != null // base can be null if the code base doesn't use at all BaseClass
from t in Application.Types where
!t.DeriveFrom(base) select t
// <Name>UI layer shouldn't use directly DB types</Name>
warnif count > 0
// UI layer is made of types in namespaces using a UI framework
let uiTypes = Application.Namespaces.UsingAny(
Projects.WithNameIn("PresentationFramework", "MFC")
).ChildTypes()
// You can easily customize this line to define what are DB types.
let dbTypes = ThirdParty.Assemblies.WithNameIn("Data").ChildTypes()
.Except(ThirdParty.Types.WithNameIn("DataSet", "DataTable", "DataRow"))
from uiType in uiTypes.UsingAny(dbTypes)
let dbTypesUsed = dbTypes.Intersect(uiType.TypesUsed)
select new { uiType, dbTypesUsed }
// <Name>Potentially dead Types</Name>
warnif count > 0
// Filter procedure for types that should'nt be considered as dead
let canTypeBeConsideredAsDeadProc = new Func<IType, bool>(
t => !t.IsPublic && // Public types might be used by client applications of your assemblies.
t.Name != "ClassToExclude"
// Select types unused
let typesUnused =
from t in JustMyCode.Types where
t.NbTypesUsingMe == 0 && canTypeBeConsideredAsDeadProc(t)
select t
// Dead types = types used only by unused types (recursive)
let deadTypesMetric = typesUnused.FillIterative(
types => from t in codeBase.Application.Types.UsedByAny(types).Except(types)
where canTypeBeConsideredAsDeadProc(t) &&
t.TypesUsingMe.Intersect(types).Count() == t.NbTypesUsingMe
select t)
from t in deadTypesMetric.DefinitionDomain
select new { t, t.TypesUsingMe, depth = deadTypesMetric[t] }