Main Content

ModelAdvisor.EdittimeCheck class

Package: ModelAdvisor

Abstract base class for creating edit-time checks

Description

Derive classes from the ModelAdvisor.EdittimeCheck abstract base class to create custom edit-time checks. To create a custom edit-time check, create a MATLAB® class that derives from the abstract base class. Then, create a check definition function that includes a handle to your class and register the custom edit-time check using an sl_customization function.

The ModelAdvisor.EdittimeCheck class is a handle class.

Class Attributes

Abstract
true
HandleCompatible
true

For information on class attributes, see Class Attributes.

Properties

expand all

Identifier for the check, specified as a string. Set this property by using the ModelAdvisor.Check class that you create as part of your check definition function. The checkID property specifies the permanent, unique identifier for the check.

Example: "advisor.edittime.inoutnamelength"

Attributes:

GetAccess
protected
SetAccess
protected

How, the Model Advisor runs the edit-time check, specified as one of these values:

  • edittimecheck.TraversalTypes.BLKITER — The check runs on newly added blocks and blocks that you have edited. These edits include changes to block names, types, and parameter values.

  • edittimecheck.TraversalTypes.ACTIVEGRAPH — The check runs on newly added blocks, blocks that you have edited, and other blocks at the same level as an edited or newly added block. Specify this traversal type property if your check must look at the whole subsystem or level of a model that a user is editing. For example, you specify this traversal type to check that a Trigger block is the top-most block in a subsystem because the check must look at other blocks within the subsystem to make this determination.

Example: eddittimecheck.TraversalTypes.BLKITER

Attributes:

GetAccess
protected
SetAccess
protected

Methods

expand all

Examples

collapse all

Create a custom edit-time check that checks that Inport and Outport blocks have certain colors depending on their output data types.

To register the custom edit-time check, create an sl_customization function. The sl_customization function accepts one argument, a customization manager object. To register the custom check, use the addModelAdvisorCheckFcn method. The input to this method is a handle to the check definition function. For this example, defineCheck is the check definition function. Create the sl_customization function and save it to your working folder.

function sl_customization(cm)
cm.addModelAdvisorCheckFcn(@defineCheck);

Create the check definition function. Inside the function, create a ModelAdvisor.Check object and specify the Check ID as an input argument. Then, specify the ModelAdvisor.Check Title and CallbackHandle properties. The CallbackHandle property is the name of the class that you create to define the edit-time check. For this example, MyEditTimeChecks is the package name and PortColor is the class name. Then, publish the check to a new folder in the Model Advisor. For this example, the folder name is DEMO: Edit-time Checks. For this example, create a defineCheck function and include the code below in it. Save the defineCheck function to your working folder.

function defineCheck
rec = ModelAdvisor.Check("advisor.edittimecheck.PortColor");
rec.Title = 'Check color of Inport and Outport blocks';
rec.CallbackHandle = 'MyEditTimeChecks.PortColor'; 
mdladvRoot = ModelAdvisor.Root;
mdladvRoot.publish(rec,'DEMO: Edit-time Checks');

Create a class that derives from the ModelAdvisor.EdittimeCheck abstract base class. For this example, create a class file named PortColor.m. Copy the code below into the PortColor.m file. Then, create a folder named +MyEditTimeChecks and save the PortColor.m file in that folder. The class must be in a folder that has the same name as the package name.

The PortColor class defines three methods: PortColor, blockDiscovered, and fix. The PortColor method sets the CheckId and TraversalType properties. This check has a traversal type of edittimecheck.TraversalTypes.BLKITER because the check must check newly added and edited blocks, but it does not have to check for affected blocks in the same subsystem or model as the edited or newly added blocks. The blockDiscovered method contains an algorithm that checks the color of Inport and Outport blocks. The fix method updates blocks that do not have correct colors.

