From 6bb6314fed00bbd630fce0bb7ad19a6671f6a5a3 Mon Sep 17 00:00:00 2001 From: danielmarbach Date: Fri, 22 Nov 2019 12:52:46 +0100 Subject: [PATCH 1/2] Reproduce bug --- .../Method_modifiers.cs | 30 +++++++++++++++++++ .../Property_modifiers.cs | 26 +++++++++++++++- 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/src/PublicApiGeneratorTests/Method_modifiers.cs b/src/PublicApiGeneratorTests/Method_modifiers.cs index 1acc4be..09141a5 100644 --- a/src/PublicApiGeneratorTests/Method_modifiers.cs +++ b/src/PublicApiGeneratorTests/Method_modifiers.cs @@ -257,6 +257,20 @@ public class ClassWithMethodHiding : PublicApiGeneratorTests.Examples.ClassWithS }"); } + [Fact] + public void Should_output_new_modifier_for_generics() + { + AssertPublicApi(typeof(ClassWithMethodExtensions<>), + @"namespace PublicApiGeneratorTests.Examples +{ + public class ClassWithMethodExtensions : PublicApiGeneratorTests.Examples.ClassWithMethodExtensions + { + public ClassWithMethodExtensions() { } + public new PublicApiGeneratorTests.Examples.ClassWithMethodExtensions Extend(string parameter) { } + } +}"); + } + [Fact] public void Should_output_protected_new_modifier() { @@ -517,6 +531,22 @@ protected AbstractClassRedeclaringAbstractMethod() } public new abstract void DoSomething(); } + + public class ClassWithMethodExtensions + { + public ClassWithMethodExtensions Extend(string parameter) + { + return this; + } + } + + public class ClassWithMethodExtensions : ClassWithMethodExtensions + { + public new ClassWithMethodExtensions Extend(string parameter) + { + return this; + } + } } // ReSharper restore ClassWithVirtualMembersNeverInherited.Global // ReSharper restore RedundantOverridenMember diff --git a/src/PublicApiGeneratorTests/Property_modifiers.cs b/src/PublicApiGeneratorTests/Property_modifiers.cs index a60a87d..80c1bb2 100644 --- a/src/PublicApiGeneratorTests/Property_modifiers.cs +++ b/src/PublicApiGeneratorTests/Property_modifiers.cs @@ -1,4 +1,4 @@ -using PublicApiGeneratorTests.Examples; +using PublicApiGeneratorTests.Examples; using Xunit; namespace PublicApiGeneratorTests @@ -215,6 +215,20 @@ public class ClassWithPropertyHiding : PublicApiGeneratorTests.Examples.ClassWit }"); } + [Fact] + public void Should_output_new_modifier_for_generics() + { + AssertPublicApi(typeof(ClassWithPropertyExtensions<>), + @"namespace PublicApiGeneratorTests.Examples +{ + public class ClassWithPropertyExtensions : PublicApiGeneratorTests.Examples.ClassWithPropertyExtensions + { + public ClassWithPropertyExtensions() { } + public new PublicApiGeneratorTests.Examples.ClassWithPropertyExtensions Extension { get; set; } + } +}"); + } + [Fact] public void Should_output_protected_new_modifier() { @@ -462,6 +476,16 @@ protected AbstractClassRedeclaringAbstractProperty() } public new abstract string Value { get; set; } } + + public class ClassWithPropertyExtensions + { + public ClassWithMethodExtensions Extension { get; set; } + } + + public class ClassWithPropertyExtensions : ClassWithPropertyExtensions + { + public new ClassWithPropertyExtensions Extension { get; set; } + } } // ReSharper restore ValueParameterNotUsed // ReSharper restore ClassNeverInstantiated.Global From 202cf95a3606909b3fcfc464b7b62605613b2f5b Mon Sep 17 00:00:00 2001 From: danielmarbach Date: Fri, 22 Nov 2019 12:53:04 +0100 Subject: [PATCH 2/2] Fix the bug --- src/PublicApiGenerator/CodeNormalizer.cs | 12 +++++------ .../ModifierMarkerNameBuilder.cs | 20 +++++++++---------- src/PublicApiGenerator/PropertyNameBuilder.cs | 2 +- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/PublicApiGenerator/CodeNormalizer.cs b/src/PublicApiGenerator/CodeNormalizer.cs index b2f7563..ede8690 100644 --- a/src/PublicApiGenerator/CodeNormalizer.cs +++ b/src/PublicApiGenerator/CodeNormalizer.cs @@ -60,8 +60,8 @@ public static string NormalizeGeneratedCode(StringWriter writer) RegexOptions.IgnorePatternWhitespace); // SingleLine is required for multi line params arrays gennedClass = Regex.Replace(gennedClass, @"(public|protected) (.*) _(.*)_292C96C3C42E4C07BEED73F5DAA0A6DF_(.*)", EventModifierMatcher); - gennedClass = Regex.Replace(gennedClass, @"(public|protected) (abstract|static|new static|virtual|override|new|unsafe) (.*) _(.*)_5DB9F56043FF464997155541DA321AD4_(.*)", PropertyModifierMatcher); - gennedClass = Regex.Replace(gennedClass, @"(public|protected) (abstract|static|new static|virtual|override|new|unsafe) (.*) _(.*)_3C0D97CD952D40AA8B6E1ECB98FFC79F_(.*)", MethodModifierMatcher); + gennedClass = Regex.Replace(gennedClass, @"(public|protected)( abstract | static | new static | virtual | override | new | unsafe | )(.*) _(.*)_5DB9F56043FF464997155541DA321AD4_(.*)", PropertyModifierMatcher); + gennedClass = Regex.Replace(gennedClass, @"(public|protected)( abstract | static | new static | virtual | override | new | unsafe | )(.*) _(.*)_3C0D97CD952D40AA8B6E1ECB98FFC79F_(.*)", MethodModifierMatcher); gennedClass = gennedClass.Replace("class " + StaticMarker, "static class "); gennedClass = gennedClass.Replace("struct " + ReadonlyMarker, "readonly struct "); gennedClass = gennedClass.Replace(ReadonlyMarker, string.Empty); // remove magic marker from readonly struct ctor @@ -97,8 +97,8 @@ static string PropertyModifierMatcher(Match match) var oldModifier = match.Groups[2].Value; var modifier = match.Groups[4].Value; - return match.ToString().Replace(string.Format(PropertyModifierMarkerTemplate, modifier), string.Empty) - .Replace(oldModifier, modifier); + var s = match.ToString().Replace(string.Format(PropertyModifierMarkerTemplate, modifier), string.Empty); + return string.IsNullOrWhiteSpace(oldModifier) ? s.Insert(s.IndexOf(oldModifier, StringComparison.Ordinal), modifier) : s.Replace(oldModifier, modifier); } static string MethodModifierMatcher(Match match) @@ -106,8 +106,8 @@ static string MethodModifierMatcher(Match match) var oldModifier = match.Groups[2].Value; var modifier = match.Groups[4].Value; - return match.ToString().Replace(string.Format(MethodModifierMarkerTemplate, modifier), string.Empty) - .Replace(oldModifier, modifier); + var s = match.ToString().Replace(string.Format(MethodModifierMarkerTemplate, modifier), string.Empty); + return string.IsNullOrWhiteSpace(oldModifier) ? s.Insert(s.IndexOf(oldModifier, StringComparison.Ordinal), modifier) : s.Replace(oldModifier, modifier); } static string RemoveUnnecessaryWhiteSpace(string publicApi) diff --git a/src/PublicApiGenerator/ModifierMarkerNameBuilder.cs b/src/PublicApiGenerator/ModifierMarkerNameBuilder.cs index 8727cd1..f3df8ec 100644 --- a/src/PublicApiGenerator/ModifierMarkerNameBuilder.cs +++ b/src/PublicApiGenerator/ModifierMarkerNameBuilder.cs @@ -11,17 +11,17 @@ public static string Build(MethodDefinition methodDefinition, MemberAttributes g return (getAccessorAttributes & MemberAttributes.ScopeMask, isNew, methodDefinition.IsVirtual, methodDefinition.IsAbstract) switch { - (MemberAttributes.Static, null, _, _) => Format(markerTemplate, "static") + name, - (MemberAttributes.Static, true, _, _) => Format(markerTemplate, "new static") + name, - (MemberAttributes.Override, _, _, _) => Format(markerTemplate, "override") + name, - (MemberAttributes.Final | MemberAttributes.Override, _, _, _) => Format(markerTemplate,"override sealed") + name, - (MemberAttributes.Final, true, _, _) => Format(markerTemplate, "new") + name, - (MemberAttributes.Abstract, null, _, _) => Format(markerTemplate, "abstract") + name, - (MemberAttributes.Abstract, true, _, _) => Format(markerTemplate, "new abstract") + name, - (MemberAttributes.Const, _, _, _) => Format(markerTemplate, "abstract override") + name, + (MemberAttributes.Static, null, _, _) => Format(markerTemplate, " static ") + name, + (MemberAttributes.Static, true, _, _) => Format(markerTemplate, " new static ") + name, + (MemberAttributes.Override, _, _, _) => Format(markerTemplate, " override ") + name, + (MemberAttributes.Final | MemberAttributes.Override, _, _, _) => Format(markerTemplate," override sealed ") + name, + (MemberAttributes.Final, true, _, _) => Format(markerTemplate, " new ") + name, + (MemberAttributes.Abstract, null, _, _) => Format(markerTemplate, " abstract ") + name, + (MemberAttributes.Abstract, true, _, _) => Format(markerTemplate, " new abstract ") + name, + (MemberAttributes.Const, _, _, _) => Format(markerTemplate, " abstract override ") + name, (MemberAttributes.Final, null, true, false) => name, - (_, null, true, false) => Format(markerTemplate, "virtual") + name, - (_, true, true, false) => Format(markerTemplate, "new virtual") + name, + (_, null, true, false) => Format(markerTemplate, " virtual ") + name, + (_, true, true, false) => Format(markerTemplate, " new virtual ") + name, _ => name }; } diff --git a/src/PublicApiGenerator/PropertyNameBuilder.cs b/src/PublicApiGenerator/PropertyNameBuilder.cs index 4032016..fc9a469 100644 --- a/src/PublicApiGenerator/PropertyNameBuilder.cs +++ b/src/PublicApiGenerator/PropertyNameBuilder.cs @@ -16,7 +16,7 @@ public static class PropertyNameBuilder } var isNew = propertyDefinition.IsNew(typeDef => typeDef?.Properties, e => - e.Name.Equals(propertyDefinition.Name, StringComparison.Ordinal) && e.PropertyType.Equals(propertyDefinition.PropertyType)); + e.Name.Equals(propertyDefinition.Name, StringComparison.Ordinal)); return ModifierMarkerNameBuilder.Build(propertyDefinition.GetMethod, getAccessorAttributes, isNew, name, CodeNormalizer.PropertyModifierMarkerTemplate);