public static void clearCaches(
     @NotNull PsiFile injected, @NotNull DocumentWindowImpl documentWindow) {
   VirtualFileWindowImpl virtualFile = (VirtualFileWindowImpl) injected.getVirtualFile();
   PsiManagerEx psiManagerEx = (PsiManagerEx) injected.getManager();
   if (psiManagerEx.getProject().isDisposed()) return;
   psiManagerEx.getFileManager().setViewProvider(virtualFile, null);
   PsiElement context =
       InjectedLanguageManager.getInstance(injected.getProject()).getInjectionHost(injected);
   PsiFile hostFile;
   if (context != null) {
     hostFile = context.getContainingFile();
   } else {
     VirtualFile delegate = virtualFile.getDelegate();
     hostFile = delegate.isValid() ? psiManagerEx.findFile(delegate) : null;
   }
   if (hostFile != null) {
     // modification of cachedInjectedDocuments must be under PsiLock
     synchronized (PsiLock.LOCK) {
       List<DocumentWindow> cachedInjectedDocuments = getCachedInjectedDocuments(hostFile);
       for (int i = cachedInjectedDocuments.size() - 1; i >= 0; i--) {
         DocumentWindow cachedInjectedDocument = cachedInjectedDocuments.get(i);
         if (cachedInjectedDocument == documentWindow) {
           cachedInjectedDocuments.remove(i);
         }
       }
     }
   }
 }
 public PsiDirectory[] getSelectedDirectories() {
   final PsiElement[] elements = getSelectedPSIElements();
   if (elements.length == 1) {
     final PsiElement element = elements[0];
     if (element instanceof PsiDirectory) {
       return new PsiDirectory[] {(PsiDirectory) element};
     } else if (element instanceof PsiDirectoryContainer) {
       return ((PsiDirectoryContainer) element).getDirectories();
     } else {
       final PsiFile containingFile = element.getContainingFile();
       if (containingFile != null) {
         final PsiDirectory psiDirectory = containingFile.getContainingDirectory();
         if (psiDirectory != null) {
           return new PsiDirectory[] {psiDirectory};
         }
         final VirtualFile file = containingFile.getVirtualFile();
         if (file instanceof VirtualFileWindow) {
           final VirtualFile delegate = ((VirtualFileWindow) file).getDelegate();
           final PsiFile delegatePsiFile = containingFile.getManager().findFile(delegate);
           if (delegatePsiFile != null && delegatePsiFile.getContainingDirectory() != null) {
             return new PsiDirectory[] {delegatePsiFile.getContainingDirectory()};
           }
         }
         return PsiDirectory.EMPTY_ARRAY;
       }
     }
   } else {
     final DefaultMutableTreeNode selectedNode = getSelectedNode();
     if (selectedNode != null) {
       return getSelectedDirectoriesInAmbiguousCase(selectedNode);
     }
   }
   return PsiDirectory.EMPTY_ARRAY;
 }
  public static int insertClassReference(
      PsiClass psiClass, PsiFile file, int startOffset, int endOffset) {
    final Project project = file.getProject();
    PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project);
    documentManager.commitAllDocuments();

    final PsiManager manager = file.getManager();

    final Document document =
        FileDocumentManager.getInstance().getDocument(file.getViewProvider().getVirtualFile());

    final PsiReference reference = file.findReferenceAt(startOffset);
    if (reference != null) {
      final PsiElement resolved = reference.resolve();
      if (resolved instanceof PsiClass) {
        if (((PsiClass) resolved).getQualifiedName() == null
            || manager.areElementsEquivalent(psiClass, resolved)) {
          return endOffset;
        }
      }
    }

    String name = psiClass.getName();
    if (name == null) {
      return endOffset;
    }

    assert document != null;
    document.replaceString(startOffset, endOffset, name);

    int newEndOffset = startOffset + name.length();
    final RangeMarker toDelete = insertTemporary(newEndOffset, document, " ");

    documentManager.commitAllDocuments();

    PsiElement element = file.findElementAt(startOffset);
    if (element instanceof PsiIdentifier) {
      PsiElement parent = element.getParent();
      if (parent instanceof PsiJavaCodeReferenceElement
          && !((PsiJavaCodeReferenceElement) parent).isQualified()
          && !(parent.getParent() instanceof PsiPackageStatement)) {
        PsiJavaCodeReferenceElement ref = (PsiJavaCodeReferenceElement) parent;

        if (psiClass.isValid()
            && !psiClass.getManager().areElementsEquivalent(psiClass, resolveReference(ref))) {
          final boolean staticImport = ref instanceof PsiImportStaticReferenceElement;
          PsiElement newElement;
          try {
            newElement =
                staticImport
                    ? ((PsiImportStaticReferenceElement) ref).bindToTargetClass(psiClass)
                    : ref.bindToElement(psiClass);
          } catch (IncorrectOperationException e) {
            return endOffset; // can happen if fqn contains reserved words, for example
          }

          final RangeMarker rangeMarker = document.createRangeMarker(newElement.getTextRange());
          documentManager.doPostponedOperationsAndUnblockDocument(document);
          documentManager.commitDocument(document);

          newElement =
              CodeInsightUtilCore.findElementInRange(
                  file,
                  rangeMarker.getStartOffset(),
                  rangeMarker.getEndOffset(),
                  PsiJavaCodeReferenceElement.class,
                  JavaLanguage.INSTANCE);
          rangeMarker.dispose();
          if (newElement != null) {
            newEndOffset = newElement.getTextRange().getEndOffset();
            if (!(newElement instanceof PsiReferenceExpression)) {
              PsiReferenceParameterList parameterList =
                  ((PsiJavaCodeReferenceElement) newElement).getParameterList();
              if (parameterList != null) {
                newEndOffset = parameterList.getTextRange().getStartOffset();
              }
            }

            if (!staticImport
                && !psiClass
                    .getManager()
                    .areElementsEquivalent(psiClass, resolveReference((PsiReference) newElement))
                && !PsiUtil.isInnerClass(psiClass)) {
              final String qName = psiClass.getQualifiedName();
              if (qName != null) {
                document.replaceString(
                    newElement.getTextRange().getStartOffset(), newEndOffset, qName);
                newEndOffset = newElement.getTextRange().getStartOffset() + qName.length();
              }
            }
          }
        }
      }
    }

    if (toDelete.isValid()) {
      document.deleteString(toDelete.getStartOffset(), toDelete.getEndOffset());
    }

    return newEndOffset;
  }
  private static MultiHostRegistrarImpl probeElementsUp(
      @NotNull PsiElement element, @NotNull PsiFile hostPsiFile, boolean probeUp) {
    PsiManager psiManager = hostPsiFile.getManager();
    final Project project = psiManager.getProject();
    InjectedLanguageManagerImpl injectedManager =
        InjectedLanguageManagerImpl.getInstanceImpl(project);
    if (injectedManager == null) {
      return null; // for tests
    }
    MultiHostRegistrarImpl registrar = null;
    PsiElement current = element;
    nextParent:
    while (current != null && current != hostPsiFile) {
      ProgressManager.checkCanceled();
      if ("EL".equals(current.getLanguage().getID())) break;
      ParameterizedCachedValue<MultiHostRegistrarImpl, PsiElement> data =
          current.getUserData(INJECTED_PSI);
      if (data == null) {
        registrar =
            InjectedPsiCachedValueProvider.doCompute(
                current, injectedManager, project, hostPsiFile);
      } else {
        registrar = data.getValue(current);
      }

      current = current.getParent(); // cache no injection for current

      if (registrar != null) {
        List<Pair<Place, PsiFile>> places = registrar.getResult();
        // check that injections found intersect with queried element
        TextRange elementRange = element.getTextRange();
        for (Pair<Place, PsiFile> pair : places) {
          Place place = pair.first;
          for (PsiLanguageInjectionHost.Shred shred : place) {
            if (shred.getHost().getTextRange().intersects(elementRange)) {
              if (place.isValid()) break nextParent;
            }
          }
        }
      }
      if (!probeUp) {
        break;
      }
    }

    if (probeUp) {
      // cache only if we walked all parents
      for (PsiElement e = element;
          e != current && e != null && e != hostPsiFile;
          e = e.getParent()) {
        ProgressManager.checkCanceled();
        if (registrar == null) {
          e.putUserData(INJECTED_PSI, null);
        } else {
          ParameterizedCachedValue<MultiHostRegistrarImpl, PsiElement> cachedValue =
              CachedValuesManager.getManager(project)
                  .createParameterizedCachedValue(INJECTED_PSI_PROVIDER, false);

          CachedValueProvider.Result<MultiHostRegistrarImpl> result =
              CachedValueProvider.Result.create(
                  registrar, PsiModificationTracker.MODIFICATION_COUNT, registrar);
          ((PsiParameterizedCachedValue<MultiHostRegistrarImpl, PsiElement>) cachedValue)
              .setValue(result);

          e.putUserData(INJECTED_PSI, cachedValue);
        }
      }
    }
    return registrar;
  }