Neovolve.CodeAnalysis.ChangeTracking 3.0.0-beta0020

This is a prerelease version of Neovolve.CodeAnalysis.ChangeTracking.
There is a newer version of this package available.
See the version list below for details.
dotnet add package Neovolve.CodeAnalysis.ChangeTracking --version 3.0.0-beta0020
                    
NuGet\Install-Package Neovolve.CodeAnalysis.ChangeTracking -Version 3.0.0-beta0020
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Neovolve.CodeAnalysis.ChangeTracking" Version="3.0.0-beta0020" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Neovolve.CodeAnalysis.ChangeTracking" Version="3.0.0-beta0020" />
                    
Directory.Packages.props
<PackageReference Include="Neovolve.CodeAnalysis.ChangeTracking" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Neovolve.CodeAnalysis.ChangeTracking --version 3.0.0-beta0020
                    
#r "nuget: Neovolve.CodeAnalysis.ChangeTracking, 3.0.0-beta0020"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Neovolve.CodeAnalysis.ChangeTracking@3.0.0-beta0020
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Neovolve.CodeAnalysis.ChangeTracking&version=3.0.0-beta0020&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Neovolve.CodeAnalysis.ChangeTracking&version=3.0.0-beta0020&prerelease
                    
Install as a Cake Tool

Neovolve.CodeAnalysis.ChangeTracking

C# code analysis tool for evaluating changes to contracts

GitHub license Nuget Nuget Actions Status

Introduction

Neovolve.CodeAnalysis.ChangeTracking is a package that calculates changes between two versions of C# code to identify what has changed in regard to Semantic Versioning. The outcome will be an overall Semantic Version change result (None, Feature, Breaking) as well as a collection of changes. Each change in the collection identifies the source and target change along with a message indicating the change and the SemVer impact of that change.

Installation

Production and beta versions are available on NuGet.

Install-Package Neovolve.CodeAnalysis.ChangeTracking

Continous Integration builds are available on MyGet.

Install-Package Neovolve.CodeAnalysis.ChangeTracking -Source https://www.myget.org/F/neovolve/api/v3/index.json

Features

This library will determine whether C# code has changed in a way that introduces a new feature or a breaking change.

Changes are evaluated for:

  • Classes
  • Interfaces
  • Structs
  • Properties
  • Fields
  • Methods
  • Attributes

The types of changes evaluated are:

  • Items removed
  • Items added
  • Items renamed
  • Changes to namespace (moved types, renamed namespace)
  • Changes of types
  • Changes to access modifiers
  • Changes to modifiers
  • Changes to generic type parameters
  • Changes to generic type constraints

Changes not currently evaluated are:

  • net5.0 record types
  • net5.0 init properties

Usage

