// returns (injected psi, leaf element at the offset, language of the leaf element)
  // since findElementAt() is expensive, we trying to reuse its result
  @NotNull
  private static Trinity<PsiElement, PsiElement, Language> tryOffset(
      @NotNull PsiFile hostFile, final int offset, @NotNull PsiDocumentManager documentManager) {
    FileViewProvider provider = hostFile.getViewProvider();
    Language leafLanguage = null;
    PsiElement leafElement = null;
    for (Language language : provider.getLanguages()) {
      PsiElement element = provider.findElementAt(offset, language);
      if (element != null) {
        if (leafLanguage == null) {
          leafLanguage = language;
          leafElement = element;
        }
        PsiElement injected = findInside(element, hostFile, offset, documentManager);
        if (injected != null) return Trinity.create(injected, element, language);
      }
      // maybe we are at the border between two psi elements, then try to find injection at the end
      // of the left element
      if (offset != 0 && (element == null || element.getTextRange().getStartOffset() == offset)) {
        PsiElement leftElement = provider.findElementAt(offset - 1, language);
        if (leftElement != null && leftElement.getTextRange().getEndOffset() == offset) {
          PsiElement injected = findInside(leftElement, hostFile, offset, documentManager);
          if (injected != null) return Trinity.create(injected, element, language);
        }
      }
    }

    return Trinity.create(null, leafElement, leafLanguage);
  }
  private void checkPsiIsCorrect(final FileViewProvider key) {
    PsiFile actualPsi = key.getPsi(key.getBaseLanguage());

    PsiTreeDebugBuilder treeDebugBuilder =
        new PsiTreeDebugBuilder().setShowErrorElements(false).setShowWhiteSpaces(false);

    String actualPsiTree = treeDebugBuilder.psiToString(actualPsi);

    String fileName = key.getVirtualFile().getName();
    PsiFile psi =
        PsiFileFactory.getInstance(myProject)
            .createFileFromText(
                fileName,
                FileTypeManager.getInstance().getFileTypeByFileName(fileName),
                actualPsi.getNode().getText(),
                LocalTimeCounter.currentTime(),
                false);

    if (actualPsi.getClass().equals(psi.getClass())) {
      String expectedPsi = treeDebugBuilder.psiToString(psi);

      if (!expectedPsi.equals(actualPsiTree)) {
        myReformatElements.clear();
        assert expectedPsi.equals(actualPsiTree)
            : "Refactored psi should be the same as result of parsing";
      }
    }
  }
