Node (@NotNull PsiExpression expression, @NotNull PsiExpression root) { Node result = new Expr(expression); PsiExpression parent; while (expression != root) { PsiElement parentElement = expression.getParent(); if (parentElement instanceof PsiExpressionList || parentElement instanceof PsiTemplate) { parentElement = parentElement.getParent(); } if (parentElement instanceof PsiStatement) { PsiSwitchExpression switchExpression = PsiTreeUtil.getParentOfType(parentElement, PsiSwitchExpression.class, true, PsiMember.class, PsiLambdaExpression.class); if (switchExpression != null && PsiTreeUtil.isAncestor(root, switchExpression, false)) { boolean isYield = parentElement instanceof PsiYieldStatement && ((PsiYieldStatement)parentElement).findEnclosingExpression() == switchExpression; boolean isRuleExpression = parentElement instanceof PsiExpressionStatement && parentElement.getParent() instanceof PsiSwitchLabeledRuleStatement && ((PsiSwitchLabeledRuleStatement)parentElement.getParent()).getEnclosingSwitchBlock() == switchExpression; if (isYield || isRuleExpression) { result = new Switch(switchExpression, Collections.singletonMap((PsiStatement)parentElement, result)); } else { result = new Switch(switchExpression, Collections.emptyMap()); } expression = switchExpression; continue; } } parent = ObjectUtils.tryCast(parentElement, PsiExpression.class); if (parent == null) { String message = PsiTreeUtil.isAncestor(root, expression, false) ? "Expected to have expression parent, got " + parentElement.getClass() : "Supplied root is not the expression ancestor"; throw new RuntimeExceptionWithAttachments(message, new Attachment("expression.txt", expression.getText()), new Attachment("root.txt", root.getText())); } result = foldNode(result, expression, parent); expression = parent; } return result; }