@NotNull
  @Override
  public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
    if (!PsiUtil.isLanguageLevel9OrHigher(holder.getFile())) {
      return PsiElementVisitor.EMPTY_VISITOR;
    }
    return new JavaElementVisitor() {
      @Override
      public void visitMethodCallExpression(@NotNull PsiMethodCallExpression call) {
        if (!CLEANER_REGISTER.test(call)) return;
        PsiExpression[] expressions = call.getArgumentList().getExpressions();
        PsiExpression trackedObject = ExpressionUtils.resolveExpression(expressions[0]);
        PsiExpression runnableExpression = ExpressionUtils.resolveExpression(expressions[1]);
        if (trackedObject == null || runnableExpression == null) return;

        final PsiElement highlightingElement;
        final String referenceName;
        if (trackedObject instanceof PsiThisExpression) {
          PsiClassType classType = tryCast(trackedObject.getType(), PsiClassType.class);
          if (classType == null) return;
          PsiClass trackedClass = classType.resolve();
          if (trackedClass == null) return;
          PsiElement elementCapturingThis = getElementCapturingThis(runnableExpression, trackedClass);
          if (elementCapturingThis == null) return;
          highlightingElement = elementCapturingThis;
          referenceName = "this";
        }
        else if (trackedObject instanceof PsiReferenceExpression) {
          PsiVariable variable = tryCast(((PsiReferenceExpression)trackedObject).resolve(), PsiVariable.class);
          if (variable == null) return;
          if (variable instanceof PsiField) return;
          if (!VariableAccessUtils.variableIsUsed(variable, runnableExpression)) return;
          Optional<PsiElement> referenceExpression = StreamEx.ofTree(((PsiElement)runnableExpression), el -> StreamEx.of(el.getChildren()))
            .findAny(el -> el instanceof PsiReferenceExpression &&
                           ((PsiReferenceExpression)el).isReferenceTo(variable));
          if (referenceExpression.isEmpty()) return;
          String variableName = variable.getName();
          if (variableName == null) return;
          highlightingElement = referenceExpression.get();
          referenceName = variableName;
        }
        else {
          return;
        }
        holder.registerProblem(highlightingElement, JavaBundle.message("inspection.capturing.cleaner", referenceName));
      }


      @Nullable
      private static PsiElement getElementCapturingThis(@NotNull PsiExpression runnableExpr,
                                                        @NotNull PsiClass trackedClass) {
        if (runnableExpr instanceof PsiMethodReferenceExpression methodReference) {
          if (PsiMethodReferenceUtil.isStaticallyReferenced(methodReference)) return null;

          PsiElement qualifier = methodReference.getQualifier();
          if (qualifier instanceof PsiThisExpression) {
            PsiClass thisClass = PsiUtil.resolveClassInType(((PsiThisExpression)qualifier).getType());
            if (thisClass != trackedClass) return null;
            return qualifier;
          }
          return null;
        }
        if (runnableExpr instanceof PsiLambdaExpression lambda) {
          if (!lambda.getParameterList().isEmpty()) return null;
          PsiElement lambdaBody = lambda.getBody();
          if (lambdaBody == null) return null;
          return getLambdaOrInnerClassElementCapturingThis(lambdaBody, trackedClass);
        }
        if (runnableExpr instanceof PsiNewExpression newExpression) {
          if (newExpression.getAnonymousClass() != null) {
            if (PsiUtil.isAvailable(JavaFeature.INNER_NOT_CAPTURE_THIS, trackedClass)) {
              PsiElement elementCapturingThis = getLambdaOrInnerClassElementCapturingThis(newExpression, trackedClass);
              if (elementCapturingThis != null) {
                return elementCapturingThis;
              }
            } else {
              return newExpression;
            }
          }
          PsiJavaCodeReferenceElement classReference = newExpression.getClassReference();
          if (classReference == null) return null;
          PsiClass aClass = tryCast(classReference.resolve(), PsiClass.class);
          if (aClass == null) return null;
          if (aClass.getContainingClass() != trackedClass) return null;
          if (aClass.hasModifierProperty(PsiModifier.STATIC)) return null;
          if (PsiUtil.isAvailable(JavaFeature.INNER_NOT_CAPTURE_THIS, trackedClass) && 
              getLambdaOrInnerClassElementCapturingThis(newExpression, trackedClass) == null) return null;
          return classReference;
        }
        return null;
      }
    };
  }
@NotNull
  @Override
  public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly)