Browse Source

Parenthesize lambda parameter lists when attributes are present

The C# 10 grammar only allows attributes on a lambda or its parameters
when the parameter list is parenthesized, but LambdaNeedsParenthesis
predates attribute support and only considered the single parameter's
type and modifiers. An attributed lambda whose parameter type is erased
for being anonymous therefore printed as '[My] a => a.X', which does not
parse. Latent since attributed-lambda decompilation was added: every
other attributed lambda has explicitly typed parameters, which already
force the parenthesized form.

Assisted-by: Claude:claude-fable-5:Claude Code
fix/lambda-parameter-syntax
Siegfried Pammer 3 weeks ago
parent
commit
089963c4eb
  1. 9
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs
  2. 10
      ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs

9
ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs

@ -599,6 +599,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.DelegateConstruction @@ -599,6 +599,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.DelegateConstruction
Console.WriteLine(x);
};
}
public static int LambdaWithAttributeOnAnonymousTypeParameter()
{
return new[] {
new {
X = 1
}
}.Select([My] (a) => a.X).Sum();
}
#endif
public static void CallRecursiveDelegate(ref RefRecursiveDelegate d)

10
ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs

@ -1061,11 +1061,21 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -1061,11 +1061,21 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
protected bool LambdaNeedsParenthesis(LambdaExpression lambdaExpression)
{
if (lambdaExpression.Attributes.Count > 0)
{
// attributes on the lambda require a parenthesized parameter list
return true;
}
if (lambdaExpression.Parameters.Count != 1)
{
return true;
}
var p = lambdaExpression.Parameters.Single();
if (p.Attributes.Count > 0)
{
// parameter attributes have no unparenthesized form
return true;
}
return !(p.Type is null && p.ParameterModifier == ReferenceKind.None && !p.IsParams);
}

Loading…
Cancel
Save