mirror of
				https://github.com/KevinMidboe/linguist.git
				synced 2025-10-29 17:50:22 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			153 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			153 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
using System.Collections.Generic;
 | 
						|
using System.Collections.ObjectModel;
 | 
						|
using System.Linq;
 | 
						|
using System.Linq.Expressions;
 | 
						|
 | 
						|
namespace MongoDB.Linq.Expressions
 | 
						|
{
 | 
						|
    internal class MongoExpressionVisitor : ExpressionVisitor
 | 
						|
    {
 | 
						|
        protected override Expression Visit(Expression exp)
 | 
						|
        {
 | 
						|
            if (exp == null)
 | 
						|
                return null;
 | 
						|
            switch ((MongoExpressionType)exp.NodeType)
 | 
						|
            {
 | 
						|
                case MongoExpressionType.Collection:
 | 
						|
                    return VisitCollection((CollectionExpression)exp);
 | 
						|
                case MongoExpressionType.Field:
 | 
						|
                    return VisitField((FieldExpression)exp);
 | 
						|
                case MongoExpressionType.Projection:
 | 
						|
                    return VisitProjection((ProjectionExpression)exp);
 | 
						|
                case MongoExpressionType.Select:
 | 
						|
                    return VisitSelect((SelectExpression)exp);
 | 
						|
                case MongoExpressionType.Aggregate:
 | 
						|
                    return VisitAggregate((AggregateExpression)exp);
 | 
						|
                case MongoExpressionType.AggregateSubquery:
 | 
						|
                    return VisitAggregateSubquery((AggregateSubqueryExpression)exp);
 | 
						|
                case MongoExpressionType.Scalar:
 | 
						|
                    return VisitScalar((ScalarExpression)exp);
 | 
						|
                default:
 | 
						|
                    return base.Visit(exp);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        protected virtual Expression VisitAggregate(AggregateExpression aggregate)
 | 
						|
        {
 | 
						|
            var exp = Visit(aggregate.Argument);
 | 
						|
            if (exp != aggregate.Argument)
 | 
						|
                return new AggregateExpression(aggregate.Type, aggregate.AggregateType, exp, aggregate.Distinct);
 | 
						|
 | 
						|
            return aggregate;
 | 
						|
        }
 | 
						|
 | 
						|
        protected virtual Expression VisitAggregateSubquery(AggregateSubqueryExpression aggregateSubquery)
 | 
						|
        {
 | 
						|
            Expression e = Visit(aggregateSubquery.AggregateAsSubquery);
 | 
						|
            ScalarExpression subquery = (ScalarExpression)e;
 | 
						|
            if (subquery != aggregateSubquery.AggregateAsSubquery)
 | 
						|
                return new AggregateSubqueryExpression(aggregateSubquery.GroupByAlias, aggregateSubquery.AggregateInGroupSelect, subquery);
 | 
						|
            return aggregateSubquery;
 | 
						|
        }
 | 
						|
 | 
						|
        protected virtual Expression VisitCollection(CollectionExpression collection)
 | 
						|
        {
 | 
						|
            return collection;
 | 
						|
        }
 | 
						|
 | 
						|
        protected virtual Expression VisitField(FieldExpression field)
 | 
						|
        {
 | 
						|
            var e = Visit(field.Expression);
 | 
						|
            if (field.Expression != e)
 | 
						|
                field = new FieldExpression(e, field.Alias, field.Name);
 | 
						|
 | 
						|
            return field;
 | 
						|
        }
 | 
						|
 | 
						|
        protected virtual Expression VisitProjection(ProjectionExpression projection)
 | 
						|
        {
 | 
						|
            var source = (SelectExpression)Visit(projection.Source);
 | 
						|
            var projector = Visit(projection.Projector);
 | 
						|
            if (source != projection.Source || projector != projection.Projector)
 | 
						|
                return new ProjectionExpression(source, projector, projection.Aggregator);
 | 
						|
            return projection;
 | 
						|
        }
 | 
						|
 | 
						|
        protected ReadOnlyCollection<OrderExpression> VisitOrderBy(ReadOnlyCollection<OrderExpression> orderBys)
 | 
						|
        {
 | 
						|
            if (orderBys != null) 
 | 
						|
            {
 | 
						|
                List<OrderExpression> alternate = null;
 | 
						|
                for (int i = 0, n = orderBys.Count; i < n; i++) 
 | 
						|
                {
 | 
						|
                    OrderExpression expr = orderBys[i];
 | 
						|
                    Expression e = this.Visit(expr.Expression);
 | 
						|
                    if (alternate == null && e != expr.Expression) 
 | 
						|
                        alternate = orderBys.Take(i).ToList();
 | 
						|
                    if (alternate != null) 
 | 
						|
                        alternate.Add(new OrderExpression(expr.OrderType, e));
 | 
						|
                }
 | 
						|
                if (alternate != null) 
 | 
						|
                    return alternate.AsReadOnly();
 | 
						|
            }
 | 
						|
            return orderBys;
 | 
						|
        }
 | 
						|
 | 
						|
        protected virtual Expression VisitScalar(ScalarExpression scalar)
 | 
						|
        {
 | 
						|
            SelectExpression select = (SelectExpression)Visit(scalar.Select);
 | 
						|
            if (select != scalar.Select)
 | 
						|
                return new ScalarExpression(scalar.Type, select);
 | 
						|
            return scalar;
 | 
						|
        }
 | 
						|
 | 
						|
        protected virtual Expression VisitSelect(SelectExpression select)
 | 
						|
        {
 | 
						|
            var from = VisitSource(select.From);
 | 
						|
            var where = Visit(select.Where);
 | 
						|
            var groupBy = Visit(select.GroupBy);
 | 
						|
            var orderBy = VisitOrderBy(select.OrderBy);
 | 
						|
            var skip = Visit(select.Skip);
 | 
						|
            var take = Visit(select.Take);
 | 
						|
            var fields = VisitFieldDeclarationList(select.Fields);
 | 
						|
            if (from != select.From || where != select.Where || orderBy != select.OrderBy || groupBy != select.GroupBy || skip != select.Skip || take != select.Take || fields != select.Fields)
 | 
						|
                return new SelectExpression(select.Alias, fields, from, where, orderBy, groupBy, select.IsDistinct, skip, take);
 | 
						|
            return select;
 | 
						|
        }
 | 
						|
 | 
						|
        protected virtual Expression VisitSource(Expression source)
 | 
						|
        {
 | 
						|
            return Visit(source);
 | 
						|
        }
 | 
						|
 | 
						|
        protected virtual Expression VisitSubquery(SubqueryExpression subquery)
 | 
						|
        {
 | 
						|
            switch ((MongoExpressionType)subquery.NodeType)
 | 
						|
            {
 | 
						|
                case MongoExpressionType.Scalar:
 | 
						|
                    return VisitScalar((ScalarExpression)subquery);
 | 
						|
            }
 | 
						|
            return subquery;
 | 
						|
        }
 | 
						|
 | 
						|
        protected virtual ReadOnlyCollection<FieldDeclaration> VisitFieldDeclarationList(ReadOnlyCollection<FieldDeclaration> fields)
 | 
						|
        {
 | 
						|
            if (fields == null)
 | 
						|
                return fields;
 | 
						|
 | 
						|
            List<FieldDeclaration> alternate = null;
 | 
						|
            for (int i = 0, n = fields.Count; i < n; i++)
 | 
						|
            {
 | 
						|
                var f = fields[i];
 | 
						|
                var e = Visit(f.Expression);
 | 
						|
                if (f.Expression != e && alternate == null)
 | 
						|
                    alternate = fields.Take(i).ToList();
 | 
						|
                if (alternate != null)
 | 
						|
                    alternate.Add(new FieldDeclaration(f.Name, e));
 | 
						|
            }
 | 
						|
            if (alternate != null)
 | 
						|
                return alternate.AsReadOnly();
 | 
						|
            return fields;
 | 
						|
        }
 | 
						|
    }
 | 
						|
} |