public static String getUnescapedText(
      PsiFile file,
      @Nullable final PsiElement startElement,
      @Nullable final PsiElement endElement) {
    final InjectedLanguageManager manager = InjectedLanguageManager.getInstance(file.getProject());
    if (manager.getInjectionHost(file) == null) {
      return file.getText()
          .substring(
              startElement == null ? 0 : startElement.getTextRange().getStartOffset(),
              endElement == null
                  ? file.getTextLength()
                  : endElement.getTextRange().getStartOffset());
    }
    final StringBuilder sb = new StringBuilder();
    file.accept(
        new PsiRecursiveElementWalkingVisitor() {

          Boolean myState = startElement == null ? Boolean.TRUE : null;

          @Override
          public void visitElement(PsiElement element) {
            if (element == startElement) myState = Boolean.TRUE;
            if (element == endElement) myState = Boolean.FALSE;
            if (Boolean.FALSE == myState) return;
            if (Boolean.TRUE == myState && element.getFirstChild() == null) {
              sb.append(getUnescapedLeafText(element, false));
            } else {
              super.visitElement(element);
            }
          }
        });
    return sb.toString();
  }
 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 static void enumerate(
      @NotNull PsiElement host,
      @NotNull PsiFile containingFile,
      boolean probeUp,
      @NotNull PsiLanguageInjectionHost.InjectedPsiVisitor visitor) {
    // do not inject into nonphysical files except during completion
    if (!containingFile.isPhysical() && containingFile.getOriginalFile() == containingFile) {
      final PsiElement context =
          InjectedLanguageManager.getInstance(containingFile.getProject())
              .getInjectionHost(containingFile);
      if (context == null) return;

      final PsiFile file = context.getContainingFile();
      if (file == null || !file.isPhysical() && file.getOriginalFile() == file) return;
    }

    if (containingFile.getViewProvider() instanceof InjectedFileViewProvider)
      return; // no injection inside injection

    PsiElement inTree = loadTree(host, containingFile);
    if (inTree != host) {
      host = inTree;
      containingFile = host.getContainingFile();
    }

    MultiHostRegistrarImpl registrar = probeElementsUp(host, containingFile, probeUp);
    if (registrar == null) {
      return;
    }
    List<Pair<Place, PsiFile>> places = registrar.getResult();
    for (Pair<Place, PsiFile> pair : places) {
      PsiFile injectedPsi = pair.second;
      visitor.visit(injectedPsi, pair.first);
    }
  }
 public static PsiElement findInjectedElementNoCommit(
     @NotNull PsiFile hostFile, final int offset) {
   if (hostFile instanceof PsiCompiledElement) return null;
   Project project = hostFile.getProject();
   if (InjectedLanguageManager.getInstance(project).isInjectedFragment(hostFile)) return null;
   final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project);
   Trinity<PsiElement, PsiElement, Language> result = tryOffset(hostFile, offset, documentManager);
   PsiElement injected = result.first;
   return injected;
 }
 public static PsiFile getTopLevelFile(@NotNull PsiElement element) {
   PsiFile containingFile = element.getContainingFile();
   if (containingFile == null) return null;
   Document document =
       PsiDocumentManager.getInstance(element.getProject()).getCachedDocument(containingFile);
   if (document instanceof DocumentWindow) {
     PsiElement host =
         InjectedLanguageManager.getInstance(containingFile.getProject())
             .getInjectionHost(containingFile);
     if (host != null) containingFile = host.getContainingFile();
   }
   return containingFile;
 }
  public static boolean isInInjectedLanguagePrefixSuffix(@NotNull final PsiElement element) {
    PsiFile injectedFile = element.getContainingFile();
    if (injectedFile == null) return false;
    Project project = injectedFile.getProject();
    InjectedLanguageManager languageManager = InjectedLanguageManager.getInstance(project);
    if (!languageManager.isInjectedFragment(injectedFile)) return false;
    TextRange elementRange = element.getTextRange();
    List<TextRange> editables =
        languageManager.intersectWithAllEditableFragments(injectedFile, elementRange);
    int combinedEdiablesLength = 0;
    for (TextRange editable : editables) {
      combinedEdiablesLength += editable.getLength();
    }

    return combinedEdiablesLength != elementRange.getLength();
  }
 // consider injected elements
 public static PsiElement findElementAtNoCommit(@NotNull PsiFile file, int offset) {
   FileViewProvider viewProvider = file.getViewProvider();
   Trinity<PsiElement, PsiElement, Language> result = null;
   if (!(viewProvider instanceof InjectedFileViewProvider)) {
     PsiDocumentManager documentManager = PsiDocumentManager.getInstance(file.getProject());
     result = tryOffset(file, offset, documentManager);
     PsiElement injected = result.first;
     if (injected != null) {
       return injected;
     }
   }
   Language baseLanguage = viewProvider.getBaseLanguage();
   if (result != null && baseLanguage == result.third) {
     return result.second; // already queried
   }
   return viewProvider.findElementAt(offset, baseLanguage);
 }
 @NotNull
 public static Editor getInjectedEditorForInjectedFile(
     @NotNull Editor hostEditor, @Nullable final PsiFile injectedFile) {
   if (injectedFile == null || hostEditor instanceof EditorWindow || hostEditor.isDisposed())
     return hostEditor;
   Project project = hostEditor.getProject();
   if (project == null) project = injectedFile.getProject();
   Document document = PsiDocumentManager.getInstance(project).getDocument(injectedFile);
   if (!(document instanceof DocumentWindowImpl)) return hostEditor;
   DocumentWindowImpl documentWindow = (DocumentWindowImpl) document;
   SelectionModel selectionModel = hostEditor.getSelectionModel();
   if (selectionModel.hasSelection()) {
     int selstart = selectionModel.getSelectionStart();
     int selend = selectionModel.getSelectionEnd();
     if (!documentWindow.containsRange(selstart, selend)) {
       // selection spreads out the injected editor range
       return hostEditor;
     }
   }
   if (!documentWindow.isValid())
     return hostEditor; // since the moment we got hold of injectedFile and this moment call,
                        // document may have been dirtied
   return EditorWindow.create(documentWindow, (EditorImpl) hostEditor, injectedFile);
 }