public final PsiTypeVariable create(final PsiElement context) {
    return new PsiTypeVariable() {
      private final int myIndex = myCurrent++;
      private final PsiElement myContext = context;

      @Override
      public boolean isValidInContext(final PsiType type) {
        if (myContext == null) {
          return true;
        }

        if (type == null) {
          return true;
        }

        return type.accept(new PsiTypeVisitor<Boolean>() {
          @Override
          public Boolean visitType(@NotNull final PsiType type) {
            return Boolean.TRUE;
          }

          @Override
          public Boolean visitArrayType(@NotNull final PsiArrayType arrayType) {
            return arrayType.getDeepComponentType().accept(this);
          }

          @Override
          public Boolean visitWildcardType(@NotNull final PsiWildcardType wildcardType) {
            final PsiType bound = wildcardType.getBound();

            if (bound != null) {
              bound.accept(this);
            }

            return Boolean.TRUE;
          }

          @Override
          public Boolean visitClassType(@NotNull final PsiClassType classType) {
            final PsiClassType.ClassResolveResult result = classType.resolveGenerics();
            final PsiClass aClass = result.getElement();
            final PsiSubstitutor aSubst = result.getSubstitutor();

            if (aClass != null) {
              final PsiManager manager = aClass.getManager();
              final JavaPsiFacade facade = JavaPsiFacade.getInstance(manager.getProject());

              if (aClass instanceof PsiTypeParameter) {
                final PsiTypeParameterListOwner owner = PsiTreeUtil.getParentOfType(myContext, PsiTypeParameterListOwner.class);

                if (owner != null) {
                  boolean found = false;

                  for (PsiTypeParameter typeParameter : PsiUtil.typeParametersIterable(owner)) {
                    found = manager.areElementsEquivalent(typeParameter, aClass);
                    if (found) break;
                  }

                  if (!found) {
                    return Boolean.FALSE;
                  }
                }
                else {
                  return Boolean.FALSE;
                }
              }
              else if (!facade.getResolveHelper().isAccessible(aClass, myContext, null)) {
                return Boolean.FALSE;
              }

              for (PsiTypeParameter parm : PsiUtil.typeParametersIterable(aClass)) {
                final PsiType type = aSubst.substitute(parm);

                if (type != null) {
                  final Boolean b = type.accept(this);

                  if (!b.booleanValue()) {
                    return Boolean.FALSE;
                  }
                }
              }

              return Boolean.TRUE;
            }
            else {
              return Boolean.FALSE;
            }
          }
        }).booleanValue();
      }

      @Override
      @NotNull
      public String getPresentableText() {
        return "$" + myIndex;
      }

      @Override
      @NotNull
      public String getCanonicalText() {
        return getPresentableText();
      }

      @Override
      public boolean isValid() {
        return true;
      }

      @Override
      public boolean equalsToText(@NotNull String text) {
        return text.equals(getPresentableText());
      }

      @Override
      public GlobalSearchScope getResolveScope() {
        return null;
      }

      @Override
      public PsiType @NotNull [] getSuperTypes() {
        return EMPTY_ARRAY;
      }

      public boolean equals(Object o) {
        if (this == o) return true;
        return o instanceof PsiTypeVariable psiTypeVariable && myIndex == psiTypeVariable.getIndex();
      }

      public int hashCode() {
        return myIndex;
      }

      @Override
      public int getIndex() {
        return myIndex;
      }
    };
  }
public final PsiTypeVariable create(final PsiElement context)