7.7. Writing your own analysis rules¶
The analysis framework shipped with the Axivion Suite allows you to write your own analysis rules. Such an additional rule can then be used as if it were part of the Axivion Suite: Its options can be edited in the graphical configuration interface, and if the rule is enabled, it is executed as part of an analysis run.
Alternatively, you can also run an external tool and capture its output.
7.7.1. Adding a Custom Rule¶
With the Python API or with the graphical interface, you can add directories to the project configuration to load additional rule sets. This section briefly discusses the file structure of additional rule sets.
A rule set is provided by one or more Python files in a rule set directory:
ruleset-root/
rule1.py
rule2.py
In this case, the path name of ruleset-root can be imported directly.
Please make sure that all Python modules contained in that directory are named
uniquely. This means that in the example above, none of the names rule1,
rule2 may already exist in the Python code supplied in Axivion Suite
nor in the Python environment.
To avoid naming conflicts of the individual modules, it is recommended to group the entire rule set into one Python package.
ruleset-root/
ruleset-package/
__init__.py
rule1.py
rule2.py
In this structure, only the ruleset-package needs to be a unique
name. It is possible to import either the path to ruleset-root or the path
to ruleset-root/ruleset-package directly.
The following shows an example custom rule as rule1.py.
# Axivion Suite
# Copyright (C) 2021-2025 Axivion GmbH
# Copyright (C) 2025 The Qt Company GmbH, a subsidiary of The Qt Group
# https://www.qt.io
from bauhaus import analysis, ir
@analysis.rule('MyOwnRules-MacroCheck')
class MyMacroCheckRule(analysis.AnalysisRule):
title = '''This is the first example rule.'''
_message_descriptions = {
'bad_macro_key': 'This kind of macro is forbidden',
}
"""The messages possibly emitted by this rule."""
report_concat: bool = False
"""Description of this option."""
def get_rulehtml_description(
self, config: analysis.RuleConfiguration | None = None
):
# Fill in your HTML description of the rule here (appears in the WebUI,
# the IDE plugins and in the configuration GUI).
return """This is an example of a custom rule.
"""
def execute(self, ir_graph: ir.Graph):
# This is the main entry point called from the framework - write your check here
for node in ir_graph.nodes_of_type(
ir.Physical.Source_Function_Macro_Definition
):
if self.is_interesting_macro(node):
# A stylecheck finding is reported with add_message
self.add_message(node, 'bad_macro_key', entity=node.Name)
def is_interesting_macro(self, node: ir.Physical.Source_Function_Macro_Definition):
# You can define your own Python methods to structure the code of your check
if node.Name.startswith('HAVE'):
return True
return bool(self.report_concat and '##' in node.Replacement)
Important things to note:
The name of the class is immaterial. What is relevant is the rule name that is passed to the
@analysis.ruledecorator. That is the name that will appear in the graphical configuration interface and that can be used to refer to the rule in a Python configuration file. For instance, you can configure the new example rule in a Python configuration file as follows:analysis = axivion.config.get_analysis() analysis['MyOwnRules-MacroCheck'].report_concat = True
Your rule class should be derived from
bauhaus.analysis.AnalysisRule, either directly or indirectly.Class variables are treated as rule options (
report_concatin the example rule).Each option must have a type hint and a default value that is compatible with the type hint. If not, this will result in a run-time error when trying to use the rule.
Proceed as follows to add this rule to the set of available rules in your project:
Create a subdirectory for your custom rules (in the above outline, that would be
ruleset-package)Store the file
rule1.pyin that directoryAlso create an empty file
__init__.pythereOpen the graphical configuration interface and select the
Analysisitem. Right-click on it to open the context menu where you then select the menu itemAdditional rules.... In the directory chooser that opens next, select your rule directory (i.e.ruleset-package)The rule
MyOwnRules-MacroCheckshould now be visible under theAnalysisitemBy default, the rule is added as an immediate child of the top-level aspect node to which the directory is added (in this case,
Analysis). To add your rule to an existing rule group in the hierarchy (e.g.,Stylechecks) you can pass the name of the parent rulegroup to the@analysis.ruledecorator:@analysis.rule('MyOwnRules-MacroCheck', rulegroup='Stylechecks')
If the named group does not exist, it is created automatically.
Rule names must be unique across the entire aspect (top-level node), i.e., the whole
Analysishierarchy in this example, so even if rules are added to different rule groups, they must not share the same name.
7.7.2. Analysis framework API¶
The analysis framework API is defined by these python modules:
Custom issue post-processing filters are registered via |
|