주요 콘텐츠

Create User-Defined Coding Standard by Using Polyspace Query Language

A user-defined coding standard is a collection of coding rules that you curate to check for bugs and defects that are relevant to your project. To create a user-defined coding standard, select the rules in which you are interested. Map your coding rules to existing Polyspace® Bug Finder™ checkers. If there is no good mapping, define your own defect using Polyspace Query Language (PQL). Finally, create the user defined coding standard by encoding your new rules and mapping in PQL.

This topic shows how to create a user-defined coding standard once you have the mapping between the coding rules in the user-defined coding standard and existing Bug Finder checkers. To learn how to create the mapping, see Find Polyspace Bug Finder Checkers That Map to Coding Rules in User-Defined Coding Standard. This topic assumes familiarity with PQL syntax. For details about PQL syntaxes, see: Create Your Own Coding Rules and Coding Standard.

Design User-Defined Coding Standard

Before implementing your own coding standard, design the coding standard so that reviewing results from the coding standard is convenient and logical. For the best practices, see Best Practices for Creating User-Defined Coding Standards.

In your design:

  • Specify the Bug Finder checkers you want to include.

  • Specify the user-defined defects that you want to create or reuse.

  • Gather related rules in to sections.

  • In addition to sections, classify the rules into categories and subsets for ease of use.

For example, this table summarizes the design of a user-defined coding standard. Related rules are classified into different sections. Each rule is assigned an Id. The Id is the identifier of a rule during result review. Rules in a specific category or subset can be enabled together. For easier configuration, the rules in the standard is further classified into categories and subsets.

SectionIdDescriptionBug Finder CheckerCategorySubset
ClassC.4Make a function a member only if it needs direct access to the representation of a classAUTOSAR C++14 Rule M9-3-3Cat-1Subset A
ClassC.22Make default operations consistentMove operation uses copy, AUTOSAR C++14 Rule A12-8-1, AUTOSAR C++14 Rule A12-1-1Cat-1Subset A
Move SemanticsMove_1A move operation may throwA move operation may throwCat-2Subset A
Move SemanticsMove_2Move operation uses copyMove operation uses copyCat-2Subset A, Subset B
Move SemanticsMove_3

const std::move input may cause a more expensive object copy

Const std::move input may cause a more expensive object copyCat-2Subset A, Subset B
ContainerContainer_1Expensive use of map instead of setExpensive use of map instead of setCat-3Subset A, Subset B
ContainerContainer_2Expensive use of map's bracket operator to insert or assign a valueExpensive use of map's bracket operator to insert or assign a valueCat-3Subset A, Subset B
SyntaxSyntax1Do not use assignment operation as condition for if and whileNo existing checker. Create as a user-defined defect.Cat-2Subset C
SyntaxSyntax2Integer variable names must indicate signedness and sizeNo existing checker. Create as a user-defined defect.Cat-2Subset C

Related rules are classified into different sections. Each rule is assigned an Id. The Id is the identifier of a rule during result review. Rules in a specific category or subset can be enabled together. For easier configuration, the rules in the standard is further classified into categories and subsets.

Initialize User-Defined Coding Standard

Create a folder called myStandard in a writable location. Open a command-line terminal in this folder and enter:

polyspace-query-language init
Two new files main.pql and pql.json is created in the folder. The pql.json file is a configuration object that Polyspace uses when compiling the standard. You do not need to edit this file in this example. The main.pql file contains the code that packages the rules and user-defined defects into a .pschk file. Open main.pql and verify that the file contains package main as the first line and then contains an empty definition of a catalog named myStandard.

Create Folder Structure

Create folders corresponding to each section in the standard. Code for the sections are created in each of these child folders. Each folder correspond to a package, which contains the section element. These elements are then assembled in main.pql. Because the package elements are defined in child folders of myStandard, Polyspace assumes that each of these package element is part of the main package. The complete folder structure for the standard looks like this:

To create this folder structure in the command line, navigate to myStandard and enter:

mkdir Class Move_Semantics Container Naming_Convention

Create Rules and Sections

In the folder Class, create new text files C_4.pql and C_22.pql in your preferred text editor or IDE. These files implement the rules with the identifier C_4 and C_22 in the preceding table. This code defines the rule element C_4 and maps it to AUTOSAR C++14 Rule M9-3-3:

package Class
#[Description ("Make a function a member only if it needs direct access to the representation of a class"), Id(C_4), Lang(C++), Category("Cat-1"), Subsets("Subset A") ]
rule C_4 = {
  std.autosar_cpp14.M9_3_3
}
In this code:

  • The Description annotation specifies the UI label for the rule.

  • The Id annotation specifies the short name for this rule.

  • The lang annotation specifies that this rule applies to C++ only.

  • The Category annotation specifies that this rule belongs to the category Cat-1.

  • The Subsets annotation specifies that this rule belongs to the subset A.

  • std.autosar_cpp14.M9_3_3 is the PQL name of the checker AUTOSAR C++14 Rule M9-3-3. The PQL name of a checker is documented in the Check Information section of the checker reference page.

Similarly, define the rule element C_22 in the file Class/C_22.pql:

package Class
#[Description ("Make default operations consistent"), Id(C_22), Lang(C++), Category("Cat-1"), Subsets("Subset A") ]
rule C_22 = {
  std.defects.MOVE_OPERATION_USES_COPY,
  std.autosar_cpp14.A12_8_1,
  std.autosar_cpp14.A12_1_1
}
After defining the two rule elements, create the section element that contains these rule elements in Class/Class.pql. Because the rule elements and section elements are in the same package, the element C_4 and C_22 are available for use in Class/Class.pql:
// Class/Class.pql
package Class

#[Description ("Class")]

