Skip to content

Commit 0481c7d

Browse files
Improve LINQ decompiler to support combining lambda parameter names if they syntactically refer to the same range variable
1 parent 03aecf0 commit 0481c7d

File tree

2 files changed

+31
-22
lines changed

2 files changed

+31
-22
lines changed

ICSharpCode.Decompiler/CSharp/Transforms/CombineQueryExpressions.cs

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@
1616
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
1717
// DEALINGS IN THE SOFTWARE.
1818

19-
using System;
2019
using System.Collections.Generic;
2120
using System.Linq;
2221

2322
using ICSharpCode.Decompiler.CSharp.Syntax;
2423
using ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching;
24+
using ICSharpCode.Decompiler.Util;
2525

2626
namespace ICSharpCode.Decompiler.CSharp.Transforms
2727
{
@@ -54,12 +54,10 @@ void CombineQueries(AstNode node, Dictionary<string, object> fromOrLetIdentifier
5454
next = child.NextSibling;
5555
CombineQueries(child, fromOrLetIdentifiers);
5656
}
57-
QueryExpression query = node as QueryExpression;
58-
if (query != null)
57+
if (node is QueryExpression query)
5958
{
6059
QueryFromClause fromClause = (QueryFromClause)query.Clauses.First();
61-
QueryExpression innerQuery = fromClause.Expression as QueryExpression;
62-
if (innerQuery != null)
60+
if (fromClause.Expression is QueryExpression innerQuery)
6361
{
6462
if (TryRemoveTransparentIdentifier(query, fromClause, innerQuery, fromOrLetIdentifiers))
6563
{
@@ -165,21 +163,17 @@ void RemoveTransparentIdentifierReferences(AstNode node, Dictionary<string, obje
165163
{
166164
RemoveTransparentIdentifierReferences(child, fromOrLetIdentifiers);
167165
}
168-
MemberReferenceExpression mre = node as MemberReferenceExpression;
169-
if (mre != null)
166+
if (node is MemberReferenceExpression mre && mre.Target is IdentifierExpression ident
167+
&& CSharpDecompiler.IsTransparentIdentifier(ident.Identifier))
170168
{
171-
IdentifierExpression ident = mre.Target as IdentifierExpression;
172-
if (ident != null && CSharpDecompiler.IsTransparentIdentifier(ident.Identifier))
173-
{
174-
IdentifierExpression newIdent = new IdentifierExpression(mre.MemberName);
175-
mre.TypeArguments.MoveTo(newIdent.TypeArguments);
176-
newIdent.CopyAnnotationsFrom(mre);
177-
newIdent.RemoveAnnotations<Semantics.MemberResolveResult>(); // remove the reference to the property of the anonymous type
178-
if (fromOrLetIdentifiers.TryGetValue(mre.MemberName, out var annotation))
179-
newIdent.AddAnnotation(annotation);
180-
mre.ReplaceWith(newIdent);
181-
return;
182-
}
169+
IdentifierExpression newIdent = new IdentifierExpression(mre.MemberName);
170+
mre.TypeArguments.MoveTo(newIdent.TypeArguments);
171+
newIdent.CopyAnnotationsFrom(mre);
172+
newIdent.RemoveAnnotations<Semantics.MemberResolveResult>(); // remove the reference to the property of the anonymous type
173+
if (fromOrLetIdentifiers.TryGetValue(mre.MemberName, out var annotation))
174+
newIdent.AddAnnotation(annotation);
175+
mre.ReplaceWith(newIdent);
176+
return;
183177
}
184178
}
185179
}

ICSharpCode.Decompiler/CSharp/Transforms/IntroduceQueryExpressions.cs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@
1717
// DEALINGS IN THE SOFTWARE.
1818

1919
using System;
20-
using System.Diagnostics;
2120
using System.Linq;
2221

2322
using ICSharpCode.Decompiler.CSharp.Syntax;
23+
using ICSharpCode.Decompiler.IL;
2424

2525
namespace ICSharpCode.Decompiler.CSharp.Transforms
2626
{
@@ -54,13 +54,14 @@ public void Run(AstNode rootNode, TransformContext context)
5454
while (IsDegenerateQuery(innerQuery))
5555
{
5656
QueryFromClause innerFromClause = (QueryFromClause)innerQuery.Clauses.First();
57-
if (fromClause.Identifier != innerFromClause.Identifier)
58-
break;
57+
ILVariable innerVariable = innerFromClause.Annotation<ILVariableResolveResult>()?.Variable;
58+
ILVariable rangeVariable = fromClause.Annotation<ILVariableResolveResult>()?.Variable;
5959
// Replace the fromClause with all clauses from the inner query
6060
fromClause.Remove();
6161
QueryClause insertionPos = null;
6262
foreach (var clause in innerQuery.Clauses)
6363
{
64+
CombineRangeVariables(clause, innerVariable, rangeVariable);
6465
query.Clauses.InsertAfter(insertionPos, insertionPos = clause.Detach());
6566
}
6667
fromClause = innerFromClause;
@@ -69,6 +70,20 @@ public void Run(AstNode rootNode, TransformContext context)
6970
}
7071
}
7172

73+
private void CombineRangeVariables(QueryClause clause, ILVariable oldVariable, ILVariable newVariable)
74+
{
75+
foreach (var identifier in clause.DescendantNodes().OfType<Identifier>())
76+
{
77+
var variable = identifier.Parent.Annotation<ILVariableResolveResult>()?.Variable;
78+
if (variable == oldVariable)
79+
{
80+
identifier.Parent.RemoveAnnotations<ILVariableResolveResult>();
81+
identifier.Parent.AddAnnotation(new ILVariableResolveResult(newVariable));
82+
identifier.ReplaceWith(Identifier.Create(newVariable.Name));
83+
}
84+
}
85+
}
86+
7287
bool IsDegenerateQuery(QueryExpression query)
7388
{
7489
if (query == null)

0 commit comments

Comments
 (0)