var oldCode = new List<CodeSource>
{
    new CodeSource(@"
        public class Test
        {
            public string Value;
        }", "Test.cs")
};
var newCode = new List<CodeSource>
{
    new CodeSource(@"
        public class Test
        {
            public bool Value;
        }", "Test.cs")
};

var calculator = ChangeCalculatorFactory.BuildCalculator();

var result = await calculator.CalculateChange(oldCode, newCode).ConfigureAwait(false);

if (result.ChangeType == ChangeType.None) 
{
    // Looks like there is no change in the members
}
else if (result.ChangeType == ChangeType.Feature)
{
    // Looks like members have been added to the code
}
else if (result.ChangeType == ChangeType.Breaking)
{
    // Looks like members have been removed or changed
}

Limitations

The library evaluates code changes by parsing the code text. The advantage of this method is that the code does not need to be compiled, dependencies do not need to be resolved and any C# project usage is supported. In fact the csproj itself is not even supported as the library only parses cs files. The disadvantage is that evaluating code changes can produce false positivies because all differences are evaluated as string values.

For example, the following two code blocks when evaluated will indicate a breaking change. In reality, it is likely that the code will compile to the same outcome.

public MyNamespace
{
    public class MyClass
    {
        public System.DateTime MyValue { get; set; }
    }
}
using System;

public MyNamespace
{
    public class MyClass
    {
        public DateTime MyValue { get; set; }
    }
}

Frequently asked questions

Why does SemVerChangeType define None instead of Patch?

This package attempts to calculate the Semantic Version impact on a C# binary based on changes to the public API surface (see attribute comparison below). Adding new signatures would be calculated as a feature and removing or modifying signatures would result in a breaking change.

There are only two other scenarios that could occur between two sets of C# code. There is either no change or there is a change to internal logic where there is no impact on the public API surface. No change should not even be identified as a patch change while changes to internal logic should be a patch change. As the library does not look at internal code, it can't actually determine the difference between these two scenarios so it does not attempt to identify a patch change as this may be misleading.

Why do attribute changes identify a feature or breaking change when the public API signature hasn't changed?

There is an edge case to the idea that the library only compares the public API surface between two versions of C# code. The library also evaluates changes to attributes based on the ComparerOptions class in order to determine a Semantic Version impact of attributes.

What this means is that the C# signatures could be the same, but attribute changes regarding XML and JSON serialization could cause a potential breaking change to consumers of the library. So signatures compiled into the binary are the same, but the attributes are telling the runtime to handle serialization differently.

For example, consider this change. Here is the old code.

using System;

public MyNamespace
{
    public class MyClass
    {
        public DateTime MyValue { get; set; }
    }
}

Here is the new code.

using System;
using System.Text.Json.Serialization;

public MyNamespace
{
    [JsonPropertyName("otherValue")]
    public class MyClass
    {
        public DateTime MyValue { get; set; }
    }
}

This is a breaking change to consumers because the json serialization of this class has changed the name of the property from MyValue to otherValue.

Resources

Combinations of data sets (combinations of access modifiers for example) were calculated using https://www.mathsisfun.com/combinatorics/combinations-permutations-calculator.html.

This project is supported by JetBrains

Product Compatible and additional computed target framework versions.
.NET net5.0 is compatible.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.1 is compatible. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
3.0.0 803 11/6/2021
3.0.0-beta0020 362 10/4/2021
3.0.0-beta0014 379 10/3/2021
3.0.0-beta0009 329 9/18/2021
3.0.0-beta0005 390 9/12/2021
3.0.0-beta0002 423 9/12/2021
2.0.1 417 8/29/2021
2.0.1-beta0001 307 8/29/2021
2.0.0 432 8/29/2021
2.0.0-beta0325 326 8/29/2021
2.0.0-beta0288 364 7/31/2021
2.0.0-beta0252 333 4/26/2021
2.0.0-beta0217 295 4/25/2021
2.0.0-beta0183 332 4/25/2021
2.0.0-beta0150 320 4/21/2021
2.0.0-beta0118 328 4/18/2021
2.0.0-beta0087 313 4/17/2021
2.0.0-beta0057 283 4/13/2021
2.0.0-beta0028 320 2/7/2021
1.1.0-beta0123 372 11/23/2020
1.1.0-beta0101 391 11/23/2020
1.1.0-beta0080 420 11/23/2020
1.1.0-beta0060 385 11/23/2020
1.1.0-beta0041 410 11/22/2020
1.1.0-beta0023 375 11/13/2020
1.1.0-beta0022 406 11/12/2020
1.1.0-beta0021 419 11/12/2020
1.1.0-beta0020 411 11/10/2020
1.1.0-beta0019 400 10/14/2020
1.1.0-beta0018 446 10/14/2020
1.1.0-beta0017 390 10/9/2020
1.1.0-beta0016 436 10/3/2020
1.1.0-beta0015 477 9/27/2020
1.1.0-beta0014 427 9/15/2020
1.1.0-beta0013 395 9/9/2020
1.1.0-beta0012 414 9/9/2020
1.1.0-beta0011 380 9/2/2020
1.1.0-beta0010 404 8/21/2020
1.1.0-beta0006 457 8/12/2020
1.1.0-beta0003 415 8/12/2020
1.1.0-beta0001 439 8/9/2020
1.0.0 610 8/8/2020
0.1.0-beta0104 452 7/14/2020
0.1.0-beta0096 411 8/8/2020
0.1.0-beta0084 423 6/2/2020
0.1.0-beta0069 468 7/20/2020
0.1.0-beta0068 466 7/20/2020
0.1.0-beta0065 415 5/25/2020
0.1.0-beta0063 432 8/8/2020
0.1.0-beta0054 426 8/5/2020
0.1.0-beta0053 388 8/5/2020
0.1.0-beta0047 458 5/22/2020
0.1.0-beta0044 441 7/20/2020
0.1.0-beta0030 403 5/22/2020
0.1.0-beta0029 399 8/5/2020
0.1.0-beta0026 450 7/20/2020
0.1.0-beta0022 398 7/20/2020
0.1.0-beta0021 393 7/19/2020
0.1.0-beta0015 456 5/21/2020
0.1.0-beta0014 461 5/15/2020
0.1.0-beta0013 470 11/25/2019
0.1.0-beta0012 518 11/16/2019