bool TryRemoveTransparentIdentifier(QueryExpression query, QueryFromClause fromClause, QueryExpression innerQuery, string continuationIdentifier, out string transparentIdentifier)
{
transparentIdentifier = fromClause.Identifier;
Match match = selectTransparentIdentifierPattern.Match(innerQuery.Clauses.Last());
if (!match.Success)
return false;
QuerySelectClause selectClause = (QuerySelectClause)innerQuery.Clauses.Last();
Expression nae1 = match.Get<Expression>("nae1").SingleOrDefault();
string nae1Name = ExtractExpressionName(ref nae1);
if (nae1Name == null)
return false;
Expression nae2 = match.Get<Expression>("nae2").SingleOrDefault();
string nae2Name = ExtractExpressionName(ref nae2);
if (nae1Name == null)
return false;
bool introduceLetClause = true;
var nae1Identifier = nae1 as IdentifierExpression;
var nae2Identifier = nae2 as IdentifierExpression;
if (nae1Identifier != null && nae2Identifier != null && nae1Identifier.Identifier == nae1Name && nae2Identifier.Identifier == nae2Name) {
introduceLetClause = false;
}
if (nae1Name != continuationIdentifier) {
if (nae2Name == continuationIdentifier) {
//Members are in reversed order
string tempName = nae1Name;
Expression tempNae = nae1;
nae1Name = nae2Name;
nae1 = nae2;
nae2Name = tempName;
nae2 = tempNae;
} else {
return false;
}
}
if (introduceLetClause && innerQuery.Clauses.OfType<QueryFromClause>().Any(from => from.Identifier == nae2Name)) {
return false;
}
if (introduceLetClause && innerQuery.Clauses.OfType<QueryJoinClause>().Any(join => join.JoinIdentifier == nae2Name)) {
return false;
}
// from * in (from x in ... select new { x = x, y = expr }) ...
// =>
// from x in ... let y = expr ...
fromClause.Remove();
selectClause.Remove();
// Move clauses from innerQuery to query
QueryClause insertionPos = null;
foreach (var clause in innerQuery.Clauses) {
query.Clauses.InsertAfter(insertionPos, insertionPos = clause.Detach());
}
if (introduceLetClause) {
query.Clauses.InsertAfter(insertionPos, new QueryLetClause { Identifier = nae2Name, Expression = nae2.Detach() });
}
return true;
}