Browse Source

WIP

natural-type-lambdas-methods
Siegfried Pammer 1 year ago
parent
commit
d9fdb9cb07
  1. 2
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  2. 4
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  3. 8
      ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs
  4. 21
      ICSharpCode.Decompiler/DecompilerSettings.cs
  5. 2
      ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs
  6. 4
      ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs
  7. 34
      ICSharpCode.Decompiler/NRExtensions.cs
  8. 12
      ICSharpCode.Decompiler/SRMExtensions.cs
  9. 9
      ILSpy/Properties/Resources.Designer.cs
  10. 3
      ILSpy/Properties/Resources.resx

2
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -327,6 +327,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -327,6 +327,8 @@ namespace ICSharpCode.Decompiler.CSharp
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;

4
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -2409,10 +2409,10 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2409,10 +2409,10 @@ namespace ICSharpCode.Decompiler.CSharp
// 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 =

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

@ -590,6 +590,10 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -590,6 +590,10 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
{
type = new SimpleType("var");
}
else if (context.Settings.NaturalTypeForLambdaAndMethodGroup && v.Type.ContainsAnonymousDelegate())
{
type = new SimpleType("var");
}
else
{
type = context.TypeSystemAstBuilder.ConvertType(v.Type);
@ -622,6 +626,10 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -622,6 +626,10 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
{
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");

21
ICSharpCode.Decompiler/DecompilerSettings.cs

@ -149,6 +149,7 @@ namespace ICSharpCode.Decompiler @@ -149,6 +149,7 @@ namespace ICSharpCode.Decompiler
{
fileScopedNamespaces = false;
recordStructs = false;
naturalTypeForLambdaAndMethodGroup = false;
}
if (languageVersion < CSharp.LanguageVersion.CSharp11_0)
{
@ -166,7 +167,7 @@ namespace ICSharpCode.Decompiler @@ -166,7 +167,7 @@ namespace ICSharpCode.Decompiler
{
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
@ -443,6 +444,24 @@ namespace ICSharpCode.Decompiler @@ -443,6 +444,24 @@ namespace ICSharpCode.Decompiler
}
}
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>

2
ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs

@ -594,7 +594,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -594,7 +594,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{
return name;
}
if (type.IsAnonymousType())
if (type.IsAnonymousType() || type.IsAnonymousDelegate())
{
name = "anon";
}

4
ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs

@ -127,11 +127,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -127,11 +127,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms
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;

34
ICSharpCode.Decompiler/NRExtensions.cs

@ -16,7 +16,6 @@ @@ -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;
@ -66,6 +65,20 @@ namespace ICSharpCode.Decompiler @@ -66,6 +65,20 @@ namespace ICSharpCode.Decompiler
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();
@ -73,14 +86,31 @@ namespace ICSharpCode.Decompiler @@ -73,14 +86,31 @@ namespace ICSharpCode.Decompiler
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);
}
@ -88,6 +118,8 @@ namespace ICSharpCode.Decompiler @@ -88,6 +118,8 @@ namespace ICSharpCode.Decompiler
{
if (IsAnonymousType(type))
ContainsAnonType = true;
if (IsAnonymousDelegate(type))
ContainsAnonDelegate = true;
return base.VisitTypeDefinition(type);
}
}

12
ICSharpCode.Decompiler/SRMExtensions.cs

@ -464,6 +464,18 @@ namespace ICSharpCode.Decompiler @@ -464,6 +464,18 @@ namespace ICSharpCode.Decompiler
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)

9
ILSpy/Properties/Resources.Designer.cs generated

@ -1109,6 +1109,15 @@ namespace ICSharpCode.ILSpy.Properties { @@ -1109,6 +1109,15 @@ namespace ICSharpCode.ILSpy.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to Use natural delegate types for lambdas and method groups.
/// </summary>
public static string DecompilerSettings_NaturalTypeForLambdaAndMethodGroup {
get {
return ResourceManager.GetString("DecompilerSettings.NaturalTypeForLambdaAndMethodGroup", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Nullable reference types.
/// </summary>

3
ILSpy/Properties/Resources.resx

@ -393,6 +393,9 @@ Are you sure you want to continue?</value> @@ -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>

Loading…
Cancel
Save