Coding

CodeProvider: Create Contract Class

I’ve used the free offering (CodeRush Xpress) from Developer Express for years, and my feelings about it can be summed up by paraphrasing Larry Wall: “A machine without CodeRush is a sad machine indeed.”  Over the last few weeks I’ve been interested in implementing my own CodeRush plugin.  Prompted in no small part by Mark Miller’s decision to implement my CodeRush plugin suggestion during the weekly CodeRush Feature Workshop, I’ve taken the plunge and written my first plugin.  Here it is.

What’s it for?

A code provider in CodeRush automatically creates typical code blocks appropriate to the current coding context.  For example, the suggestion Mark Miller implemented was to add the IDisposable interface to an existing class.  When called on a class that does not implement IDisposable, this code provider adds “IDisposable” to the type declaration, implements the appropriate methods, and ensures that any disposable fields owned by the class are disposed.  Writing this code by hand typically took a bout 20 minutes.  Using Visual Studio code snippets got that down to about 5 minutes.  Using CodeRush, the code is generated instantly and consistently.  Pretty cool.

For those of you out there using Code Contracts, I’ve created a code provider that will implement a buddy class to hold contracts for an interface.  The provider will add a namespace reference to System.Diagnostics.Contracts to your interface file, decorate your interface with the ContractClassAttribute, then generate the buddy class in a separate class.  The buddy class file will import all the namespace references from the interface file, and the code provider will decorate it with the ContractClassForAttribute.  Each method and property on the interface will be explicitly implemented in the buddy class.  Property getters and non-void methods will return the default values for their types.  A TODO comment is placed into each member body, indicating where the contracts should go.

A little sugar

Since I’m scratching my own itch with this plugin, I decided to take it as far as I could.  I use FxCop and StyleCop on all my production code, so I wanted to make sure that the buddy class would leave me as little work to do as possible.  So, if the interface file has a file header comment, this is copied, updated with the buddy class file name, then placed at the head of buddy class file.  The namespace references are sorted in the order that StyleCop expects, and placed inside the the file namespace.  The provider generates an Xml documentation summary comment for the buddy class.  When Xml documentation comments are found on the interface, these are copied onto the appropriate methods in the buddy class.

Example

A few days ago I didn’t even know how to implement an interface contract, but I figured it was possible and quickly found this article Code Contracts Primer – Part 6 Interface Contracts by Derik Whittaker.  If Part 6 is any indication of the quality of this series, then Derik’s articles are a great place to start learning about Code Contracts if you are new to the subject.  (Another nice resource is Towards Code Correctness: Integrating Software Contracts and Unit Testing).  I’m going to use an example I’ve adapted from Derik’s article to show how the “Create Contract Class” code provider works.

You start with an interface that you would like to create specifications for:

//-----------------------------------------------------------------------
// <copyright file="IPayrollCalculator.cs" company="Jim Counts">
//     Copyright (c) Jim Counts 2011. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace PayrollCalculatorExample
{
  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;

  /// <summary>
  /// Describes a payroll calculator.
  /// </summary>
  public interface IPayrollCalculator
  {
    /// <summary>
    /// Gets the state or province.
    /// </summary>
    string StateOrProvince { get; }

    /// <summary>
    /// Gets or sets a value indicating whether to withhold tax.
    /// </summary>
    /// <value>
    ///   <c>true</c> if withholding tax; otherwise, <c>false</c>.
    /// </value>
    bool WithholdTax { get; set; }

    /// <summary>
    /// Calculates the paycheck.
    /// </summary>
    /// <param name="baseRate">The base rate.</param>
    /// <param name="hoursWorked">The hours worked.</param>
    /// <returns>The paycheck amount.</returns>
    double CalculatePaycheck(double baseRate, int hoursWorked);

    /// <summary>
    /// Determines the base rate.
    /// </summary>
    /// <param name="employeeType">Type of the employee.</param>
    /// <returns>The employee base rate.</returns>
    double DetermineBaseRate(EmployeeType employeeType);
  }
}

