Beispiel #1
0
        public static void CheckValueTypeClone(ResolveResult resolveResult, Expression expression, IAbstractEmitterBlock block, int insertPosition)
        {
            if (resolveResult == null || resolveResult.IsError)
            {
                return;
            }

            if (block.Emitter.IsAssignment)
            {
                return;
            }

            var conversion = block.Emitter.Resolver.Resolver.GetConversion(expression);

            if (conversion.IsBoxingConversion || conversion.IsUnboxingConversion)
            {
                return;
            }

            if (resolveResult is InvocationResolveResult)
            {
                bool ret = true;
                if (expression.Parent is InvocationExpression)
                {
                    var invocationExpression = (InvocationExpression)expression.Parent;
                    if (invocationExpression.Arguments.Any(a => a == expression))
                    {
                        ret = false;
                    }
                }
                else if (expression.Parent is AssignmentExpression)
                {
                    ret = false;
                }
                else if (expression.Parent is VariableInitializer)
                {
                    ret = false;
                }

                if (ret)
                {
                    return;
                }
            }

            var rrtype = resolveResult.Type;

            var forEachResolveResult = resolveResult as ForEachResolveResult;

            if (forEachResolveResult != null)
            {
                rrtype = forEachResolveResult.ElementType;
            }

            var nullable = rrtype.IsKnownType(KnownTypeCode.NullableOfT);
            var type     = nullable ? ((ParameterizedType)rrtype).TypeArguments[0] : rrtype;

            if (type.Kind == TypeKind.Struct)
            {
                if (Helpers.IsImmutableStruct(block.Emitter, type))
                {
                    return;
                }

                var memberResult = resolveResult as MemberResolveResult;

                var field = memberResult != null ? memberResult.Member as DefaultResolvedField : null;

                if (field != null && field.IsReadOnly)
                {
                    if (nullable)
                    {
                        block.Emitter.Output.Insert(insertPosition, JS.Types.SYSTEM_NULLABLE + "." + JS.Funcs.Math.LIFT1 + "(\"" + JS.Funcs.CLONE + "\", ");
                        block.WriteCloseParentheses();
                    }
                    else
                    {
                        block.Write("." + JS.Funcs.CLONE + "()");
                    }

                    return;
                }

                var isOperator = false;
                if (expression != null &&
                    (expression.Parent is BinaryOperatorExpression || expression.Parent is UnaryOperatorExpression))
                {
                    var orr = block.Emitter.Resolver.ResolveNode(expression.Parent, block.Emitter) as OperatorResolveResult;

                    isOperator = orr != null && orr.UserDefinedOperatorMethod != null;
                }

                if (expression == null || isOperator ||
                    expression.Parent is NamedExpression ||
                    expression.Parent is ObjectCreateExpression ||
                    expression.Parent is ArrayInitializerExpression ||
                    expression.Parent is ReturnStatement ||
                    expression.Parent is InvocationExpression ||
                    expression.Parent is AssignmentExpression ||
                    expression.Parent is VariableInitializer ||
                    expression.Parent is ForeachStatement && resolveResult is ForEachResolveResult)
                {
                    if (expression != null && expression.Parent is InvocationExpression)
                    {
                        var invocationExpression = (InvocationExpression)expression.Parent;
                        if (invocationExpression.Target == expression)
                        {
                            return;
                        }
                    }

                    if (nullable)
                    {
                        block.Emitter.Output.Insert(insertPosition, JS.Types.SYSTEM_NULLABLE + "." + JS.Funcs.Math.LIFT1 + "(\"" + JS.Funcs.CLONE + "\", ");
                        block.WriteCloseParentheses();
                    }
                    else
                    {
                        block.Write("." + JS.Funcs.CLONE + "()");
                    }
                }
            }
        }