@NotNull private static PsiExpression getTopLevel(Project project, @NotNull PsiExpression expression) { int i = 0; while (expression.getParent() instanceof PsiExpression) { i++; final PsiExpression parent = (PsiExpression) expression.getParent(); if (parent instanceof PsiConditionalExpression && ((PsiConditionalExpression) parent).getCondition() == expression) break; expression = parent; if (expression instanceof PsiAssignmentExpression) break; if (i > 10 && expression instanceof PsiBinaryExpression) { ParameterizedCachedValue<PsiExpression, Pair<Project, PsiExpression>> value = expression.getUserData(TOP_LEVEL_EXPRESSION); if (value != null && value.hasUpToDateValue()) { return getToplevelExpression( project, expression); // optimization: use caching for big hierarchies } } } return expression; }
@Override public CachedValueProvider.Result<PsiExpression> compute( Pair<Project, PsiExpression> pair) { PsiExpression param = pair.second; Project project = pair.first; PsiExpression topLevel = getTopLevel(project, param); ParameterizedCachedValue<PsiExpression, Pair<Project, PsiExpression>> cachedValue = param.getUserData(TOP_LEVEL_EXPRESSION); assert cachedValue != null; int i = 0; for (PsiElement element = param; element != topLevel; element = element.getParent(), i++) { if (i % 10 == 0) { // optimization: store up link to the top level expression in each 10nth // element element.putUserData(TOP_LEVEL_EXPRESSION, cachedValue); } } return CachedValueProvider.Result.create( topLevel, PsiManager.getInstance(project).getModificationTracker()); }