private static @NotNull Map<LocalInspectionToolWrapper, List<ProblemDescriptor>> inspectElements(@NotNull List<? extends LocalInspectionToolWrapper> toolWrappers,
                                                                                                   @NotNull PsiFile psiFile,
                                                                                                   @NotNull TextRange restrictRange,
                                                                                                   boolean isOnTheFly,
                                                                                                   @NotNull ProgressIndicator indicator,
                                                                                                   boolean ignoreSuppressedElements,
                                                                                                   @NotNull List<? extends PsiElement> elements,
                                                                                                   @NotNull Set<String> elementDialectIds,
                                                                                                   // when returned true -> add to the holder, false -> do not add to the holder
                                                                                                   @NotNull PairProcessor<? super LocalInspectionToolWrapper, ? super ProblemDescriptor> foundDescriptorCallback) {
    Map<LocalInspectionToolWrapper, List<ProblemDescriptor>> resultDescriptors = new ConcurrentHashMap<>();
    withSession(psiFile, restrictRange, restrictRange, HighlightSeverity.INFORMATION, isOnTheFly, session -> {
      List<LocalInspectionToolWrapper> applicableTools = filterToolsApplicableByLanguage(toolWrappers, elementDialectIds, elementDialectIds);

      InspectionVisitorOptimizer inspectionVisitorsOptimizer = new InspectionVisitorOptimizer(elements);

      InspectListener inspectionListener = isOnTheFly ? null : psiFile.getProject().getMessageBus().syncPublisher(GlobalInspectionContextEx.INSPECT_TOPIC);

      Processor<LocalInspectionToolWrapper> processor = toolWrapper -> {
        ProblemsHolder holder = new ProblemsHolder(InspectionManager.getInstance(psiFile.getProject()), psiFile, isOnTheFly) {
          @Override
          public void registerProblem(@NotNull ProblemDescriptor descriptor) {
            if (!isOnTheFly) {
              ProblemHighlightType highlightType = descriptor.getHighlightType();
              if (warnAboutInformationLevelInBatchMode(highlightType, toolWrapper, psiFile)) {
                return;
              }
              if (highlightType == ProblemHighlightType.POSSIBLE_PROBLEM) {
                return;
              }
            }

            if (foundDescriptorCallback.process(toolWrapper, descriptor)) {
              super.registerProblem(descriptor);
            }
          }
        };
        LocalInspectionTool tool = toolWrapper.getTool();

        try {
          long inspectionStartTime = System.nanoTime();
          boolean inspectionWasRun;
          PsiElementVisitor visitor = createVisitor(tool, holder, isOnTheFly, session);
          // if inspection returned an empty visitor, then it should be skipped
          if (visitor == PsiElementVisitor.EMPTY_VISITOR) {
            inspectionWasRun = false;
          }
          else {
            inspectionWasRun = true;
            tool.inspectionStarted(session, isOnTheFly);
            inspectionVisitorsOptimizer.acceptElements(elements, visitor);
            tool.inspectionFinished(session, holder);
          }

          long inspectionDuration = TimeoutUtil.getDurationMillis(inspectionStartTime);

          if (inspectionListener != null && inspectionWasRun) {
            inspectionListener.inspectionFinished(
              inspectionDuration,
              Thread.currentThread().getId(),
              holder.getResultCount(),
              toolWrapper,
              InspectListener.InspectionKind.LOCAL,
              psiFile,
              psiFile.getProject()
            );
          }
        }
        catch (Exception e) {
          if (inspectionListener != null) {
            inspectionListener.inspectionFailed(
              toolWrapper.getID(),
              e,
              psiFile,
              psiFile.getProject()
            );
          }
          throw e;
        }

        if (holder.hasResults()) {
          List<ProblemDescriptor> descriptors = ContainerUtil.filter(holder.getResults(), descriptor -> {
            PsiElement element = descriptor.getPsiElement();
            return element == null || !ignoreSuppressedElements || !SuppressionUtil.inspectionResultSuppressed(element, tool);
          });
          resultDescriptors.put(toolWrapper, descriptors);
        }

        return true;
      };
      JobLauncher.getInstance().invokeConcurrentlyUnderProgress(applicableTools, indicator, processor);
    });

    return resultDescriptors;
  }
private static @NotNull Map<LocalInspectionToolWrapper, List<ProblemDescriptor>> inspectElements(@NotNull List<? extends LocalInspectionToolWrapper> toolWrappers,
                                                                                                   @NotNull PsiFile psiFile,
                                                                                                   @NotNull TextRange restrictRange,
                                                                                                   boolean isOnTheFly,
                                                                                                   @NotNull ProgressIndicator indicator,
                                                                                                   boolean ignoreSuppressedElements,
                                                                                                   @NotNull List<? extends PsiElement> elements,
                                                                                                   @NotNull Set<String> elementDialectIds,
                                                                                                   // when returned true -> add to the holder, false -> do not add to the holder
                                                                                                   @NotNull PairProcessor<? super LocalInspectionToolWrapper, ? super ProblemDescriptor> foundDescriptorCallback)