Browse Source

Improve LINQ decompiler to support combining lambda parameter names if they syntactically refer to the same range variable

pull/3416/head
Siegfried Pammer 3 months ago
parent
commit
0481c7d1ee
  1. 32
      ICSharpCode.Decompiler/CSharp/Transforms/CombineQueryExpressions.cs
  2. 21
      ICSharpCode.Decompiler/CSharp/Transforms/IntroduceQueryExpressions.cs

32
ICSharpCode.Decompiler/CSharp/Transforms/CombineQueryExpressions.cs

@ -16,12 +16,12 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching; using ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching;
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.CSharp.Transforms namespace ICSharpCode.Decompiler.CSharp.Transforms
{ {
@ -54,12 +54,10 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
next = child.NextSibling; next = child.NextSibling;
CombineQueries(child, fromOrLetIdentifiers); CombineQueries(child, fromOrLetIdentifiers);
} }
QueryExpression query = node as QueryExpression; if (node is QueryExpression query)
if (query != null)
{ {
QueryFromClause fromClause = (QueryFromClause)query.Clauses.First(); QueryFromClause fromClause = (QueryFromClause)query.Clauses.First();
QueryExpression innerQuery = fromClause.Expression as QueryExpression; if (fromClause.Expression is QueryExpression innerQuery)
if (innerQuery != null)
{ {
if (TryRemoveTransparentIdentifier(query, fromClause, innerQuery, fromOrLetIdentifiers)) if (TryRemoveTransparentIdentifier(query, fromClause, innerQuery, fromOrLetIdentifiers))
{ {
@ -165,21 +163,17 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
{ {
RemoveTransparentIdentifierReferences(child, fromOrLetIdentifiers); RemoveTransparentIdentifierReferences(child, fromOrLetIdentifiers);
} }
MemberReferenceExpression mre = node as MemberReferenceExpression; if (node is MemberReferenceExpression mre && mre.Target is IdentifierExpression ident
if (mre != null) && CSharpDecompiler.IsTransparentIdentifier(ident.Identifier))
{ {
IdentifierExpression ident = mre.Target as IdentifierExpression; IdentifierExpression newIdent = new IdentifierExpression(mre.MemberName);
if (ident != null && CSharpDecompiler.IsTransparentIdentifier(ident.Identifier)) mre.TypeArguments.MoveTo(newIdent.TypeArguments);
{ newIdent.CopyAnnotationsFrom(mre);
IdentifierExpression newIdent = new IdentifierExpression(mre.MemberName); newIdent.RemoveAnnotations<Semantics.MemberResolveResult>(); // remove the reference to the property of the anonymous type
mre.TypeArguments.MoveTo(newIdent.TypeArguments); if (fromOrLetIdentifiers.TryGetValue(mre.MemberName, out var annotation))
newIdent.CopyAnnotationsFrom(mre); newIdent.AddAnnotation(annotation);
newIdent.RemoveAnnotations<Semantics.MemberResolveResult>(); // remove the reference to the property of the anonymous type mre.ReplaceWith(newIdent);
if (fromOrLetIdentifiers.TryGetValue(mre.MemberName, out var annotation)) return;
newIdent.AddAnnotation(annotation);
mre.ReplaceWith(newIdent);
return;
}
} }
} }
} }

21
ICSharpCode.Decompiler/CSharp/Transforms/IntroduceQueryExpressions.cs

@ -17,10 +17,10 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Diagnostics;
using System.Linq; using System.Linq;
using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.IL;
namespace ICSharpCode.Decompiler.CSharp.Transforms namespace ICSharpCode.Decompiler.CSharp.Transforms
{ {
@ -54,13 +54,14 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
while (IsDegenerateQuery(innerQuery)) while (IsDegenerateQuery(innerQuery))
{ {
QueryFromClause innerFromClause = (QueryFromClause)innerQuery.Clauses.First(); QueryFromClause innerFromClause = (QueryFromClause)innerQuery.Clauses.First();
if (fromClause.Identifier != innerFromClause.Identifier) ILVariable innerVariable = innerFromClause.Annotation<ILVariableResolveResult>()?.Variable;
break; ILVariable rangeVariable = fromClause.Annotation<ILVariableResolveResult>()?.Variable;
// Replace the fromClause with all clauses from the inner query // Replace the fromClause with all clauses from the inner query
fromClause.Remove(); fromClause.Remove();
QueryClause insertionPos = null; QueryClause insertionPos = null;
foreach (var clause in innerQuery.Clauses) foreach (var clause in innerQuery.Clauses)
{ {
CombineRangeVariables(clause, innerVariable, rangeVariable);
query.Clauses.InsertAfter(insertionPos, insertionPos = clause.Detach()); query.Clauses.InsertAfter(insertionPos, insertionPos = clause.Detach());
} }
fromClause = innerFromClause; fromClause = innerFromClause;
@ -69,6 +70,20 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
} }
} }
private void CombineRangeVariables(QueryClause clause, ILVariable oldVariable, ILVariable newVariable)
{
foreach (var identifier in clause.DescendantNodes().OfType<Identifier>())
{
var variable = identifier.Parent.Annotation<ILVariableResolveResult>()?.Variable;
if (variable == oldVariable)
{
identifier.Parent.RemoveAnnotations<ILVariableResolveResult>();
identifier.Parent.AddAnnotation(new ILVariableResolveResult(newVariable));
identifier.ReplaceWith(Identifier.Create(newVariable.Name));
}
}
}
bool IsDegenerateQuery(QueryExpression query) bool IsDegenerateQuery(QueryExpression query)
{ {
if (query == null) if (query == null)

Loading…
Cancel
Save