Code Query Language 1.8 Specification

CQL 1.8

 

 

CQL 1.8 is supported by CppDepend

http://www.CppDepend.com

 

 

Copyright SMACCHIA.COM S.A.R.L 2006/2007/2008

All right reserved

 

 


 

Content

Content 2

Introduction. 5

CQL and VisualCppDepend. 5

Learning the CQL language. 6

The CQL language and real-world needs. 7

Some examples of queries and constraints written in CQL. 8

Examples of code Quality constraints. 8

Examples of naming constraints. 10

Examples of design constraints. 10

Examples of encapsulation constraints. 10

Examples of queries on the graph of dependencies. 11

Examples of queries on the inheritance tree. 12

Examples of queries to get extremum... 13

CQL queries elements. 14

SELECT METHODS. 14

SELECT FIELDS. 14

SELECT TYPES. 14

SELECT NAMESPACES. 15

SELECT PROJECTS. 15

WARN IF xxx IN: Query vs. Constraint 15

TOP xxx: Restrict the number of rows in the result 15

FROM / OUT OF xxx: Domain of search. 16

WHERE xxx: Define a set of conditions. 16

ORDER BY xxx: Order rows of the result 17

Comments. 17

Query naming. 17

CQL name conditions. 17

Kind of Code Elements’ Names Prefixes. 20

The OPTIONAL: Code Elements’ Names Prefix. 20

NameLike “regex”  ANTMF. 21

NameIs “name”  ANTMF. 21

FullNameIs “name”  ANTMF. 21

CQL metric conditions. 21

NbLinesOfCode  ANTM... 21

NbLinesOfCode  ANTM... 22

NbLinesOfComment  ANTM... 23

PercentageComment  ANTM... 23

NbMethods  ANTM... 24

NbFields  ANTF. 24

NbTypes ANT. 25

NbNamespaces AN.. 25

NbParameters M... 26

NbVariables  M... 26

NbOverloads M... 26

CyclomaticComplexity  TM... 27

SizeOfInst  TF. 28

TypeRank  T. 29

MethodRank  M... 29

DepthOfInheritance  T. 30

NbChildren  T. 30

FieldCa F. 30

MethodCe M... 31

MethodCa M... 31

TypeCe  T. 32

TypeCa  T. 32

NamespaceCe N.. 32

NamespaceCa N.. 33

ABT  T (Association Between Types). 33

LCOM  T (Lack Of Cohesion Of Methods). 33

LCOMHS  T (Lack Of Cohesion Of Methods Henderson-Sellers). 34

AssemblyLevel A.. 35

NamespaceLevel N.. 35

TypeLevel T. 35

MethodLevel T. 35

Abstractness  A.. 35

Instability  A.. 36

NormDistFromMainSeq  A.. 36

DistFromMainSeq  A.. 37

RelationalCohesion  A.. 37

ProjectCa  A.. 37

ProjectCe  A.. 38

CQL code structure conditions. 40

IsUsing  ANTM... 41

DepthOfIsUsing  ANTM... 41

IsDirectlyUsing  ANTM... 42

IsUsedBy  ANTMF. 43

DepthOfIsUsedBy  ANTMF. 43

IsDirectlyUsedBy  ANTMF. 44

CreateA  M... 44

DepthOfCreateA  M... 45

DeriveFrom  T. 45

DepthOfDeriveFrom  T. 45

Implement  T. 46

HasAttribute  ATMF. 46

IsOfType  F. 46

ReturnType  M... 46

CQL boolean conditions. 47

IsPublic  TMF. 47

IsInternal  TMF. 47

IsProtected  TMF. 47

IsProtectedOrInternal  TMF. 47

IsProtectedAndInternal  TMF. 48

IsPrivate  TMF. 48

IsInFrameworkAssembly  NTMF. 48

IsFrameworkAssembly  A.. 48

IsEnumValue  F. 48

IsConstructor  M... 49

IsStatic  TMF. 49

IsOverloaded  M... 49

IsVirtual  M... 50

IsAbstract  TM... 50

IsTemplate  TM... 51

IsUsingPointers  TM... 51

IsFinalizer  M... 51

HasFinalizer T. 51

HasLevel ANTM... 52

ContainsNamespaceDependencyCycles A.. 52

ContainsTypeDependencyCycles T. 52

ContainsMethodDependencyCycles M... 52

IsEntryPoint  M... 52

IsOperator  M... 52

IsLiteral  F. 53

IsClassConstructor  M... 54

IsClass  T. 54

IsStructure  T. 54

IsEnumeration  T. 55

IsInterface  T. 55

IsExceptionClass  T. 56

