JsExpression GetDependentAncestorNode(JsExpression expr) { while (expr.Parent is JsExpression parent && !expr.HasAnnotation <MayBeNullAnnotation>() && expr.Role == JsTreeRoles.TargetExpression) { expr = parent; } return(expr); }
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)); }); } } }