Tutorial: Creating Custom Rules

CodeIt.Right ships with a wide range of rule libraries included, but the great thing is that you are not limited to just those.   You can extend the range by doing any or all of the following:

You can easily define your own (custom) rules. What makes this possible is the "CodeIt.Right SDK". The SDK documentation is available online at https://submain.com/codeit.right/sdk/ as well as locally as part of your CodeIt.Right Help file.

In this tutorial I will show you how to create the "Use Certain Suffixes For Derived Types" rule.  Although this is a rule that ships with CodeIt.Right, it’s a good example to explain the steps involved.  After you have seen how we created this rule, you will be able to use a similar sequence of steps to create your own custom rules.

To create this rule we will:

  • Create a Custom Rule Template using the Wizard that CodeIt.Right adds to Visual Studio
  • Implement a set of methods and properties that will find and correct violations of the rule
  • Define Configurable Properties for the rule, so users will be able to create instances of the rule and tweak it to their needs
  • Deploy the new rule

Create a Custom Rule Template Using the Wizard

While you don't have to use the wizard, it's a good way to create your first rule. 

With that said, here's how:  Open Visual Studio.    In the menu bar, click File, and then click New Project

image1

In the New Project dialog box, in the Project Types pane, select CodeIt.Right Projects if that option is not already selected.

image2

