Browse Source

Support for `struct` types written in non-primary constructor form that contain field initialization statements has been added. This type was previously mentioned in the commit with the message "The logic was temporarily adjusted so that the `StructWithDefaultCtor` type in the unit test could pass the test. In fact, the member initialization statement in its constructor could be moved."

Here's an example:
```cs
    public struct StructWithDefaultCtor2
    {
        public int X = 42;
        public int Y = Math.Max(1, 2);
        public event EventHandler MyEvent = delegate { };
        public int Z { get; set; } = Math.Max(3, 5);

        public StructWithDefaultCtor2()
        {

        }
    }

    public struct StructWithDefaultCtor3
    {
        public int X = 42;
        public int Y = Math.Max(1, 2);
        public event EventHandler MyEvent;
        public int Z { get; set; }

        public StructWithDefaultCtor3()
        {
            MyEvent = delegate { };
            Z = Math.Max(3, 5);
        }
    }
```
pull/3598/head
sonyps5201314 2 months ago
parent
commit
793d4171f2
  1. 45
      ICSharpCode.Decompiler/CSharp/Transforms/TransformFieldAndConstructorInitializers.cs

45
ICSharpCode.Decompiler/CSharp/Transforms/TransformFieldAndConstructorInitializers.cs

@ -188,6 +188,11 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -188,6 +188,11 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
HandleStaticFieldInitializers(typeDeclaration.Members);
}
class IsMustRetainedSingleEmptyConstructor
{
}
void HandleInstanceFieldInitializers(IEnumerable<AstNode> members)
{
var instanceCtors = members.OfType<ConstructorDeclaration>().Where(c => (c.Modifiers & Modifiers.Static) == 0).ToArray();
@ -215,12 +220,18 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -215,12 +220,18 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
bool hasPrimaryCtor = record?.PrimaryConstructor != null;
do
{
Match m = fieldInitializerPattern.Match(instanceCtorsNotChainingWithThis[0].Body.FirstOrDefault());
var bodyFirstOrDefault = instanceCtorsNotChainingWithThis[0].Body.FirstOrDefault();
Match m = fieldInitializerPattern.Match(bodyFirstOrDefault);
if (!m.Success)
break;
IMember fieldOrPropertyOrEvent = (m.Get<AstNode>("fieldAccess").Single().GetSymbol() as IMember)?.MemberDefinition;
if (!(fieldOrPropertyOrEvent is IField) && !(fieldOrPropertyOrEvent is IProperty) && !(fieldOrPropertyOrEvent is IEvent))
IProperty property = fieldOrPropertyOrEvent as IProperty;
if (!(fieldOrPropertyOrEvent is IField) && property == null && !(fieldOrPropertyOrEvent is IEvent))
break;
if (isStruct && property != null && bodyFirstOrDefault.Annotations.FirstOrDefault() is not IL.StObj)
{
break;
}
var fieldOrPropertyOrEventDecl = members.FirstOrDefault(f => f.GetSymbol() == fieldOrPropertyOrEvent) as EntityDeclaration;
// Cannot transform if it is a custom event.
if (fieldOrPropertyOrEventDecl is CustomEventDeclaration)
@ -270,9 +281,6 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -270,9 +281,6 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
// cannot transform if member is not found
if (fieldOrPropertyOrEventDecl == null)
break;
// or if this is a struct, but not the primary ctor
if (isStruct && !hasPrimaryCtor)
break;
}
allSame = true;
@ -293,7 +301,16 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -293,7 +301,16 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
if (allSame)
{
foreach (var ctor in instanceCtorsNotChainingWithThis)
{
ctor.Body.First().Remove();
if (isStruct && !hasPrimaryCtor)
{
if (!ctor.Body.HasChildren)
{
ctor.AddAnnotation(new IsMustRetainedSingleEmptyConstructor());
}
}
}
if (fieldOrPropertyOrEventDecl == null)
continue;
if (ctorIsUnsafe && IntroduceUnsafeModifier.IsUnsafe(initializer))
@ -334,11 +351,19 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -334,11 +351,19 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
if (emptyCtorPattern.IsMatch(ctor))
{
bool retainBecauseOfDocumentation = ctor.GetSymbol() is IMethod ctorMethod
&& context.Settings.ShowXmlDocumentation
&& context.DecompileRun.DocumentationProvider?.GetDocumentation(ctorMethod) != null;
if (!retainBecauseOfDocumentation)
ctor.Remove();
var isMustRetainedSingleEmptyConstructor = ctor.Annotation<IsMustRetainedSingleEmptyConstructor>();
if (isMustRetainedSingleEmptyConstructor != null)
{
ctor.RemoveAnnotations<IsMustRetainedSingleEmptyConstructor>();
}
else
{
bool retainBecauseOfDocumentation = ctor.GetSymbol() is IMethod ctorMethod
&& context.Settings.ShowXmlDocumentation
&& context.DecompileRun.DocumentationProvider?.GetDocumentation(ctorMethod) != null;
if (!retainBecauseOfDocumentation)
ctor.Remove();
}
}
}
}

Loading…
Cancel
Save