public static @NotNull Map<LocalInspectionToolWrapper, List<ProblemDescriptor>> inspectEx(@NotNull List<? extends LocalInspectionToolWrapper> toolWrappers,
                                                                                   @NotNull PsiFile psiFile,
                                                                                   @NotNull TextRange restrictRange,
                                                                                   @NotNull TextRange priorityRange,
                                                                                   boolean isOnTheFly,
                                                                                   boolean inspectInjectedPsi,
                                                                                   boolean ignoreSuppressedElements,
                                                                                   @NotNull ProgressIndicator indicator,
                                                                                   // when returned true -> add to the holder, false -> do not add to the holder
                                                                                   @NotNull PairProcessor<? super LocalInspectionToolWrapper, ? super ProblemDescriptor> foundDescriptorCallback) {
    if (toolWrappers.isEmpty()) return Collections.emptyMap();

    List<Divider.DividedElements> allDivided = new ArrayList<>();
    Divider.divideInsideAndOutsideAllRoots(psiFile, restrictRange, priorityRange, Predicates.alwaysTrue(), new CommonProcessors.CollectProcessor<>(allDivided));

    List<PsiElement> elements = ContainerUtil.concat(
      ContainerUtil.map(allDivided, d -> ContainerUtil.concat(d.inside(), d.outside(), d.parents())));

    Map<LocalInspectionToolWrapper, List<ProblemDescriptor>> map = inspectElements(toolWrappers, psiFile, restrictRange, ignoreSuppressedElements, isOnTheFly, indicator, elements, foundDescriptorCallback);
    if (inspectInjectedPsi) {
      InjectedLanguageManager injectedLanguageManager = InjectedLanguageManager.getInstance(psiFile.getProject());
      Set<Pair<PsiFile, PsiElement>> injectedFiles = new HashSet<>();
      for (PsiElement element : elements) {
        if (element instanceof PsiLanguageInjectionHost) {
          List<Pair<PsiElement, TextRange>> files = injectedLanguageManager.getInjectedPsiFiles(element);
          if (files != null) {
            for (Pair<PsiElement, TextRange> pair : files) {
              PsiFile injectedFile = (PsiFile)pair.getFirst();
              injectedFiles.add(Pair.create(injectedFile, element));
            }
          }
        }
      }
      if (!JobLauncher.getInstance().invokeConcurrentlyUnderProgress(new ArrayList<>(injectedFiles), indicator, pair -> {
        PsiFile injectedFile = pair.getFirst();
        PsiElement host = pair.getSecond();
        List<PsiElement> injectedElements = new ArrayList<>();
        Set<String> injectedDialects = new HashSet<>();
        getAllElementsAndDialectsFrom(injectedFile, injectedElements, injectedDialects);
        Map<LocalInspectionToolWrapper, List<ProblemDescriptor>> result =
          inspectElements(toolWrappers, injectedFile, injectedFile.getTextRange(), isOnTheFly, indicator, ignoreSuppressedElements,
                          injectedElements,
                          injectedDialects, foundDescriptorCallback);
        for (Map.Entry<LocalInspectionToolWrapper, List<ProblemDescriptor>> entry : result.entrySet()) {
          LocalInspectionToolWrapper toolWrapper = entry.getKey();
          List<ProblemDescriptor> descriptors = entry.getValue();
          List<ProblemDescriptor> filtered = ignoreSuppressedElements ? ContainerUtil.filter(descriptors, descriptor -> !toolWrapper.getTool().isSuppressedFor(host)) : descriptors;
          // in case two injected fragments contain result of the same inspection, concatenate them
          // assume map is ConcurrentHashMap here, otherwise synchronization would be needed
          map.merge(toolWrapper, filtered, (oldList, newList)->ContainerUtil.concat(oldList, newList));
        }
        return true;
      })) {
        throw new ProcessCanceledException();
      }
    }

    return map;
  }
public static @NotNull Map<LocalInspectionToolWrapper, List<ProblemDescriptor>> inspectEx(@NotNull List<? extends LocalInspectionToolWrapper> toolWrappers,
                                                                                   @NotNull PsiFile psiFile,
                                                                                   @NotNull TextRange restrictRange,
                                                                                   @NotNull TextRange priorityRange,
                                                                                   boolean isOnTheFly,
                                                                                   boolean inspectInjectedPsi,
                                                                                   boolean ignoreSuppressedElements,
                                                                                   @NotNull ProgressIndicator indicator,
                                                                                   // when returned true -> add to the holder, false -> do not add to the holder
                                                                                   @NotNull PairProcessor<? super LocalInspectionToolWrapper, ? super ProblemDescriptor> foundDescriptorCallback)