public Expression ConvertFluentToQuery(Expression node)
        {
            node = node.Clone();

            var artificialParent = new ExpressionStatement();

            artificialParent.Expression = node;

            DecompileQueries(node);
            // After all queries were decompiled, detect degenerate queries (queries not property terminated with 'select' or 'group')
            // and fix them, either by adding a degenerate select, or by combining them with another query.
            foreach (QueryExpression query in artificialParent.Descendants.OfType <QueryExpression>())
            {
                QueryFromClause fromClause = (QueryFromClause)query.Clauses.First();
                if (IsDegenerateQuery(query))
                {
                    string identifierName = fromClause.Identifier;

                    // introduce select for degenerate query
                    query.Clauses.Add(new QuerySelectClause {
                        Expression = new IdentifierExpression(identifierName)
                    });
                }

                if (fromClause.Type.IsNull)
                {
                    // See if the data source of this query is a degenerate query,
                    // and combine the queries if possible.
                    QueryExpression innerQuery = fromClause.Expression as QueryExpression;
                    while (IsDegenerateQuery(innerQuery))
                    {
                        QueryFromClause innerFromClause = (QueryFromClause)innerQuery.Clauses.First();
                        if (fromClause.Identifier != innerFromClause.Identifier && !innerFromClause.Identifier.StartsWith("<>"))
                        {
                            break;
                        }
                        // Replace the fromClause with all clauses from the inner query
                        fromClause.Remove();
                        foreach (var identifierChild in innerQuery.Descendants.OfType <Identifier>().Where(identifier => identifier.Name == innerFromClause.Identifier))
                        {
                            //When the identifier is "<>X", then replace it with the outer one
                            identifierChild.ReplaceWith(fromClause.IdentifierToken.Clone());
                        }
                        QueryClause insertionPos = null;
                        foreach (var clause in innerQuery.Clauses)
                        {
                            query.Clauses.InsertAfter(insertionPos, insertionPos = clause.Detach());
                        }
                        fromClause = innerFromClause;
                        innerQuery = fromClause.Expression as QueryExpression;
                    }
                }
            }

            return(artificialParent.Expression.Clone());
        }
        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);
        }