/// <summary>
        /// Builds a parsed call expression for a property setter from the matching getter. The property must be interceptable as a faked method.
        /// </summary>
        /// <typeparam name="TValue">The return type of the getter.</typeparam>
        /// <param name="parsedCallExpression">
        /// The parsed call expression describing the getter.
        /// Must have a non-null <see cref="ParsedCallExpression.CallTarget"/>.
        /// </param>
        /// <returns>A parsed call expression describing the setter that matches the supplied getter.</returns>
        public static ParsedCallExpression BuildSetterFromGetter <TValue>(ParsedCallExpression parsedCallExpression)
        {
            var propertyName   = GetPropertyName(parsedCallExpression);
            var parameterTypes = new Type[parsedCallExpression.ArgumentsExpressions.Length + 1];

            for (int i = 0; i < parsedCallExpression.ArgumentsExpressions.Length; ++i)
            {
                parameterTypes[i] = parsedCallExpression.ArgumentsExpressions[i].ArgumentInformation.ParameterType;
            }

            parameterTypes[parsedCallExpression.ArgumentsExpressions.Length] = parsedCallExpression.CalledMethod.ReturnType;

            // The DeclaringType may be null, so fall back to the faked object type.
            // (It's unlikely to happen, though, and would require the client code to have passed a specially
            // constructed expression to ACallToSet; perhaps a dynamically generated method created
            // via lightweight code generation.)
            var callTargetType = parsedCallExpression.CalledMethod.DeclaringType
                                 ?? Fake.GetFakeManager(parsedCallExpression.CallTarget !).FakeObjectType;
            var setPropertyName   = "set_" + propertyName;
            var indexerSetterInfo = callTargetType.GetMethod(setPropertyName, parameterTypes);

            if (indexerSetterInfo is null)
            {
                if (parsedCallExpression.ArgumentsExpressions.Any())
                {
                    var expressionDescription = GetExpressionDescription(parsedCallExpression);
                    throw new ArgumentException(ExceptionMessages.ExpressionIsIndexedPropertyWithoutSetter(expressionDescription));
                }

                throw new ArgumentException(ExceptionMessages.PropertyHasNoSetter(propertyName));
            }

            var originalParameterInfos = indexerSetterInfo.GetParameters();

            var newParsedSetterValueExpression = new ParsedArgumentExpression(
                BuildArgumentThatMatchesAnything <TValue>(),
                originalParameterInfos.Last());

            var arguments = new ParsedArgumentExpression[originalParameterInfos.Length];

            Array.Copy(parsedCallExpression.ArgumentsExpressions, arguments, originalParameterInfos.Length - 1);
            arguments[originalParameterInfos.Length - 1] = newParsedSetterValueExpression;

            return(new ParsedCallExpression(indexerSetterInfo, parsedCallExpression.CallTarget, arguments));
        }