예제 #3
0
  @Override
  @SuppressWarnings({"CloneDoesntDeclareCloneNotSupportedException", "CloneDoesntCallSuperClone"})
  protected PsiFileImpl clone() {
    FileViewProvider viewProvider = getViewProvider();
    FileViewProvider providerCopy = viewProvider.clone();
    final Language language = getLanguage();
    if (providerCopy == null) {
      throw new AssertionError(
          "Unable to clone the view provider: " + viewProvider + "; " + language);
    }
    PsiFileImpl clone = BlockSupportImpl.getFileCopy(this, providerCopy);
    copyCopyableDataTo(clone);

    if (getTreeElement() != null) {
      // not set by provider in clone
      final FileElement treeClone = (FileElement) calcTreeElement().clone();
      clone.setTreeElementPointer(
          treeClone); // should not use setTreeElement here because cloned file still have
                      // VirtualFile (SCR17963)
      treeClone.setPsi(clone);
    }

    if (viewProvider.isEventSystemEnabled()) {
      clone.myOriginalFile = this;
    } else if (myOriginalFile != null) {
      clone.myOriginalFile = myOriginalFile;
    }

    return clone;
  }
  @Override
  public void beforeDocumentChange(DocumentEvent event) {
    final Document document = event.getDocument();

    final FileViewProvider viewProvider = getCachedViewProvider(document);
    if (viewProvider == null) return;
    if (!isRelevant(viewProvider)) return;

    VirtualFile virtualFile = viewProvider.getVirtualFile();
    if (virtualFile.getFileType().isBinary()) return;

    final List<PsiFile> files = viewProvider.getAllFiles();
    PsiFile psiCause = null;
    for (PsiFile file : files) {
      mySmartPointerManager.fastenBelts(file, event.getOffset(), null);

      if (TextBlock.get(file).isLocked()) {
        psiCause = file;
      }
    }

    if (psiCause == null) {
      beforeDocumentChangeOnUnlockedDocument(viewProvider);
    }

    ((SingleRootFileViewProvider) viewProvider).beforeDocumentChanged(psiCause);
  }
  @Nullable
  public static Commenter getCommenter(
      final PsiFile file,
      final Editor editor,
      final Language lineStartLanguage,
      final Language lineEndLanguage) {

    final FileViewProvider viewProvider = file.getViewProvider();

    for (MultipleLangCommentProvider provider :
        MultipleLangCommentProvider.EP_NAME.getExtensions()) {
      if (provider.canProcess(file, viewProvider)) {
        return provider.getLineCommenter(file, editor, lineStartLanguage, lineEndLanguage);
      }
    }

    final Language fileLanguage = file.getLanguage();
    Language lang =
        lineStartLanguage == null
                || LanguageCommenters.INSTANCE.forLanguage(lineStartLanguage) == null
                || fileLanguage.getBaseLanguage()
                    == lineStartLanguage // file language is a more specific dialect of the line
            // language
            ? fileLanguage
            : lineStartLanguage;

    if (viewProvider instanceof TemplateLanguageFileViewProvider
        && lang == ((TemplateLanguageFileViewProvider) viewProvider).getTemplateDataLanguage()) {
      lang = viewProvider.getBaseLanguage();
    }

    return LanguageCommenters.INSTANCE.forLanguage(lang);
  }
  private void doPostponedFormattingInner(final FileViewProvider key) {

    final List<ASTNode> astNodes = myReformatElements.remove(key);
    final Document document = key.getDocument();
    // Sort ranges by end offsets so that we won't need any offset adjustment after reformat or
    // reindent
    if (document == null) return;

    final VirtualFile virtualFile = key.getVirtualFile();
    if (!virtualFile.isValid()) return;

    final TreeSet<PostprocessFormattingTask> postProcessTasks =
        new TreeSet<PostprocessFormattingTask>();
    Collection<Disposable> toDispose = ContainerUtilRt.newArrayList();
    try {
      // process all roots in viewProvider to find marked for reformat before elements and create
      // appropriate range markers
      handleReformatMarkers(key, postProcessTasks);
      toDispose.addAll(postProcessTasks);

      // then we create ranges by changed nodes. One per node. There ranges can intersect. Ranges
      // are sorted by end offset.
      if (astNodes != null) createActionsMap(astNodes, key, postProcessTasks);

      if ("true".equals(System.getProperty("check.psi.is.valid"))
          && ApplicationManager.getApplication().isUnitTestMode()) {
        checkPsiIsCorrect(key);
      }

      while (!postProcessTasks.isEmpty()) {
        // now we have to normalize actions so that they not intersect and ordered in most
        // appropriate way
        // (free reformatting -> reindent -> formatting under reindent)
        final List<PostponedAction> normalizedActions =
            normalizeAndReorderPostponedActions(postProcessTasks, document);
        toDispose.addAll(normalizedActions);

        // only in following loop real changes in document are made
        for (final PostponedAction normalizedAction : normalizedActions) {
          CodeStyleSettings settings =
              CodeStyleSettingsManager.getSettings(myPsiManager.getProject());
          boolean old = settings.ENABLE_JAVADOC_FORMATTING;
          settings.ENABLE_JAVADOC_FORMATTING = false;
          try {
            normalizedAction.execute(key);
          } finally {
            settings.ENABLE_JAVADOC_FORMATTING = old;
          }
        }
      }
    } finally {
      for (Disposable disposable : toDispose) {
        //noinspection SSBasedInspection
        disposable.dispose();
      }
    }
  }