IsObsolete  TMF. 57

CQL boolean conditions dedicated to Build Comparison. 57

WasAdded  ANTMF. 57

WasRemoved  ANTMF. 58

CodeWasChanged ANTM... 58

CommentsWereChanged ANTM... 58

VisibilityWasChanged TMF. 59

WasChanged  ANTMF. 59

BecameObsolete TMF. 59

IsUsedRecently ANTMF. 60

IsNotUsedAnymore ANTMF. 60

IsUsedDifferently ANT. 60

IsInNewerBuild ANTMF. 61

IsInOlderBuild ANTMF. 61

CQL boolean conditions dedicated to Purity / Side-Effects / Mutability. 64

IsImmutable  TF. 64

ChangesObjectState  M... 65

ChangesTypeState  M... 65

ReadsMutableObjectState  M... 65

ReadsMutableTypeState  M... 66

ReadsImmutableObjectState  M... 66

ReadsImmutableTypeState  M... 66

IsWritingField  M... 67

DepthOfIsWritingField  M... 67

IsDirectlyWritingField  M... 67

 

Introduction

CQL is a language which allows writing queries on the code structure of any.NET and C++ application.

 For example, the following CQL query returns all the methods of your application with more than 200 lines, ordered from the biggest to the smallest:

 

SELECT METHODS WHERE NbLinesOfCode > 200 ORDER BY NbLinesOfCode DESC

 

You might wish to avoid methods with more than 200 lines since they are hard to maintain. After having shrunk all your methods, you certainly want to be notified when during development a method exceeds this threshold. The CQL language addresses this need by allowing the transformation of queries into constraints. For example, here is our previous query rewritten as a constraint:

 

WARN IF Count > 0 IN SELECT METHODS WHERE NbLinesOfCode > 200 ORDER BY NbLinesOfCode DESC

 

With almost a hundred keywords, the CQL language allows you to deal with various conditions on your code structure. It allows to write code quality constraints, naming constraints, design constraints, encapsulation constraints, queries on the graph of dependencies, queries on the inheritance tree,  queries to get the biggest or smallest code elements according to almost 30 metrics and much more.

 

CQL and VisualCppDepend

The tool VisualCppDepend allows the editing and execution of CQL queries and constraints. A GUI allows you to have a unique understanding of your application. VisualCppDepend can also be used to generate reports during each build of your application.

 

VisualNDepend2_Big

 

Learning the CQL language

Writing CQL queries and constraints is straightforward thanks to the three following features:

 

VisualNDependCQLEditor

 

VisualNDependCQLEditor2

The CQL language and real-world needs

The CQL language has been conceived to understand and control real-world application. In a real-world environment, there are often exceptions (like automatically generated methods which are often very big) and you need to allow a few particular methods to exceed this threshold without being bothered by our previous constraint. The CQL language offers numerous features allowing you to deal with such exceptions. For example, all generated methods might contain the word “Generated” in their names:

 

WARN IF Count > 0 IN SELECT METHODS WHERE  NbLinesOfCode > 200 AND !NameLike "Generated" ORDER BY NbLinesOfCode DESC

 

Or maybe, all generated methods are in dedicated projects, namespaces or types:

 

WARN IF Count > 0 IN SELECT METHODS OUT OF NAMESPACES "MyApp.Generated1","MyApp.Generated2" WHERE NbLinesOfCode > 200 ORDER BY NbLinesOfCode DESC

 

Or maybe, you prefer to mention each one explicitly:

 

WARN IF Count > 0 IN SELECT METHODS WHERE NbLinesOfCode > 200 AND !(NameIs "Method1(Int32)" OR FullNameIs "MyApp.MyType.Method2(String)" ) ORDER BY NbLinesOfCode DESC

 

You can also mix all these features in the same constraint:

 

WARN IF Count > 0 IN SELECT METHODS OUT OF NAMESPACES "MyApp.Generated1","MyApp.Generated2" WHERE NbLinesOfCode > 200 AND !(NameIs "Method1(Int32)" OR FullNameIs "MyApp.MyType.Method2(String)" ) AND !NameLike "Generated" ORDER BY NbLinesOfCode DESC

Storing CQL queries and constraints in your C++ source code

CppDepend stores your CQL queries and constraints in the project file. As the source code is the design you might prefer storing your CQL queries and constraints directly in your source code.

Some examples of queries and constraints written in CQL

Examples of code Quality constraints

WARN IF Count > 0 IN SELECT METHODS WHERE NbLinesOfCode > 200 ORDER BY NbLinesOfCode DESC

// METHODS WHERE NbLinesOfCode > 200 are extremely complex and

