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); } } }
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)); }); } } }
/// <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);