Contents
Table of Contents | ||
---|---|---|
|
...
- Verification of compliance with coding standards: are standards been followed in the software implementationsimplementation?
- Inefficiencies in code (examples: string concatenation, improper use of synchronization, unnecessary object construction...).
- Security checks (like tainting like tainting propagation, to see if a user-controller input can reach a "sink", a resource like a database, without proper validation).
- Dependency analysis, to detect design smells ("god class", " implementation dependency", low cohesion and high coupling), or architecture violations ("a layer is using another layer, and should not").
- Code metrics evaluation. A code metric on a software artifact represent represents a certain property (like size or coupling) of the analyzed software.
Each check is coded in a unit (Kiuwan RULE), called Kiuwan RULE, comprising check of:
- Check code (a Java class)
...
- ,
- A rule definition (XML file) including configuration and documentation.
The rule definition XML descriptor contains an :
- An identifier,
- An implementation classname,
...
- Technologies that analyze,
...
- Message/description,
...
- Priority (1=critical ... 5=informative),
...
- Configuration properties,
...
- Examples for a bad / repair code,
...
- Benefits and incovenients for adopting the rule, etc.
Rules are aggregated in rulesets (parts of the quality model), used during static analysis.
...
There are different alternatives for developing rules in Kiuwan, according to the level of abstraction: Abstract Abstract Syntaxt Tree, NavigableNode, XPath or Query API, NavigableNode, XPath or Query API.
Certain " primitive " objects could be passed in many parts of the rules API , and are used in many places in the Kiuwan API:
Primitive | Effect | Method to implement |
---|---|---|
NodeVisitor | Apply logic to node | void visit(BaseNode) |
NodePredicate | Does this node satisfy X? | boolean is(BaseNode) |
NodeSearch | "Find a related node from a given node" | BaseNode apply(BaseNode) |
Navigation | Perform certain navigation on AST starting at given node, | NodeSet navigate(BaseNode) |
As examples for typical NodeSearch
, think of finding the variable declaration for a certain variable usage, function definition for a call, container node for any other node, etc.
...
To help processing AST for common needs, a set of utility classes are of utility classes are provided for each technology. See JavaDoc for full details.
...
- acceptChildren(NodeVisitor), apply a certain operation (encoded in visitor) to this node and its immediate children.
- child(NodePredicate), to find first direct child matching predicate.
- findAllChildren(NodePredicate), returns list of child nodes matching predicate.
- countChildren(NodePredicate) and similar methods, to count children matching predicate.
- hasChildren(NodePredicate), return true if at least one child matches predicate.
TreeNode itself is an Iterable iterable that iterates on direct children:
...
- getLeftSibling() The immediate brother to the left
- getLeftSiblings() Iterator to brothers to the left, traversed from right to left.
- onLeftSiblings(NodePredicate) Iterable for processing left brothers that match predicate in a for-each loop.
- getRightSibling() The immediate brother to the right
- getRightSiblings() Iterator to brothers to the right, traversed from left to right.
- onRightSiblings(NodePredicate) Iterable for processing right brothers that match predicate in a for-each loop.
Additionally there are " safe " simple navigation methods that check if the requested parent or child exists, returning NULLTREE so methods could be chained without fear of runtime exceptions.
...
The simplest way to code a Kiuwan rule is an XPath rule, that express using XPath notation the condition that AST nodes must match to be considered violations of the rule. An XPath rule is declarative, and does not need to be programmed, but require a certain knowledge of the AST.
...
XPath-based rules could be implemented configuring com.als.core.rule.XPathRuleXPath
, passing proper XPath expression in xpath rule property.
Many convenient XPath functions are provided, for full details on XPath, see the XPath section.
Query API
The class com.optimyth.qaking.highlevelapi.dsl.Query
represents a query in an abstract syntax tree (or high-level tree). Query provides a " fluent interface " for expressing a search on AST, specifying the sequence of operations (find, filter, navigate, visit) to perform, starting at a given set of nodes. Each operation is configured by passing primitive objects (NodePredicate, NodeVisitor, NodeSearch or Navigation). Then one of the run()
methods should be called to execute the operations registered.
...
Appropiate primitives could be found for each supported language; for example, for Java, com.optimyth.qaking.java.hla.JavaPredicates
provides instances for returnsNull
and isGetter
.
When a query is executed using run()
over a certain set of initial nodes (typically the root HLA or LLA node), nodes reached by each operation are remembered and act as as context nodes for nodes for the next operation in sequence.
Operations that could be registered in a Query are:
Operation | Effect | Signature |
---|---|---|
find sucessors | Find all successors matching predicate | find(NodePredicate match) |
find following a navigation | Find nodes traversed by navigation, matching predicate | find(NodePredicate match, Navigation navigation) |
navigate | Traverses the given navigation from current (context) nodes | navigate(Navigation) |
filter | Filter current context nodes | filter(NodePredicate) |
visit | Visits each node in current context | visit(NodeVisitor) |
navigate & visit | Visit each node reachable via given navigation with visitor | visit(NodeVisitor, Navigation) |
custom operation | Registers a custom operation | operation(QueryOperation) |
snapshot | Create a "snapshot" of current context nodeset, giving it a name | snapshot(String) |
report | Emit a rule violation for each current context node or snapshot, | report() |
execute query | Executes the query, specifying initial node(s) | run(Rule, RuleContext) |
If you know about XPath, the com.optimyth.qaking.highlevelapi.navigation.Region
provides Navigation instances for each XPath axis:
Region name | XPath axis | Nodes traversed |
---|---|---|
SELF | self:: | context node itself |
ROOT | / | go to root node |
CHILDREN | child:: | immediate children |
PARENT | parent:: | parent node |
ANCESTORS | ancestor-or-self:: | ancestors, including self |
SUCCESSORS | descendant:: | subtree nodes from node, not including itself |
LEFTSIBLINGS | preceding-sibling:: | Siblings of node at left, not including itself |
RIGHTSIBLINGS | following-sibling:: | Siblings of node at right, not including itself |
PRECEDING | preceding:: | Nodes appearing before node (before in code text) |
FOLLOWING | following:: | Nodes appearing after node (before in code text) |
NOTE - Thread-safety: Query is thread-safe if primitives passed are thread-safe. This means that you may use a Query object as instance field of a rule, and call query.run() on the visit() method of the rule to process each input source, in multi-thread analysis this do not produce race conditions.
...
The control-flow graph is a graph where nodes represent statement statements and other code items (like variable declarations or function declarations). Nodes are connected according to the control flow (a statement s1 is connected to statement s2 if s2 may follow execution of s1 under certain conditions). Traversal of the CFG is useful to follow control logic, and certain properties of data flowing thru through the statements in the CFG could be derived statically (this is called "data-flow analysis").
...