// todo: reduce it
        private MemberAccessExpression.Operator GetActualMemberAccess(
            MemberAccessExpression memberAccessExpression, TypeResolver typeResolverReference, IEnumerable<ExpressionReturnTypeResolver.ResolvedContextItem> resolvedCodeElements, bool memberWasFound)
        {
            if (memberAccessExpression.OperatorType == MemberAccessExpression.Operator.Dot)
            {
                if (typeResolverReference.IsResolved && (typeResolverReference.IsClassName || typeResolverReference.IsEnum))
                {
                    return MemberAccessExpression.Operator.QualifiedAlias;
                }

                if (resolvedCodeElements.Any())
                {
                    var first = resolvedCodeElements.First();
                    var typeDefinitionMetadataICodeElementAdapterBase = first.Type as TypeDefinitionMetadataICodeElementAdapterBase;
                    if (typeDefinitionMetadataICodeElementAdapterBase != null && typeDefinitionMetadataICodeElementAdapterBase.IsValueType)
                    {
                        return MemberAccessExpression.Operator.Dot;
                    }

                    return MemberAccessExpression.Operator.Pointer;
                }

                if (memberAccessExpression.LeftHandSide is LiteralExpression
                    && typeResolverReference.IsResolved
                    && !typeResolverReference.IsFieldOrVariable)
                {
                    return MemberAccessExpression.Operator.QualifiedAlias;
                }

                var current = memberAccessExpression;
                while (current != null)
                {
                    if (current.LeftHandSide is MethodInvocationExpression)
                    {
                        return MemberAccessExpression.Operator.Dot;
                    }

                    current = current.LeftHandSide as MemberAccessExpression;
                }

                return memberWasFound ? MemberAccessExpression.Operator.Dot : MemberAccessExpression.Operator.QualifiedAlias;
            }

            return memberAccessExpression.OperatorType;
        }
 /// <summary>
 /// The save.
 /// </summary>
 /// <param name="typeResolver">
 /// The resolved type reference.
 /// </param>
 /// <param name="writer">
 /// The writer.
 /// </param>
 /// <param name="savingOptions">
 /// The saving Options.
 /// </param>
 private void Save(TypeResolver typeResolver, IndentedTextWriter writer, SavingOptions savingOptions)
 {
     writer.Write(
         savingOptions.HasFlag(SavingOptions.UseFullyQualifiedNames) || !typeResolver.IsNamespaceInUsingDerictives
             ? typeResolver.GetCxFullyQualifiedType(savingOptions)
             : typeResolver.GetCxType(savingOptions));
 }
        /// <summary>
        /// The save.
        /// </summary>
        /// <param name="memberAccessExpression">
        /// The member access expression.
        /// </param>
        private void Save(MemberAccessExpression memberAccessExpression)
        {
            // todo: investigate why it returns multiple result with the same methods
            var expressionReturnTypeResolver = new ExpressionReturnTypeResolver(this);
            var resolvedCodeElements = expressionReturnTypeResolver.Resolve(memberAccessExpression.LeftHandSide);
            var members = resolvedCodeElements.ToList();

            var resolvedTypeReference = new TypeResolver(memberAccessExpression.LeftHandSide.Text, this);

            if (resolvedTypeReference.IsClassName || resolvedTypeReference.IsEnum)
            {
                bool isFullyQualified = memberAccessExpression.LeftHandSide.Text.StartsWith(resolvedTypeReference.Namespace);
                this.cppWriter.Write(
                    isFullyQualified
                        ? resolvedTypeReference.GetCXFullyQualifiedName(SavingOptions.None)
                        : resolvedTypeReference.GetCxName(SavingOptions.None));
            }
            else
            {
                @switch(memberAccessExpression.LeftHandSide);
            }

            this.Save(this.GetActualMemberAccess(memberAccessExpression, resolvedTypeReference, members, expressionReturnTypeResolver.IsMemberFound));

            @switch(memberAccessExpression.RightHandSide);
        }
        private void Save(Attribute attribute, IndentedTextWriter writer)
        {
            writer.Write("[");

            var first = true;
            foreach (var attributeExpression in attribute.AttributeExpressions)
            {
                if (!first)
                {
                    writer.Write(", ");
                }
                else
                {
                    first = false;
                }

                var methodInvocationExpression = attributeExpression.Initialization as MethodInvocationExpression;
                if (methodInvocationExpression != null)
                {
                    var resolvedType = new TypeResolver(methodInvocationExpression.Name.Text, this);
                    writer.Write(
                        resolvedType.IsResolved
                            ? resolvedType.GetCXFullyQualifiedName(SavingOptions.UseFullyQualifiedNames)
                            : methodInvocationExpression.Name.Text.Replace(".", "::"));

                    writer.Write('(');

                    this.SwitchStreams();
                    this.Save(methodInvocationExpression.Arguments);
                    this.SwitchStreams();

                    writer.Write(')');

                    continue;
                }

                var memberAccessExpression = attributeExpression.Initialization as MemberAccessExpression;
                if (memberAccessExpression != null)
                {
                    var resolvedType = new TypeResolver(memberAccessExpression.Text, this);
                    writer.Write(
                        resolvedType.IsResolved
                            ? resolvedType.GetCXFullyQualifiedName(SavingOptions.UseFullyQualifiedNames)
                            : memberAccessExpression.Text.Replace(".", "::"));
                }
            }

            writer.WriteLine("]");
        }
        public string GetCxName(SavingOptions savingOptions)
        {
            if (this.isAuto)
            {
                return "auto";
            }

            if (!this.IsReference)
            {
                return this.type;
            }

            if (!this.isTemplate)
            {
                return ConvertNamespaceChars(this.type);
            }

            var sb = new StringBuilder(100);

            // you need to convert all template types into correct types
            sb.Append(this.GetCxTypeNameWithoutTemplateParameters());

            sb.Append('<');

            var first = true;
            foreach (var templateType in CXXConverterLogic.GetGenericsTypes(this.type))
            {
                var referencedType = new TypeResolver(templateType, this.namesResolver);

                if (!first)
                {
                    sb.Append(", ");
                }

                first = false;
                sb.Append(
                    savingOptions.HasFlag(SavingOptions.UseFullyQualifiedNames)
                        ? referencedType.GetCxFullyQualifiedType(SavingOptions.None)
                        : referencedType.GetCxType(SavingOptions.None));
            }

            sb.Append('>');

            return sb.ToString();
        }
        public static void WriteArrayIndexes(Expression expression, IndentedTextWriter writer, string typeReferenceString, int pos, TypeResolver typeResolver, bool fieldDeclaration)
        {
            // Array converter
            // we converting [,,...,] -> [][]....[]
            string typeIndexes = typeReferenceString.Substring(pos, typeReferenceString.Length - pos);

            List<string> indexes = new List<string>();

            CXXConverterLogic.GetIndexes(expression, indexes);

            if (indexes.Count == 0 && typeResolver.IsReference)
            {
                return;
            }

            writer.Write(String.Concat(fieldDeclaration && indexes.Count == 0 ? "[0" : "[", String.Join("][", indexes.ToArray()), "]"));
        }