In the Templates pane, select the template for your choice of programming language (Visual Basic or C#). The custom rule in this example uses Visual Basic but you can view and download both Visual Basic and C# versions of this example from here

Complete the Name, Location, and Solution fields for the custom rule.

Click OK. The New Rule Wizard dialog box appears.

In the New Rule Wizard dialog box, complete as many of the fields as possible. Fields that have a red asterisk to the right are required. Then click Next.

image3

Select the options that determine the scope for the custom rule. To select or deselect all the options, select All.  Then click Next.

image4

Select the targets for the custom rule. When done, click Finish.

image5

A status bar that displays the progress of the creation of the custom rule will appear in the Visual Studio window.  When this process has completed, you are ready for the next step, editing the custom rule template.

Edit the Generated Template

After a custom rule template has been created, you can edit it in the Solution Explorer. You can edit template information, the content generated by the New Rule Wizard, and implement code of the Check and Correct methods.

Select the rule in Solution Explorer to edit it. The generated regions of the rule are collapsed by default.

image6

Insert the Imports statement shown below into Line 8 of the code:

Imports SubMain.CodeItRight.Sdk.Utils

Since we are creating Naming category rule, edit the Inherits statement in line 14 so that the class inherits from NamingRuleBase to leverage naming specific rule built-ins, as shown below:

<Serializable, Category("Naming")> _ Public Class Rule Inherits NamingRuleBase

If you are creating not a Naming rule, leave the Inherits RuleBase code.

Expand the Wizard Generated Code region to review the code that was generated based on options selected in the New Rule Wizard. You can edit the options if necessary. Note that the rule's ID is an automatically generated GUID, you can edit it as well.  If you do this, make sure your ID is not equal to any of the built-in CodeIt.Right rules or even better set a rule ID that doesn't follow CodeIt.Right internal ID schema.

#Region "Data Entered On Wizard form" Private Const InputID As String = "2f7b6deb-9074-4001-83e4-24cbba341071" Private Const InputName As String = "Use Certain Suffixes For Derived Types" Private Const InputTitle As String = "Specific suffixes must be used for Derived Types" Private Const InputSeverity As SeverityLevel = SeverityLevel.Warning Private Const InputScopes As RuleScopes = RuleScopes.Public or RuleScopes.ProtectedInternal or RuleScopes.Private or RuleScopes.Abstract or RuleScopes.Sealed or RuleScopes.Readonly or RuleScopes.Virtual or RuleScopes.Override or RuleScopes.Unsafe or RuleScopes.Const or RuleScopes.Volatile or RuleScopes.WriteOnly or RuleScopes.WithEvents Private Const InputAuthor As String = "SubMain Team" Private Const InputEmail As String = "support@submain.com" Private Const InputUrl As String = "" Private Const InputAvailableTargets As RuleTargets = RuleTargets.Class Private Const InputViolationDescription As String = "" #End Region #Region "Constructor" Public Sub New() Me.Name = InputName Me.Title = InputTitle Me.Severity = InputSeverity Me.Targets = Me.AvailableTargets Me.Scopes = InputScopes End Sub #End Region Public Overrides ReadOnly Property ID As String Get Return InputID End Get End Property Public Overrides ReadOnly Property AvailableTargets As RuleTargets Get Return InputAvailableTargets End Get End Property Public Overrides ReadOnly Property Author As String Get Return InputAuthor End Get End Property Public Overrides ReadOnly Property Email As String Get Return InputEmail End Get End Property Public Overrides ReadOnly Property Url As String Get Return InputUrl End Get End Property Public Overrides ReadOnly Property ViolationDescription As String Get Return InputViolationDescription End Get End Property Public Overloads Function Correct(ByVal correctionOptionIndex as Integer) As Boolean MyBase.Correct(correctionOptionIndex) Select Case correctionOptionIndex Case Else End Select Return False End Function #End Region

In the Template to be populated by rule author region, edit the AutoCorrectionOptions property to establish all the options for automatic correction of violations to the rule. Each option is added to the drop-down list in the Action column when code is analyzed. (An error will be flagged up in the code editor, but GetCorrect0Name will be implemented in the next step).

Public Overrides ReadOnly Property AutoCorrectionOptions as String() Get If (MyBase._userCorrectOptions.Count = 0) Then ' Get title of the correction option Dim text As String = Me.GetCorrect0Name If ([text].Length > 0) Then ' Add to the list of available options MyBase._userCorrectOptions.Add([text]) End If End If Return MyBase.AutoCorrectionOptions End Get End Property

Still in the Template to be populated by rule author region, edit the Correction method to establish how violations to the rule are corrected. In the example below, the correct suffix is added to the code element. The new name is then checked using the helper function NamingRuleUtilities.FixForUniqueName to make sure it is unique in the solution. If not, the name is further modified so that it is unique. SuffixToCheck is a configurable property that we will define later in this tutorial.

Private Function GetCorrect0Name() As String Dim baseName As String = String.Empty If (Not MyBase.Element Is Nothing) Then Dim info As ICodeElementInfo = MyBase.Element.ToCodeElementInfo If (Not info Is Nothing) Then ' Get the code element name Dim displayName As String = info.DisplayName ' Add the correct suffix If ((Not Me.SuffixToCheck Is Nothing) AndAlso (Me.SuffixToCheck.Length > 0)) Then baseName = (displayName & Me.SuffixToCheck) End If End If End If ' Make sure the new name is unique Return NamingRuleUtilities.FixForUniqueName(baseName, MyBase.Element) End Function

In the Template to be populated by rule author region, edit the Check method to establish if violations to the rule are found. In the example below, each appropriate code element is checked for the correct suffix. If the element does not include the correct suffix, it is flagged as a violation. MustImplement is another configurable property defined later in the tutorial. Method ITypeInfo.IsAssignableFrom returns True if the code element derived from the type stored in MustImplement. Helper function NamingRuleUtilities.HasSuffix returns True if the code element has the suffix, False otherwise.

Configurable Properties

Configurable Properties are a flexible mechanism by which you develop rules that can be customized in user profiles (rule instances). They must be marked with the <ConfigurableProperty> attribute.

For our rule we need two configurable properties –

  • MustImplement - will filter and only run the rule against code elements that derive from the type assigned in this property.
  • SuffixToCheck - will allow a suffix to be defined for each rule instance that the code element identified in MustImplement should have.
Private _mustimplement As String <ConfigurableProperty, ComponentModel.Description("Type should implement the specified type or interface")> _ Public Property MustImplement As String Get Return Me._mustimplement End Get Set(ByVal value As String) Me._mustimplement = value End Set End Property Private _suffixToCheck As String <ConfigurableProperty, ComponentModel.Description("Certain Suffix to be checked")> _ Public Property SuffixToCheck As String Get Return Me._suffixToCheck End Get Set(ByVal value As String) Me._suffixToCheck = value End Set End Property

When you use the Profile Editor later to create instances of this rule, you will see these configurable properties – as demonstrated in the screenshot below.

image7

For information on how to create Rule Instances from this and other rules, please refer to this tutorial.

Adding another rule to the same project

At this point of the tutorial we have one custom rule implemented in the project (library). If you want to add other rule(s) to the library, you need to right-click project in the Solution Explorer, select Add New Item and pick Custom Rule Class under CodeIt.Right Items - this will start New Rule Wizard.

image8

Build and Deploy the New Rule

The final part of the process is to deploy the new rule.  To do this,

  1. Build your custom rule project
  2. Copy the resulting .dll assembly into the <CodeIt.Right installation>\Rules directory (typically Program Files\SubMain\CodeIt.Right\Rules)
  3. Add a new instance of the new rule to your user profile. See How to add rule to User Profile.

Note: You don't need to close Visual Studio when deploy new or updated rule library. CodeIt.Right picks up the rule library changes every time you analyze code or open Profile Editor.

Where do I find samples?

Your best source for rule examples is CodeIt.Right's own rule library (see the <CodeIt.Right installation>\Rules directory). As of this post we have implemented several hundred rule classes with 300+ rule instances in the default profile. Feel free to explore what we've provided using your favorite .NET decompiler and learn what's inside of each rule.

Further Reading and Resources