classdef PortColor < ModelAdvisor.EdittimeCheck
    % Check that ports conform to software design standards for background color.
    %
    %   Background Color                Data Types
    %   orange                          Boolean
    %   green                           all floating-point
    %   cyan                            all integers
    %   Light Blue                      Enumerations and Bus Objects
    %   white                           auto
    %


    methods
        % Set the Check ID and traversal type.
        function obj=PortColor(checkId)
            obj=obj@ModelAdvisor.EdittimeCheck(checkId);
            obj.traversalType = edittimecheck.TraversalTypes.BLKITER;                       
        end
        % Specify the edit-time check algorithm using the blockDiscovered method.
        function violation = blockDiscovered(obj, blk)
            violation = []; 
            % To check when this check gets called, insert a breakpoint here. 
            if strcmp(get_param(blk,'BlockType'),'Inport') || strcmp(get_param(blk,'BlockType'),'Outport')
                
                dataType = get_param(blk,'OutDataTypeStr');
                currentBgColor = get_param(blk,'BackgroundColor');
                
                if strcmp(dataType,'boolean')
                        if ~strcmp(currentBgColor, 'orange')
                            % Create a violation object using the ModelAdvisor.ResultDetail class.
                            violation = ModelAdvisor.ResultDetail;
                            ModelAdvisor.ResultDetail.setData(violation,'SID',Simulink.ID.getSID(blk));
                            violation.CheckID = obj.checkId;
                            violation.Description = 'Inport/Outport blocks with Boolean outputs should be orange.';
                            violation.title = 'Port Block Color';
                            violation.ViolationType = 'Warning';
                        end
                elseif any(strcmp({'single','double'},dataType))
                        if ~strcmp(currentBgColor, 'green')
                            violation = ModelAdvisor.ResultDetail;
                            ModelAdvisor.ResultDetail.setData(violation,'SID',Simulink.ID.getSID(blk));
                            violation.CheckID = obj.checkId;
                            violation.Description = 'Inport/Outport blocks with floating-point outputs should be green.';
                            violation.title = 'Port Block Color';
                            violation.ViolationType = 'Warning';
                        end
                elseif any(strcmp({'uint8','uint16','uint32','int8','int16','int32'}, dataType))
                        if ~strcmp(currentBgColor, 'cyan')
                            violation = ModelAdvisor.ResultDetail;
                            ModelAdvisor.ResultDetail.setData(violation,'SID',Simulink.ID.getSID(blk));
                            violation.CheckID = obj.checkId;
                            violation.Description = 'Inport/Outport blocks with integer outputs should be cyan.';
                            violation.title = 'Port Block Color';
                            violation.ViolationType = 'Warning';
                        end
                elseif contains(dataType,'Bus:')
                    if ~strcmp(currentBgColor, 'lightBlue')
                        violation = ModelAdvisor.ResultDetail;
                        ModelAdvisor.ResultDetail.setData(violation,'SID',Simulink.ID.getSID(blk));
                        violation.CheckID = obj.checkId;
                        violation.Description = 'Inport/Outport blocks with bus outputs should be light blue.';
                        violation.title = 'Port Block Color';
                        violation.ViolationType = 'Warning';
                    end
                 elseif contains(dataType,'Enum:')
                    if ~strcmp(currentBgColor, 'lightBlue')
                        violation = ModelAdvisor.ResultDetail;
                        ModelAdvisor.ResultDetail.setData(violation,'SID',Simulink.ID.getSID(blk));
                        violation.CheckID = obj.checkId;
                        violation.Description = 'Inport/Outport blocks with enumeration outputs should be light blue.';
                        violation.title = 'Port Block Color';
                        violation.ViolationType = 'Warning';
                    end
                elseif contains(dataType, 'auto')
                    if ~strcmp(currentBgColor, 'white')
                        violation = ModelAdvisor.ResultDetail;
                        ModelAdvisor.ResultDetail.setData(violation,'SID',Simulink.ID.getSID(blk));
                        violation.CheckID = obj.checkId;
                        violation.Description = 'Inport/Outport blocks with auto outputs should be white.';
                        violation.title = 'Port Block Color';
                        violation.ViolationType = 'Warning';
                    end                    
                end
            end  
        end
        
              
        % Optionally, provide a fix  for the violation object.
        function success = fix(obj, violation)
            success = false;
            dataType = get_param(violation.Data,'OutDataTypeStr');
            if strcmp(dataType,'boolean')
                set_param(violation.Data,'BackgroundColor','orange');
            elseif any(strcmp({'single','double'},dataType))
                set_param(violation.Data,'BackgroundColor','green');
            elseif any(strcmp({'uint8','uint16','uint32','int8','int16','int32'}, dataType))
                set_param(violation.Data,'BackgroundColor','cyan');
            elseif contains(dataType,'Bus:')  || contains(dataType,'Enum:')
                set_param(violation.Data,'BackgroundColor','lightBlue');
            elseif contains(dataType,'auto')
                set_param(violation.Data,'BackgroundColor','white');
            end
            success = true;
        end
    end
end

Refresh the Model Advisor to update the cache with the new check on the path.

Advisor.Manager.refresh_customizations

To use the check, copy the AdvisorCustomizationExample.slx model to your current working folder.

copyfile(fullfile(matlabroot,'examples','slcheck','main',...
'AdvisorCustomizationExample.slx'),'AdvisorCustomizationExample.slx','f');

Model to check for edit-time violations

Open the Model Advisor Configuration Editor by clicking the Modeling tab and selecting Model Advisor > Configuration Editor or by entering this command at the command prompt:

Simulink.ModelAdvisor.openConfigUI;

Create a custom configuration that consists of the custom edit-time check. Save the configuration as my_config.json. Close the Model Advisor Configuration Editor. Set the custom configuration to the my_config.json file.

ModelAdvisor.setModelConfiguration('AdvisorCustomizationExample', 'my_config.json');

Turn on edit-time checking by clicking the Modeling tab and selecting Model Advisor > Edit-Time Checks. The Configuration Parameters dialog box opens and you select the Edit-Time Checks parameter. Alternatively, you can enter this command at the command prompt:

edittime.setAdvisorChecking('AdvisorCustomizationExample','on');

To view the edit-time warnings, click the blocks highlighted in yellow.

At the top level of the model, the two Inport blocks have an output data type of int32. They produce edit-time warnings because they should be cyan. The Outport block does not produce a violation because it has an auto data type and is white.

To fix the edit-time warnings, in an edit-time check warning window, click Fix.

Version History

Introduced in R2022a