@NotNull
  @Override
  public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
    boolean useVar = IntroduceVariableBase.createVarType() || forceUseVar;
    return new JavaElementVisitor() {
      private final Options options = new Options(maxNotUsedComponentCounts,
                                                  Math.min(maxComponentCounts, MAX_COMPONENT_COUNTS),
                                                  Math.min(maxLevel, MAX_LEVEL), useVar, isOnTheFly);

      @Override
      public void visitForeachStatement(@NotNull PsiForeachStatement statement) {
        super.visitForeachStatement(statement);
        ComponentContext context = createContext(statement, options);
        if (context == null) return;
        processComponentContext(context, this::highlight);
      }

      @Override
      public void visitForeachPatternStatement(@NotNull PsiForeachPatternStatement statement) {
        super.visitForeachPatternStatement(statement);
        boolean showAsInfo = false;
        if (options.maxLevel <= 0) {
          return;
        }
        PsiStatement foreachBody = statement.getBody();
        if (foreachBody == null) {
          return;
        }
        PsiPattern pattern = statement.getIterationPattern();
        if (!(pattern instanceof PsiDeconstructionPattern deconstructionPattern)) {
          return;
        }
        Deque<DeconstructionContext> queueToProcess = new ArrayDeque<>();
        queueToProcess.add(new DeconstructionContext(1, deconstructionPattern, statement));
        while (!queueToProcess.isEmpty()) {
          DeconstructionContext currentContext = queueToProcess.poll();
          int level = currentContext.level;
          if (level >= options.maxLevel + 1) {
            if (!options.isOnTheFly) {
              return;
            }
            showAsInfo = true;
          }
          PsiDeconstructionPattern currentDeconstruction = currentContext.pattern;
          PsiDeconstructionList list = currentDeconstruction.getDeconstructionList();
          for (PsiPattern component : list.getDeconstructionComponents()) {
            if (component instanceof PsiDeconstructionPattern newDeconstruction) {
              queueToProcess.add(new DeconstructionContext(level + 1, newDeconstruction, currentContext.foreachPatternStatement));
              continue;
            }
            if (component instanceof PsiTypeTestPattern typeTestPattern) {
              PsiTypeElement typeElement = typeTestPattern.getCheckType();
              PsiPatternVariable variable = typeTestPattern.getPatternVariable();
              if (typeElement == null || variable == null) {
                continue;
              }
              PsiType type = typeElement.getType();
              PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
              if (type instanceof PsiClassType referenceType) {
                substitutor = referenceType.resolveGenerics().getSubstitutor();
              }
              PsiClass parameterClass = PsiUtil.resolveClassInClassTypeOnly(type);
              if (parameterClass == null) {
                continue;
              }
              ShowInfoFolder showInfoFolder = new ShowInfoFolder();
              showInfoFolder.showInfo = showAsInfo;
              ComponentContext context =
                new ComponentContext(level, variable, parameterClass, substitutor, currentContext.foreachPatternStatement, options,
                                     showInfoFolder);
              processComponentContext(context, this::highlight);
            }
          }
        }
      }

      private void highlight(@NotNull ComponentContext context,
                             @NotNull Map<String, List<PsiElement>> components) {
        if (context.showInfoFolder.showInfo && !context.options.isOnTheFly) {
          return;
        }
        registerProblemForIdentifier(context.currentParameter, context, holder);
      }

      private void registerProblemForIdentifier(@NotNull PsiVariable variable,
                                                @NotNull ComponentContext context,
                                                @NotNull ProblemsHolder holder) {
        PsiIdentifier[] identifiers = PsiTreeUtil.getChildrenOfType(variable, PsiIdentifier.class);
        if (identifiers == null || identifiers.length != 1) {
          return;
        }
        PsiIdentifier identifier = identifiers[0];
        LocalQuickFix localQuickFix = getLocalQuickFix(context);
        if (context.showInfoFolder.showInfo) {
          holder.registerProblem(identifier,
                                 InspectionGadgetsBundle.message("inspection.enhanced.for.with.record.pattern.can.be.used.message"),
                                 ProblemHighlightType.INFORMATION,
                                 localQuickFix);
        }
        else {
          List<LocalQuickFix> fixes = new ArrayList<>();
          fixes.add(localQuickFix);
          int length = context.recordClass.getRecordComponents().length;
          if (length > 1) {
            fixes.add(
              LocalQuickFix.from(new UpdateInspectionOptionFix(
                ForEachWithRecordPatternCanBeUsedInspection.this, "maxComponentCounts",
                InspectionGadgetsBundle.message("inspection.enhanced.for.with.record.pattern.can.be.used.maximum.number.disabled", length),
                length - 1)));
          }
          Integer level = context.level;
          if (level != null && level > 0) {
            fixes.add(LocalQuickFix.from(new UpdateInspectionOptionFix(
              ForEachWithRecordPatternCanBeUsedInspection.this, "maxLevel",
              InspectionGadgetsBundle.message("inspection.enhanced.for.with.record.pattern.can.be.used.maximum.depth.disabled", level), 
              level - 1)));
          }
          holder.registerProblem(identifier,
                                 InspectionGadgetsBundle.message("inspection.enhanced.for.with.record.pattern.can.be.used.message"),
                                 fixes.toArray(LocalQuickFix.EMPTY_ARRAY));
        }
      }

      @NotNull
      private LocalQuickFix getLocalQuickFix(@NotNull ComponentContext context) {
        return new ForEachWithRecordCanBeUsedFix(context.base, context.currentParameter);
      }
    };
  }
@NotNull
  @Override
  public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly)