Naming Convention Checker

Overview

DAC gives you the possibility to bring in certain conventions relating to the naming of project symbols, and to check whether the names you have defined in the project correspond to the conventions assigned. If the names of the symbols in your project are standardized, then finding your way around in the project is much easier. In this way you can tell, by looking at what follows a variable name, what its type is, whether the variable is local, static, global, etc. These conventions are introduced for reasons of legibility and intelligibility of the code written. An example of this is the set of rules known as Hungarian notation. Hungarian notation has been accepted as a standard according to which the variable name is preceded by key letters describing which type of data the variable represents. Using this notation allows you to identify variable type using the prefix it carries. These prefixes are also used together, according to demand (e.g. a long pointer to string with a null-ending would have the prefix "lpsz").

Many other rules can also be assigned.

Naming Convention Check as a feature within DAC encompasses the following:

a. Naming Convention check via a set of rules which you can assign using a dialog;

b. Rules based on regular expressions;

c. Rules which reside in a file, so that they can be used in multiple projects;

d. Naming Convention Check can be started independently from the Start menu or set to start automatically, right after Static Code Analysis;

e. Check results are displayed in the form of warnings in the Message Logs. You can set these warnings to be displayed in a Message Logs tab or together with Static Code Analysis warnings.

Rules for Symbol Naming 

You assign each rule using two regular expressions. The first regular expression is called regular expression for type. The second regular expression is called regular expression for name. You can find a description of regular expressions in "Editor", the one difference being that the characters $ and ^ (which in regular expressions used in Editor signal the beginning and end of a line) are treated like ordinary characters here.

Naming Convention rule macros related to source files could be defined and used in regular expressions so that symbols of the source file could be checked if they contain specific prefix, suffix or other part of the name. Macro name can contain only alphanumeric characters. If filename contains spaces or '%', it must be enclosed in "". Format: %MacroName% "Filename_without_extension" = MacroValue

Using a regular expression for type you assign type, that is the kind of symbol for whose name you would like to assign a rule. In a regular expression for type you can use the following words and characters:

C language keywords which name basic types (int, char, float ...),
C language keywords which name type modifiers (short, const, volatile, auto, ... ),
Expressions which, together with other expressions, enable you to form compound types (strings and pointers), and these are array of and ptr to,
C language keywords struct, union, typedef and enum, used to describe structured (structures and unions) and enumerated types,
The expression function returning, used to describe functions,
The expression macro, used to describe macros. Old type description "#define" is supported for compatibility reasons.

Using a regular expression for name you assign the naming rule itself. These regular expressions will be explained through examples.

Examples of Regular Expressions

Using Naming Convention macros:

%sncname% mainmod = MAM // MainMmod.*
...
function returning int = main|fri_P%sncname%_.*    // e.g. for MainMod.c: global function "fri_PMAM_foo"
static function returning int = fri_S%sncname%_.*  // e.g. for MainMod.c: static function "fri_SMAM_foo"

A regular expression for type can, in the simplest case, represent a basic or compound type, as in the following example:

char
float
ptr to char
array of ptr to array of int

You, therefore, use such expressions to mark some symbol types for the naming of which you would like to assign a rule. The language of regular expressions, however, provides a much wider symbol type class to choose from. For example:

ptr to .+

marks all pointer, that is, a pointer to any object in the code.

A symbol naming rule has the following format:

<symbol_type> = <naming_rule>

where <symbol_type> is described by a regular expression for type, and the <naming_rule> is described by a regular expression for name.

Table 1: Examples of regular expressions  

Expression

Description

char = c[A-Z][a-z0-9]*

A char type variable must begin with an initial lowercase "c" followed by an uppercase letter, and then by an arbitrary combination of lowercase letters and numerals. Underscore is not allowed.

int = i[A-Z][a-z0-9]*

An int type variable must begin with an initial lowercase "i" followed by an uppercase letter, and then by an arbitrary combination of lowercase letters and numerals. Underscore is not allowed.

array of .+ = a.*

Array type variables must begin with a lowercase letter "a", while the rest is arbitrary.

array of ptr to char = apc(_|[a-z])+

Variables of the string of pointers to characters type must begin with a combination of lowercase letters "apc", followed by an arbitrary combination of lowercase letters and underscore characters, with at least one character following the obligatory prefix "apc".

