diff --git a/src/bgen/Generator.cs b/src/bgen/Generator.cs index 4fc29f748a..f84a55cddf 100644 --- a/src/bgen/Generator.cs +++ b/src/bgen/Generator.cs @@ -4879,11 +4879,13 @@ public partial class Generator : IMemberGatherer { WriteDocumentation (type); PrintAttributes (type, platform: true, preserve: true, advice: true); - print ("[Protocol (Name = \"{1}\", WrapperType = typeof ({0}Wrapper){2}{3})]", + print ("[Protocol (Name = \"{1}\", WrapperType = typeof ({0}Wrapper){2}{3}{4})]", TypeName, protocol_name, protocolAttribute.IsInformal ? ", IsInformal = true" : string.Empty, - protocolAttribute.FormalSince is not null ? $", FormalSince = \"{protocolAttribute.FormalSince}\"" : string.Empty); + protocolAttribute.FormalSince is not null ? $", FormalSince = \"{protocolAttribute.FormalSince}\"" : string.Empty, + backwardsCompatibleCodeGeneration ? string.Empty : ", BackwardsCompatibleCodeGeneration = false" + ); var sb = new StringBuilder (); diff --git a/tests/cecil-tests/ProtocolTest.cs b/tests/cecil-tests/ProtocolTest.cs index 3ef51758dc..7dfe9dc74b 100644 --- a/tests/cecil-tests/ProtocolTest.cs +++ b/tests/cecil-tests/ProtocolTest.cs @@ -30,13 +30,24 @@ namespace Cecil.Tests { continue; var hasProtocolAttribute = false; var hasProtocolMemberAttribute = false; + bool? isBackwardsCompatible = null; foreach (var ca in type.CustomAttributes) { - hasProtocolAttribute |= ca.AttributeType.Is ("Foundation", "ProtocolAttribute"); + if (ca.AttributeType.Is ("Foundation", "ProtocolAttribute")) { + hasProtocolAttribute = true; + foreach (var prop in ca.Properties) { + if (prop.Name == "BackwardsCompatibleCodeGeneration") { + isBackwardsCompatible = (bool) prop.Argument.Value; + break; + } + } + } hasProtocolMemberAttribute |= ca.AttributeType.Is ("Foundation", "ProtocolMemberAttribute"); } if (!hasProtocolAttribute) continue; if (!hasProtocolMemberAttribute) + continue; // doesn't need to be compatible if it doesn't have any members. + if (isBackwardsCompatible == false) continue; found.Add (type.FullName); } @@ -1146,7 +1157,12 @@ namespace Cecil.Tests { }; var unexpectedFailures = found.Except (expectedFailures); - Assert.That (unexpectedFailures, Is.Empty, $"{found.Count} new protocols found where 'BackwardsCompatibleCodeGeneration' should be set to 'false'."); + if (unexpectedFailures.Any ()) { + Console.WriteLine ("Protocols missing 'BackwardsCompatibleCodeGeneration = false':"); + foreach (var f in unexpectedFailures.OrderBy (v => v)) + Console.WriteLine ($" {f}"); + } + Assert.That (unexpectedFailures, Is.Empty, $"{unexpectedFailures.Count ()} new protocols found where 'BackwardsCompatibleCodeGeneration' should be set to 'false'."); } } } diff --git a/tools/common/StaticRegistrar.cs b/tools/common/StaticRegistrar.cs index 3984795ba4..052cb722db 100644 --- a/tools/common/StaticRegistrar.cs +++ b/tools/common/StaticRegistrar.cs @@ -1427,6 +1427,11 @@ namespace Registrar { throw ErrorHelper.CreateError (4147, Errors.MT4147, "ProtocolAttribute", type.FullName); rv.FormalSinceVersion = version; break; +#if !XAMCORE_5_0 + case "BackwardsCompatibleCodeGeneration": + rv.BackwardsCompatibleCodeGeneration = (bool) prop.Argument.Value; + break; +#endif default: throw ErrorHelper.CreateError (4147, Errors.MT4147, "ProtocolAttribute", type.FullName); } @@ -5790,6 +5795,9 @@ namespace Registrar { public string Name { get; set; } public bool IsInformal { get; set; } public Version FormalSinceVersion { get; set; } +#if !XAMCORE_5_0 + public bool BackwardsCompatibleCodeGeneration { get; set; } +#endif } class BlockProxyAttribute : Attribute {