Skip to content

Commit d57b08c

Browse files
Fix #3010: Remove compiler-generated attributes for required members with custom ctors.
1 parent b9c9e05 commit d57b08c

File tree

3 files changed

+50
-19
lines changed

3 files changed

+50
-19
lines changed

ICSharpCode.Decompiler.Tests/TestCases/Pretty/AutoProperties.cs

+17
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
44
{
55
internal class AutoProperties
66
{
7+
#if CS110
8+
public required int RequiredField;
9+
#endif
710
public int A { get; } = 1;
811

912
public int B { get; set; } = 2;
@@ -22,9 +25,23 @@ internal class AutoProperties
2225

2326
public int issue1319 { get; }
2427

28+
#if CS110
29+
public required int RequiredProperty { get; set; }
30+
#endif
31+
2532
public AutoProperties(int issue1319)
2633
{
2734
this.issue1319 = issue1319;
35+
#if CS110
36+
RequiredProperty = 42;
37+
RequiredField = 42;
38+
#endif
2839
}
2940
}
41+
#if !NET70
42+
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
43+
internal sealed class RequiredMemberAttribute : Attribute
44+
{
45+
}
46+
#endif
3047
}

ICSharpCode.Decompiler.Tests/TestCases/Pretty/Records.cs

+4-1
Original file line numberDiff line numberDiff line change
@@ -256,10 +256,13 @@ public CompilerFeatureRequiredAttribute(string featureName)
256256
internal class IsExternalInit
257257
{
258258
}
259-
259+
#endif
260+
#if !NET70
260261
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
261262
internal sealed class RequiredMemberAttribute : Attribute
262263
{
263264
}
265+
#endif
266+
#if !NET60
264267
}
265268
#endif

ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

+29-18
Original file line numberDiff line numberDiff line change
@@ -1397,16 +1397,7 @@ EntityDeclaration DoDecompile(ITypeDefinition typeDef, DecompileRun decompileRun
13971397
}
13981398
if (settings.IntroduceRefModifiersOnStructs)
13991399
{
1400-
if (FindAttribute(typeDecl, KnownAttribute.Obsolete, out var attr))
1401-
{
1402-
if (obsoleteAttributePattern.IsMatch(attr))
1403-
{
1404-
if (attr.Parent is AttributeSection section && section.Attributes.Count == 1)
1405-
section.Remove();
1406-
else
1407-
attr.Remove();
1408-
}
1409-
}
1400+
RemoveObsoleteAttribute(typeDecl, "Types with embedded references are not supported in this version of your compiler.");
14101401
RemoveCompilerFeatureRequiredAttribute(typeDecl, "RefStructs");
14111402
}
14121403
if (settings.RequiredMembers)
@@ -1584,14 +1575,6 @@ EnumValueDisplayMode DetectBestEnumValueDisplayMode(ITypeDefinition typeDef, PEF
15841575
return firstValue == 0 ? EnumValueDisplayMode.None : EnumValueDisplayMode.FirstOnly;
15851576
}
15861577

1587-
static readonly Syntax.Attribute obsoleteAttributePattern = new Syntax.Attribute() {
1588-
Type = new TypePattern(typeof(ObsoleteAttribute)),
1589-
Arguments = {
1590-
new PrimitiveExpression("Types with embedded references are not supported in this version of your compiler."),
1591-
new Choice() { new PrimitiveExpression(true), new PrimitiveExpression(false) }
1592-
}
1593-
};
1594-
15951578
EntityDeclaration DoDecompile(IMethod method, DecompileRun decompileRun, ITypeResolveContext decompilationContext)
15961579
{
15971580
Debug.Assert(decompilationContext.CurrentMember == method);
@@ -1645,6 +1628,10 @@ EntityDeclaration DoDecompile(IMethod method, DecompileRun decompileRun, ITypeRe
16451628
methodDecl.Modifiers &= ~(Modifiers.New | Modifiers.Virtual);
16461629
methodDecl.Modifiers |= Modifiers.Override;
16471630
}
1631+
if (method.IsConstructor && settings.RequiredMembers && RemoveCompilerFeatureRequiredAttribute(methodDecl, "RequiredMembers"))
1632+
{
1633+
RemoveObsoleteAttribute(methodDecl, "Constructors of types with required members are not supported in this version of your compiler.");
1634+
}
16481635
return methodDecl;
16491636

16501637
bool IsTypeHierarchyKnown(IType type)
@@ -1877,6 +1864,30 @@ internal static bool RemoveCompilerFeatureRequiredAttribute(EntityDeclaration en
18771864
return found;
18781865
}
18791866

1867+
internal static bool RemoveObsoleteAttribute(EntityDeclaration entityDecl, string message)
1868+
{
1869+
bool found = false;
1870+
foreach (var section in entityDecl.Attributes)
1871+
{
1872+
foreach (var attr in section.Attributes)
1873+
{
1874+
var symbol = attr.Type.GetSymbol();
1875+
if (symbol is ITypeDefinition td && td.FullTypeName == KnownAttribute.Obsolete.GetTypeName()
1876+
&& attr.Arguments.Count >= 1 && attr.Arguments.First() is PrimitiveExpression pe
1877+
&& pe.Value is string s && s == message)
1878+
{
1879+
attr.Remove();
1880+
found = true;
1881+
}
1882+
}
1883+
if (section.Attributes.Count == 0)
1884+
{
1885+
section.Remove();
1886+
}
1887+
}
1888+
return found;
1889+
}
1890+
18801891
bool FindAttribute(EntityDeclaration entityDecl, KnownAttribute attributeType, out Syntax.Attribute attribute)
18811892
{
18821893
attribute = null;

0 commit comments

Comments
 (0)