SubMain - CodeIt.Right The First Time!

/Community

A Support Community for SubMain Products
 Home Products Services Download Purchase Support
in Search
 
Home Forums Blogs Tutorials Downloads
Welcome to SubMain Community Sign in | Join | Help

Tutorials

Tutorial: Creating Custom Rules

The best part about CodeIt.Right is that you are not limited to just the rule libraries included into the box. You can easily define your own (custom) rules. What makes this possible is the "CodeIt.Right SDK". The SDK documentation is available online at http://submain.com/codeit.right/sdk/ as well as locally as part of your CodeIt.Right help file.

In this tutorial we will create "Use Certain Suffixes For Derived Types" rule. We will

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

Create Custom Rule Template Using Wizard

  1. Open Visual Studio

  2. In the menu bar, click File, and then click New Project

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

  4. In the Templates pane, select the template for the appropriate programming language (Visual Basic or Visual C#). The custom rule in the examples uses Visual Basic.

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

  6. Click OK. The New Rule Wizard dialog box appears.

  7. 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. Click Next.

  8. Select the options to determine the scope for the custom rule. To select or deselect all the options, select All. Click Next.

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

The status bar at the bottom of the Visual Studio window displays the progress of the creation of the custom rule.

Edit the Generated Template

After a custom rule template is 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.

  1. Double-click the rule in Soultion Explorer to edit it. The generated regions of the rule are collapsed by default.

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

    #Region "Wizard Generated Code"
    
    #Region "Data Entered On Wizard form"
    
        Private Const InputID As String = "0500daf7-f2a0-4549-b90e-bd8f6d515bb5"
        Private Const InputName As String = "UseCertainSuffixesForDerivedTypes"
        Private Const InputTitle As String = "Use Certain Suffixes 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.Extern or RuleScopes.Unsafe _
          or RuleScopes.SpecialName or RuleScopes.Const or RuleScopes.Volatile or RuleScopes.WriteOnly _
          or RuleScopes.WithEvents or RuleScopes.Default
        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
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    

  3. 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. The GetCorrect0Name will be implemented in the next bullet.

    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
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    

  4. 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 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
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    

  5. In the Template to be populated by rule author region, edit the Check method to establish 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 is code element has the suffix, False otherwise.

    Public Overrides Function Check(ByVal element As IElementInfo) As Boolean
    
        If (Not element Is Nothing) Then
    
            Dim info As ICodeElementInfo = element.ToCodeElementInfo
    
            If (Not info Is Nothing) Then
    
                ' Get the code element name
                Dim displayName As String = info.DisplayName
    
                ' If configurable properties SuffixToCheck and MustImplement have values
                If (((Not Me.SuffixToCheck Is Nothing) AndAlso (Me.SuffixToCheck.Length > 0)) _
                   AndAlso ((Not Me.MustImplement Is Nothing) AndAlso (Me.MustImplement.Length > 0))) Then
    
                    Dim info2 As ITypeInfo = TryCast(info, ITypeInfo)
    
                    ' If element derives from the type (MustImplement) and doesn't have correct suffix (SuffixToCheck)
                    If (((Not info2 Is Nothing) AndAlso info2.IsAssignableFrom(Me.MustImplement)) _
                       AndAlso Not NamingRuleUtilities.HasSuffix(displayName, Me.SuffixToCheck)) Then
    
                        ' Flag the violation
                        Return True
    
                    End If
    
                End If
    
            End If
    
        End If
    
        Return False
    
    End Function
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    

Configurable Properties

Configurable Properties are flexible mechanism that allows to develop rules that can be customized in user profiles (rule instances). They must be marked with attribute <ConfigurableProperty>.

For our rule we need two configurable properties -

  • MustImplement - will filter and only run the rest of the rule against code elements that derive from the type assigned in this property
  • SuffixToCheck - will allow to define for each rule instance suffix to be that the code element derived from MustImplement should have

  • <ConfigurableProperty, 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
    
    <ConfigurableProperty, 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
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    

Here is how properties are configured for a specific instance of the rule we developed in this tutorial - "Exception class name must have 'Exception' suffix" (click the image for full size):

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 another rule or more 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.

Build and Deploy new rule

Our rule is now ready to be deployed.

  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 you 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 75+ rule classes with 100+ rule instances in the detault profile. Feel free to explore what we've got using Lutz Roeder's wonderful Reflector and learn what's inside of each rule.

Keep an eye on is our community Custom Rule Repository - it will grow as users develop and share their rules. This is also the place where we post our complete sample rule projects.

Further Reading and Resources

  1. CodeIt.Right SDK Documentation
  2. CodeIt.Right Tutorials
  3. How to create own Profile
  4. How to add rule to User Profile
  5. Defining ViolationDescription and CorrectionDescription properties (to be published)
  6. Built-in API helper functions
  7. Custom Rule Repository
  8. FxCop rule mapping (to be published)
  9. Using SuppressMessage Attribute (to be published)
  10. Top 10 most useful API helper functions explained (to be published)
Published Sunday, March 16, 2008 4:17 PM by Serge B.

Comments

 

SubMain News said:

by Serge Baranovsky v1.1 progress &amp; Enterprise Edition The v1.1 release that includes .NET 3.5 syntax

May 2, 2008 6:01 PM
 

Tutorials said:

You already know how you can create new custom rules using CodeIt.Right SDK , of not, you may want to

October 29, 2009 1:05 AM
Anonymous comments are disabled
    
 
     
 
Home |  Products |  Services |  Download |  Purchase |  Support |  Community |  About Us |