public ICodeNode VisitObjectCreationExpression(ObjectCreationExpression node)
		{
            if(node.Type == null || node.Constructor == null || !node.Type.IsGenericInstance)
            {
                return null;
            }

            TypeDefinition typeDef = node.Type.Resolve();
            if (!typeDef.IsAnonymous())
            {
                return null;
            }

            initializerExpressions = new BlockExpression(null);
            ProcessAnonymousType(typeDef, node.Type as GenericInstanceType, node.Constructor.Resolve(), node.Arguments);

            node.Initializer = new InitializerExpression(initializerExpressions, InitializerType.ObjectInitializer);

            List<Instruction> instructions = new List<Instruction>(node.MappedInstructions);
            foreach (Expression argument in node.Arguments)
            {
                instructions.AddRange(argument.UnderlyingSameMethodInstructions);
            }
			InitializerExpression initializer = new InitializerExpression(initializerExpressions, InitializerType.AnonymousInitializer);
			return new AnonymousObjectCreationExpression(node.Constructor, typeDef, initializer, instructions);
		}
        private Expression GetMethodHandleExpression(MethodReference methodReference, IEnumerable<Instruction> instructions)
        {
            TypeDefinition corlibTypeTypeDefinition = GetSystemTypeTypeDefinition();

            string[] parametersNames = methodReference.HasParameters ? new string[] { "System.String", "System.Type[]" } : new string[] { "System.String" };
            MethodReference getMethodReference = GetSystemTypeMethodReference(corlibTypeTypeDefinition, "GetMethod", parametersNames);

            MethodReference getMethodHandleReference = GetHandlePropertyGetterReference(typeof(System.Reflection.MethodBase), "get_MethodHandle");

            TypeOfExpression typeOfExpression = new TypeOfExpression(methodReference.DeclaringType, null);
            MethodReferenceExpression getMethodMethodReferenceExpression = new MethodReferenceExpression(typeOfExpression, getMethodReference, null);
            MethodInvocationExpression getMethodMethodInvocationExpression = new MethodInvocationExpression(getMethodMethodReferenceExpression, null);
            LiteralExpression argument = new LiteralExpression(methodReference.Name, this.typeSystem, null);
            getMethodMethodInvocationExpression.Arguments.Add(argument);

            if (methodReference.HasParameters)
            {
                BlockExpression blockExpression = new BlockExpression(null);
                foreach (ParameterDefinition parameter in methodReference.Parameters)
                {
                    blockExpression.Expressions.Add(new TypeOfExpression(parameter.ParameterType, null));
                }

				InitializerExpression initializer = new InitializerExpression(blockExpression, InitializerType.ArrayInitializer);
				ArrayCreationExpression getMethodTypeParametersArray = new ArrayCreationExpression(corlibTypeTypeDefinition, initializer, null);
                getMethodTypeParametersArray.Dimensions.Add(new LiteralExpression(blockExpression.Expressions.Count, this.typeSystem, null));

                getMethodMethodInvocationExpression.Arguments.Add(getMethodTypeParametersArray);
            }

            MethodReferenceExpression getMethodHandleMethodReferenceExpression = new MethodReferenceExpression(getMethodMethodInvocationExpression, getMethodHandleReference, null);
            MethodInvocationExpression getMethodHandleMethodInvocationExpression = new MethodInvocationExpression(getMethodHandleMethodReferenceExpression, instructions);
            PropertyReferenceExpression methodHandlePropertyReferenceExpression = new PropertyReferenceExpression(getMethodHandleMethodInvocationExpression, null);

            return methodHandlePropertyReferenceExpression;
        }
		public override void VisitBlockExpression(BlockExpression node)
		{
			WriteToken("{ ");
			VisitList(node.Expressions);
			WriteToken(" }");
		}
        private void RecordVariableAssignment(ExpressionStatement node)
        {
            BinaryExpression assignment = node.Expression as BinaryExpression;
            VariableReference variable = (assignment.Left as VariableReferenceExpression).Variable;
            assignment.Right = (Expression)Visit(assignment.Right);
            Expression rightClone = assignment.Right.CloneExpressionOnly();
            this.variableToValueMap[variable] = rightClone;

            HashSet<ExpressionStatement> statements;
            if (!this.variableToAssigingStatementsMap.TryGetValue(variable, out statements))
            {
                statements = new HashSet<ExpressionStatement>();
                this.variableToAssigingStatementsMap[variable] = statements;
            }

            statements.Add(node);

            ArrayCreationExpression arrayCreation = rightClone as ArrayCreationExpression;
            if (arrayCreation == null || arrayCreation.Dimensions == null || arrayCreation.Dimensions.Count != 1 || arrayCreation.Initializer != null && arrayCreation.Initializer.Expressions != null &&
                arrayCreation.Initializer.Expressions.Count > 0)
            {
                return;
            }

			var blockExpression = new BlockExpression(null);
			arrayCreation.Initializer = new InitializerExpression(blockExpression, InitializerType.ArrayInitializer);
			this.variableToLastUninitializedIndex[variable] = 0;
        }
		// MyCollection list = new MyCollection() { 1, { 2, 2 } , 3 };
		// 
		// ==
		// 
		// MyCollection temp = new MyCollection();
		// temp.Add(1);
		// temp.Add(2, 2);
		// temp.Add(3);
		// MyCollection list = temp;

		protected override bool TryMatchInternal(StatementCollection statements, int startIndex, out Statement result, out int replacedStatementsCount)
		{
			result = null;
			replacedStatementsCount = 0;

			ObjectCreationExpression objectCreation;
			Expression assignee;
			if (!TryGetObjectCreation(statements, startIndex, out objectCreation, out assignee))
			{
				return false;
			}

			if (objectCreation.Initializer != null && objectCreation.Initializer.InitializerType != InitializerType.CollectionInitializer)
			{
				return false;
			}

			if (!ImplementsInterface(objectCreation.Type, "System.Collections.IEnumerable"))
			{
				return false;
			}

			ExpressionCollection addedExpressions = new ExpressionCollection();

			for (int i = startIndex + 1; i < statements.Count; i++)
			{
				Expression expression;
				if (!TryGetNextExpression(statements[i], out expression))
				{
					break;
				}

				if (expression.CodeNodeType != CodeNodeType.MethodInvocationExpression)
				{
					break;
				}
				MethodInvocationExpression methodInvocation = (expression as MethodInvocationExpression);
				MethodDefinition methodDefinition = methodInvocation.MethodExpression.MethodDefinition;

				if (!CompareTargets(assignee, methodInvocation.MethodExpression.Target))
				{
					break;
				}

				if (methodDefinition.Name != "Add")
				{
					break;
				}

				if (methodInvocation.Arguments.Count == 0)
				{
					break;
				}
				else if (methodInvocation.Arguments.Count == 1)
				{
					addedExpressions.Add(methodInvocation.Arguments[0].Clone());
				}
				else
				{
					ExpressionCollection currentArguments = new ExpressionCollection(
						methodInvocation.Arguments.Select(x => x.Clone()));

					BlockExpression blockExpression = new BlockExpression(currentArguments, null);
					addedExpressions.Add(blockExpression);
				}
			}

			if (addedExpressions.Count == 0)
			{
				return false;
			}

			if (objectCreation.Initializer == null)
			{
				var initializer = new InitializerExpression(addedExpressions, InitializerType.CollectionInitializer);
				initializer.IsMultiLine = true;
				objectCreation.Initializer = initializer;
			}
			else
			{
				foreach (var item in addedExpressions)
				{
					objectCreation.Initializer.Expressions.Add(item);
				}
			}

			result = statements[startIndex];
			replacedStatementsCount = addedExpressions.Count + 1;
			return true;
		}
 public void RebuildDimensions(ref ExpressionCollection elements, ExpressionCollection dimensions)
 {
     int count = elements.Count;
     for (int i = dimensions.Count - 1; i > 0; i--)
     {
         ExpressionCollection currentCollection = new ExpressionCollection();
         int currentDimension = (int)(dimensions[i] as LiteralExpression).Value;
         for (int j = 0; j < count; j += currentDimension)
         {
             BlockExpression currentBlock = new BlockExpression(null);
             currentBlock.Expressions = new ExpressionCollection();
             for (int k = 0; k < currentDimension; k++)
             {
                 currentBlock.Expressions.Add(elements[j + k]);
             }
             currentCollection.Add(currentBlock);
         }
         elements = currentCollection;
         count /= currentDimension;
     }
 }
 public virtual void VisitBlockExpression(BlockExpression node)
 {
     Visit(node.Expressions);
 }
 public override Expression CloneExpressionOnly()
 {
     BlockExpression result = new BlockExpression(Expressions.CloneExpressionsOnly(), null);
     return result;
 }
        public override Expression Clone()
        {
			BlockExpression result = new BlockExpression(Expressions.Clone(), this.instructions);
            return result;
        }
		public InitializerExpression(BlockExpression expression, InitializerType initializerType, IEnumerable<Instruction> instructions)
			: base(instructions)
		{
			this.Expression = expression;
			this.InitializerType = initializerType;
		}
		public InitializerExpression(BlockExpression expression, InitializerType initializerType)
			: this(expression, initializerType, Enumerable.Empty<Instruction>())
		{
		}
		private void AddArrayInitializerCasts(TypeDefinition arrayType, BlockExpression blockExpression)
		{
			for (int i = 0; i < blockExpression.Expressions.Count; i++)
			{
				Expression element = blockExpression.Expressions[i];

				// Multidimensional array
				if (element.CodeNodeType == CodeNodeType.BlockExpression)
				{
					AddArrayInitializerCasts(arrayType, element as BlockExpression);
				}
				// Array elements
				else if (ShouldAddCast(arrayType, element.ExpressionType))
				{
					blockExpression.Expressions[i] = new CastExpression(element, arrayType, null);
				}
			}
		}