When evolving an API, you have to introduce breaking changes sooner or later. The traditional way of dealing with that is to mark the deprecated types and members with the [Obsolete] attribute and explain how to migrate to the new API using the attribute's message.
JetBrains Fleet provides a more elegant solution that allows API users to find and automatically convert the old API to a new one. As the API author, you need to mark the obsolete type or member with the [CodeTemplate] attribute from JetBrains.Annotations where you can specify a search pattern to match the old API and a replacement pattern for it. The attribute will act as a custom code inspection with the corresponding quick-fix.
[CodeTemplateAttribute] is recognized by all other JetBrains products that analyze C# code, for example, JetBrains RiderJetBrains ReSharper.
Let's see how it works using an example:
public class MyAssert
{
// Deprecated API. Usages look like:
// MyAssert.IsTrue(args.Length > 0);
public static void IsTrue(bool condition)
{
if (!condition)
throw new Exception("Assertion failed");
}
// New API. Usages should look like:
// MyAssert.That(args.Length > 0, Is.True);
public static void That<T>(T value, Constraint<T> constraint)
{
// ...
}
}
public class Constraint<T> { }
class Is
{
public static Constraint<bool> True => null;
public static Constraint<bool> False => null;
}
Let's annotate the deprecated IsTrue() method with the [CodeTemplate] attribute:
[CodeTemplate(
searchTemplate: "$member$($expr$)",
Message = "The API is deprecated, use 'MyAssert.That' instead",
ReplaceTemplate = "MyAssert.That($expr$, Is.True)",
ReplaceMessage = "Convert to 'MyAssert.That'")]
public static void IsTrue(bool condition)
{
if (!condition)
throw new Exception("Assertion failed");
}
Now JetBrains Fleet will report all usages of MyAssert.IsTrue() and suggest a migration fix: