/// <summary>
        /// Checks the built-in types and empty strings within a document.
        /// </summary>
        /// <param name="document">
        /// The document containing the tokens.
        /// </param>
        /// <param name="settings">
        /// The current settings.
        /// </param>
        private void IterateTokenList(CsDocument document, Settings settings)
        {
            Param.AssertNotNull(document, "document");
            Param.Ignore(settings);

            for (Node <CsToken> tokenNode = document.Tokens.First; tokenNode != null; tokenNode = tokenNode.Next)
            {
                CsToken token = tokenNode.Value;

                if (token.CsTokenClass == CsTokenClass.Type || token.CsTokenClass == CsTokenClass.GenericType)
                {
                    // Check that the type is using the built-in types, if applicable.
                    this.CheckBuiltInType(tokenNode, document);

                    if (token.CsTokenClass == CsTokenClass.GenericType)
                    {
                        this.CheckShorthandForNullableTypes(tokenNode.Value);
                    }
                }
                else if (token.CsTokenType == CsTokenType.String)
                {
                    // Check that the string is not using the empty string "" syntax.
                    this.CheckEmptyString(tokenNode);
                }
                else if (token.CsTokenClass == CsTokenClass.RegionDirective && settings.DoNotUseRegions)
                {
                    Region region = (Region)token;
                    if (region.Beginning && !region.Generated && !region.IsGeneratedCodeRegion)
                    {
                        // There should not be any regions in the code.
                        this.AddViolation(token.FindParentElement(), token.LineNumber, Rules.DoNotUseRegions);
                    }
                }
                else if (settings.AvoidStringFormatUseStringInterpolation && token.CsTokenType == CsTokenType.Other && token.Text == "Format")
                {
                    // Check this rule only if project target framework version is greater or equal 4.6
                    if (document.SourceCode.Project.TargetFrameworkVersion >= 4.6)
                    {
                        MemberAccessExpression expression = token.Parent?.Parent as MemberAccessExpression;

                        // Check if literal expression is not null and check text to avoid user's custom code like enumeration.
                        if (expression != null && expression.Text == "string.Format")
                        {
                            CsToken region = (CsToken)token;
                            if (!region.Generated)
                            {
                                // There should not be any regions in the code.
                                this.AddViolation(token.FindParentElement(), token.LineNumber, Rules.AvoidStringFormatUseStringInterpolation);
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Reads a member access expression.
        /// </summary>
        /// <param name="leftSide">
        /// The left side of the expression.
        /// </param>
        /// <param name="previousPrecedence">
        /// The precedence of the previous expression.
        /// </param>
        /// <param name="unsafeCode">
        /// Indicates whether the code is marked as unsafe.
        /// </param>
        /// <returns>
        /// Returns the expression.
        /// </returns>
        private MemberAccessExpression GetMemberAccessExpression(Expression leftSide, ExpressionPrecedence previousPrecedence, bool unsafeCode)
        {
            Param.AssertNotNull(leftSide, "leftSide");
            Param.Ignore(previousPrecedence);
            Param.Ignore(unsafeCode);

            MemberAccessExpression expression = null;

            OperatorType operatorType;
            MemberAccessExpression.Operator expressionOperatorType;
            ExpressionPrecedence precedence;

            Reference<ICodePart> expressionReference = new Reference<ICodePart>();

            // The next symbol must one of the member access types.
            Symbol symbol = this.GetNextSymbol(expressionReference);

            if (symbol.SymbolType == SymbolType.Dot)
            {
                operatorType = OperatorType.MemberAccess;
                expressionOperatorType = MemberAccessExpression.Operator.Dot;
                precedence = ExpressionPrecedence.Primary;
            }
            else if (symbol.SymbolType == SymbolType.Pointer)
            {
                operatorType = OperatorType.Pointer;
                expressionOperatorType = MemberAccessExpression.Operator.Pointer;
                precedence = ExpressionPrecedence.Primary;
            }
            else if (symbol.SymbolType == SymbolType.QualifiedAlias)
            {
                operatorType = OperatorType.QualifiedAlias;
                expressionOperatorType = MemberAccessExpression.Operator.QualifiedAlias;
                precedence = ExpressionPrecedence.Global;
            }
            else
            {
                Debug.Fail("Unexpected operator type");
                throw new InvalidOperationException();
            }

            // Check the precedence. A member access has primary precedence.
            if (CheckPrecedence(previousPrecedence, precedence))
            {
                // Add this to the document.
                this.tokens.Add(this.GetOperatorToken(operatorType, expressionReference));

                // Get the member being accessed. This must be a literal.
                LiteralExpression member = this.GetLiteralExpression(expressionReference, unsafeCode);
                if (member == null)
                {
                    throw this.CreateSyntaxException();
                }

                // Create the token list.
                CsTokenList partialTokens = new CsTokenList(this.tokens, leftSide.Tokens.First, this.tokens.Last);

                // Create the expression.
                expression = new MemberAccessExpression(partialTokens, expressionOperatorType, leftSide, member);
                expressionReference.Target = expression;
            }

            return expression;
        }
        /// <summary>
        /// The save.
        /// </summary>
        /// <param name="operator">
        /// The operator.
        /// </param>
        private void Save(MemberAccessExpression.Operator @operator)
        {
            var operatorString = string.Empty;

            switch (@operator)
            {
                case MemberAccessExpression.Operator.Dot:
                    operatorString = ".";
                    break;
                case MemberAccessExpression.Operator.Pointer:
                    operatorString = "->";
                    break;
                case MemberAccessExpression.Operator.QualifiedAlias:
                    operatorString = "::";
                    break;
                default:
                    break;
            }

            this.cppWriter.Write(operatorString);
        }
        // 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="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);
        }