// should be split in smaller methods

// (except if they are automatically generated by a tool).

 

WARN IF Count > 0 IN SELECT METHODS WHERE ILCyclomaticComplexity > 40 ORDER BY ILCyclomaticComplexity DESC

// METHODS WHERE ILCyclomaticComplexity > 20 are hard to understand and maintain.

// METHODS WHERE ILCyclomaticComplexity > 40 are extremely complex and should be split

// in smaller methods (except if they are automatically generated by a tool).

 

WARN IF Count > 0 IN SELECT METHODS WHERE NbParameters > 5 ORDER BY NbParameters DESC

// METHODS WHERE NbParameters > 5 might be painful to call and might degrade performance.

// You should prefer using additional properties/fields to the declaring type to handle

// numerous states. Another alternative is to provide a class or structure dedicated to

// handle arguments passing (for example see the class System.Diagnostics.ProcessStartInfo

// and the method System.Diagnostics.Process.Start(ProcessStartInfo))

 

WARN IF Count > 0 IN SELECT METHODS WHERE NbVariables > 15 ORDER BY NbVariables DESC

// METHODS WHERE NbVariables > 8 are hard to understand and maintain.

// METHODS WHERE NbVariables > 15 are extremely complex and should be split in

// smaller methods (except if they are automatically generated by a tool).

 

WARN IF Count > 0 IN SELECT TYPES WHERE NbMethods > 20 ORDER BY LCOM DESC

// TYPES WHERE NbMethods > 20 might be hard to understand and maintain

// but there might be cases where it is relevant to have a high value for NbMethods.

// For example, the System.Windows.Forms.DataGridView standard class has more than 1000 methods.

 

WARN IF Count > 0 IN SELECT TYPES WHERE NbFields > 20 AND !IsEnumeration

// TYPES WHERE NbFields > 20 AND !IsEnumeration might be hard to understand and maintain

// but there might be cases where it is relevant to have a high value for NbFields.

// For example, the System.Windows.Forms.Control standard class has more than 200 fields.

// The value of the metric SizeOfInst might be a better indicator of complex type.

 

WARN IF Count > 0 IN SELECT TYPES WHERE SizeOfInst > 64 ORDER BY SizeOfInst DESC

// TYPES WHERE SizeOfInst > 64 might degrade performance (depending on the number of

// instances created at runtime) and might be hard to maintain.

// However it is not a rule since sometime there is no alternative

// (the size of instances of the System.Net.NetworkInformation.SystemIcmpV6Statistics

// standard class is 2064 bytes).

 

WARN IF Count > 0 IN SELECT TYPES WHERE LCOM > 0.8 AND NbFields > 10 AND NbMethods >10 ORDER BY LCOM DESC

// TYPES WHERE LCOM > 0.8 AND NbFields > 10 AND NbMethods >10 might be problematic.

// However, it is very hard to avoid such non-cohesive types. The LCOMHS metric

// is often considered as more efficient to detect non-cohesive types.

 

WARN IF Count > 0 IN SELECT TYPES WHERE LCOMHS > 1.0 AND NbFields > 10 AND NbMethods >10 ORDER BY LCOMHS DESC

// TYPES WHERE LCOMHS > 1.0 AND NbFields > 10 AND NbMethods >10 should be avoided.

// Note that this constraint is stronger than the constraint

// TYPES WHERE LCOM > 0.8 AND NbFields > 10 AND NbMethods >10.

 

SELECT TYPES WHERE DepthOfInheritance > 6 ORDER BY DepthOfInheritance DESC

// TYPES WHERE DepthOfInheritance > 6 might be hard to maintain. However it is not

// a rule since sometime your classes might inherit from tier classes which have a

// high value for depth of inheritance. For example, the average depth of inheritance

// for framework classes which derive from System.Windows.Forms.Control is 5.3.

 

WARN IF Count > 0 IN SELECT TYPES WHERE (SizeOfInst > 200 ) ORDER BY SizeOfInst DESC

// Type with big instances can be problematic

// (Obviously the SizeOfInst metric does not do a deep traverse.

//  Any instance reference field will count for 4 bytes.

//  It is also unable to cop with generic types properly)

 

 

WARN IF Percentage > 15 IN SELECT PROJECTS WHERE NormDistFromMainSeq > 0.7 ORDER BY NormDistFromMainSeq DESC

 

WARN IF Count > 0 IN SELECT PROJECTS WHERE RelationalCohesion < 1.5 OR RelationalCohesion > 4.0

// As classes inside an project should be strongly related,

// the cohesion should be high. On the other hand, a value which is too high may