예제 #7
0
 @Override
 public boolean isValid() {
   FileViewProvider provider = getViewProvider();
   final VirtualFile vFile = provider.getVirtualFile();
   if (!vFile.isValid()) return false;
   if (!provider.isEventSystemEnabled()) return true; // "dummy" file
   if (myManager.getProject().isDisposed()) return false;
   return isPsiUpToDate(vFile);
 }
예제 #8
0
 protected boolean isPsiUpToDate(@NotNull VirtualFile vFile) {
   final FileViewProvider provider = myManager.findViewProvider(vFile);
   Language language = getLanguage();
   if (provider == null || provider.getPsi(language) == this) { // provider == null in tests
     return true;
   }
   Language baseLanguage = provider.getBaseLanguage();
   return baseLanguage != language && provider.getPsi(baseLanguage) == this;
 }
  @NotNull
  private static DiffLog makeFullParse(
      @NotNull PsiFileImpl fileImpl,
      @NotNull CharSequence newFileText,
      @NotNull ProgressIndicator indicator,
      @NotNull CharSequence lastCommittedText) {
    if (fileImpl instanceof PsiCodeFragment) {
      FileElement parent = fileImpl.getTreeElement();
      final FileElement holderElement =
          new DummyHolder(fileImpl.getManager(), null).getTreeElement();
      holderElement.rawAddChildren(
          fileImpl.createContentLeafElement(
              holderElement.getCharTable().intern(newFileText, 0, newFileText.length())));
      DiffLog diffLog = new DiffLog();
      diffLog.appendReplaceFileElement(parent, (FileElement) holderElement.getFirstChildNode());

      return diffLog;
    } else {
      FileViewProvider viewProvider = fileImpl.getViewProvider();
      viewProvider.getLanguages();
      FileType fileType = viewProvider.getVirtualFile().getFileType();
      String fileName = fileImpl.getName();
      final LightVirtualFile lightFile =
          new LightVirtualFile(
              fileName,
              fileType,
              newFileText,
              viewProvider.getVirtualFile().getCharset(),
              fileImpl.getViewProvider().getModificationStamp());
      lightFile.setOriginalFile(viewProvider.getVirtualFile());

      FileViewProvider copy = viewProvider.createCopy(lightFile);
      if (copy.isEventSystemEnabled()) {
        throw new AssertionError(
            "Copied view provider must be non-physical for reparse to deliver correct events: "
                + viewProvider);
      }
      copy.getLanguages();
      SingleRootFileViewProvider.doNotCheckFileSizeLimit(
          lightFile); // optimization: do not convert file contents to bytes to determine if we
                      // should codeinsight it
      PsiFileImpl newFile = getFileCopy(fileImpl, copy);

      newFile.setOriginalFile(fileImpl);

      final FileElement newFileElement = (FileElement) newFile.getNode();
      final FileElement oldFileElement = (FileElement) fileImpl.getNode();
      if (!lastCommittedText.toString().equals(oldFileElement.getText())) {
        throw new IncorrectOperationException();
      }
      DiffLog diffLog =
          mergeTrees(fileImpl, oldFileElement, newFileElement, indicator, lastCommittedText);

      ((PsiManagerEx) fileImpl.getManager()).getFileManager().setViewProvider(lightFile, null);
      return diffLog;
    }
  }
예제 #10
0
 private static PsiElement[] getElementsIntersectingRange(
     PsiFile file, final int startOffset, final int endOffset) {
   final FileViewProvider viewProvider = file.getViewProvider();
   final Set<PsiElement> result = new LinkedHashSet<PsiElement>();
   for (Language language : viewProvider.getLanguages()) {
     final PsiFile psiRoot = viewProvider.getPsi(language);
     if (HighlightingLevelManager.getInstance(file.getProject()).shouldInspect(psiRoot)) {
       result.addAll(
           CollectHighlightsUtil.getElementsInRange(psiRoot, startOffset, endOffset, true));
     }
   }
   return PsiUtilCore.toPsiElementArray(result);
 }
