Browse Source

`IsBaseCtorCall` no longer checks the number of parameters. Otherwise, it would cause the translation of the `DeserializationException` type in `https://github.com/restsharp/RestSharp/blob/dev/src/RestSharp/Serializers/DeseralizationException.cs` to fail, as it is a primary constructor declaration that calls a base constructor with two arguments.

Additionally, dotPeek's `IsPrimaryConstructorFast` function has been introduced. This is because, after the aforementioned modification to `IsBaseCtorCall`, the `NamedParameter` type in RestSharp was being incorrectly identified as a primary constructor. Without this correction, it would lead to many compilation errors.
pull/3598/head
sonyps5201314 2 months ago
parent
commit
828fb52390
  1. 57
      ICSharpCode.Decompiler/CSharp/RecordDecompiler.cs

57
ICSharpCode.Decompiler/CSharp/RecordDecompiler.cs

@ -20,6 +20,7 @@ using System; @@ -20,6 +20,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using System.Threading;
@ -159,6 +160,50 @@ namespace ICSharpCode.Decompiler.CSharp @@ -159,6 +160,50 @@ namespace ICSharpCode.Decompiler.CSharp
}
}
public static bool IsPrimaryConstructorFast(IMethod constructor, bool isStruct, bool recordPrimaryConstructor)
{
if (constructor.Parameters.Count == 0 && (isStruct || !recordPrimaryConstructor))
{
return false;
}
//下面注释的这一段就暂时不翻译了,因为目前在ILSpy中无法进行翻译,
//因为在ILSpy中RecordDecompiler.DetectPrimaryConstructor会先于TransformFieldAndConstructorInitializers执行,
//而在dotPeek中是先执行ExtractInstanceCtorInitializerTransformation再执行DetectPrimaryConstructorTransformation的
/*
IConstructorInitializer constructorInitializer = constructor.ConstructorInitializer;
if (constructorInitializer != null && constructorInitializer.Target is IThisReferenceExpression)
{
return false;
}
*/
if (!constructor.IsAbstract && constructor.DeclaringType.Kind != TypeKind.Interface && !constructor.HasBody)//IsExtern
{
return false;
}
if (constructor.DeclaringType.GetDefinition()?.IsAbstract ?? false)
{
var module = constructor.ParentModule as MetadataModule;
var handle = (MethodDefinitionHandle)constructor.MetadataToken;
var metadata = module.metadata;
var def = metadata.GetMethodDefinition(handle);
var attributes = def.Attributes;
if (!attributes.HasFlag(MethodAttributes.Family))//IsFamily
{
return false;
}
}
else if (!(constructor.Accessibility == Accessibility.Public))//IsPublic
{
return false;
}
if (constructor is VarArgInstanceMethod)
{
return false;
}
return true;
}
IMethod DetectPrimaryConstructor()
{
if (recordTypeDef.IsRecord)
@ -190,11 +235,12 @@ namespace ICSharpCode.Decompiler.CSharp @@ -190,11 +235,12 @@ namespace ICSharpCode.Decompiler.CSharp
return null;
//判定主构造函数的唯一准则是:
//首先它不能是拷贝构造函数,
//首先它不能是拷贝构造函数,且能通过IsPrimaryConstructorFast的判定逻辑,
//然后这个构造函数中前面部分都是类成员属性/字段赋值语句,
//之后是调用基类构造函数的语句即"base..ctor(...);",
//再之后就是返回语句了,即"base..ctor(...);"之后不存在任何其他初始化语句。
//且主构造函数的参数和类成员之间无任何对应关系!
//注意:不存在捕获参数的情况下,主构造函数的参数和类成员之间无任何对应关系!
//注意:目前即使一个函数的原始代码形式是常规构造函数,但是如果它符合本IsPrimaryConstructor函数的判定规则也会将它翻译成主构造函数形式
bool IsPrimaryConstructor(IMethod method, IMethod unspecializedMethod)
{
Debug.Assert(method.IsConstructor);
@ -202,6 +248,9 @@ namespace ICSharpCode.Decompiler.CSharp @@ -202,6 +248,9 @@ namespace ICSharpCode.Decompiler.CSharp
if (IsCopyConstructor(method))
return false;
if (!IsPrimaryConstructorFast(method, isStruct, false))
return false;
var body = DecompileBody(method);
if (body == null)
return false;
@ -435,7 +484,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -435,7 +484,7 @@ namespace ICSharpCode.Decompiler.CSharp
return false;
if (!object.Equals(baseCtorCall.Method.DeclaringType, baseClass))
return false;
if (baseCtorCall.Arguments.Count != (isInheritedRecord ? 2 : 1))
if (baseCtorCall.Arguments.Count <= 0)
return false;
if (!baseCtorCall.Arguments[0].MatchLdThis())
return false;
@ -471,6 +520,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -471,6 +520,8 @@ namespace ICSharpCode.Decompiler.CSharp
{
return false;
}
if (baseCtorCall.Arguments.Count != (isInheritedRecord ? 2 : 1))
return false;
if (isInheritedRecord)
{
if (!baseCtorCall.Arguments[1].MatchLdLoc(other))

Loading…
Cancel
Save