In this section:
About Node Sets
When creating complex rules, you may want to create conditions that are contingent upon specific attributes or relationships between multiple nodes. For example, if you have multiple nodes in a rule condition, you may want to specify at which point static analysis starts and stops counting the number of "hits" (instances of the specified conditions defined in the rule). You may also want a rule that reports when the total number of hits in two different sets of nodes is greater than 0. In such cases, you would create a rule that includes one or more set components.
Set components are a category of components that represent sets of nodes. These components include collectors and set operators. Collectors let you restrict a node or node set’s quantity. Set operators let you specify a relationship between two or more set components. For example, they could be used to create a rule that checks that the total number of hits in two rule conditions is less than 1.
Using Set Operators to Specify Relationships Between Set Components
With set operators, you can create rule segments that report the number of hits for a relationship between two set components. For example, you could create a rule segment that collects the number of hits of the pattern of nodes that are in either set component A, or in set component B.
Set operators are rule elements that indicate:
- Which two set components you want to represent a relationship between.
- What type of relationship you want to establish between the two associated set components.
Because set operators establish relationships between set components, they must be connected to the set component that the set operator is attached to and reference another set component. The other component is the “operand” of the set operator. Set operators can be used to establish four types of relationships:
- a union of two set components
- an intersection of two set components
- an exclusive-or relationship between two set components
- a difference between two set components
A union is the set of nodes that are:
- in the attached collector, or
- in the operand, or
- in both the attached collector and the operand.
For example, if A represents a set component that contains nodes xx, yy, and zz, and B represents a set component that contains nodes ww, xx, and yy, a union between A and B would match xx, yy, zz, and ww.
An intersection is the set of nodes that are in both the attached set component and the operand. For example, if A represents a set component that contains nodes xx, yy, and zz, and B represents a set component that contains nodes ww, xx, and yy, an intersection between A and B would match xx and yy.
A difference is the set of nodes that are either:
- In the attached set component (the “left” side) but not in the operand (the “right” side), or
- In the operand (the “right” side), but not in the attached set component (the “left” side).
A right-left difference represents the nodes in the operand, but not the set operator, while a left-right difference represents the nodes that are in the set operator, but not in the operand. For example, if A represents a set component that contains nodes xx, yy, and zz, and B represents a set component that contains nodes ww, xx, and yy, an A-B difference between A and B would match zz, while a B-A difference would match ww.
An XOR (exclusive-or) relationship is the set of nodes that are in either the attached set component or the operand, but not the nodes that are in both. For example, if A represents a set component that contains nodes xx, yy, and zz, and B represents a set component that contains nodes ww, xx, and yy, a XOR between A and B would match zz and ww.
To establish relationships between two set components (X and Y), you would:
- Attach a set operator to one set component (X) by right-clicking it and choosing Set Operator> <relationship> from the shortcut menu.
- Attach a label to the other set component (Y).
- Specify that you want Y to be the set operator’s operand by selecting Y’s label as the set component’s operand value.
A common reason for using set operators is creating a rule that restricts the number of hits for a union, intersection, difference, or XOR node set.
The following image is the implementation of "Unused local variable".
- The first collector (labeled A) collects local variables used in non-declaration statements.
- The second collector collects local variables declared in the method.
- “IsDecl” stands for “Is this declaration?” If set to true, the node returns true for declaration statements. If set to false, it returns true for non-declaration statement.
- The Difference set operator is used to find the difference between the two node sets.
- The Count node with $$>0 checks if the Difference set has at least one item. If so, a violation is reported.
To create a rule that counts and restricts the total number of hits that occur for a specific type of relationship between two node sets:
- Create a rule condition that contains a set component (such as a collector).
- Right-click the set component and choose Label> <label name> from the shortcut menu to label it. Once you have done this, you can make this component an operand of a set operator.
- Create another rule condition that contains a set component.
- Right-click the newly-added set component and choose Create Set Operator> <desired type of relationship> from the shortcut menu. A set operator will be attached to the set component.
- Right-click the circle on the top right of the set operator and choose the label of the first set component to indicate the operand of the set operator.
- Right-click the set operator and choose Count from the shortcut menu.
- Modify the value included in the count node (if necessary) to restrict the number of hits allowed for the specified relationship.
Once you have added an output arrow to your rule and specified rule properties, your rule will be complete.
Customizing Counts with Collectors, Counts, and Trigger Points
About Trigger Points
RuleWizard’s Collector and Count commands enable you to create a rule condition that restricts a node or node set’s quantity. To create such a rule condition:
- Create a collector
- Right-click the collector and choose Count.
The Collector command keeps track of the number of times that the specified pattern is found. The Count command places a condition on what number of instances constitutes a rule violation.
When a rule that restricts a node’s quantity is enforced, the number of instances of the pattern are collected in the collector, the count is checked, and a violation is reported if the count falls within the parameters specified in the rule.
By specifying when static analysis should empty the collector, you can determine precisely how the count is determined. This is done through the use of “trigger points.” Trigger points determine the node at which Parasoft static analysis starts and stops counting the number of instances that occur. The correct trigger point number to use is determined by counting back from the node to which the collector is attached, to the node at which you want the collector emptied and a violation reported (if the specified pattern is found).
Trigger Point Examples
In the following example, trigger point 1 indicates to empty the collector after each switch statement is searched. The switch node is one node “back” from the Body node to which the collector and trigger point are attached.
This rule would look for a switch statement for each file then look for default statements in that switch statement’s body. The number of expressions that met this criteria would be placed in the collector, the count would be checked, and a violation would be reported if the count were zero. When another switch statement was parsed, the collector would then be emptied, and this process would be repeated for that switch statement.
If you had a trigger point of 2 (the highest possible value in this example), the collector would be emptied only after the entire file was searched. The collector accumulates all values found from the file node (1 actual and one applied node (the file is an applied node) back from the node to which the trigger point and collector are attached), and the collector would not be emptied until a new file was parsed.
In the following example, trigger point 1 indicates to empty the collector after each member function is searched. The Member Function node is one node “back” from the a=b node to which the collector and trigger point are attached.
This rule would look for a member function in the class’ body of each class then look in that member function for expressions in the form “a=b”. The number of expressions that met this criteria would be placed in the collector, the count would be checked, and a violation would be reported if the count were zero. When another member function is parsed, the collector would be emptied and the process would be repeated for that member function.
If you changed the trigger point to 2, static analysis would look at all member functions and count the number of matching expressions in all member functions before emptying the collector. The collector accumulates all values found from the Class node (two nodes back from the node to which the trigger point and collector are attached) and the collector is not emptied until it a new class is parsed.
If you had a trigger point of 3 (the highest possible value in this example), static analysis would empty the collector only after the entire file was searched. The collector accumulates all values found from the file node--two actual and one applied node; the file is an applied node--back from the node to which the trigger point and collector are attached, and the collector is not emptied until a new file is parsed.
Creating a Trigger Point
When you create a collector, it is assigned a number 1 trigger point by default. To change the trigger point value, right-click the trigger point number and choose the desired value from the shortcut menu.
Guidelines for using trigger points:
- To get the maximum value for a particular trigger point, count the number of nodes from the node with the attached collector to the top node of the rule, then add 1.
- You cannot place a trigger point on a node for which a direct check is performed.
- You cannot add an output arrow between the collector and the node/applied node that the trigger point number points to. For example, in the above rule you could place an output arrow at the Class node when you have a trigger point of 1 or 2, but for trigger point 3 you would need to attach the output arrow to the collector (rather than to the Class node).
Determining the Output Type of a Set Component
If you place an output arrow on a set component, you will be asked to determine when the output “fires” or reports that the pattern has been violated. The following output options are available for set components.
This output option fires on each hit or each node contained in the set. This type of output arrow is placed below the center of the set operator it is attached to.
When you choose this type of output, the violation output can contain fields of nodes contained in the set operator. For example, if you have a collector that contains variables in Java or C++ and you select a Hits Output, you can use an output message, such as “Initialize all variables in constructor. Variable $name is not initialized.” When this rule is actually violated, the $name variable will be replaced with the name of the uninitialized variable.
If you have a collector that counts the number of <LI> tags that occur in a certain context and you select a Hits Output, to take another example, you can use an output message such as “<$tag> does not appear in the correct context.” When this rule is actually violated, the <$tag> value will be replaced with the name of the tag (<LI>).
This output option fires once for the set when the set is triggered at the trigger point. This type of output arrow is placed below the left side of the set operator that it is attached to, or below the trigger point number.
When you choose this type of output, the violation output can contain properties of the collector, but not properties of nodes contained in the set operator. Currently, the only variable you can use here is $count.
If your rule includes a collector, you can have your output include the number of hits that the collector has accumulated. To do this, enter COUNT(A) where A is the label of the collector whose count you want reported in the appropriate output message.
You can also have your output message list the items that a collector has accumulated. To do this, enter LIST(A) where A is the label of the collector whose “list” you want reported in the appropriate.
Assertions use the set references MIN, MAX, AVERAGE, and MEDIAN. They are used on set components whose elements are number nodes to compare the values of the counts.
For example, the Example.FBM rule represented in the graphic below checks that all the field declarations in a type declaration appear before all method declarations--a standard Java convention. The Jtest 9.x built-in rule CODSTA.FO can normally be used to check this standard, but this RuleWizard rule is provided to show how to use assertions in RuleWizard rules.
This rule ignores fields and methods defined in inner types (as opposed to top-level types) for simplicity. The "Class" nodes with the condition "IsInner= F" which are attached to the "Body/ Field" node and the "Body/ Method" node are used to filter out fields and methods defined in inner classes. The "IsImplicit= F" node attached to the "Body/ Method" node is used to filter out the default implicit no-argument constructor for classes with no other constructors.
The collector A is used to collect the line numbers for all the field declarations. The collector B is used to collect the line numbers for the start of all the method declarations. The assertion is used to check that all the field declarations come before all the method declarations. Right-click the head node and choose Create Assertion to create the assertion node. If MAX(A) > MIN(B), we know that not all field declarations come before all method declarations; thus, we report a violation in this case.