예제 #11
0
  @NotNull
  private static PsiAnchor doCreateAnchor(@NotNull PsiElement element) {
    if (element instanceof PsiFile) {
      VirtualFile virtualFile = ((PsiFile) element).getVirtualFile();
      if (virtualFile != null) return new PsiFileReference(virtualFile, (PsiFile) element);
      return new HardReference(element);
    }
    if (element instanceof PsiDirectory) {
      VirtualFile virtualFile = ((PsiDirectory) element).getVirtualFile();
      return new PsiDirectoryReference(virtualFile, element.getProject());
    }

    PsiFile file = element.getContainingFile();
    if (file == null) {
      return new HardReference(element);
    }
    VirtualFile virtualFile = file.getVirtualFile();
    if (virtualFile == null) return new HardReference(element);

    PsiAnchor stubRef = createStubReference(element, file);
    if (stubRef != null) return stubRef;

    if (!element.isPhysical()) {
      return wrapperOrHardReference(element);
    }

    TextRange textRange = element.getTextRange();
    if (textRange == null) {
      return wrapperOrHardReference(element);
    }

    Language lang = null;
    final FileViewProvider viewProvider = file.getViewProvider();
    for (Language l : viewProvider.getLanguages()) {
      if (viewProvider.getPsi(l) == file) {
        lang = l;
        break;
      }
    }

    if (lang == null) {
      return wrapperOrHardReference(element);
    }

    return new TreeRangeReference(
        file,
        textRange.getStartOffset(),
        textRange.getEndOffset(),
        AnchorTypeInfo.obtainInfo(element, lang),
        virtualFile);
  }
  @Nullable
  public static PsiElement getNextSibling(PsiElement element) {
    if (element instanceof PsiFile) {
      final FileViewProvider viewProvider = ((PsiFile) element).getViewProvider();
      element = viewProvider.getPsi(viewProvider.getBaseLanguage());
    }
    if (element == null) return null;
    final PsiElement parent = element.getParent();
    if (parent == null) return null;

    final PsiElement[] children = parent.getChildren();
    final int index = getChildIndex(children, element);
    return 0 <= index && index < children.length - 1 ? children[index + 1] : null;
  }
  @Override
  public void documentChanged(DocumentEvent event) {
    final Document document = event.getDocument();
    final FileViewProvider viewProvider = getCachedViewProvider(document);
    if (viewProvider == null) return;
    if (!isRelevant(viewProvider)) return;

    ApplicationManager.getApplication().assertWriteAccessAllowed();
    final List<PsiFile> files = viewProvider.getAllFiles();
    boolean commitNecessary = true;
    for (PsiFile file : files) {
      mySmartPointerManager.unfastenBelts(file, event.getOffset());

      final TextBlock textBlock = TextBlock.get(file);
      if (textBlock.isLocked()) {
        commitNecessary = false;
        continue;
      }

      textBlock.documentChanged(event);
      assert file instanceof PsiFileImpl
              || "mock.file".equals(file.getName())
                  && ApplicationManager.getApplication().isUnitTestMode()
          : event + "; file=" + file + "; allFiles=" + files + "; viewProvider=" + viewProvider;
    }

    boolean forceCommit =
        ApplicationManager.getApplication().hasWriteAction(ExternalChangeAction.class)
            && (SystemProperties.getBooleanProperty("idea.force.commit.on.external.change", false)
                || ApplicationManager.getApplication().isHeadlessEnvironment());

    // Consider that it's worth to perform complete re-parse instead of merge if the whole document
    // text is replaced and
    // current document lines number is roughly above 5000. This makes sense in situations when
    // external change is performed
    // for the huge file (that causes the whole document to be reloaded and 'merge' way takes a
    // while to complete).
    if (event.isWholeTextReplaced() && document.getTextLength() > 100000) {
      document.putUserData(BlockSupport.DO_NOT_REPARSE_INCREMENTALLY, Boolean.TRUE);
    }

    if (commitNecessary) {
      myUncommittedDocuments.add(document);
      if (forceCommit) {
        commitDocument(document);
      } else if (!((DocumentEx) document).isInBulkUpdate()) {
        myDocumentCommitProcessor.commitAsynchronously(myProject, document, event);
      }
    }
  }
 public void execute(FileViewProvider viewProvider) {
   final Document document = viewProvider.getDocument();
   final PsiFile psiFile = viewProvider.getPsi(viewProvider.getBaseLanguage());
   for (Pair<Integer, RangeMarker> integerRangeMarkerPair : myRangesToReindent) {
     RangeMarker marker = integerRangeMarkerPair.second;
     final CharSequence charsSequence =
         document.getCharsSequence().subSequence(marker.getStartOffset(), marker.getEndOffset());
     final int oldIndent = integerRangeMarkerPair.first;
     final TextRange[] whitespaces =
         CharArrayUtil.getIndents(charsSequence, marker.getStartOffset());
     final int indentAdjustment = getNewIndent(psiFile, marker.getStartOffset()) - oldIndent;
     if (indentAdjustment != 0)
       adjustIndentationInRange(psiFile, document, whitespaces, indentAdjustment);
   }
 }
