bool TryRemoveTransparentIdentifier(QueryExpression query, QueryFromClause fromClause, QueryExpression innerQuery)
        {
            if (!IsTransparentIdentifier(fromClause.Identifier))
            {
                return(false);
            }
            Match match = selectTransparentIdentifierPattern.Match(innerQuery.Clauses.Last());

            if (!match.Success)
            {
                return(false);
            }
            QuerySelectClause       selectClause = (QuerySelectClause)innerQuery.Clauses.Last();
            NamedArgumentExpression nae1         = match.Get <NamedArgumentExpression>("nae1").Single();
            NamedArgumentExpression nae2         = match.Get <NamedArgumentExpression>("nae2").Single();

            if (nae1.Identifier != ((IdentifierExpression)nae1.Expression).Identifier)
            {
                return(false);
            }
            IdentifierExpression nae2IdentExpr = nae2.Expression as IdentifierExpression;

            if (nae2IdentExpr != null && nae2.Identifier == nae2IdentExpr.Identifier)
            {
                // from * in (from x in ... select new { x = x, y = y }) ...
                // =>
                // from x in ... ...
                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());
                }
            }
            else
            {
                // 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());
                }
                query.Clauses.InsertAfter(insertionPos, new QueryLetClause {
                    Identifier = nae2.Identifier, Expression = nae2.Expression.Detach()
                });
            }
            return(true);
        }
        bool TryRemoveTransparentIdentifier(QueryExpression query, QueryFromClause fromClause, QueryExpression innerQuery, Dictionary <string, object> letClauses)
        {
            if (!IsTransparentIdentifier(fromClause.Identifier))
            {
                return(false);
            }
            QuerySelectClause selectClause = innerQuery.Clauses.Last() as QuerySelectClause;
            Match             match        = selectTransparentIdentifierPattern.Match(selectClause);

            if (!match.Success)
            {
                return(false);
            }

            // from * in (from x in ... select new { members of anonymous type }) ...
            // =>
            // from x in ... { let x = ... } ...
            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());
            }

            foreach (var expr in match.Get <Expression>("expr"))
            {
                switch (expr)
                {
                case IdentifierExpression identifier:
                    // nothing to add
                    continue;

                case NamedExpression namedExpression:
                    if (namedExpression.Expression is IdentifierExpression identifierExpression && namedExpression.Name == identifierExpression.Identifier)
                    {
                        letClauses[namedExpression.Name] = identifierExpression.Annotation <ILVariableResolveResult>();
                        continue;
                    }
                    QueryLetClause letClause = new QueryLetClause {
                        Identifier = namedExpression.Name, Expression = namedExpression.Expression.Detach()
                    };
                    var annotation = new LetIdentifierAnnotation();
                    letClause.AddAnnotation(annotation);
                    letClauses[namedExpression.Name] = annotation;
                    query.Clauses.InsertAfter(insertionPos, letClause);
                    break;
                }
            }
            return(true);
        }
