UExpression (@NotNull UExpression expression, boolean allowStringTransformation, @NotNull RestrictionInfoFactory<?> factory) { UExpression parent = expression; while (true) { UElement parentElement = parent.getUastParent(); if (parentElement instanceof ULocalVariable && parentElement.getUastParent() instanceof UDeclarationsExpression) { // Kotlin has strange hierarchy for elvis operator UExpressionList elvis = ObjectUtils.tryCast(parentElement.getUastParent().getUastParent(), UExpressionList.class); if (elvis != null) { parentElement = elvis; } } if (parentElement instanceof UExpressionList) { UExpression lastExpression = ContainerUtil.getLastItem(((UExpressionList)parentElement).getExpressions()); if (lastExpression != null && AnnotationContext.expressionsAreEquivalent(parent, lastExpression)) { // Result of expression list is the last expression in the list in Kotlin parentElement = parentElement.getUastParent(); } } UExpression next = ObjectUtils.tryCast(parentElement, UExpression.class); if (next == null || next instanceof UNamedExpression) return parent; if (next instanceof USwitchClauseExpression) { if (((USwitchClauseExpression)next).getCaseValues().contains(AnnotationContext.normalize(parent))) return parent; UExpressionList switchBody = ObjectUtils.tryCast(next.getUastParent(), UExpressionList.class); if (switchBody == null) return parent; USwitchExpression switchExpression = ObjectUtils.tryCast(switchBody.getUastParent(), USwitchExpression.class); if (switchExpression == null) return parent; next = switchExpression; } ULambdaExpression lambda = ObjectUtils.tryCast(next, ULambdaExpression.class); if (next instanceof UReturnExpression) { lambda = ObjectUtils.tryCast(((UReturnExpression)next).getJumpTarget(), ULambdaExpression.class); if (lambda == null) return parent; } if (lambda != null) { UCallExpression uastParent = ObjectUtils.tryCast(lambda.getUastParent(), UCallExpression.class); if (uastParent == null) return parent; PsiMethod method = uastParent.resolve(); if (method == null || !isPassthroughMethod(method, uastParent, lambda, factory)) return parent; next = uastParent; } if (next instanceof UQualifiedReferenceExpression && !TypeUtils.isJavaLangString(next.getExpressionType()) && !TypeUtils.typeEquals(CommonClassNames.JAVA_LANG_CHAR_SEQUENCE, next.getExpressionType())) { return parent; } if (next instanceof UPolyadicExpression && (!allowStringTransformation || ((UPolyadicExpression)next).getOperator() != UastBinaryOperator.PLUS)) { return parent; } if (next instanceof UCallExpression) { if (!UastExpressionUtils.isArrayInitializer(next) && !UastExpressionUtils.isNewArrayWithInitializer(next)) { PsiMethod method = ((UCallExpression)next).resolve(); boolean shouldGoThroughCall = TypeUtils.isJavaLangString(next.getExpressionType()) && (allowStringTransformation && isStringProcessingMethod(method, factory) || isPassthroughMethod(method, (UCallExpression)next, parent, factory)); if (!shouldGoThroughCall) return parent; } } if (next instanceof UIfExpression && AnnotationContext.expressionsAreEquivalent(parent, ((UIfExpression)next).getCondition())) { return parent; } if (next instanceof USwitchExpression) { final UExpression condExpression = ((USwitchExpression)next).getExpression(); if (condExpression != null && AnnotationContext.expressionsAreEquivalent(parent, condExpression)) { return parent; } } if (next instanceof UArrayAccessExpression) { return parent; } parent = next; } }