section Class = {
  C_4,
  C_22
}

For the other section, create the rules in their own .pql files in the respective folders and then use the rule elements to create the section elements:

  • Create the rule Container_1 in myStandard/Container/Container_1.pql:

    package Container
    #[Description ("Expensive use of map instead of set"), Id(Container_1), Lang(C++), Category("Cat-3"), Subsets("Subset A", "Subset B")]
    rule Container_1 = {
      std.defects.EXPENSIVE_USE_OF_MAP_INSTEAD_OF_SET
    }

  • Create the rule Container_2 in myStandard/Container/Container_2.pql:

    package Container
    #[Description ("Expensive use of map's bracket operator to insert or assign a value"), Id(Container_2), Lang(C++), Category("Cat-3"), Subsets("Subset A", "Subset B")]
    rule Container_2 = {
      std.defects.EXPENSIVE_MAP_INSERT_OR_ASSIGN
    }

  • Create the section Container inmyStandard/Container/Container.pql

    package Container
    
    #[Description ("Container")]
    
    section Container = {
      Container_1,
      Container_2
    
    }

  • Create the rule Move_1 in myStandard/Move_Semantics/Move_1.pql:

    package MoveSemantics
    #[Description ("Move operation may throw"), Id(Move_1), Lang(C++), Category("Cat-2"), Subsets("Subset A")]
    rule Move_1 = {
      std.defects.MOVE_OPERATION_MAY_THROW
    }

  • Create the rule Move_2 in myStandard/Move_Semantics/Move_2.pql:

    package MoveSemantics
    #[Description ("Move operation uses copy"), Id(Move_2), Lang(C++), Category("Cat-2"), Subsets("Subset A", "Subset B")]
    rule Move_2 = {
      std.defects.MOVE_OPERATION_USES_COPY
    }

  • Create the rule Move_3 in myStandard/Move_Semantics/Move_3.pql:

    package MoveSemantics
    #[Description ("Const std::move input may cause a more expensive object copy"), Id(Move_3), Lang(C++), Category("Cat-2"), Subsets("Subset A", "Subset B")]
    rule Move_3 = {
      std.defects.EXPENSIVE_STD_MOVE_CONST_OBJECT
    }

  • Create the section Move_Semantics in myStandard/Move_Semantics/MoveSemantics.pql

    package MoveSemantics
    
    #[Description ("Move Semantics")]
    
    section MS = {
      Move_1,
      Move_2,
      Move_3
    }

  • Create the rule nameNotDescriptive in myStandard/Naming_Convention/nameNotDescriptive.pql:

    package NC
    #[Description ("Do not use single letter as a name"), Id(NC_1), Category("Cat-2"), Subsets("Subset C")]
    rule nameNotDescriptive = {
    	defect inappropriateIntName =
    	when
    	Cpp.Variable.is(&var)
    	and var.name(&varName)
    	and var.type(&varType)
    	and varType.isIntegral()
    	and getPrefix(varType, &prefix)
    	and not varName.startsWith(prefix)
    	raise "Expected prefix: \"{prefix}\""
    	on var
    }
    
    predicate getPrefix(Cpp.Type.Type vartype, Lang.String &prefix) {
    	return
    	((vartype.isSigned() and Lang.createString( "s", &str))
    	 or (vartype.isUnsigned() and Lang.createString( "u", &str)))
    	and vartype.sizeInBits(&nBits)
    	and Lang.toString(nBits, &sizestr)
    	and Lang.catString(str, sizestr, &prefix)
    }

  • Create the section Naming_Convention in myStandard/Naming_Convention/Naming_Convention.pql

    package NC
    
    #[Description ("Naming Convention")]
    
    section VarName = {
    nameNotDescriptive
    }

Assemble Coding Standard

After defining the section elements, assemble the standard in main.pql. Each section element is defined in a child package of the main package. Use dot notation to place the sections in the catalog myStandard:

package main

// Main PQL file defines the catalog of your PQL project.
// The catalog is a collection of sections.
#[Categories("Cat-3","Cat-2","Cat-1")]
catalog myStandard = {
  Class.Class,
  Container.Container,
  MoveSemantics.MS,
  NC.VarName
 
}
This code also specifies Cat-1, Cat-2, and Cat-3 as the only permissible categories in the standard, with Cat-3 being the lowest priority and Cat-1 being the highest priority.

Create .pschk File

User defined coding standards are used by Polyspace as .pschk files. To create the Polyspace user-defined coding standard (.pschk) file, navigate to the folder myStandard in the command line and enter:

polyspace-query-language package .
The command creates the file myStandard.pschk in the folder myStandard. You can open this coding standard in the Checkers Selection window.

The Checkers Selection window showing the user-defined coding standard.

In this coding standard:

  • The section labels match the Description attribute defined in the PQL code.

  • The rule name and identifiers correspond to the Description and Id attribute defined in the PQL code.

  • The rules are classified into categories and subsets specified by Category and Subsets attributes of the rules.

After creating the .pschk file, you can share the file with other Polyspace users in your organization.

To check for violations of the user-defined coding standard, use one of these methods:

  • Command line — Use the .pschk file as an input to the option Checkers activation file (-checkers-activation-file).

  • Polyspace Platform user interface — In the Configuration pane, select Static Analysis > Defects and Coding Standards. Enter the .pschk file in the Checkers activation file box.

  • Polyspace as You Code™ — Specify the .pschk file in the Checkers Selection window. You can open the Checkers Selection window from your Polyspace as You Code extension. See Configure Checkers (Polyspace as You Code).

For more details about finding violations of the user-defined coding standard, see Check for Violations of User-Defined Coding Standard Using Polyspace Bug Finder.

See Also

Topics