public override void VisitInvocationExpression(InvocationExpression invocationExpression)
            {
                InvocationExpression outerInvocationExpression = invocationExpression;
                //Note the invocations are in reverse order, so x.Foo().Bar() will have [0] be the Bar() and [1] be the Foo()
                List <InvocationExpression> invocations = new List <InvocationExpression>();
                LinqMethod outerMethod = null;
                Expression target      = null;

                for (;;)
                {
                    var resolveResult = ctx.Resolve(invocationExpression) as MemberResolveResult;
                    if (resolveResult == null || !(resolveResult.Member is IMethod))
                    {
                        break;
                    }

                    var method = LinqMethods.FirstOrDefault(candidate => candidate.FullName == resolveResult.Member.FullName &&
                                                            candidate.ParameterCount == ((IMethod)resolveResult.Member.MemberDefinition).Parameters.Count);
                    if (method == null || (invocations.Any() && method.IsLast))
                    {
                        break;
                    }

                    var mre = invocationExpression.Target as MemberReferenceExpression;
                    if (mre == null)
                    {
                        break;
                    }

                    if (outerMethod == null)
                    {
                        outerMethod = method;
                    }
                    invocations.Add(invocationExpression);

                    target = mre.Target;

                    var newInvocation = target as InvocationExpression;
                    if (newInvocation == null)
                    {
                        break;
                    }

                    invocationExpression = newInvocation;
                }

                if (target == null)
                {
                    base.VisitInvocationExpression(invocationExpression);
                    return;
                }
                if (!outerMethod.IsPoorStyleAlone && invocations.Count == 1)
                {
                    base.VisitInvocationExpression(invocationExpression);
                    return;
                }

                var currentTypeDeclaration   = outerInvocationExpression.GetParent <TypeDeclaration>();
                var currentTypeResolveResult = ctx.Resolve(currentTypeDeclaration) as TypeResolveResult;

                if (currentTypeResolveResult == null)
                {
                    base.VisitInvocationExpression(invocationExpression);
                    return;
                }

                var currentTypeDefinition = currentTypeResolveResult.Type.GetDefinition();

                var targetResolveResult = ctx.Resolve(target);

                if (!CanIndex(currentTypeDefinition, targetResolveResult))
                {
                    base.VisitInvocationExpression(invocationExpression);
                    return;
                }

                string countPropertyName = GetCountProperty(currentTypeDefinition, targetResolveResult);

                string lastInvocationName = ((MemberReferenceExpression)invocations[0].Target).MemberName;

                bool endsReversed  = invocations.Count(invocation => ((MemberReferenceExpression)invocation.Target).MemberName == "Reverse") % 2 != 0;
                bool requiresCount = lastInvocationName == "Count" || lastInvocationName == "Any" ||
                                     (endsReversed ? lastInvocationName == "First" || lastInvocationName == "ElementAt" : lastInvocationName == "Last");

                if (countPropertyName == null && requiresCount)
                {
                    base.VisitInvocationExpression(invocationExpression);
                    return;
                }

                AddIssue(new CodeIssue(invocations.Last().LParToken.StartLocation,
                                       invocations.First().RParToken.EndLocation,
                                       ctx.TranslateString("Use of Linq method when there's a better alternative"),
                                       ctx.TranslateString("Replace method by simpler version"),
                                       script => {
                    Expression startOffset = null;
                    Expression endOffset   = null;
                    Expression expression  = null;

                    bool reversed = false;
                    foreach (var invocation in invocations.AsEnumerable().Reverse())
                    {
                        string invocationName = ((MemberReferenceExpression)invocation.Target).MemberName;

                        switch (invocationName)
                        {
                        case "Skip":
                            Expression offset = reversed ? endOffset : startOffset;
                            if (offset == null)
                            {
                                offset = invocation.Arguments.Last().Clone();
                            }
                            else
                            {
                                offset = new BinaryOperatorExpression(offset,
                                                                      BinaryOperatorType.Add,
                                                                      invocation.Arguments.Last().Clone());
                            }

                            if (reversed)
                            {
                                endOffset = offset;
                            }
                            else
                            {
                                startOffset = offset;
                            }

                            break;

                        case "Reverse":
                            reversed = !reversed;
                            break;

                        case "First":
                        case "ElementAt":
                        case "Last":
                            {
                                bool fromEnd          = (invocationName == "Last") ^ reversed;
                                Expression index      = invocationName == "ElementAt" ? invocation.Arguments.Last().Clone() : null;
                                Expression baseOffset = fromEnd ? endOffset : startOffset;
                                //Our indexWithOffset is baseOffset + index
                                //A baseOffset/index of null is considered "0".

                                Expression indexWithOffset = baseOffset == null ? index :
                                                             index == null ? baseOffset :
                                                             new BinaryOperatorExpression(baseOffset, BinaryOperatorType.Add, index);

                                Expression indexerExpression = indexWithOffset;
                                if (fromEnd)
                                {
                                    var endExpression = new BinaryOperatorExpression(new MemberReferenceExpression(target.Clone(), countPropertyName),
                                                                                     BinaryOperatorType.Subtract,
                                                                                     new PrimitiveExpression(1));
                                    if (indexerExpression == null)
                                    {
                                        indexerExpression = endExpression;
                                    }
                                    else
                                    {
                                        indexerExpression = new BinaryOperatorExpression(endExpression,
                                                                                         BinaryOperatorType.Subtract,
                                                                                         new ParenthesizedExpression(indexerExpression));
                                    }
                                }

                                indexerExpression = indexerExpression ?? new PrimitiveExpression(0);

                                var newExpression = new IndexerExpression(target.Clone(),
                                                                          indexerExpression);

                                script.Replace(outerInvocationExpression, newExpression);
                                break;
                            }

                        case "Count":
                        case "Any":
                            {
                                Expression takenMembers;
                                if (startOffset == null)
                                {
                                    takenMembers = endOffset;
                                }
                                else if (endOffset == null)
                                {
                                    takenMembers = startOffset;
                                }
                                else
                                {
                                    takenMembers = new BinaryOperatorExpression(startOffset,
                                                                                BinaryOperatorType.Add,
                                                                                endOffset);
                                }

                                var countExpression = new MemberReferenceExpression(target.Clone(), countPropertyName);

                                Expression newExpression;
                                if (invocationName == "Count")
                                {
                                    if (takenMembers == null)
                                    {
                                        newExpression = countExpression;
                                    }
                                    else
                                    {
                                        newExpression = new BinaryOperatorExpression(countExpression,
                                                                                     BinaryOperatorType.Subtract,
                                                                                     new ParenthesizedExpression(takenMembers));
                                    }
                                }
                                else
                                {
                                    newExpression = new BinaryOperatorExpression(countExpression,
                                                                                 BinaryOperatorType.GreaterThan,
                                                                                 new ParenthesizedExpression(takenMembers));
                                }

                                script.Replace(outerInvocationExpression, newExpression);
                                break;
                            }
                        }
                    }
                }));

                base.VisitInvocationExpression(invocationExpression);
            }