Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
siegfriedpammer committed Mar 16, 2024
1 parent f038055 commit d9fdb9c
Show file tree
Hide file tree
Showing 10 changed files with 92 additions and 7 deletions.
2 changes: 2 additions & 0 deletions ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,8 @@ public static bool MemberIsHidden(Metadata.PEFile module, EntityHandle member, D
return true;
if (settings.Dynamic && type.IsDelegate(metadata) && (name.StartsWith("<>A", StringComparison.Ordinal) || name.StartsWith("<>F", StringComparison.Ordinal)))
return true;
if (settings.AnonymousMethods && type.IsAnonymousDelegate(metadata))
return true;
}
if (settings.ArrayInitializers && settings.SwitchStatementOnString && name.StartsWith("<PrivateImplementationDetails>", StringComparison.Ordinal))
return true;
Expand Down
4 changes: 2 additions & 2 deletions ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2409,10 +2409,10 @@ internal ExpressionWithResolveResult TranslateFunction(IType delegateType, ILFun
// C# 10 lambdas can have attributes, but anonymous methods cannot
isLambda = true;
}
else if (settings.UseLambdaSyntax && ame.Parameters.All(p => p.ParameterModifier == ParameterModifier.None))
else if (settings.UseLambdaSyntax)
{
// otherwise use lambda only if an expression lambda is possible
isLambda = (body.Statements.Count == 1 && body.Statements.Single() is ReturnStatement);
isLambda = body.Statements.Count == 1 && body.Statements.Single() is ReturnStatement;
}
// Remove the parameter list from an AnonymousMethodExpression if the parameters are not used in the method body
var parameterReferencingIdentifiers =
Expand Down
8 changes: 8 additions & 0 deletions ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,10 @@ void InsertVariableDeclarations(TransformContext context)
{
type = new SimpleType("var");
}
else if (context.Settings.NaturalTypeForLambdaAndMethodGroup && v.Type.ContainsAnonymousDelegate())
{
type = new SimpleType("var");
}
else
{
type = context.TypeSystemAstBuilder.ConvertType(v.Type);
Expand Down Expand Up @@ -622,6 +626,10 @@ void InsertVariableDeclarations(TransformContext context)
{
type = new SimpleType("var");
}
else if (context.Settings.NaturalTypeForLambdaAndMethodGroup && v.Type.ContainsAnonymousDelegate())
{
type = new SimpleType("var");
}
else if (dirExpr.Annotation<UseImplicitlyTypedOutAnnotation>() != null)
{
type = new SimpleType("var");
Expand Down
21 changes: 20 additions & 1 deletion ICSharpCode.Decompiler/DecompilerSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ public void SetLanguageVersion(CSharp.LanguageVersion languageVersion)
{
fileScopedNamespaces = false;
recordStructs = false;
naturalTypeForLambdaAndMethodGroup = false;
}
if (languageVersion < CSharp.LanguageVersion.CSharp11_0)
{
Expand All @@ -166,7 +167,7 @@ public CSharp.LanguageVersion GetMinimumRequiredVersion()
{
if (parameterNullCheck || scopedRef || requiredMembers || numericIntPtr || utf8StringLiterals || unsignedRightShift || checkedOperators)
return CSharp.LanguageVersion.CSharp11_0;
if (fileScopedNamespaces || recordStructs)
if (fileScopedNamespaces || recordStructs || naturalTypeForLambdaAndMethodGroup)
return CSharp.LanguageVersion.CSharp10_0;
if (nativeIntegers || initAccessors || functionPointers || forEachWithGetEnumeratorExtension
|| recordClasses || withExpressions || usePrimaryConstructorSyntax || covariantReturns
Expand Down Expand Up @@ -443,6 +444,24 @@ public bool FileScopedNamespaces {
}
}

bool naturalTypeForLambdaAndMethodGroup = true;

/// <summary>
/// Use C# 10 natural types for delegates and lambdas.
/// </summary>
[Category("C# 10.0 / VS 2022")]
[Description("DecompilerSettings.NaturalTypeForLambdaAndMethodGroup")]
public bool NaturalTypeForLambdaAndMethodGroup {
get { return naturalTypeForLambdaAndMethodGroup; }
set {
if (naturalTypeForLambdaAndMethodGroup != value)
{
naturalTypeForLambdaAndMethodGroup = value;
OnPropertyChanged();
}
}
}

bool parameterNullCheck = false;

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -594,7 +594,7 @@ static string GetNameByType(IType type)
{
return name;
}
if (type.IsAnonymousType())
if (type.IsAnonymousType() || type.IsAnonymousDelegate())
{
name = "anon";
}
Expand Down
4 changes: 2 additions & 2 deletions ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,11 +127,11 @@ static bool IsAnonymousMethod(ITypeDefinition decompiledTypeDefinition, IMethod

static bool ContainsAnonymousType(IMethod method)
{
if (method.ReturnType.ContainsAnonymousType())
if (method.ReturnType.ContainsAnonymousTypeOrDelegate())
return true;
foreach (var p in method.Parameters)
{
if (p.Type.ContainsAnonymousType())
if (p.Type.ContainsAnonymousTypeOrDelegate())
return true;
}
return false;
Expand Down
34 changes: 33 additions & 1 deletion ICSharpCode.Decompiler/NRExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;

using ICSharpCode.Decompiler.Documentation;
using ICSharpCode.Decompiler.TypeSystem;
Expand Down Expand Up @@ -66,28 +65,61 @@ public static bool IsAnonymousType(this IType type)
return false;
}

public static bool IsAnonymousDelegate(this IType type)
{
if (type == null)
return false;
if (string.IsNullOrEmpty(type.Namespace) && type.HasGeneratedName()
&& type.Kind == TypeKind.Delegate
&& (type.Name.Contains("AnonymousDelegate") || type.Name.StartsWith("<>F{")))
{
ITypeDefinition td = type.GetDefinition();
return td != null && td.IsCompilerGenerated();
}
return false;
}

public static bool ContainsAnonymousType(this IType type)
{
var visitor = new ContainsAnonTypeVisitor();
type.AcceptVisitor(visitor);
return visitor.ContainsAnonType;
}

public static bool ContainsAnonymousDelegate(this IType type)
{
var visitor = new ContainsAnonTypeVisitor();
type.AcceptVisitor(visitor);
return visitor.ContainsAnonDelegate;
}

public static bool ContainsAnonymousTypeOrDelegate(this IType type)
{
var visitor = new ContainsAnonTypeVisitor();
type.AcceptVisitor(visitor);
return visitor.ContainsAnonType || visitor.ContainsAnonDelegate;
}

class ContainsAnonTypeVisitor : TypeVisitor
{
public bool ContainsAnonType;
public bool ContainsAnonDelegate;

public override IType VisitOtherType(IType type)
{
if (IsAnonymousType(type))
ContainsAnonType = true;
if (IsAnonymousDelegate(type))
ContainsAnonDelegate = true;
return base.VisitOtherType(type);
}

public override IType VisitTypeDefinition(ITypeDefinition type)
{
if (IsAnonymousType(type))
ContainsAnonType = true;
if (IsAnonymousDelegate(type))
ContainsAnonDelegate = true;
return base.VisitTypeDefinition(type);
}
}
Expand Down
12 changes: 12 additions & 0 deletions ICSharpCode.Decompiler/SRMExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,18 @@ public static bool IsAnonymousType(this TypeDefinition type, MetadataReader meta
return false;
}

public static bool IsAnonymousDelegate(this TypeDefinition type, MetadataReader metadata)
{
string name = metadata.GetString(type.Name);
if (type.Namespace.IsNil && type.HasGeneratedName(metadata)
&& type.IsDelegate(metadata)
&& (name.Contains("AnonymousDelegate") || name.StartsWith("<>F{")))
{
return type.IsCompilerGenerated(metadata);
}
return false;
}

#region HasGeneratedName

public static bool IsGeneratedName(this StringHandle handle, MetadataReader metadata)
Expand Down
9 changes: 9 additions & 0 deletions ILSpy/Properties/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions ILSpy/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,9 @@ Are you sure you want to continue?</value>
<data name="DecompilerSettings.NativeIntegers" xml:space="preserve">
<value>Use nint/nuint types</value>
</data>
<data name="DecompilerSettings.NaturalTypeForLambdaAndMethodGroup" xml:space="preserve">
<value>Use natural delegate types for lambdas and method groups</value>
</data>
<data name="DecompilerSettings.NullPropagation" xml:space="preserve">
<value>Decompile ?. and ?[] operators</value>
</data>
Expand Down

0 comments on commit d9fdb9c

Please sign in to comment.