boolean (@NotNull final PsiParameter parameter, @NotNull final JavaSliceBuilder builder, @NotNull final Processor<? super SliceUsage> processor) { PsiElement declarationScope = parameter.getDeclarationScope(); if (declarationScope instanceof PsiForeachStatement statement) { PsiExpression iterated = statement.getIteratedValue(); return statement.getIterationParameter() != parameter || iterated == null || builder.incrementNesting().process(iterated, processor); } if (!(declarationScope instanceof PsiMethod method)) return true; final PsiType actualParameterType = parameter.getType(); final PsiParameter[] actualParameters = method.getParameterList().getParameters(); final int paramSeqNo = ArrayUtilRt.find(actualParameters, parameter); assert paramSeqNo != -1; // first, check if we are looking for a specific method call. // it happens when we were processing that very same method() return values somewhere up the tree SliceUsage specificMethodCall = findSpecificMethodCallUpTheTree(builder.getParent(), method); if (specificMethodCall != null) { SliceValueFilter filter = specificMethodCall.params.valueFilter; return processMethodCall(builder.withFilter(f -> f.copyStackFrom(filter)), processor, actualParameterType, actualParameters, paramSeqNo, specificMethodCall.getElement()); } Collection<PsiMethod> superMethods = ContainerUtil.newHashSet(method.findDeepestSuperMethods()); superMethods.add(method); final Set<PsiReference> processed = new HashSet<>(); //usages of super method and overridden method can overlap for (final PsiMethod superMethod : superMethods) { if (!MethodReferencesSearch.search(superMethod, builder.getSearchScope(), true).forEach(reference -> { ProgressManager.checkCanceled(); synchronized (processed) { if (!processed.add(reference)) return true; } PsiElement refElement = reference.getElement(); return processMethodCall(builder, processor, actualParameterType, actualParameters, paramSeqNo, refElement); })) { return false; } } return true; }