Difference between revisions of "CA Adding New Rules"

(Initial version, part of Standard Rules section)
 
(Standard Rules: section done)
Line 101: Line 101:
 
Calling <e>make_with_defaults</e> initializes the attributes to their default values and makes sure that the class invariant is true. If you want to set an attribute to a custom value you can do so by setting it after the call to <e>make_with_defaults</e>.
 
Calling <e>make_with_defaults</e> initializes the attributes to their default values and makes sure that the class invariant is true. If you want to set an attribute to a custom value you can do so by setting it after the call to <e>make_with_defaults</e>.
  
The creation procedure from the template takes an argument of type <e>PREFERENCE_MANAGER</e>. This is used for initializing preferences that are specific to your rule. Such preferences usually represent integral or boolean values. If you do ''not'' need any custom preferences then you can leave out the argument ''a_pref_manager'' of ''make'' and you can remove the whole <e>initialize_options</e> feature.
+
The creation procedure from the template takes an argument of type <e>PREFERENCE_MANAGER</e>. This is used for initializing preferences that are specific to your rule. Such preferences usually represent integral or boolean values. If you do ''not'' need any custom preferences then you can leave out the argument <e>a_pref_manager</e> of <e>make</e> and you can remove the whole <e>initialize_options</e> feature.
  
 
=== AST processing ===
 
=== AST processing ===
Line 112: Line 112:
  
 
=== Properties ===
 
=== Properties ===
 +
 +
The ''title'' and the ''description'' of the rule may be constant strings, they may also be localized strings. The ''rule ID'' must be unique among all rules. It should not contain spaces and should be reasonably short. The main rules that come with ''Code Analysis'' have IDs that are numbered from CA001 to CA999 (many of which are not used).
  
 
=== Formatted Violation Description ===
 
=== Formatted Violation Description ===
 +
 +
Your rule should be able to produce a formatted description of a concrete rule violation. This description is for example used in the Code Analysis tool panel of the GUI. There, class names and feature names are enabled for pick-and-drop. Variable names, numbers, and strings will be displayed in a nice way, too. In addition, this description is used in command line mode. In order to produce normal, unformatted text, use <e>{TEXT_FORMATTER}.add</e>. For adding formatted elements use features like <e>{TEXT_FORMATTER}.add_local</e>, <e>{TEXT_FORMATTER}.add_feature_name</e> and similar.
  
 
== More Customized Rules ==
 
== More Customized Rules ==

Revision as of 03:26, 7 February 2014

<< 5. Command Line Usage | 7. Architectural Overview >>


The Code Analysis framework was designed with regard to the fact that adding new rules should be as simple and as fast as possible. Looking at the initial set of rules that were implemented, nearly all of them have an implementation of less than 200 lines of code. Many of them use even less than 100 lines of code. Rules that search the code for certain patterns (this applies to the vast majority of rules) are particularly simple to implement.

Standard Rules

All rules must conform to CA_RULE. The class you implement for a rule is on one hand responsible for checking the rule and contains metadata about the rule (i. e. title, description) on the other hand. As of now, rules must moreover conform to either CA_STANDARD_RULE or CA_CFG_RULE, both of which are subtypes of CA_RULE. A large number of possible rules are standard rules, no matter whether they are trivial or more complicated.

All Standard rules are checked by iterating on the abstract syntax tree (AST) of the class code. The developer who adds a new rule can very well ignore the details thereof. He needs to know however which AST nodes his rule needs to process. For each type of AST node you need to add an agent so your routine will be called during the iteration on the AST.

To start implementing your rule you have basically two possibilities. (1) You start from scratch, implementing all deferred features of CA_STANDARD_RULE or (2) you use the following template.

Standard Rule Template

class
  CA_YOUR_RULE
 
inherit
  CA_STANDARD_RULE
 
create
  make
 
feature {NONE} -- Initialization
 
  make (a_pref_manager: attached PREFERENCE_MANAGER)
      -- Initialization for `Current'.
    do
      make_with_defaults
        -- This initializes the attributes to their default values:
        -- Severity = warning
        -- Default Severity Score = 50 (`severity score' can be changed by user)
        -- Rule enabled by default = True (`Rule enabled' can be changed by user)
        -- Only for system wide checks = False
        -- Checks library classes = True
        -- Checks nonlibrary classes = True
 
        initialize_options (a_pref_manager)
 
        -- TODO: Add your initialization here.
    end
 
  initialize_options (a_pref_manager: attached PREFERENCE_MANAGER)
      -- Initializes the rule preferences.
    local
      l_factory: BASIC_PREFERENCE_FACTORY
    do
      create l_factory
 
        -- TODO: Add the initialization of your custom preferences here.
        -- Example:
--    threshold := l_factory.new_integer_preference_value (a_pref_manager,
--      preference_namespace + "Threshold",
--      30)  -- default value
--    min_local_name_length.set_default_value ("30") -- default value, too
--    min_local_name_length.set_validation_agent (agent is_integer_string_within_bounds (?, 1, 1_000_000))
    end
 
feature {NONE} -- Activation
 
  register_actions (a_checker: attached CA_ALL_RULES_CHECKER)
    do
      -- TODO: Add agents for the features in section `Rule checking' here.
    end
 
feature {NONE} -- Rule checking
 
  -- TODO: Add the AST processing here.
 
feature -- Properties
 
  title: STRING_32
    do
        -- TODO: Add the title of your rule here.
      Result := "(Your title)"
    end
 
    -- TODO: Add the ID of your rule here. Should be unique!
  id: STRING_32 = "(YourID)"
 
  description: STRING_32
    do
        -- TODO: Add the rule description here.
      Result :=  "(Your description)"
    end
 
  format_violation_description (a_violation: attached CA_RULE_VIOLATION; a_formatter: attached TEXT_FORMATTER)
    do
      -- TODO: Add a formatted description of a concrete violation of this rule here.
    end
 
end

Let us have a closer look at the various parts of a rule class.

Initialization

Calling make_with_defaults initializes the attributes to their default values and makes sure that the class invariant is true. If you want to set an attribute to a custom value you can do so by setting it after the call to make_with_defaults.

The creation procedure from the template takes an argument of type PREFERENCE_MANAGER. This is used for initializing preferences that are specific to your rule. Such preferences usually represent integral or boolean values. If you do not need any custom preferences then you can leave out the argument a_pref_manager of make and you can remove the whole initialize_options feature.

AST processing

The main part of your rule implementation consists of checking the source code for rule violations. Say, for example, that you want to check if instructions to have certain properties. Then you would add a feature like process_if (a_if_ast: IF_AS) to the section Rule checking. Also, you would need to modify the register_actions feature by adding the line

a_checker.add_if_pre_action (agent process_if).

Of course you may register as many such agents as you want.

Properties

The title and the description of the rule may be constant strings, they may also be localized strings. The rule ID must be unique among all rules. It should not contain spaces and should be reasonably short. The main rules that come with Code Analysis have IDs that are numbered from CA001 to CA999 (many of which are not used).

Formatted Violation Description

Your rule should be able to produce a formatted description of a concrete rule violation. This description is for example used in the Code Analysis tool panel of the GUI. There, class names and feature names are enabled for pick-and-drop. Variable names, numbers, and strings will be displayed in a nice way, too. In addition, this description is used in command line mode. In order to produce normal, unformatted text, use {TEXT_FORMATTER}.add. For adding formatted elements use features like {TEXT_FORMATTER}.add_local, {TEXT_FORMATTER}.add_feature_name and similar.

More Customized Rules

Accessing Type Information

Accessing the Control Flow Graph