/CodeContracts-remover

Code Fixes for Roslyn that remove CodeContracts from source code

Primary LanguageC#MIT LicenseMIT

CodeContracts Remover

This repository contains Code Fixes for Roslyn that help to remove CodeContracts from source code.

List of provided analyzers and code fixes (in the order of application):

  • CR01_RetrieveCodeContractFromBase - indicates that the Contract.Requires method can be retrieved from Contract class of from base class;
  • CR02_RequiresGenericToIfThrow - indicates that Contract.Requires<TException>() method should be replaced with if...throw statement;
  • CR03_ContractToDebugAssertReplace - indicates that Contract.Requires(), Contract.Assert() and Contract.Assume() should be replaced with Debug.Assert();
  • CR04_EliminateCallsToContractMethods - indicates that all other Contract methods (Ensure, EnsureOnThrow, etc.) should be removed from source code;
  • CR05_EliminateContractClass - indicates that Contract class (class that marked with ContractClassForAttribute) can be removed from source code;
  • CR06_EliminateInvariantMethods - indicates that Contract invariant method (method marked with ContractInvariantMethodAttribute) can be removed from source code.

How to use

Download compiled version of library from binary folder or compile it from sources. Add ContractRemover.dll as roslyn analyzer to your project. Apply all fixes in the order stated above.

Examples

  1. CR01_RetrieveCodeContractFromBase
public class TestImpl : TestAbstract
{
    public override void Method1(string val)
    {
        throw new NotImplementedException();
    }
}

[ContractClass(typeof(TestAbstractCC))]
public abstract class TestAbstract
{
    public abstract void Method1(string val);
}
[ContractClassFor(typeof(TestAbstract))]
abstract class TestAbstractCC : TestAbstract
{
    public override void Method1(string val)
    {
        Contract.Requires(val != null);
        throw new NotImplementedException();
    }
}

will be translated to

public class TestImpl : TestAbstract
{
    public override void Method1(string val)
    {
        Contract.Requires(val != null);      // This line was extracted from TestAbstractCC
        throw new NotImplementedException();
    }
}

[ContractClass(typeof(TestAbstractCC))]
public abstract class TestAbstract
{
    public abstract void Method1(string val);
}
[ContractClassFor(typeof(TestAbstract))]
abstract class TestAbstractCC : TestAbstract
{
    public override void Method1(string val)
    {
        Contract.Requires(val != null);
        throw new NotImplementedException();
    }
}
  1. CR02_RequiresGenericToIfThrow
static void Method(string val, int data)
{
    Contract.Requires<ArgumentNullException>(val != null);
    Contract.Requires<ArgumentOutOfRangeException>(data >= 0);
}

will be translated to

static void Method(string val, int data)
{
    if (val == null)
        throw new ArgumentNullException(nameof(val));
    if (data < 0)
        throw new ArgumentOutOfRangeException(nameof(data), "data >= 0");
}
  1. CR03_ContractToDebugAssertReplace
static void Method(string val, int data)
{
    Contract.Requires(val != null);
    Contract.Assert(data >= 0);
}

will be translated to

static void Method(string val, int data)
{
    Debug.Assert(val != null, "val != null");
    Debug.Assert(data >= 0, "data >= 0");
}
  1. CR04_EliminateCallsToContractMethods
static int Method(string val, int data)
{
    Contract.Ensures(Contract.Result<int>() > 0);
}

will be translated to

static int Method(string val, int data)
{
}
  1. CR05_EliminateContractClass
public class TestImpl : TestAbstract
{
    public override void Method1(string val)
    {
        Contract.Requires(val != null);
        throw new NotImplementedException();
    }
}

[ContractClass(typeof(TestAbstractCC))]
public abstract class TestAbstract
{
    public abstract void Method1(string val);
}
[ContractClassFor(typeof(TestAbstract))]
abstract class TestAbstractCC : TestAbstract
{
    public override void Method1(string val)
    {
        Contract.Requires(val != null);
        throw new NotImplementedException();
    }
}

will be translated to

public class TestImpl : TestAbstract
{
    public override void Method1(string val)
    {
        Contract.Requires(val != null);
        throw new NotImplementedException();
    }
}

public abstract class TestAbstract
{
    public abstract void Method1(string val);
}
  1. CR06_EliminateInvariantMethods
public class TestImpl : TestAbstract
{
    public string Data { get; set; }
    
    [ContractInvariantMethod]
    private void Invariant()
    {
        Contract.Invariant(Data != null);
    }	
}

will be translated to

public class TestImpl : TestAbstract
{
    public string Data { get; set; }
}