diff --git a/ICSharpCode.NRefactory.CSharp/QueryExpressionExpander.cs b/ICSharpCode.NRefactory.CSharp/QueryExpressionExpander.cs
index cac18cdae7..1b310d4f90 100644
--- a/ICSharpCode.NRefactory.CSharp/QueryExpressionExpander.cs
+++ b/ICSharpCode.NRefactory.CSharp/QueryExpressionExpander.cs
@@ -13,14 +13,14 @@ namespace ICSharpCode.NRefactory.CSharp {
///
/// Maps original range variables to some node in the new tree that represents them.
///
- public IDictionary RangeVariables { get; private set; }
+ public IDictionary RangeVariables { get; private set; }
///
/// Maps clauses to method calls. The keys will always be either a or a
///
public IDictionary Expressions { get; private set; }
- public QueryExpressionExpansionResult(AstNode astNode, IDictionary rangeVariables, IDictionary expressions) {
+ public QueryExpressionExpansionResult(AstNode astNode, IDictionary rangeVariables, IDictionary expressions) {
AstNode = astNode;
RangeVariables = rangeVariables;
Expressions = expressions;
@@ -91,7 +91,7 @@ namespace ICSharpCode.NRefactory.CSharp {
return null;
}
- public IDictionary rangeVariables = new Dictionary();
+ public IDictionary rangeVariables = new Dictionary();
public IDictionary expressions = new Dictionary();
Dictionary activeRangeVariableSubstitutions = new Dictionary();
@@ -110,7 +110,7 @@ namespace ICSharpCode.NRefactory.CSharp {
if (currentTransparentType.Count == 1) {
var clonedRangeVariable = (Identifier)currentTransparentType[0].Item1.Clone();
if (!rangeVariables.ContainsKey(currentTransparentType[0].Item1))
- rangeVariables[currentTransparentType[0].Item1] = clonedRangeVariable;
+ rangeVariables[currentTransparentType[0].Item1] = param;
param.AddChild(clonedRangeVariable, Roles.Identifier);
}
else {
@@ -219,8 +219,9 @@ namespace ICSharpCode.NRefactory.CSharp {
body = AddMemberToCurrentTransparentType(resultParam, queryFromClause.IdentifierToken, new IdentifierExpression(queryFromClause.Identifier), false);
}
- var resultSelector = CreateLambda(new[] { resultParam, CreateParameter(clonedIdentifier) }, body);
- rangeVariables[queryFromClause.IdentifierToken] = clonedIdentifier;
+ var resultSelectorParam2 = CreateParameter(clonedIdentifier);
+ var resultSelector = CreateLambda(new[] { resultParam, resultSelectorParam2 }, body);
+ rangeVariables[queryFromClause.IdentifierToken] = resultSelectorParam2;
return currentResult.Invoke("SelectMany", innerSelector, resultSelector);
}
@@ -244,8 +245,8 @@ namespace ICSharpCode.NRefactory.CSharp {
var inExpression = VisitNested(queryJoinClause.InExpression, null);
var key1SelectorFirstParam = CreateParameterForCurrentRangeVariable();
var key1Selector = CreateLambda(new[] { key1SelectorFirstParam }, VisitNested(queryJoinClause.OnExpression, key1SelectorFirstParam));
- var key2Param = Identifier.Create(queryJoinClause.JoinIdentifier);
- var key2Selector = CreateLambda(new[] { CreateParameter(key2Param) }, VisitNested(queryJoinClause.EqualsExpression, null));
+ var key2Param = CreateParameter(Identifier.Create(queryJoinClause.JoinIdentifier));
+ var key2Selector = CreateLambda(new[] { key2Param }, VisitNested(queryJoinClause.EqualsExpression, null));
var resultSelectorFirstParam = CreateParameterForCurrentRangeVariable();
@@ -269,8 +270,8 @@ namespace ICSharpCode.NRefactory.CSharp {
if (resultSelectorBody == null)
resultSelectorBody = AddMemberToCurrentTransparentType(resultSelectorFirstParam, queryJoinClause.IntoIdentifierToken, new IdentifierExpression(queryJoinClause.IntoIdentifier), false);
- var intoParam = Identifier.Create(queryJoinClause.IntoIdentifier);
- var resultSelector = CreateLambda(new[] { resultSelectorFirstParam, CreateParameter(intoParam) }, resultSelectorBody);
+ var intoParam = CreateParameter(Identifier.Create(queryJoinClause.IntoIdentifier));
+ var resultSelector = CreateLambda(new[] { resultSelectorFirstParam, intoParam }, resultSelectorBody);
rangeVariables[queryJoinClause.IntoIdentifierToken] = intoParam;
return currentResult.Invoke("GroupJoin", inExpression, key1Selector, key2Selector, resultSelector);
@@ -292,12 +293,19 @@ namespace ICSharpCode.NRefactory.CSharp {
return current;
}
+ bool IsSingleRangeVariable(Expression expr) {
+ if (currentTransparentType.Count > 1)
+ return false;
+ var unpacked = ParenthesizedExpression.UnpackParenthesizedExpression(expr);
+ return expr is IdentifierExpression && ((IdentifierExpression)expr).Identifier == currentTransparentType[0].Item1.Name;
+ }
+
public override AstNode VisitQuerySelectClause(QuerySelectClause querySelectClause) {
if (eatSelect) {
eatSelect = false;
return currentResult;
}
- else if (currentTransparentType.Count == 1 && ((QueryExpression)querySelectClause.Parent).Clauses.Count > 2 && querySelectClause.Expression is IdentifierExpression && ((IdentifierExpression)querySelectClause.Expression).Identifier == currentTransparentType[0].Item1.Name) {
+ else if (((QueryExpression)querySelectClause.Parent).Clauses.Count > 2 && IsSingleRangeVariable(querySelectClause.Expression)) {
// A simple query that ends with a trivial select should be removed.
return currentResult;
}
@@ -311,7 +319,7 @@ namespace ICSharpCode.NRefactory.CSharp {
var param = CreateParameterForCurrentRangeVariable();
var keyLambda = CreateLambda(new[] { param }, VisitNested(queryGroupClause.Key, param));
- if (currentTransparentType.Count == 1 && queryGroupClause.Projection is IdentifierExpression && ((IdentifierExpression)queryGroupClause.Projection).Identifier == currentTransparentType[0].Item1.Name) {
+ if (IsSingleRangeVariable(queryGroupClause.Projection)) {
// We are grouping by the single active range variable, so we can use the single argument form of GroupBy
return currentResult.Invoke("GroupBy", keyLambda);
}
diff --git a/ICSharpCode.NRefactory.Tests/CSharp/QueryExpressionExpanderTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/QueryExpressionExpanderTests.cs
index 06fe18ac21..dae227a5d5 100644
--- a/ICSharpCode.NRefactory.Tests/CSharp/QueryExpressionExpanderTests.cs
+++ b/ICSharpCode.NRefactory.Tests/CSharp/QueryExpressionExpanderTests.cs
@@ -40,7 +40,7 @@ namespace ICSharpCode.NRefactory.CSharp {
var actual = new QueryExpressionExpander().ExpandQueryExpression(node);
AssertCorrect(actual.AstNode, "args.Select(a => int.Parse(a))");
dynamic astNode = actual.AstNode;
- AssertLookupCorrect(actual.RangeVariables, new[] { Tuple.Create(new TextLocation(1, 6), (AstNode)ElementAt(ElementAt(astNode.Arguments, 0).Parameters, 0).NameToken) });
+ AssertLookupCorrect(actual.RangeVariables, new[] { Tuple.Create(new TextLocation(1, 6), (AstNode)ElementAt(ElementAt(astNode.Arguments, 0).Parameters, 0)) });
AssertLookupCorrect(actual.Expressions, new[] { Tuple.Create(new TextLocation(1, 1), (AstNode)astNode.Target.Target), Tuple.Create(new TextLocation(1, 16), actual.AstNode) });
}
@@ -50,7 +50,7 @@ namespace ICSharpCode.NRefactory.CSharp {
var actual = new QueryExpressionExpander().ExpandQueryExpression(node);
AssertCorrect(actual.AstNode, "args.Cast