void (@NotNull TransformationContext context, @NotNull PairConsumer<? super PsiClass, ? super PsiSubstitutor> consumer) { Deque<Pair<PsiClass, PsiSubstitutor>> stack = new ArrayDeque<>(); for (PsiClassType superType : context.getSuperTypes()) { ClassResolveResult result = superType.resolveGenerics(); PsiClass superClass = result.getElement(); if (superClass == null) continue; stack.push(Pair.create(superClass, result.getSubstitutor())); } Set<PsiClass> visited = new HashSet<>(); while (!stack.isEmpty()) { Pair<PsiClass, PsiSubstitutor> current = stack.pop(); PsiClass currentClass = current.first; if (currentClass == context.getCodeClass()) { continue; } PsiSubstitutor currentSubstitutor = current.second; if (!visited.add(currentClass)) continue; if (GrTraitUtil.isTrait(currentClass)) { consumer.consume(currentClass, currentSubstitutor); } for (PsiClass superClass : currentClass.getSupers()) { PsiSubstitutor superSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(superClass, currentClass, currentSubstitutor); stack.push(Pair.create(superClass, superSubstitutor)); } } }