예제 #15
0
 private static Language findLanguage(PsiFile file) {
   FileViewProvider vp = file.getViewProvider();
   Set<Language> languages = vp.getLanguages();
   for (Language language : languages) {
     if (file.equals(vp.getPsi(language))) {
       return language;
     }
   }
   throw new AssertionError(
       "Non-retrievable file: "
           + file.getClass()
           + "; "
           + file.getLanguage()
           + "; "
           + languages);
 }
 private static void handleReformatMarkers(
     final FileViewProvider key, final TreeSet<PostprocessFormattingTask> rangesToProcess) {
   final Document document = key.getDocument();
   if (document == null) {
     return;
   }
   for (final FileElement fileElement : ((SingleRootFileViewProvider) key).getKnownTreeRoots()) {
     fileElement.acceptTree(
         new RecursiveTreeElementWalkingVisitor() {
           protected void visitNode(TreeElement element) {
             if (CodeEditUtil.isMarkedToReformatBefore(element)) {
               CodeEditUtil.markToReformatBefore(element, false);
               rangesToProcess.add(
                   new ReformatWithHeadingWhitespaceTask(
                       document.createRangeMarker(
                           element.getStartOffset(), element.getStartOffset())));
             } else if (CodeEditUtil.isMarkedToReformat(element)) {
               CodeEditUtil.markToReformat(element, false);
               rangesToProcess.add(
                   new ReformatWithHeadingWhitespaceTask(
                       document.createRangeMarker(
                           element.getStartOffset(),
                           element.getStartOffset() + element.getTextLength())));
             }
             super.visitNode(element);
           }
         });
   }
 }
  @Override
  public void beforeDocumentChange(@NotNull DocumentEvent event) {
    if (myStopTrackingDocuments) return;

    final Document document = event.getDocument();
    if (!(document instanceof DocumentWindow) && !myLastCommittedTexts.containsKey(document)) {
      myLastCommittedTexts.put(
          document,
          Pair.create(document.getImmutableCharSequence(), document.getModificationStamp()));
    }

    VirtualFile virtualFile = FileDocumentManager.getInstance().getFile(document);
    boolean isRelevant = virtualFile != null && isRelevant(virtualFile);

    final FileViewProvider viewProvider = getCachedViewProvider(document);
    boolean inMyProject = viewProvider != null && viewProvider.getManager() == myPsiManager;
    if (!isRelevant || !inMyProject) {
      return;
    }

    final List<PsiFile> files = viewProvider.getAllFiles();
    PsiFile psiCause = null;
    for (PsiFile file : files) {
      if (file == null) {
        throw new AssertionError(
            "View provider "
                + viewProvider
                + " ("
                + viewProvider.getClass()
                + ") returned null in its files array: "
                + files
                + " for file "
                + viewProvider.getVirtualFile());
      }

      if (mySynchronizer.isInsideAtomicChange(file)) {
        psiCause = file;
      }
    }

    if (psiCause == null) {
      beforeDocumentChangeOnUnlockedDocument(viewProvider);
    }

    ((SingleRootFileViewProvider) viewProvider).beforeDocumentChanged(psiCause);
  }
 @Override
 public void visitFile(PsiFile file) {
   final VirtualFile virtualFile = file.getVirtualFile();
   if (virtualFile != null) {
     String relative =
         ProjectUtilCore.displayUrlRelativeToProject(
             virtualFile, virtualFile.getPresentableUrl(), myProject, true, false);
     myContext.incrementJobDoneAmount(myContext.getStdJobDescriptors().BUILD_GRAPH, relative);
   }
   final FileViewProvider viewProvider = file.getViewProvider();
   final Set<Language> relevantLanguages = viewProvider.getLanguages();
   for (Language language : relevantLanguages) {
     visitElement(viewProvider.getPsi(language));
   }
   myPsiManager.dropResolveCaches();
   InjectedLanguageManager.getInstance(myProject).dropFileCaches(file);
 }
 // 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);
 }
