@Override
 public synchronized int registerTextEditorHighlightingPass(
     @NotNull TextEditorHighlightingPassFactory factory,
     @Nullable int[] runAfterCompletionOf,
     @Nullable int[] runAfterOfStartingOf,
     boolean runIntentionsPassAfter,
     int forcedPassId) {
   assert !checkedForCycles;
   PassConfig info =
       new PassConfig(
           factory,
           runAfterCompletionOf == null || runAfterCompletionOf.length == 0
               ? ArrayUtil.EMPTY_INT_ARRAY
               : runAfterCompletionOf,
           runAfterOfStartingOf == null || runAfterOfStartingOf.length == 0
               ? ArrayUtil.EMPTY_INT_ARRAY
               : runAfterOfStartingOf);
   int passId = forcedPassId == -1 ? nextAvailableId++ : forcedPassId;
   PassConfig registered = myRegisteredPassFactories.get(passId);
   assert registered == null
       : "Pass id " + passId + " has already been registered in: " + registered.passFactory;
   myRegisteredPassFactories.put(passId, info);
   if (factory instanceof DirtyScopeTrackingHighlightingPassFactory) {
     myDirtyScopeTrackingFactories.add((DirtyScopeTrackingHighlightingPassFactory) factory);
   }
   return passId;
 }
  private void checkForCycles() {
    final TIntObjectHashMap<TIntHashSet> transitivePredecessors =
        new TIntObjectHashMap<TIntHashSet>();

    myRegisteredPassFactories.forEachEntry(
        new TIntObjectProcedure<PassConfig>() {
          @Override
          public boolean execute(int passId, PassConfig config) {
            TIntHashSet allPredecessors = new TIntHashSet(config.completionPredecessorIds);
            allPredecessors.addAll(config.startingPredecessorIds);
            transitivePredecessors.put(passId, allPredecessors);
            allPredecessors.forEach(
                new TIntProcedure() {
                  @Override
                  public boolean execute(int predecessorId) {
                    PassConfig predecessor = myRegisteredPassFactories.get(predecessorId);
                    if (predecessor == null) return true;
                    TIntHashSet transitives = transitivePredecessors.get(predecessorId);
                    if (transitives == null) {
                      transitives = new TIntHashSet();
                      transitivePredecessors.put(predecessorId, transitives);
                    }
                    transitives.addAll(predecessor.completionPredecessorIds);
                    transitives.addAll(predecessor.startingPredecessorIds);
                    return true;
                  }
                });
            return true;
          }
        });
    transitivePredecessors.forEachKey(
        new TIntProcedure() {
          @Override
          public boolean execute(int passId) {
            if (transitivePredecessors.get(passId).contains(passId)) {
              throw new IllegalArgumentException(
                  "There is a cycle introduced involving pass "
                      + myRegisteredPassFactories.get(passId).passFactory);
            }
            return true;
          }
        });
  }
 @NotNull
 @Override
 public List<TextEditorHighlightingPass> instantiateMainPasses(
     @NotNull final PsiFile psiFile, @NotNull final Document document) {
   final THashSet<TextEditorHighlightingPass> ids = new THashSet<TextEditorHighlightingPass>();
   myRegisteredPassFactories.forEachKey(
       new TIntProcedure() {
         @Override
         public boolean execute(int passId) {
           PassConfig passConfig = myRegisteredPassFactories.get(passId);
           TextEditorHighlightingPassFactory factory = passConfig.passFactory;
           if (factory instanceof MainHighlightingPassFactory) {
             final TextEditorHighlightingPass pass =
                 ((MainHighlightingPassFactory) factory)
                     .createMainHighlightingPass(psiFile, document);
             if (pass != null) {
               ids.add(pass);
             }
           }
           return true;
         }
       });
   return new ArrayList<TextEditorHighlightingPass>(ids);
 }
  @Override
  @NotNull
  public List<TextEditorHighlightingPass> instantiatePasses(
      @NotNull final PsiFile psiFile,
      @NotNull final Editor editor,
      @NotNull final int[] passesToIgnore) {
    synchronized (this) {
      if (!checkedForCycles) {
        checkedForCycles = true;
        checkForCycles();
      }
    }
    PsiDocumentManager documentManager = PsiDocumentManager.getInstance(myProject);
    final Document document = editor.getDocument();
    PsiFile fileFromDoc = documentManager.getPsiFile(document);
    if (!(fileFromDoc instanceof PsiCompiledElement)) {
      assert fileFromDoc == psiFile : "Files are different: " + psiFile + ";" + fileFromDoc;
      Document documentFromFile = documentManager.getDocument(psiFile);
      assert documentFromFile == document
          : "Documents are different. Doc: "
              + document
              + "; Doc from file: "
              + documentFromFile
              + "; File: "
              + psiFile
              + "; Virtual file: "
              + PsiUtilCore.getVirtualFile(psiFile);
    }
    final TIntObjectHashMap<TextEditorHighlightingPass> id2Pass =
        new TIntObjectHashMap<TextEditorHighlightingPass>();
    final TIntArrayList passesRefusedToCreate = new TIntArrayList();
    myRegisteredPassFactories.forEachKey(
        new TIntProcedure() {
          @Override
          public boolean execute(int passId) {
            if (ArrayUtil.find(passesToIgnore, passId) != -1) {
              return true;
            }
            PassConfig passConfig = myRegisteredPassFactories.get(passId);
            TextEditorHighlightingPassFactory factory = passConfig.passFactory;
            final TextEditorHighlightingPass pass = factory.createHighlightingPass(psiFile, editor);

            if (pass == null) {
              passesRefusedToCreate.add(passId);
            } else {
              // init with editor's colors scheme
              pass.setColorsScheme(editor.getColorsScheme());

              TIntArrayList ids = new TIntArrayList(passConfig.completionPredecessorIds.length);
              for (int id : passConfig.completionPredecessorIds) {
                if (myRegisteredPassFactories.containsKey(id)) ids.add(id);
              }
              pass.setCompletionPredecessorIds(
                  ids.isEmpty() ? ArrayUtil.EMPTY_INT_ARRAY : ids.toNativeArray());
              ids = new TIntArrayList(passConfig.startingPredecessorIds.length);
              for (int id : passConfig.startingPredecessorIds) {
                if (myRegisteredPassFactories.containsKey(id)) ids.add(id);
              }
              pass.setStartingPredecessorIds(
                  ids.isEmpty() ? ArrayUtil.EMPTY_INT_ARRAY : ids.toNativeArray());
              pass.setId(passId);
              id2Pass.put(passId, pass);
            }
            return true;
          }
        });

    DaemonCodeAnalyzerEx daemonCodeAnalyzer = DaemonCodeAnalyzerEx.getInstanceEx(myProject);
    final FileStatusMap statusMap = daemonCodeAnalyzer.getFileStatusMap();
    passesRefusedToCreate.forEach(
        new TIntProcedure() {
          @Override
          public boolean execute(int passId) {
            statusMap.markFileUpToDate(document, passId);
            return true;
          }
        });

    return (List) Arrays.asList(id2Pass.getValues());
  }