Exemple #3
0
 public void Run(AstNode rootNode, TransformContext context)
 {
     if (!context.Settings.QueryExpressions)
     {
         return;
     }
     this.context = context;
     DecompileQueries(rootNode);
     // 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 rootNode.Descendants.OfType <QueryExpression>())
     {
         QueryFromClause fromClause = (QueryFromClause)query.Clauses.First();
         if (IsDegenerateQuery(query))
         {
             // introduce select for degenerate query
             query.Clauses.Add(new QuerySelectClause {
                 Expression = new IdentifierExpression(fromClause.Identifier).CopyAnnotationsFrom(fromClause)
             });
         }
         // 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)
             {
                 break;
             }
             // Replace the fromClause with all clauses from the inner query
             fromClause.Remove();
             QueryClause insertionPos = null;
             foreach (var clause in innerQuery.Clauses)
             {
                 query.Clauses.InsertAfter(insertionPos, insertionPos = clause.Detach());
             }
             fromClause = innerFromClause;
             innerQuery = fromClause.Expression as QueryExpression;
         }
     }
 }
            bool TryRemoveTransparentIdentifier(QueryExpression query, QueryFromClause fromClause, QueryExpression innerQuery)
            {
                if (!IsTransparentIdentifier(fromClause.Identifier))
                {
                    return(false);
                }
                Match match = selectTransparentIdentifierPattern.Match(innerQuery.Clauses.Last());

                if (!match.Success)
                {
                    return(false);
                }
                QuerySelectClause selectClause = (QuerySelectClause)innerQuery.Clauses.Last();
                NamedExpression   nae1         = match.Get <NamedExpression>("nae1").SingleOrDefault();
                NamedExpression   nae2         = match.Get <NamedExpression>("nae2").SingleOrDefault();

                if (nae1 != null && nae1.Name != ((IdentifierExpression)nae1.Expression).Identifier)
                {
                    return(false);
                }
                Expression           nae2Expr      = match.Get <Expression>("nae2Expr").Single();
                IdentifierExpression nae2IdentExpr = nae2Expr as IdentifierExpression;

                if (nae2IdentExpr != null && (nae2 == null || nae2.Name == nae2IdentExpr.Identifier))
                {
                    // from * in (from x in ... select new { x = x, y = y }) ...
                    // =>
                    // from x in ... ...
                    fromClause.Remove();
                    selectClause.Remove();
                    // Move clauses from innerQuery to query
                    QueryClause insertionPos = null;
                    foreach (var clause in innerQuery.Clauses)
                    {
                        query.Clauses.InsertAfter(insertionPos, insertionPos = Detach(clause));
                    }
                }
                else
                {
                    // 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 = Detach(clause));
                    }
                    string ident;
                    if (nae2 != null)
                    {
                        ident = nae2.Name;
                    }
                    else if (nae2Expr is MemberReferenceExpression)
                    {
                        ident = ((MemberReferenceExpression)nae2Expr).MemberName;
                    }
                    else
                    {
                        throw new InvalidOperationException("Could not infer name from initializer in AnonymousTypeCreateExpression");
                    }
                    query.Clauses.InsertAfter(insertionPos, new QueryLetClause {
                        Identifier = ident, Expression = Detach(nae2Expr)
                    });
                }
                return(true);
            }
		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 (nae2Name == 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;
		}
		bool TryRemoveTransparentIdentifier(QueryExpression query, QueryFromClause fromClause, QueryExpression innerQuery)
		{
			if (!IsTransparentIdentifier(fromClause.Identifier))
				return false;
			Match match = selectTransparentIdentifierPattern.Match(innerQuery.Clauses.Last());
			if (!match.Success)
				return false;
			QuerySelectClause selectClause = (QuerySelectClause)innerQuery.Clauses.Last();
			NamedExpression nae1 = match.Get<NamedExpression>("nae1").SingleOrDefault();
			NamedExpression nae2 = match.Get<NamedExpression>("nae2").SingleOrDefault();
			if (nae1 != null && nae1.Name != ((IdentifierExpression)nae1.Expression).Identifier)
				return false;
			Expression nae2Expr = match.Get<Expression>("nae2Expr").Single();
			IdentifierExpression nae2IdentExpr = nae2Expr as IdentifierExpression;
			if (nae2IdentExpr != null && (nae2 == null || nae2.Name == nae2IdentExpr.Identifier)) {
				// from * in (from x in ... select new { x = x, y = y }) ...
				// =>
				// from x in ... ...
				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());
				}
			} else {
				// 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());
				}
				string ident;
				if (nae2 != null)
					ident = nae2.Name;
				else if (nae2Expr is IdentifierExpression)
					ident = ((IdentifierExpression)nae2Expr).Identifier;
				else if (nae2Expr is MemberReferenceExpression)
					ident = ((MemberReferenceExpression)nae2Expr).MemberName;
				else
					throw new InvalidOperationException("Could not infer name from initializer in AnonymousTypeCreateExpression");
				query.Clauses.InsertAfter(insertionPos, new QueryLetClause { Identifier = ident, Expression = nae2Expr.Detach() });
			}
			return true;
		}
		bool TryRemoveTransparentIdentifier(QueryExpression query, QueryFromClause fromClause, QueryExpression innerQuery, 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;

			// 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());
			}
			query.Clauses.InsertAfter(insertionPos, new QueryLetClause { Identifier = nae2Name, Expression = nae2.Detach() });
			return true;
		}
		bool TryRemoveTransparentIdentifier(QueryExpression query, QueryFromClause fromClause, QueryExpression innerQuery)
		{
			if (!IsTransparentIdentifier(fromClause.Identifier))
				return false;
			Match match = selectTransparentIdentifierPattern.Match(innerQuery.Clauses.Last());
			if (!match.Success)
				return false;
			QuerySelectClause selectClause = (QuerySelectClause)innerQuery.Clauses.Last();
			NamedArgumentExpression nae1 = match.Get<NamedArgumentExpression>("nae1").Single();
			NamedArgumentExpression nae2 = match.Get<NamedArgumentExpression>("nae2").Single();
			if (nae1.Identifier != ((IdentifierExpression)nae1.Expression).Identifier)
				return false;
			IdentifierExpression nae2IdentExpr = nae2.Expression as IdentifierExpression;
			if (nae2IdentExpr != null && nae2.Identifier == nae2IdentExpr.Identifier) {
				// from * in (from x in ... select new { x = x, y = y }) ...
				// =>
				// from x in ... ...
				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());
				}
			} else {
				// 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());
				}
				query.Clauses.InsertAfter(insertionPos, new QueryLetClause { Identifier = nae2.Identifier, Expression = nae2.Expression.Detach() });
			}
			return true;
		}