예제 #20
0
  private static void mapJsp(FileContent inputData, final List<LinkInfo> result) {
    final FileViewProvider viewProvider = inputData.getPsiFile().getViewProvider();

    PsiFile psiFile = null;
    if (viewProvider instanceof TemplateLanguageFileViewProvider) {
      final Language dataLanguage =
          ((TemplateLanguageFileViewProvider) viewProvider).getTemplateDataLanguage();
      if (dataLanguage == HTMLLanguage.INSTANCE || dataLanguage == XHTMLLanguage.INSTANCE) {
        psiFile = viewProvider.getPsi(dataLanguage);
      }
    } else {
      psiFile = viewProvider.getPsi(viewProvider.getBaseLanguage());
    }

    if (psiFile != null) {
      final XmlRecursiveElementVisitor visitor =
          new XmlRecursiveElementVisitor() {
            @Override
            public void visitXmlTag(XmlTag tag) {
              if (LINK.equalsIgnoreCase(tag.getLocalName())) {

                final String href = getAttributeValue(tag, HREF_ATTR);
                final String media = getAttributeValue(tag, MEDIA_ATTR);
                final String type = getAttributeValue(tag, TYPE_ATTR);
                final String rel = getAttributeValue(tag, REL_ATTR);
                final String title = getAttributeValue(tag, TITLE_ATTR);

                addResult(
                    result,
                    tag.getTextOffset(),
                    href,
                    media,
                    type,
                    rel,
                    title,
                    isHrefScripted(tag));
              }

              super.visitXmlTag(tag);
            }
          };

      psiFile.accept(visitor);
    }
  }
  @Nullable
  @Override
  public Document getDocument(@NotNull PsiFile file) {
    if (file instanceof PsiBinaryFile) return null;

    Document document = getCachedDocument(file);
    if (document != null) {
      if (!file.getViewProvider().isPhysical() && document.getUserData(HARD_REF_TO_PSI) == null) {
        PsiUtilCore.ensureValid(file);
        cachePsi(document, file);
      }
      return document;
    }

    FileViewProvider viewProvider = file.getViewProvider();
    if (!viewProvider.isEventSystemEnabled()) return null;

    document = FileDocumentManager.getInstance().getDocument(viewProvider.getVirtualFile());
    if (document != null) {
      if (document.getTextLength() != file.getTextLength()) {
        String message =
            "Document/PSI mismatch: "
                + file
                + " ("
                + file.getClass()
                + "); physical="
                + viewProvider.isPhysical();
        if (document.getTextLength() + file.getTextLength() < 8096) {
          message +=
              "\n=== document ===\n" + document.getText() + "\n=== PSI ===\n" + file.getText();
        }
        throw new AssertionError(message);
      }

      if (!viewProvider.isPhysical()) {
        PsiUtilCore.ensureValid(file);
        cachePsi(document, file);
        file.putUserData(HARD_REF_TO_DOCUMENT, document);
      }
    }

    return document;
  }
  protected boolean finishCommitInWriteAction(
      @NotNull final Document document,
      @NotNull final List<Processor<Document>> finishProcessors,
      final boolean synchronously) {
    if (myProject.isDisposed()) return false;
    assert !(document instanceof DocumentWindow);
    myIsCommitInProgress = true;
    boolean success = true;
    try {
      final FileViewProvider viewProvider = getCachedViewProvider(document);
      if (viewProvider != null) {
        for (Processor<Document> finishRunnable : finishProcessors) {
          success = finishRunnable.process(document);
          if (synchronously) {
            assert success : finishRunnable + " in " + finishProcessors;
          }
          if (!success) {
            break;
          }
        }
        if (success) {
          myLastCommittedTexts.remove(document);
          viewProvider.contentsSynchronized();
        }
      } else {
        handleCommitWithoutPsi(document);
      }
    } finally {
      myDocumentCommitProcessor.log(
          "in PDI.finishDoc: ", null, synchronously, success, myUncommittedDocuments);
      if (success) {
        myUncommittedDocuments.remove(document);
        myDocumentCommitProcessor.log(
            "in PDI.finishDoc: removed doc", null, synchronously, success, myUncommittedDocuments);
      }
      myIsCommitInProgress = false;
      myDocumentCommitProcessor.log(
          "in PDI.finishDoc: exit", null, synchronously, success, myUncommittedDocuments);
    }

    return success;
  }
  private CodeFormatterFacade getFormatterFacade(final FileViewProvider viewProvider) {
    final CodeStyleSettings styleSettings =
        CodeStyleSettingsManager.getSettings(myPsiManager.getProject());
    final PsiDocumentManager documentManager =
        PsiDocumentManager.getInstance(myPsiManager.getProject());
    final Document document = viewProvider.getDocument();
    final CodeFormatterFacade codeFormatter = new CodeFormatterFacade(styleSettings);

    documentManager.commitDocument(document);
    return codeFormatter;
  }