Then, put your cursor on the interface declaration and use CTRL+~ to bring up the CodeRush menu.  Select the “Create Contract Class” menu item and the code provider goes to work.

CRMenu

The provider creates a new class in a new file.  The name is chosen by convention.  The provider removes the leading ‘I’ from the interface name and concatenates “Contract” to the end.  So in this example, it generates a class called PayrollCalculatorContract, and puts it in PayrollCalculatorContract.cs:

//-----------------------------------------------------------------------
// <copyright file="PayrollCalculatorContract.cs" company="Jim Counts">
//     Copyright (c) Jim Counts 2011. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace PayrollCalculatorExample
{
  using System;
  using System.Collections.Generic;
  using System.Diagnostics.Contracts;
  using System.Linq;
  using System.Text;

  /// <summary>PayrollCalculatorContract class contains CodeContract declarations for IPayrollCalculator.</summary>
  [ContractClassFor(typeof(IPayrollCalculator))]
  public sealed class PayrollCalculatorContract : IPayrollCalculator
  {
    /// <summary>
    /// Gets the state or province.
    /// </summary>
    string IPayrollCalculator.StateOrProvince
    {
      get
      {
        // TODO: Add Contracts Here
        // CodeContracts runtime will ignore this return value.
        return default(string);
      }
    }

    /// <summary>
    /// Gets or sets a value indicating whether to withhold tax.
    /// </summary>
    /// <value>
    ///<c>true</c> if withholding tax; otherwise, <c>false</c>.
    /// </value>
    bool IPayrollCalculator.WithholdTax
    {
      get
      {
        // TODO: Add Contracts Here
        // CodeContracts runtime will ignore this return value.
        return default(bool);
      }
      set
      {
        // TODO: Add Contracts Here
      }
    }

    double IPayrollCalculator.CalculatePaycheck(double baseRate, int hoursWorked)
    {
      // TODO: Add Contracts Here
      // CodeContracts runtime will ignore this return value.
      return default(double);
    }

    double IPayrollCalculator.DetermineBaseRate(EmployeeType employeeType)
    {
      // TODO: Add Contracts Here
      // CodeContracts runtime will ignore this return value.
      return default(double);
    }
  }
}

The type declaration for IPayrollCalculator is decorated with the appropriate attribute, and the Contracts namespace reference is tucked right between System.Collections.Generic and System.Linq:

namespace PayrollCalculatorExample
{
  using System;
  using System.Collections.Generic;
  using System.Diagnostics.Contracts;
  using System.Linq;
  using System.Text;

  /// <summary>
  /// Describes a payroll calculator.
  /// </summary>
  [ContractClass(typeof(PayrollCalculatorContract))]
  public interface IPayrollCalculator
  {

When the provider finishes, you will be looking at the buddy class implementation, and the project should compile as is.  In this example, StyleCop has three complaints, two of them related to fact that there is not a blank line between the getter and setter for “WithholdTax” and one complaint that there is not a leading space preceding the <value> tag in the XML documentation for “WithholdTax”.  Pretty nice.  If you care about those warnings, you have two things to fix, and if you don’t you can get straight to writing your contracts!

Warts

This code provider is definitely alpha.  I know it may have some issues with VB.NET interfaces that are not nested inside an explicit namespace.  I haven’t done any testing with anything except C#, or any coding style except my own.  Also, the provider is ripe for refactoring.   Just because it makes a pretty buddy class, don’t assume the provider is pretty… it ain’t.  Anyway, I hope to clean it up in future revisions.

Thanks

Thanks go out to Developer Express for providing such a powerful tool for free, Mark Miller and Rory Becker for hosting the weekly CodeRush Feature Workshop, and once again to Rory for maintaining the CodeRush and DXCore Community Plugins site.  I would not have been able to figure out half the tricks implemented in this code provider without access to the source code for CR_GenerateTest.

Code

Here is the initial code drop, with before and after examples.

3 thoughts on “CodeProvider: Create Contract Class

  1. I invite you to post sources to the community site. You can add wiki page there, and others will be able to download your plugin without scouting web for it

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s