@Override
      public void visitCodeBlock(@NotNull PsiCodeBlock block) {
        if (block.getTextLength() < minLength) return;
        PsiParameterListOwner container = PsiTreeUtil.getParentOfType(block, PsiParameterListOwner.class);
        if (container == null) return;
        PsiElement body = container.getBody();
        if (body == null) return;
        PsiStatement[] statements = block.getStatements();
        BitSet declarations = getDeclarations(statements);
        if (declarations.isEmpty()) return;
        int maxLength = body.getTextLength() * 3 / 5;
        if (maxLength < minLength) return;
        int maxCount;
        if (block == body) {
          maxCount = statements.length - 1;
          if (ArrayUtil.getLastElement(statements) instanceof PsiReturnStatement) {
            maxCount--;
          }
        }
        else {
          maxCount = statements.length;
        }
        PsiElement fragment = ControlFlowUtil.findCodeFragment(block);
        for (int count = maxCount; count > 1; count--) {
          for (int from = 0; from < statements.length - count; from++) {
            int to = from + count;
            
            // Check that we have at least one declaration
            int nextDeclaration = declarations.nextSetBit(from);
            if (nextDeclaration == -1 || nextDeclaration >= to) continue;
            PsiStatement[] range = Arrays.copyOfRange(statements, from, to);
            if (ContainerUtil.exists(range, e -> e instanceof PsiSwitchLabelStatementBase)) continue;
            TextRange textRange = getRange(range);
            int length = range[range.length - 1].getTextRange().getEndOffset() - range[0].getTextRange().getStartOffset();
            if (length < minLength || textRange.getLength() > maxLength) continue;
            try {
              ControlFlowWrapper wrapper = new ControlFlowWrapper(fragment, range);
              Collection<PsiStatement> exitStatements = wrapper.prepareExitStatements(range);
              if (!exitStatements.isEmpty()) continue;
              if (wrapper.isGenerateConditionalExit() || wrapper.isReturnPresentBetween()) continue;
              PsiVariable[] variables = wrapper.getOutputVariables();
              if (variables.length != 1) continue;
              PsiVariable output = variables[0];
              if (SideEffectsVisitor.hasSideEffectOrSimilarUseOutside(range, output)) continue;

              List<PsiVariable> inputVariables = wrapper.getInputVariables(fragment, range, variables);
              if (inputVariables.size() > maxParameters) continue;
              ExtractMethodAnalyzerKt.findExtractOptions(Arrays.asList(range), false); // check whether ExtractException will happen
              if (voidPrefix(fragment, range, output)) continue;
              if (!outputUsedInLastStatement(range, output)) continue;
              wrapper.checkExitStatements(range, fragment);
              if (to < statements.length) {
                PsiStatement nextStatement = statements[to];
                if (nextStatement instanceof PsiReturnStatement ret && 
                    ExpressionUtils.isReferenceTo(ret.getReturnValue(), output)) {
                  textRange = textRange.union(ret.getTextRangeInParent());
                }
              }
              List<LocalQuickFix> fixes = new ArrayList<>();
              ExtractMethodFix extractFix = new ExtractMethodFix(from, count, output, inputVariables);
              fixes.add(extractFix);
              if (inputVariables.size() > 1) {
                fixes.add(LocalQuickFix.from(new UpdateInspectionOptionFix(
                  ExtractMethodRecommenderInspection.this, "maxParameters",
                  JavaAnalysisBundle.message("inspection.extract.method.dont.suggest.parameters", inputVariables.size()),
                  inputVariables.size() - 1)));
              }
              if (length < 10_000) {
                fixes.add(LocalQuickFix.from(new UpdateInspectionOptionFix(
                  ExtractMethodRecommenderInspection.this, "minLength",
                  JavaAnalysisBundle.message("inspection.extract.method.dont.suggest.length"),
                  length + 1)));
              }
              int firstLineBreak = textRange.substring(block.getText()).indexOf('\n');
              PsiElement anchor = block;
              if (firstLineBreak > -1) {
                textRange = TextRange.from(textRange.getStartOffset(), firstLineBreak);
                TextRange firstStatementRange = statements[from].getTextRangeInParent();
                if (firstStatementRange.getStartOffset() == textRange.getStartOffset() &&
                    firstStatementRange.getEndOffset() >= textRange.getEndOffset()) {
                  anchor = statements[from];
                  extractFix.shouldUseParent();
                  textRange = textRange.shiftLeft(textRange.getStartOffset());
                }
              }
              holder.registerProblem(anchor, JavaAnalysisBundle.message("inspection.extract.method.message", output.getName()),
                                     ProblemHighlightType.WEAK_WARNING,
                                     textRange,
                                     fixes.toArray(LocalQuickFix.EMPTY_ARRAY));
              return;
            }
            catch (PrepareFailedException | ControlFlowWrapper.ExitStatementsNotSameException | ExtractException ignored) {
            }
          }
        }
      }
@Override
      public void visitCodeBlock(@NotNull PsiCodeBlock block)