예제 #24
0
  @Override
  @NotNull
  public PsiFile[] getPsiRoots() {
    final FileViewProvider viewProvider = getViewProvider();
    final Set<Language> languages = viewProvider.getLanguages();

    final PsiFile[] roots = new PsiFile[languages.size()];
    int i = 0;
    for (Language language : languages) {
      PsiFile psi = viewProvider.getPsi(language);
      if (psi == null) {
        LOG.error("PSI is null for " + language + "; in file: " + this);
      }
      roots[i++] = psi;
    }
    if (roots.length > 1) {
      Arrays.sort(roots, FILE_BY_LANGUAGE_ID);
    }
    return roots;
  }
 public void beforeDocumentChanged(@NotNull FileViewProvider viewProvider) {
   if (isViewProviderLocked(viewProvider)) {
     Throwable cause = viewProvider.getUserData(REFORMAT_ORIGINATOR);
     @NonNls
     String message =
         "Document is locked by write PSI operations. "
             + "Use PsiDocumentManager.doPostponedOperationsAndUnblockDocument() to commit PSI changes to the document."
             + (cause == null ? "" : " See cause stacktrace for the reason to lock.");
     throw cause == null ? new RuntimeException(message) : new RuntimeException(message, cause);
   }
   postponedFormatting(viewProvider);
 }
  @NotNull
  public static PsiFileImpl getFileCopy(
      @NotNull PsiFileImpl originalFile, @NotNull FileViewProvider providerCopy) {
    FileViewProvider viewProvider = originalFile.getViewProvider();
    Language language = originalFile.getLanguage();

    PsiFile file = providerCopy.getPsi(language);
    if (file != null && !(file instanceof PsiFileImpl)) {
      throw new RuntimeException(
          "View provider "
              + viewProvider
              + " refused to provide PsiFileImpl for "
              + language
              + details(providerCopy, viewProvider));
    }

    PsiFileImpl newFile = (PsiFileImpl) file;

    if (newFile == null
        && language == PlainTextLanguage.INSTANCE
        && originalFile == viewProvider.getPsi(viewProvider.getBaseLanguage())) {
      newFile = (PsiFileImpl) providerCopy.getPsi(providerCopy.getBaseLanguage());
    }

    if (newFile == null) {
      throw new RuntimeException(
          "View provider "
              + viewProvider
              + " refused to parse text with "
              + language
              + details(providerCopy, viewProvider));
    }

    return newFile;
  }
