public void AssemblyVersionMustBeStrictlyCompatible() { string leftSyntax = "[assembly: System.Reflection.AssemblyVersionAttribute(\"1.0.0.0\")]"; string rightSyntax = "[assembly: System.Reflection.AssemblyVersionAttribute(\"2.0.0.0\")]"; IAssemblySymbol leftSymbol = SymbolFactory.GetAssemblyFromSyntax(leftSyntax); IAssemblySymbol rightSymbol = SymbolFactory.GetAssemblyFromSyntax(rightSyntax); Assert.Equal(new Version(1, 0, 0, 0), leftSymbol.Identity.Version); Assert.Equal(new Version(2, 0, 0, 0), rightSymbol.Identity.Version); // Compatible assembly versions ApiComparer differ = new(); IEnumerable <CompatDifference> differences = differ.GetDifferences(leftSymbol, rightSymbol); Assert.Empty(differences); differ.StrictMode = true; // Not strictly compatible differences = differ.GetDifferences(leftSymbol, rightSymbol); Assert.Single(differences); CompatDifference expected = new(DiagnosticIds.AssemblyIdentityMustMatch, string.Empty, DifferenceType.Changed, $"{leftSymbol.Name}, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"); Assert.Equal(expected, differences.First()); }
public void LeftAssemblyKeyTokenNull(bool strictMode) { string syntax = "namespace EmptyNs { }"; IAssemblySymbol leftSymbol = SymbolFactory.GetAssemblyFromSyntax(syntax); IAssemblySymbol rightSymbol = SymbolFactory.GetAssemblyFromSyntax(syntax, publicKey: _publicKey); Assert.False(leftSymbol.Identity.HasPublicKey); Assert.Equal(_publicKey, rightSymbol.Identity.PublicKey); ApiComparer differ = new(); differ.StrictMode = strictMode; IEnumerable <CompatDifference> differences = differ.GetDifferences(leftSymbol, rightSymbol); if (strictMode) { Assert.Single(differences); CompatDifference expected = new(DiagnosticIds.AssemblyIdentityMustMatch, string.Empty, DifferenceType.Changed, $"{rightSymbol.Name}, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"); Assert.Equal(expected, differences.First()); } else { Assert.Empty(differences); } }
public void NestedTypeVsNamespaces() { string leftSyntax = @" namespace A { public class B { } } "; string rightSyntax = @" public class A { public class B { } } "; ApiComparer differ = new(); bool enableNullable = false; IAssemblySymbol left = SymbolFactory.GetAssemblyFromSyntax(leftSyntax, enableNullable); IAssemblySymbol right = SymbolFactory.GetAssemblyFromSyntax(rightSyntax, enableNullable); IEnumerable <CompatDifference> differences = differ.GetDifferences(new[] { left }, new[] { right }); CompatDifference[] expected = new[] { new CompatDifference(DiagnosticIds.TypeMustExist, string.Empty, DifferenceType.Removed, "T:A.B"), }; Assert.Equal(expected, differences); }
public static void NoDifferencesWithNoWarn() { string leftSyntax = @" namespace CompatTests { public class First { public void MissingMember() { } public int MissingProperty { get; } public int MissingField; } } "; string rightSyntax = @" namespace CompatTests { public class First { } } "; IAssemblySymbol left = SymbolFactory.GetAssemblyFromSyntax(leftSyntax); IAssemblySymbol right = SymbolFactory.GetAssemblyFromSyntax(rightSyntax); ApiDiffer differ = new(); differ.NoWarn = DiagnosticIds.MemberMustExist; IEnumerable <CompatDifference> differences = differ.GetDifferences(new[] { left }, new[] { right }); Assert.Empty(differences); }
public static void MembersWithDifferentNullableAnnotationsNoErrors() { string leftSyntax = @" namespace CompatTests { public class First { public string? MyMethod(string? a) => null; } } "; string rightSyntax = @" namespace CompatTests { public class First { public string MyMethod(string a) => null; } } "; IAssemblySymbol left = SymbolFactory.GetAssemblyFromSyntax(leftSyntax, enableNullable: true); IAssemblySymbol right = SymbolFactory.GetAssemblyFromSyntax(rightSyntax); ApiComparer differ = new(); IEnumerable <CompatDifference> differences = differ.GetDifferences(left, right); Assert.Empty(differences); }
public static void AddedEnum() { string leftSyntax = @" namespace CompatTests { public enum First { A = 0, B = 1, C = 2, D = 3, } } "; string rightSyntax = @" namespace CompatTests { public enum First { D = 3, C = 2, B = 1, A = 0, } public enum Second {} } "; IAssemblySymbol left = SymbolFactory.GetAssemblyFromSyntax(leftSyntax); IAssemblySymbol right = SymbolFactory.GetAssemblyFromSyntax(rightSyntax); ApiComparer differ = new(); IEnumerable <CompatDifference> differences = differ.GetDifferences(new[] { left }, new[] { right }); Assert.Empty(differences); }
public void ParameterlessConstructorRemovalIsReported() { string leftSyntax = @" namespace CompatTests { public sealed class First { } } "; string rightSyntax = @" namespace CompatTests { public class First { private First() { } } } "; IAssemblySymbol left = SymbolFactory.GetAssemblyFromSyntax(leftSyntax); IAssemblySymbol right = SymbolFactory.GetAssemblyFromSyntax(rightSyntax); ApiComparer differ = new(); IEnumerable <CompatDifference> differences = differ.GetDifferences(left, right); CompatDifference[] expected = new[] { new CompatDifference(DiagnosticIds.MemberMustExist, string.Empty, DifferenceType.Removed, "M:CompatTests.First.#ctor") }; Assert.Equal(expected, differences); }
public static void ParametersWithDifferentModifiersNoErrors() { string leftSyntax = @" namespace CompatTests { public class First { public string MyMethod(ref string a) => throw null; public void MyOutMethod(out string a) => throw null; } } "; string rightSyntax = @" namespace CompatTests { public class First { public string MyMethod(string a) => throw null; public void MyOutMethod(string a) { } } } "; IAssemblySymbol left = SymbolFactory.GetAssemblyFromSyntax(leftSyntax); IAssemblySymbol right = SymbolFactory.GetAssemblyFromSyntax(rightSyntax); ApiComparer differ = new(); IEnumerable <CompatDifference> differences = differ.GetDifferences(left, right); Assert.Empty(differences); }
public void MissingTypeFromTypeForwardIsReported() { string forwardedTypeSyntax = @" namespace CompatTests { public class ForwardedTestType { } } "; string leftSyntax = @" [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(CompatTests.ForwardedTestType))] namespace CompatTests { public class First { } } "; string rightSyntax = @" namespace CompatTests { public class First { } } "; IAssemblySymbol left = SymbolFactory.GetAssemblyFromSyntaxWithReferences(leftSyntax, new[] { forwardedTypeSyntax }); IAssemblySymbol right = SymbolFactory.GetAssemblyFromSyntax(rightSyntax); ApiComparer differ = new(); IEnumerable <CompatDifference> differences = differ.GetDifferences(left, right); CompatDifference[] expected = new[] { new CompatDifference(DiagnosticIds.TypeMustExist, string.Empty, DifferenceType.Removed, "T:CompatTests.ForwardedTestType") }; Assert.Equal(expected, differences); }
public static void MultipleRightsNoDifferences() { string leftSyntax = @" namespace CompatTests { public class First { public class FirstNested { public class SecondNested { public class ThirdNested { public string MyField; } } } } } "; string[] rightSyntaxes = new[] { leftSyntax, leftSyntax, leftSyntax, leftSyntax }; ApiComparer differ = new(); ElementContainer <IAssemblySymbol> left = new(SymbolFactory.GetAssemblyFromSyntax(leftSyntax), new MetadataInformation(string.Empty, string.Empty, "ref")); IList <ElementContainer <IAssemblySymbol> > right = SymbolFactory.GetElementContainersFromSyntaxes(rightSyntaxes); IEnumerable <(MetadataInformation, MetadataInformation, IEnumerable <CompatDifference>)> differences = differ.GetDifferences(left, right); AssertExtensions.MultiRightEmptyDifferences(left.MetadataInformation, rightSyntaxes.Length, differences); }
public void MultipleRightsMissingTypeForwardIsReported() { string forwardedTypeSyntax = @" namespace CompatTests { public class ForwardedTestType { } } "; string rightWithForward = @" [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(CompatTests.ForwardedTestType))] "; string[] rightSyntaxes = new[] { rightWithForward, "namespace CompatTests { internal class Foo { } }", rightWithForward }; IEnumerable <string> references = new[] { forwardedTypeSyntax }; ElementContainer <IAssemblySymbol> left = new(SymbolFactory.GetAssemblyFromSyntax(forwardedTypeSyntax), new MetadataInformation(string.Empty, string.Empty, "ref")); IList <ElementContainer <IAssemblySymbol> > right = SymbolFactory.GetElementContainersFromSyntaxes(rightSyntaxes, references); ApiComparer differ = new(); IEnumerable <(MetadataInformation, MetadataInformation, IEnumerable <CompatDifference>)> differences = differ.GetDifferences(left, right); CompatDifference[][] expected = { Array.Empty <CompatDifference>(), new[] { new CompatDifference(DiagnosticIds.TypeMustExist,string.Empty, DifferenceType.Removed, "T:CompatTests.ForwardedTestType"), }, Array.Empty <CompatDifference>(), }; AssertExtensions.MultiRightResult(left.MetadataInformation, expected, differences); }
public static void TypesMissingOnBothSidesAreReported() { string leftSyntax = @" namespace CompatTests { public class LeftType { } } "; string rightSyntax = @" namespace CompatTests { public class RightType { } } "; ApiComparer differ = new(); differ.StrictMode = true; IAssemblySymbol left = SymbolFactory.GetAssemblyFromSyntax(leftSyntax); IAssemblySymbol right = SymbolFactory.GetAssemblyFromSyntax(rightSyntax); IEnumerable <CompatDifference> differences = differ.GetDifferences(left, right); List <CompatDifference> expected = new() { new CompatDifference(DiagnosticIds.TypeMustExist, string.Empty, DifferenceType.Removed, "T:CompatTests.LeftType"), new CompatDifference(DiagnosticIds.TypeMustExist, string.Empty, DifferenceType.Added, "T:CompatTests.RightType"), }; Assert.Equal(expected, differences); }
public void PromotedBaseClassOrInterfaceIsNotReported() { string leftSyntax = @" namespace CompatTests { public class First : FirstBase, IFirstInterface { } public class Second : SecondBase { } public class SecondBase { } public class FirstBase { } public interface IFirstInterface { } } "; string rightSyntax = @" namespace CompatTests { public class First : NewBase { } public class Second : NewSecondBase { } public class NewBase : FirstBase, INewInterface { } public class FirstBase { } public class SecondBase { } public class NewSecondBase : NewSecondBaseBase { } public class NewSecondBaseBase : SecondBase { } public interface IFirstInterface { } public interface INewInterface : IFirstInterface { } } "; IAssemblySymbol left = SymbolFactory.GetAssemblyFromSyntax(leftSyntax); IAssemblySymbol right = SymbolFactory.GetAssemblyFromSyntax(rightSyntax); ApiComparer differ = new(); Assert.Empty(differ.GetDifferences(left, right)); }
public static void MultipleRightsMissingTypesOnLeftAreReported() { string leftSyntax = @" namespace CompatTests { public class First { } } "; string[] rightSyntaxes = new[] { @" namespace CompatTests { public class First { } } ", @" namespace CompatTests { public class First { } public class Second { } } ", @" namespace CompatTests { public class First { } public class Third { } } " }; ApiComparer differ = new(); differ.StrictMode = true; ElementContainer <IAssemblySymbol> left = new(SymbolFactory.GetAssemblyFromSyntax(leftSyntax), new MetadataInformation(string.Empty, string.Empty, "ref")); IList <ElementContainer <IAssemblySymbol> > right = SymbolFactory.GetElementContainersFromSyntaxes(rightSyntaxes); IEnumerable <(MetadataInformation, MetadataInformation, IEnumerable <CompatDifference>)> differences = differ.GetDifferences(left, right); CompatDifference[][] expected = { Array.Empty <CompatDifference>(), new[] { new CompatDifference(DiagnosticIds.TypeMustExist,string.Empty, DifferenceType.Added, "T:CompatTests.Second"), }, new[] { new CompatDifference(DiagnosticIds.TypeMustExist,string.Empty, DifferenceType.Added, "T:CompatTests.Third"), }, }; AssertExtensions.MultiRightResult(left.MetadataInformation, expected, differences); }
public void MembersPushedDownToNewBaseNotReported() { string leftSyntax = @" namespace CompatTests { public class First : FirstBase { } public class Second : SecondBase { public string MyMethod() => string.Empty; public int MyProperty => 0; } public class SecondBase : ThirdBase { public void AnotherMethod() { } public string MethodWithArguments(string a) => MethodWithArguments(a, string.Empty); public string MethodWithArguments(string a, string b) => MethodWithArguments(a, string.Empty, string.Empty); public string MethodWithArguments(string a, string b, string c) => c; } public class FirstBase { } public class ThirdBase { } } "; string rightSyntax = @" namespace CompatTests { public class First : NewBase { } public class Second : NewSecondBase { public int MyProperty => 0; } public class NewBase : FirstBase { } public class FirstBase { } public class NewSecondBase : SecondBase { public string MyMethod() => string.Empty; } public class SecondBase : NewThirdBase { public void AnotherMethod() { } public string MethodWithArguments(string a) => MethodWithArguments(a, string.Empty); } public class NewThirdBase : ThirdBase { public string MethodWithArguments(string a, string b) => MethodWithArguments(a, string.Empty, string.Empty); public string MethodWithArguments(string a, string b, string c) => c; } public class ThirdBase { } } "; IAssemblySymbol left = SymbolFactory.GetAssemblyFromSyntax(leftSyntax); IAssemblySymbol right = SymbolFactory.GetAssemblyFromSyntax(rightSyntax); ApiComparer differ = new(); Assert.Empty(differ.GetDifferences(left, right)); }
public void NoDifferencesShouldBeReported(string leftSyntax, string rightSyntax) { IAssemblySymbol left = SymbolFactory.GetAssemblyFromSyntax(leftSyntax); IAssemblySymbol right = SymbolFactory.GetAssemblyFromSyntax(rightSyntax); ApiComparer differ = new(); IEnumerable <CompatDifference> differences = differ.GetDifferences(left, right); Assert.Empty(differences); }
public void AddedAbstractMemberNoVisibleConstructor(string leftSyntax, string rightSyntax) { IAssemblySymbol left = SymbolFactory.GetAssemblyFromSyntax(leftSyntax); IAssemblySymbol right = SymbolFactory.GetAssemblyFromSyntax(rightSyntax); ApiComparer differ = new(); IEnumerable <CompatDifference> differences = differ.GetDifferences(left, right); Assert.Empty(differences); }
public static void IncludeInternalsIsRespectedForMembers_IndividualAssemblies(bool includeInternals) { string rightSyntax = @" namespace CompatTests { public class First { public string MultipleOverrides() => string.Empty; public string MultipleOverrides(string a) => string.Empty; public string MultipleOverrides(string a, string b) => string.Empty; public string MultipleOverrides(string a, int b, string c) => string.Empty; internal string MultipleOverrides(string a, int b, int c) => string.Empty; internal int InternalProperty { get; set; } } } "; string leftSyntax = @" namespace CompatTests { public class First { public string MultipleOverrides() => string.Empty; public string MultipleOverrides(string a) => string.Empty; public string MultipleOverrides(string a, string b) => string.Empty; public string MultipleOverrides(string a, int b, string c) => string.Empty; internal int InternalProperty { get; } } } "; IAssemblySymbol left = SymbolFactory.GetAssemblyFromSyntax(leftSyntax); IAssemblySymbol right = SymbolFactory.GetAssemblyFromSyntax(rightSyntax); ApiComparer differ = new(); differ.IncludeInternalSymbols = includeInternals; differ.StrictMode = true; IEnumerable <CompatDifference> differences = differ.GetDifferences(left, right); if (includeInternals) { CompatDifference[] expected = new[] { new CompatDifference(DiagnosticIds.MemberMustExist, string.Empty, DifferenceType.Added, "M:CompatTests.First.MultipleOverrides(System.String,System.Int32,System.Int32)"), new CompatDifference(DiagnosticIds.MemberMustExist, string.Empty, DifferenceType.Added, "M:CompatTests.First.set_InternalProperty(System.Int32)"), }; Assert.Equal(expected, differences); } else { Assert.Empty(differences); } }
public void SealInheritableTypeReported(string leftSyntax, string rightSyntax) { IAssemblySymbol left = SymbolFactory.GetAssemblyFromSyntax(leftSyntax); IAssemblySymbol right = SymbolFactory.GetAssemblyFromSyntax(rightSyntax); ApiComparer differ = new(); IEnumerable <CompatDifference> differences = differ.GetDifferences(left, right); CompatDifference difference = new(DiagnosticIds.CannotSealType, string.Empty, DifferenceType.Changed, "T:CompatTests.First"); Assert.Contains(difference, differences); }
public void MultipleRightsNoDifferences() { string leftSyntax = @" namespace CompatTests { public class First { } } "; string[] rightSyntaxes = new[] { @" namespace CompatTests { public class First { } }", @" namespace CompatTests { public class First { protected First() { } } }", @" namespace CompatTests { public class First { internal First() { } } }" }; IAssemblySymbol left = SymbolFactory.GetAssemblyFromSyntax(leftSyntax); MetadataInformation leftMetadata = new("left", "net6.0", "ref/a.dll"); ElementContainer <IAssemblySymbol> leftContainer = new(left, leftMetadata); IList <ElementContainer <IAssemblySymbol> > right = SymbolFactory.GetElementContainersFromSyntaxes(rightSyntaxes); ApiComparer differ = new(); differ.IncludeInternalSymbols = true; IEnumerable <(MetadataInformation left, MetadataInformation right, IEnumerable <CompatDifference> differences)> result = differ.GetDifferences(leftContainer, right); AssertExtensions.MultiRightEmptyDifferences(leftMetadata, 3, result); }
public void SealNonInheritableTypeNotReported(string leftSyntax, string rightSyntax) { IAssemblySymbol left = SymbolFactory.GetAssemblyFromSyntax(leftSyntax); IAssemblySymbol right = SymbolFactory.GetAssemblyFromSyntax(rightSyntax); ApiComparer differ = new(); IEnumerable <CompatDifference> differences = differ.GetDifferences(left, right); foreach (CompatDifference difference in differences) { Assert.NotEqual(DiagnosticIds.CannotSealType, difference.DiagnosticId); } }
public static void MissingNestedTypeIsReported(bool includeInternalSymbols) { string leftSyntax = @" namespace CompatTests { public class First { public class FirstNested { public class SecondNested { } } internal class InternalNested { internal class DoubleNested { } } } } "; string rightSyntax = @" namespace CompatTests { public class First { internal class InternalNested { } } } "; ApiComparer differ = new(); differ.IncludeInternalSymbols = includeInternalSymbols; IAssemblySymbol left = SymbolFactory.GetAssemblyFromSyntax(leftSyntax); IAssemblySymbol right = SymbolFactory.GetAssemblyFromSyntax(rightSyntax); IEnumerable <CompatDifference> differences = differ.GetDifferences(new[] { left }, new[] { right }); List <CompatDifference> expected = new() { new CompatDifference(DiagnosticIds.TypeMustExist, string.Empty, DifferenceType.Removed, "T:CompatTests.First.FirstNested"), }; if (includeInternalSymbols) { expected.Add( new CompatDifference(DiagnosticIds.TypeMustExist, string.Empty, DifferenceType.Removed, "T:CompatTests.First.InternalNested.DoubleNested") ); } Assert.Equal(expected, differences); }
public static void IncludeInternalsIsRespectedForMembers(bool includeInternals) { string leftSyntax = @" namespace CompatTests { public class First { public string MultipleOverrides() { } public string MultipleOverrides(string a) { } public string MultipleOverrides(string a, string b) { } public string MultipleOverrides(string a, int b, string c) { } internal string MultipleOverrides(string a, int b, int c) { } internal int InternalProperty { get; set; } } } "; string rightSyntax = @" namespace CompatTests { public class First { public string MultipleOverrides() { } public string MultipleOverrides(string a) { } public string MultipleOverrides(string a, string b) { } public string MultipleOverrides(string a, int b, string c) { } internal int InternalProperty { get; } } } "; IAssemblySymbol left = SymbolFactory.GetAssemblyFromSyntax(leftSyntax); IAssemblySymbol right = SymbolFactory.GetAssemblyFromSyntax(rightSyntax); ApiDiffer differ = new(includeInternalSymbols : includeInternals); IEnumerable <CompatDifference> differences = differ.GetDifferences(new[] { left }, new[] { right }); if (includeInternals) { CompatDifference[] expected = new[] { new CompatDifference(DiagnosticIds.MemberMustExist, "Member 'CompatTests.First.MultipleOverrides(string, int, int)' exists on the contract but not on the implementation", DifferenceType.Removed, "M:CompatTests.First.MultipleOverrides(System.String,System.Int32,System.Int32)"), new CompatDifference(DiagnosticIds.MemberMustExist, "Member 'CompatTests.First.InternalProperty.set' exists on the contract but not on the implementation", DifferenceType.Removed, "M:CompatTests.First.set_InternalProperty(System.Int32)"), }; Assert.Equal(expected, differences); } else { Assert.Empty(differences); } }
public static void MissingMembersOnLeftAreReported() { string leftSyntax = @" namespace CompatTests { public class First { public string Parameterless() => string.Empty; } public delegate void EventHandler(object sender, System.EventArgs e); } "; string rightSyntax = @" namespace CompatTests { public class First { public string Parameterless() => string.Empty; public void ShouldReportMethod(string a, string b) { } public string ShouldReportMissingProperty { get; } public string this[int index] { get => string.Empty; } public event EventHandler ShouldReportMissingEvent; public int ReportMissingField = 0; } public delegate void EventHandler(object sender, System.EventArgs e); } "; IAssemblySymbol left = SymbolFactory.GetAssemblyFromSyntax(leftSyntax); IAssemblySymbol right = SymbolFactory.GetAssemblyFromSyntax(rightSyntax); ApiComparer differ = new(); differ.StrictMode = true; IEnumerable <CompatDifference> differences = differ.GetDifferences(new[] { left }, new[] { right }); CompatDifference[] expected = new[] { new CompatDifference(DiagnosticIds.MemberMustExist, string.Empty, DifferenceType.Added, "M:CompatTests.First.ShouldReportMethod(System.String,System.String)"), new CompatDifference(DiagnosticIds.MemberMustExist, string.Empty, DifferenceType.Added, "M:CompatTests.First.get_ShouldReportMissingProperty"), new CompatDifference(DiagnosticIds.MemberMustExist, string.Empty, DifferenceType.Added, "M:CompatTests.First.get_Item(System.Int32)"), new CompatDifference(DiagnosticIds.MemberMustExist, string.Empty, DifferenceType.Added, "M:CompatTests.First.add_ShouldReportMissingEvent(CompatTests.EventHandler)"), new CompatDifference(DiagnosticIds.MemberMustExist, string.Empty, DifferenceType.Added, "M:CompatTests.First.remove_ShouldReportMissingEvent(CompatTests.EventHandler)"), new CompatDifference(DiagnosticIds.MemberMustExist, string.Empty, DifferenceType.Added, "F:CompatTests.First.ReportMissingField"), }; Assert.Equal(expected, differences); }
public void StrictModeSealedLeftIsReported(string leftSyntax, string rightSyntax) { IAssemblySymbol left = SymbolFactory.GetAssemblyFromSyntax(leftSyntax); IAssemblySymbol right = SymbolFactory.GetAssemblyFromSyntax(rightSyntax); ApiComparer differ = new(); differ.StrictMode = true; CompatDifference[] differences = differ.GetDifferences(left, right).ToArray(); CompatDifference difference = new(DiagnosticIds.CannotSealType, string.Empty, DifferenceType.Changed, "T:CompatTests.First"); Assert.Contains(difference, differences); Assert.True(differences[0].Message.IndexOf("left") < differences[0].Message.IndexOf("right")); }
public void AddedAbstractMemberIsReported(string leftSyntax, string rightSyntax, bool includeInternals) { IAssemblySymbol left = SymbolFactory.GetAssemblyFromSyntax(leftSyntax); IAssemblySymbol right = SymbolFactory.GetAssemblyFromSyntax(rightSyntax); ApiComparer differ = new(); differ.IncludeInternalSymbols = includeInternals; IEnumerable <CompatDifference> differences = differ.GetDifferences(left, right); CompatDifference[] expected = new[] { new CompatDifference(DiagnosticIds.CannotAddAbstractMember, string.Empty, DifferenceType.Added, "M:CompatTests.First.SecondAbstract") }; Assert.Equal(expected, differences); }
public void RemovedFromLeftReportedOnStrictMode() { string leftSyntax = @" namespace CompatTests { public class First { } public class FirstBase { } public interface IFirstInterface { } } "; string rightSyntax = @" namespace CompatTests { public class First : FirstBase, IFirstInterface { } public class FirstBase { } public interface IFirstInterface { } } "; IAssemblySymbol left = SymbolFactory.GetAssemblyFromSyntax(leftSyntax); IAssemblySymbol right = SymbolFactory.GetAssemblyFromSyntax(rightSyntax); ApiComparer differ = new(); differ.StrictMode = true; CompatDifference[] differences = differ.GetDifferences(left, right).ToArray(); CompatDifference[] expected = new[] { new CompatDifference(DiagnosticIds.CannotRemoveBaseType, string.Empty, DifferenceType.Changed, "T:CompatTests.First"), new CompatDifference(DiagnosticIds.CannotRemoveBaseInterface, string.Empty, DifferenceType.Changed, "T:CompatTests.First"), }; Assert.Equal(expected, differences); string firstMessage = differences[0].Message; string secondMessage = differences[1].Message; firstMessage.Contains("CompatTests.FirstBase"); secondMessage.Contains("CompatTests.IFirstInterface"); Assert.True(firstMessage.IndexOf("right") > firstMessage.IndexOf("left")); Assert.True(secondMessage.IndexOf("right") > firstMessage.IndexOf("left")); }
public static void MissingMembersOnEnumReported() { string leftSyntax = @" namespace CompatTests { public enum First { A = 0, B = 1, C = 2, D = 3, } } "; string rightSyntax = @" namespace CompatTests { public enum First { F = 5, E = 4, D = 3, C = 2, } } "; IAssemblySymbol left = SymbolFactory.GetAssemblyFromSyntax(leftSyntax); IAssemblySymbol right = SymbolFactory.GetAssemblyFromSyntax(rightSyntax); ApiComparer differ = new(); differ.StrictMode = true; IEnumerable <CompatDifference> differences = differ.GetDifferences(new[] { left }, new[] { right }); CompatDifference[] expected = new[] { new CompatDifference(DiagnosticIds.MemberMustExist, string.Empty, DifferenceType.Removed, "F:CompatTests.First.A"), new CompatDifference(DiagnosticIds.MemberMustExist, string.Empty, DifferenceType.Removed, "F:CompatTests.First.B"), new CompatDifference(DiagnosticIds.MemberMustExist, string.Empty, DifferenceType.Added, "F:CompatTests.First.F"), new CompatDifference(DiagnosticIds.MemberMustExist, string.Empty, DifferenceType.Added, "F:CompatTests.First.E"), }; Assert.Equal(expected, differences); }
public static void HiddenMemberInRightIsNotReported() { string leftSyntax = @" namespace CompatTests { public class FirstBase { public void MyMethod() { } public string MyMethodWithParams(string a, int b, FirstBase c) => string.Empty; public T MyGenericMethod<T, T2, T3>(string name, T2 a, T3 b) => throw null; public virtual string MyVirtualMethod() => string.Empty; } public class Second : FirstBase { } } "; string rightSyntax = @" namespace CompatTests { public class FirstBase { public void MyMethod() { } public string MyMethodWithParams(string a, int b, FirstBase c) => string.Empty; public T MyGenericMethod<T, T2, T3>(string name, T2 a, T3 b) => throw null; public virtual string MyVirtualMethod() => string.Empty; } public class Second : FirstBase { public new void MyMethod() { } public new string MyMethodWithParams(string a, int b, FirstBase c) => string.Empty; public new T MyGenericMethod<T, T2, T3>(string name, T2 a, T3 b) => throw null; public override string MyVirtualMethod() => string.Empty; } } "; IAssemblySymbol left = SymbolFactory.GetAssemblyFromSyntax(leftSyntax); IAssemblySymbol right = SymbolFactory.GetAssemblyFromSyntax(rightSyntax); ApiComparer differ = new(); differ.StrictMode = true; IEnumerable <CompatDifference> differences = differ.GetDifferences(new[] { left }, new[] { right }); Assert.Empty(differences); }
public void AddedMembersAreReported() { string leftSyntax = @" namespace CompatTests { public interface IFoo { } } "; string rightSyntax = @" namespace CompatTests { public interface IFoo { string MyMethod(); byte MyPropertyWithoutDefaultImplementation { get; set; } event System.EventHandler MyEventWithoutImplementation; // .NET Framework doesn't support default implementations. #if !NETFRAMEWORK static int MyField = 2; event System.EventHandler MyEvent { add { } remove { } } int MyPropertyWithDefaultImplementation { get => 0; set { } } #endif } } "; IAssemblySymbol left = SymbolFactory.GetAssemblyFromSyntax(leftSyntax); IAssemblySymbol right = SymbolFactory.GetAssemblyFromSyntax(rightSyntax); ApiComparer differ = new(); IEnumerable <CompatDifference> differences = differ.GetDifferences(left, right); CompatDifference[] expected = new[] { new CompatDifference(DiagnosticIds.CannotAddMemberToInterface, string.Empty, DifferenceType.Added, "M:CompatTests.IFoo.MyMethod"), new CompatDifference(DiagnosticIds.CannotAddMemberToInterface, string.Empty, DifferenceType.Added, "P:CompatTests.IFoo.MyPropertyWithoutDefaultImplementation"), new CompatDifference(DiagnosticIds.CannotAddMemberToInterface, string.Empty, DifferenceType.Added, "E:CompatTests.IFoo.MyEventWithoutImplementation"), }; Assert.Equal(expected, differences); }