public override void VisitAssignmentExpression(JsAssignmentExpression assignmentExpression)
        {
            base.VisitAssignmentExpression(assignmentExpression);

            // change assignment to observable property to observable invocation
            // only do for RestultIsObservable, not ResultMayBeObservable
            if (assignmentExpression.Left.HasAnnotation <ResultIsObservableAnnotation>())
            {
                var value    = assignmentExpression.Right.Detach();
                var assignee = assignmentExpression.Left.Detach();
                assignee.RemoveAnnotations <ResultIsObservableAnnotation>();
                if (value.IsComplexType())
                {
                    assignmentExpression.ReplaceWith(_ => new JsIdentifierExpression("dotvvm").Member("serialization").Member("deserialize").Invoke(value, assignee));
                }
                else
                {
                    // A = B -> A(B)
                    assignee.RemoveAnnotations <MayBeNullAnnotation>();
                    JsExpression newExpression = new JsInvocationExpression(assignee, value)
                                                 .WithAnnotation(ObservableSetterInvocationAnnotation.Instance);
                    if (assignmentExpression.Parent is JsExpression resultConsumer)
                    {
                        // assignment's result
                        if (assignee is JsMemberAccessExpression memberAccess)
                        {
                            // x.A(B) -> x.A(B).A
                            newExpression = AddAnnotations(newExpression.Member(memberAccess.MemberName).Invoke().WithAnnotation(ObservableUnwrapInvocationAnnotation.Instance), value);
                        }
                        else
                        {
                            // f() = CC -> f()(_a = CC), _a
                            var tmp = new JsTemporaryVariableParameter();
                            value.ReplaceWith(_ => new JsAssignmentExpression(new JsSymbolicParameter(tmp), value));
                            newExpression = AddAnnotations(new JsBinaryExpression(newExpression, BinaryOperatorType.Sequence, new JsSymbolicParameter(tmp)), value);
                        }
                    }
                    assignmentExpression.ReplaceWith(newExpression);
                }
            }
        }
示例#2
0
        protected void ProcessTargetedExpression(JsExpression expression, JsExpression defaultValue)
        {
            var target = expression.GetChildByRole(JsTreeRoles.TargetExpression);

            if (target.HasAnnotation <MayBeNullAnnotation>())
            {
                // A().B -> (A() || {}).B
                if (defaultValue != null &&
                    (expression.HasAnnotation <MayBeNullAnnotation>() || expression.IsRootResultExpression()) &&
                    target.IsComplexType() &&
                    IntroduceVariableFor(target, 1))
                {
                    target.ReplaceWith(_ =>
                                       new JsBinaryExpression(target, BinaryOperatorType.ConditionalOr, defaultValue));
                }
                // {A().B}.MORESTUFF -> (a=A()) == null : null ? a.B.MORESTUFF
                else
                {
                    var dependentExpression = GetDependentAncestorNode(expression);
                    if (IntroduceVariableFor(target))
                    {
                        var variable = new JsSymbolicParameter(new JsTemporaryVariableParameter());
                        target.ReplaceWith(variable);
                        target = new JsAssignmentExpression(variable.Clone(), target);
                    }
                    else
                    {
                        target = target.Clone();
                    }

                    ReplaceOrEmit(dependentExpression, _ => {
                        return(CreateNullCondition(target, dependentExpression).WithAnnotation(MayBeNullAnnotation.Instance));
                    });
                }
            }
        }
示例#3
0
 /// <summary>
 /// Equalses the specified other.
 /// </summary>
 /// <param name="other">The other.</param>
 /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
 protected bool Equals(JsAssignmentExpression other) =>
 Equals(Operator, other.Operator) && Equals(Left, other.Left) && Equals(Right, other.Right);