예제 #27
0
  protected void reportStubAstMismatch(String message, StubTree stubTree, Document cachedDocument) {
    rebuildStub();
    clearStub("stub-psi mismatch");
    scheduleDropCachesWithInvalidStubPsi();

    String msg = message;
    msg += "\n file=" + this;
    msg += ", modStamp=" + getModificationStamp();
    msg += "\n stub debugInfo=" + stubTree.getDebugInfo();
    msg += "\n document before=" + cachedDocument;

    ObjectStubTree latestIndexedStub =
        StubTreeLoader.getInstance().readFromVFile(getProject(), getVirtualFile());
    msg += "\nlatestIndexedStub=" + latestIndexedStub;
    if (latestIndexedStub != null) {
      msg +=
          "\n   same size="
              + (stubTree.getPlainList().size() == latestIndexedStub.getPlainList().size());
      msg += "\n   debugInfo=" + latestIndexedStub.getDebugInfo();
    }

    FileViewProvider viewProvider = getViewProvider();
    msg += "\n viewProvider=" + viewProvider;
    msg += "\n viewProvider stamp: " + viewProvider.getModificationStamp();

    VirtualFile file = viewProvider.getVirtualFile();
    msg += "; file stamp: " + file.getModificationStamp();
    msg += "; file modCount: " + file.getModificationCount();

    Document document = FileDocumentManager.getInstance().getCachedDocument(file);
    if (document != null) {
      msg += "\n doc saved: " + !FileDocumentManager.getInstance().isDocumentUnsaved(document);
      msg += "; doc stamp: " + document.getModificationStamp();
      msg += "; doc size: " + document.getTextLength();
      msg += "; committed: " + PsiDocumentManager.getInstance(getProject()).isCommitted(document);
    }

    throw new AssertionError(msg + "\n------------\n");
  }
 private static String details(FileViewProvider providerCopy, FileViewProvider viewProvider) {
   return "; languages: "
       + viewProvider.getLanguages()
       + "; base: "
       + viewProvider.getBaseLanguage()
       + "; copy: "
       + providerCopy
       + "; copy.base: "
       + providerCopy.getBaseLanguage()
       + "; vFile: "
       + viewProvider.getVirtualFile()
       + "; copy.vFile: "
       + providerCopy.getVirtualFile()
       + "; fileType: "
       + viewProvider.getVirtualFile().getFileType()
       + "; copy.original(): "
       + (providerCopy.getVirtualFile() instanceof LightVirtualFile
           ? ((LightVirtualFile) providerCopy.getVirtualFile()).getOriginalFile()
           : null);
 }
예제 #29
0
 public void unloadContent() {
   ApplicationManager.getApplication().assertWriteAccessAllowed();
   clearCaches();
   myViewProvider.beforeContentsSynchronized();
   synchronized (PsiLock.LOCK) {
     FileElement treeElement = derefTreeElement();
     DebugUtil.startPsiModification("unloadContent");
     try {
       if (treeElement != null) {
         myTreeElementPointer = null;
         treeElement.detachFromFile();
         DebugUtil.onInvalidated(treeElement);
       }
       clearStub("unloadContent");
     } finally {
       DebugUtil.finishPsiModification();
     }
   }
 }
 private void postponeFormatting(@NotNull FileViewProvider viewProvider, @NotNull ASTNode child) {
   if (!CodeEditUtil.isNodeGenerated(child) && child.getElementType() != TokenType.WHITE_SPACE) {
     final int oldIndent = CodeEditUtil.getOldIndentation(child);
     LOG.assertTrue(
         oldIndent >= 0,
         "for not generated items old indentation must be defined: element="
             + child
             + ", text="
             + child.getText());
   }
   List<ASTNode> list = myReformatElements.get(viewProvider);
   if (list == null) {
     list = new ArrayList<ASTNode>();
     myReformatElements.put(viewProvider, list);
     if (STORE_REFORMAT_ORIGINATOR_STACKTRACE) {
       viewProvider.putUserData(REFORMAT_ORIGINATOR, new Throwable());
     }
   }
   list.add(child);
 }