Browse Source

Fix #2475: Fix support for records with custom copy ctor

pull/2476/head
SilverFox 4 years ago
parent
commit
89eebc387a
  1. 7
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Records.cs
  2. 22
      ICSharpCode.Decompiler/CSharp/RecordDecompiler.cs
  3. 8
      ICSharpCode.Decompiler/CSharp/Transforms/TransformFieldAndConstructorInitializers.cs

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

@ -2,6 +2,13 @@
{ {
public record Base(string A); public record Base(string A);
public record CopyCtor(string A)
{
protected CopyCtor(CopyCtor _)
{
}
}
public record Derived(int B) : Base(B.ToString()); public record Derived(int B) : Base(B.ToString());
public record Empty; public record Empty;

22
ICSharpCode.Decompiler/CSharp/RecordDecompiler.cs

@ -170,6 +170,8 @@ namespace ICSharpCode.Decompiler.CSharp
var m = method.Specialize(subst); var m = method.Specialize(subst);
if (IsPrimaryConstructor(m)) if (IsPrimaryConstructor(m))
return method; return method;
primaryCtorParameterToAutoProperty.Clear();
autoPropertyToPrimaryCtorParameter.Clear();
} }
return null; return null;
@ -254,13 +256,9 @@ namespace ICSharpCode.Decompiler.CSharp
/// </summary> /// </summary>
public bool MethodIsGenerated(IMethod method) public bool MethodIsGenerated(IMethod method)
{ {
if (method.IsConstructor) if (IsCopyConstructor(method))
{ {
if (method.Parameters.Count == 1 return IsGeneratedCopyConstructor(method);
&& IsRecordType(method.Parameters[0].Type))
{
return IsGeneratedCopyConstructor(method);
}
} }
switch (method.Name) switch (method.Name)
@ -333,6 +331,18 @@ namespace ICSharpCode.Decompiler.CSharp
&& autoPropertyToPrimaryCtorParameter.ContainsKey((IProperty)property.Specialize(subst)); && autoPropertyToPrimaryCtorParameter.ContainsKey((IProperty)property.Specialize(subst));
} }
public bool IsCopyConstructor(IMethod method)
{
if (method == null)
return false;
Debug.Assert(method.DeclaringTypeDefinition == recordTypeDef);
return method.IsConstructor
&& method.Parameters.Count == 1
&& IsRecordType(method.Parameters[0].Type);
}
private bool IsGeneratedCopyConstructor(IMethod method) private bool IsGeneratedCopyConstructor(IMethod method)
{ {
/* /*

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

@ -177,6 +177,10 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
if (!context.DecompileRun.RecordDecompilers.TryGetValue(ctorMethodDef.DeclaringTypeDefinition, out var record)) if (!context.DecompileRun.RecordDecompilers.TryGetValue(ctorMethodDef.DeclaringTypeDefinition, out var record))
record = null; record = null;
//Filter out copy constructor of records
if (record != null)
instanceCtorsNotChainingWithThis = instanceCtorsNotChainingWithThis.Where(ctor => !record.IsCopyConstructor(ctor.GetSymbol() as IMethod)).ToArray();
// Recognize field or property initializers: // Recognize field or property initializers:
// Translate first statement in all ctors (if all ctors have the same statement) into an initializer. // Translate first statement in all ctors (if all ctors have the same statement) into an initializer.
bool allSame; bool allSame;
@ -202,9 +206,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
if (initializer.Annotation<ILVariableResolveResult>()?.Variable.Kind == IL.VariableKind.Parameter) if (initializer.Annotation<ILVariableResolveResult>()?.Variable.Kind == IL.VariableKind.Parameter)
{ {
// remove record ctor parameter assignments // remove record ctor parameter assignments
if (IsPropertyDeclaredByPrimaryCtor(fieldOrPropertyOrEvent as IProperty, record)) if (!IsPropertyDeclaredByPrimaryCtor(fieldOrPropertyOrEvent as IProperty, record))
initializer.Remove();
else
break; break;
} }
else else

Loading…
Cancel
Save