protected bool IntroduceVariableFor(JsExpression expression, int limit = 2) { if (expression is JsIdentifierExpression) { return(false); } if (expression is JsSymbolicParameter symbol) { return(false); } if (limit > 0 && (expression is JsMemberAccessExpression memberAccess || expression is JsInvocationExpression invocation && invocation.Arguments.Count == 0 && invocation.HasAnnotation <ObservableUnwrapInvocationAnnotation>())) { return(IntroduceVariableFor(expression.GetChildByRole(JsTreeRoles.TargetExpression), limit - 1)); } return(true); }
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)); }); } } }