// indicate over-coupling. A good range for RelationalCohesion is 1.5 to 4.0.

Examples of naming constraints

WARN IF Count > 0 IN SELECT FIELDS WHERE NameLike "^m_" AND IsStatic

// A static field should not be named 'm_XXX'

 

WARN IF Count > 0 IN SELECT FIELDS WHERE NameLike "^s_" AND !IsStatic

// A non-static field should not be named 's_XXX'

 

WARN IF Count > 0 IN SELECT TYPES WHERE IsInterface AND !NameLike "^I"

// The name of an interface should begin with a 'I'

 

WARN IF Count > 0 IN SELECT TYPES WHERE IsExceptionClass AND !NameLike "Exception$"

// The name of an exception class should end with 'Exception'

 

 

WARN IF Count > 0 IN SELECT TYPES WHERE

   !NameLike "^[A-Z]" AND // The name of a type should begin with an Upper letter.

   !NameLike "__StaticArrayInit" AND  // Except __StaticArrayInit generated type

   !NameLike "<"                      // Except C# compiler generated type

 

WARN IF Count > 0 IN SELECT METHODS WHERE

   !NameLike "^[A-Z]"

// The name of a regular method should begin with an Upper letter.

Examples of design constraints

WARN IF Count > 0 IN SELECT TYPES WHERE SizeOfInst ==0 AND !IsStatic AND !IsTemplate

// It indicate stateless types that might eventually be turned into static classes.

 

Examples of encapsulation constraints

WARN IF Count > 0 IN SELECT FIELDS WHERE IsPublic

// A field should not be public or internal, except for performance reasons.

 

 

WARN IF Count > 0 IN SELECT TYPES OUT OF NAMESPACES "System.Xml" WHERE DepthOfIsUsing "System.Xml.XmlChildNodes" == 1

// Restrict the possibility of using the type "System.Xml.XmlChildNodes" only to certain namespace.

 

WARN IF Count > 0 IN SELECT METHODS OUT OF NAMESPACES "System.Xml" WHERE

DepthOfIsUsing  "System.Xml.XmlNamedNodeMap.InsertNodeAt(Int32,XmlNode)"== 1

// Restrict the possibility of calling the method "System.Xml.XmlNamedNodeMap.InsertNodeAt(Int32,XmlNode)"

// only to certain namespace.

 

WARN IF Count > 0 IN SELECT METHODS OUT OF TYPES

"System.Xml.XmlDocumentFragment",

"System.Xml.XmlEntityReference",

"System.Xml.XmlDocumentType",

"System.Xml.XmlEntity",

"System.Xml.XmlDocument",

"System.Xml.XmlAttribute",

"System.Xml.XmlElement" WHERE DepthOfCreateA "System.Xml.XmlLoader" ==1 ORDER BY DepthOfCreateA

// Restrict the possibility of creating an instance of "System.Xml.XmlLoader" only to certain type.

 

WARN IF Count > 0 IN SELECT METHODS OUT OF NAMESPACES "System.Xml"

WHERE DepthOfCreateA "System.Xml.XmlLoader" == 1 ORDER BY DepthOfCreateA

// Restrict the possibility of creating an instance of "System.Xml.XmlLoader" only to certain namespaces.

 

WARN IF Count > 1 IN SELECT NAMESPACES OUT OF PROJECTS "System.Windows.Forms"

WHERE DepthOfIsUsing "System.Windows.Forms.Internal" == 1

// Restrict the possibility of using a namespace only to one project.

 

WARN IF Count > 0 IN SELECT METHODS OUT OF NAMESPACES "System.Windows.Forms" WHERE

DepthOfIsUsing "System.Windows.Forms.DataGridView+HitTestInfo.typeInternal" == 1

// Restrict the possibility of using the field

// "System.Windows.Forms.DataGridView+HitTestInfo.typeInternal"

// only to certain namespace.

Examples of queries on the graph of dependencies

SELECT METHODS WHERE IsUsing "System.Xml.XmlWriter..ctor()" ORDER BY DepthOfIsUsing

// 'IsUsing/IsUsedBy/DepthOfIsUsing/DepthOfIsUsedBy' conditions are useful

// to understand who calls statically who for example to anticipate future impacts

// of some refactoring or to provide some customized encapsulation constraints.

 

SELECT METHODS WHERE DepthOfIsUsing "System.Xml.XmlWriter..ctor()" <=3

// 'IsUsing/IsUsedBy/DepthOfIsUsing/DepthOfIsUsedBy' conditions are useful

// to understand who calls statically who for example to anticipate future impacts

// of some refactoring or to provide some customized encapsulation constraints.

 

<