Structures are used without specifying their members. For example, if the project contains the defined structure

typedef struct complex { int re; int im; } Complex;

and you would like the names of all variables of the Complex type to begin with the prefix cmplx followed by an uppercase A or B character, and the remainder of the name (if there is any) to contain only lowercase letters, then you can write:

struct complex = cmplxA|B[a-z]*

If you would like to describe an enumerated type using a regular expression for type, for example

typedef enum days { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday } Days;

and you would like all variables of this type to begin with a lowercase e with an arbitrary extension, then you can write the rule:

enum days = e.+

If you would like to assign a regular expression as a naming convention relating to functions, you can write the following rules:

function returning int = main|fi.+
function returning .+ = f.+

by means of which you have specified that all functions which return the result of the int type should have a name beginning with the lowercase letters fi, and all other functions should have names beginning with the lowercase letter f.

If you would like to assign a regular expression as a naming convention relating to macros, then use the word macro in this way:

macro = ([A-Z]|_)+

which, in this example, means that the macro name is written exclusively with uppercase letters, with the use of underscore characters.

If a symbol corresponds to a regular expression for type of more than one rule, the corresponding warning is reported only if its name cannot correspond to the regular expression for name of any of these rules.

If you want to define a rule for variables which are defined within functions, you have to put in the keyword auto. If you want to define the rule for variables which are defined outside the functions, and which are not static, you just specify the type.

We will show this in the following example:

int a;
static int b;
void f1( void )
{
  int c;
  c = a+b;
}

If you specify the rule for this example

int = q.*

you will get a warning only for variable "a".

If you specify the rule

auto int = q.*

you will get a warning only for variable "c".

If you specify the rule

.+int = q.*

you will get a warning for all three variables.

A type modifier in a rule must be entered in front of the type. For example, if you want to check the names of variables of the following types:

long signed int
long unsigned int
short unsigned int
short signed int

appropriate regular type expressions in your rules must be respectively:

signed long int
unsigned long int
unsigned short int
signed short int

You should be careful while using structures and unions. Let us look at the following example:

union umyunion { float a; int c; } uMyUnion;

Let the name-checking rule be

union = u.+

By using this rule the symbol umyunion will be checked, and the rule for checking uMyUnion symbol should be:

union umyunion = u.+

Let us look at the following example of an unnamed union:

union { int a; int b; } uMyUnion2;

If you want to enter the rule for uMyUnion2 Names Convention checking, you need to write the regular expression for union <unnamed> type, so that checking for unnamed union type variables or structure type variables would differ from checking for structures or unions .

Therefore, uMyUnion2 checking rule should be as in the following example:

union <unnamed> = u.+

How to Define Symbol Naming Rules

Assigning naming rules is based on the concept of a file with rules. You can create this file yourself or select one of the existing ones. You can also open one of the existing files and alter it in accordance with your needs. In this way it is possible to use the same rules for multiple projects.

Starting Naming Convention Check

You can start Naming Convention Check in one of two ways:

Naming Convention Check Message Log

Check results are displayed in the Message Logs, in the form of a warning.

Double-clicking the line in the Message Logs with warning takes you to the location of the definition of the symbol in question in the project source code.

Symbol Names Checking Messages Tab

If you enable the Report separately option, these warnings will be displayed in a separate Message Logs tab. If you have disabled this option, warnings are displayed together with Static Code Analysis warnings.

You can find more about warnings in Appendix B - Messages in a section "Naming Convention Check Warnings"

Limitations

The rules for naming symbols are liable to limitations imposed by regular languages. The rules which concern the semantics of a particular name are also not supported. You cannot use types you yourself have defined to check variable names. Also, types obtained by macro replacement from basic types cannot be used in this context.

For example, if the following appears somewhere in the project

#define BOOL int
...
BOOL x;

then you cannot use the type BOOL as part of a regular expression; in other words, you cannot require, for example, that all variables of the type BOOL have a lowercase "b" for the first letter, and that variables of the type int begin with a lowercase "i".

Likewise, the rules you assign are liable to limitations imposed by regular languages1. Rules pertaining to the semantics of a name specified are also not supported.

1 Fischer, C. N., LeBlanc Jr., R. J., "Crafting A Compiler", Benjamin/Cummings Publishing Company, 1988.


Copyright 1993-2017, RistanCASE GmbH