public static void collectTypeParameters(final Set<? super PsiTypeParameter> used, final PsiElement element,
                                           final Condition<? super PsiTypeParameter> filter) {
    element.accept(new JavaRecursiveElementVisitor() {
      @Override public void visitReferenceElement(@NotNull PsiJavaCodeReferenceElement reference) {
        super.visitReferenceElement(reference);
        if (!reference.isQualified() &&
            reference.resolve() instanceof PsiTypeParameter typeParameter &&
            PsiTreeUtil.isAncestor(typeParameter.getOwner(), element, false) &&
            filter.value(typeParameter)) {
          used.add(typeParameter);
        }
      }

      @Override
      public void visitExpression(final @NotNull PsiExpression expression) {
        super.visitExpression(expression);
        final PsiType type = expression.getType();
        if (type != null) {
          final PsiTypesUtil.TypeParameterSearcher searcher = new PsiTypesUtil.TypeParameterSearcher();
          type.accept(searcher);
          for (PsiTypeParameter typeParam : searcher.getTypeParameters()) {
            if (PsiTreeUtil.isAncestor(typeParam.getOwner(), element, false) && filter.value(typeParam)){
              used.add(typeParam);
            }
          }
        }
      }
    });
  }
public static void collectTypeParameters(final Set<? super PsiTypeParameter> used, final PsiElement element,
                                           final Condition<? super PsiTypeParameter> filter)