private UnionScope(@NotNull GlobalSearchScope[] scopes) {
   super(
       ContainerUtil.getFirstItem(
           ContainerUtil.mapNotNull(
               scopes,
               new Function<GlobalSearchScope, Project>() {
                 @Override
                 public Project fun(GlobalSearchScope scope) {
                   return scope.getProject();
                 }
               }),
           null));
   if (scopes.length <= 1)
     throw new IllegalArgumentException("Too few scopes: " + Arrays.asList(scopes));
   myScopes = scopes;
   final int[] nested = {0};
   ContainerUtil.process(
       scopes,
       new Processor<GlobalSearchScope>() {
         @Override
         public boolean process(GlobalSearchScope scope) {
           nested[0] =
               Math.max(
                   nested[0],
                   scope instanceof UnionScope ? ((UnionScope) scope).myNestingLevel : 0);
           return true;
         }
       });
   myNestingLevel = 1 + nested[0];
   if (myNestingLevel > 1000) {
     throw new IllegalStateException(
         "Too many scopes combined: " + myNestingLevel + StringUtil.last(toString(), 500, true));
   }
 }
    private void registerActions(
        @NotNull final KeyStroke firstKeyStroke,
        @NotNull final List<Pair<AnAction, KeyStroke>> actions,
        final DataContext ctx) {
      ContainerUtil.process(
          actions,
          new Processor<Pair<AnAction, KeyStroke>>() {
            @Override
            public boolean process(final Pair<AnAction, KeyStroke> pair) {
              final String actionText = pair.getFirst().getTemplatePresentation().getText();
              final AbstractAction a =
                  new AbstractAction() {
                    @Override
                    public void actionPerformed(final ActionEvent e) {
                      cancel();
                      invokeAction(pair.getFirst(), ctx);
                    }
                  };

              final KeyStroke keyStroke = pair.getSecond();
              registerAction(actionText, keyStroke, a);

              if (keyStroke.getModifiers() == 0) {
                // do a little trick here, so if I will press Command+R and the second keystroke is
                // just 'R',
                // I want to be able to hold the Command while pressing 'R'

                final KeyStroke additionalKeyStroke =
                    KeyStroke.getKeyStroke(keyStroke.getKeyCode(), firstKeyStroke.getModifiers());
                final String _existing = getActionForKeyStroke(additionalKeyStroke);
                if (_existing == null)
                  registerAction("__additional__" + actionText, additionalKeyStroke, a);
              }

              return true;
            }
          });
    }
 @Override
 public int compare(@NotNull final VirtualFile file1, @NotNull final VirtualFile file2) {
   final int[] result = {0};
   ContainerUtil.process(
       myScopes,
       new Processor<GlobalSearchScope>() {
         @Override
         public boolean process(GlobalSearchScope scope) {
           int res1 =
               scope.contains(file1) && scope.contains(file2) ? scope.compare(file1, file2) : 0;
           if (result[0] == 0) {
             result[0] = res1;
             return true;
           }
           if (result[0] > 0 != res1 > 0) {
             result[0] = 0;
             return false;
           }
           return true;
         }
       });
   return result[0];
 }
    private InjectionsTable(final List<InjInfo> injections) {
      super(new ListTableModel<InjInfo>(createInjectionColumnInfos(), injections, 1));
      setAutoResizeMode(AUTO_RESIZE_LAST_COLUMN);
      getColumnModel().getColumn(2).setCellRenderer(createLanguageCellRenderer());
      getColumnModel().getColumn(1).setCellRenderer(createDisplayNameCellRenderer());
      getColumnModel().getColumn(0).setResizable(false);
      setShowGrid(false);
      setShowVerticalLines(false);
      setGridColor(getForeground());
      TableUtil.setupCheckboxColumn(getColumnModel().getColumn(0));

      new DoubleClickListener() {
        @Override
        protected boolean onDoubleClick(MouseEvent e) {
          final int row = rowAtPoint(e.getPoint());
          if (row < 0) return false;
          if (columnAtPoint(e.getPoint()) <= 0) return false;
          myInjectionsTable.getSelectionModel().setSelectionInterval(row, row);
          performEditAction();
          return true;
        }
      }.installOn(this);

      final String[] maxName = new String[] {""};
      ContainerUtil.process(
          injections,
          new Processor<InjInfo>() {
            public boolean process(final InjInfo injection) {
              String languageId = injection.injection.getInjectedLanguageId();
              Language language = InjectedLanguage.findLanguageById(languageId);
              String displayName = language == null ? languageId : language.getDisplayName();
              if (maxName[0].length() < displayName.length()) maxName[0] = displayName;
              return true;
            }
          });
      ContainerUtil.process(
          InjectedLanguage.getAvailableLanguages(),
          new Processor<Language>() {
            public boolean process(final Language language) {
              String displayName = language.getDisplayName();
              if (maxName[0].length() < displayName.length()) maxName[0] = displayName;
              return true;
            }
          });
      Icon icon = FileTypes.PLAIN_TEXT.getIcon();
      int preferred =
          (int) (new JLabel(maxName[0], icon, SwingConstants.LEFT).getPreferredSize().width * 1.1);
      getColumnModel().getColumn(2).setMinWidth(preferred);
      getColumnModel().getColumn(2).setPreferredWidth(preferred);
      getColumnModel().getColumn(2).setMaxWidth(preferred);
      new TableViewSpeedSearch<InjInfo>(this) {
        @Override
        protected String getItemText(@NotNull InjInfo element) {
          final BaseInjection injection = element.injection;
          return injection.getSupportId()
              + " "
              + injection.getInjectedLanguageId()
              + " "
              + injection.getDisplayName();
        }
      };
    }
  public void startRunInjectors(@NotNull final Document hostDocument, final boolean synchronously) {
    if (myProject.isDisposed()) return;
    if (!synchronously && ApplicationManager.getApplication().isWriteAccessAllowed()) return;
    // use cached to avoid recreate PSI in alien project
    final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(myProject);
    final PsiFile hostPsiFile = documentManager.getCachedPsiFile(hostDocument);
    if (hostPsiFile == null) return;

    final CopyOnWriteArrayList<DocumentWindow> injected =
        (CopyOnWriteArrayList<DocumentWindow>)
            InjectedLanguageUtil.getCachedInjectedDocuments(hostPsiFile);
    if (injected.isEmpty()) return;

    if (myProgress.isCanceled()) {
      myProgress = new DaemonProgressIndicator();
    }

    final Processor<DocumentWindow> commitProcessor =
        new Processor<DocumentWindow>() {
          @Override
          public boolean process(DocumentWindow documentWindow) {
            if (myProject.isDisposed()) return false;
            ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
            if (indicator != null && indicator.isCanceled()) return false;
            if (documentManager.isUncommited(hostDocument) || !hostPsiFile.isValid())
              return false; // will be committed later

            Segment[] ranges = documentWindow.getHostRanges();
            Segment rangeMarker = ranges.length > 0 ? ranges[0] : null;
            PsiElement element =
                rangeMarker == null
                    ? null
                    : hostPsiFile.findElementAt(rangeMarker.getStartOffset());
            if (element == null) {
              synchronized (PsiLock.LOCK) {
                injected.remove(documentWindow);
              }
              return true;
            }
            final DocumentWindow[] stillInjectedDocument = {null};
            // it is here where the reparse happens and old file contents replaced
            InjectedLanguageUtil.enumerate(
                element,
                hostPsiFile,
                true,
                new PsiLanguageInjectionHost.InjectedPsiVisitor() {
                  @Override
                  public void visit(
                      @NotNull PsiFile injectedPsi,
                      @NotNull List<PsiLanguageInjectionHost.Shred> places) {
                    stillInjectedDocument[0] =
                        (DocumentWindow) injectedPsi.getViewProvider().getDocument();
                    PsiDocumentManagerImpl.checkConsistency(injectedPsi, stillInjectedDocument[0]);
                  }
                });
            synchronized (PsiLock.LOCK) {
              if (stillInjectedDocument[0] == null) {
                injected.remove(documentWindow);
              } else if (stillInjectedDocument[0] != documentWindow) {
                injected.remove(documentWindow);
                injected.addIfAbsent(stillInjectedDocument[0]);
              }
            }

            return true;
          }
        };
    final Runnable commitInjectionsRunnable =
        new Runnable() {
          @Override
          public void run() {
            if (myProgress.isCanceled()) return;
            JobLauncher.getInstance()
                .invokeConcurrentlyUnderProgress(
                    new ArrayList<DocumentWindow>(injected),
                    myProgress,
                    !synchronously,
                    commitProcessor);
          }
        };

    if (synchronously) {
      if (Thread.holdsLock(PsiLock.LOCK)) {
        // hack for the case when docCommit was called from within PSI modification, e.g. in
        // formatter.
        // we can't spawn threads to do injections there, otherwise a deadlock is imminent
        ContainerUtil.process(new ArrayList<DocumentWindow>(injected), commitProcessor);
      } else {
        commitInjectionsRunnable.run();
      }
    } else {
      JobLauncher.getInstance()
          .submitToJobThread(
              Job.DEFAULT_PRIORITY,
              new Runnable() {
                @Override
                public void run() {
                  ApplicationManagerEx.getApplicationEx()
                      .tryRunReadAction(commitInjectionsRunnable);
                }
              });
    }
  }
 public boolean processAllClassNames(Processor<String> processor) {
   return ContainerUtil.process(getAllClassNames(), processor);
 }
  @Override
  public void startRunInjectors(@NotNull final Document hostDocument, final boolean synchronously) {
    if (myProject.isDisposed()) return;
    if (!synchronously && ApplicationManager.getApplication().isWriteAccessAllowed()) return;
    // use cached to avoid recreate PSI in alien project
    final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(myProject);
    final PsiFile hostPsiFile = documentManager.getCachedPsiFile(hostDocument);
    if (hostPsiFile == null) return;

    final ConcurrentList<DocumentWindow> injected =
        InjectedLanguageUtil.getCachedInjectedDocuments(hostPsiFile);
    if (injected.isEmpty()) return;

    if (myProgress.isCanceled()) {
      myProgress = new DaemonProgressIndicator();
    }
    final Set<DocumentWindow> newDocuments = Collections.synchronizedSet(new THashSet<>());
    final Processor<DocumentWindow> commitProcessor =
        documentWindow -> {
          if (myProject.isDisposed()) return false;
          ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
          if (indicator != null && indicator.isCanceled()) return false;
          if (documentManager.isUncommited(hostDocument) || !hostPsiFile.isValid())
            return false; // will be committed later

          // it is here where the reparse happens and old file contents replaced
          InjectedLanguageUtil.enumerate(
              documentWindow,
              hostPsiFile,
              (injectedPsi, places) -> {
                DocumentWindow newDocument =
                    (DocumentWindow) injectedPsi.getViewProvider().getDocument();
                if (newDocument != null) {
                  PsiDocumentManagerBase.checkConsistency(injectedPsi, newDocument);
                  newDocuments.add(newDocument);
                }
              });
          return true;
        };
    final Runnable commitInjectionsRunnable =
        () -> {
          if (myProgress.isCanceled()) return;
          JobLauncher.getInstance()
              .invokeConcurrentlyUnderProgress(
                  new ArrayList<>(injected), myProgress, true, commitProcessor);

          synchronized (ourInjectionPsiLock) {
            injected.clear();
            injected.addAll(newDocuments);
          }
        };

    if (synchronously) {
      if (Thread.holdsLock(PsiLock.LOCK)) {
        // hack for the case when docCommit was called from within PSI modification, e.g. in
        // formatter.
        // we can't spawn threads to do injections there, otherwise a deadlock is imminent
        ContainerUtil.process(new ArrayList<>(injected), commitProcessor);
      } else {
        commitInjectionsRunnable.run();
      }
    } else {
      JobLauncher.getInstance()
          .submitToJobThread(
              () ->
                  ApplicationManagerEx.getApplicationEx()
                      .tryRunReadAction(commitInjectionsRunnable),
              null);
    }
  }