コード例 #1
0
 @NotNull
 public CharSequence getVcsContent(@NotNull Range range) {
   synchronized (myLock) {
     TextRange textRange = getVcsTextRange(range);
     final int startOffset = textRange.getStartOffset();
     final int endOffset = textRange.getEndOffset();
     return myVcsDocument.getImmutableCharSequence().subSequence(startOffset, endOffset);
   }
 }
コード例 #2
0
  private static PsiFile createFileCopy(PsiFile file, long caret, long selEnd) {
    final VirtualFile virtualFile = file.getVirtualFile();
    boolean mayCacheCopy =
        file.isPhysical()
            &&
            // we don't want to cache code fragment copies even if they appear to be physical
            virtualFile != null
            && virtualFile.isInLocalFileSystem();
    long combinedOffsets = caret + (selEnd << 32);
    if (mayCacheCopy) {
      final Trinity<PsiFile, Document, Long> cached =
          SoftReference.dereference(file.getUserData(FILE_COPY_KEY));
      if (cached != null
          && cached.first.getClass().equals(file.getClass())
          && isCopyUpToDate(cached.second, cached.first)) {
        final PsiFile copy = cached.first;
        if (copy.getViewProvider().getModificationStamp()
                > file.getViewProvider().getModificationStamp()
            && cached.third.longValue() != combinedOffsets) {
          // the copy PSI might have some caches that are not cleared on its modification because
          // there are no events in the copy
          //   so, clear all the caches
          // hopefully it's a rare situation that the user invokes completion in different parts of
          // the file
          //   without modifying anything physical in between
          ((PsiModificationTrackerImpl) file.getManager().getModificationTracker()).incCounter();
        }
        final Document document = cached.second;
        assert document != null;
        file.putUserData(
            FILE_COPY_KEY,
            new SoftReference<Trinity<PsiFile, Document, Long>>(
                Trinity.create(copy, document, combinedOffsets)));

        Document originalDocument = file.getViewProvider().getDocument();
        assert originalDocument != null;
        assert originalDocument.getTextLength() == file.getTextLength() : originalDocument;
        document.setText(originalDocument.getImmutableCharSequence());
        return copy;
      }
    }

    final PsiFile copy = (PsiFile) file.copy();
    if (mayCacheCopy) {
      final Document document = copy.getViewProvider().getDocument();
      assert document != null;
      file.putUserData(
          FILE_COPY_KEY,
          new SoftReference<Trinity<PsiFile, Document, Long>>(
              Trinity.create(copy, document, combinedOffsets)));
    }
    return copy;
  }
コード例 #3
0
 public static FormattingDocumentModelImpl createOn(PsiFile file) {
   Document document = getDocumentToBeUsedFor(file);
   if (document != null) {
     if (PsiDocumentManager.getInstance(file.getProject()).isUncommited(document)) {
       LOG.error("Document is uncommitted");
     }
     if (!file.textMatches(document.getImmutableCharSequence())) {
       LOG.error("Document and psi file texts should be equal: file " + file);
     }
     return new FormattingDocumentModelImpl(document, file);
   } else {
     return new FormattingDocumentModelImpl(new DocumentImpl(file.getText()), file);
   }
 }
コード例 #4
0
  @Override
  @NotNull
  protected FutureTask<Boolean> prepareTask(
      @NotNull final PsiFile file, final boolean processChangedTextOnly)
      throws IncorrectOperationException {
    return new FutureTask<>(
        () -> {
          FormattingProgressTask.FORMATTING_CANCELLED_FLAG.set(false);
          try {
            CharSequence before = null;
            Document document = PsiDocumentManager.getInstance(myProject).getDocument(file);
            if (getInfoCollector() != null) {
              LOG.assertTrue(document != null);
              before = document.getImmutableCharSequence();
            }

            CaretVisualPositionKeeper caretPositionKeeper = new CaretVisualPositionKeeper(document);

            if (processChangedTextOnly) {
              ChangedRangesInfo info =
                  FormatChangedTextUtil.getInstance().getChangedRangesInfo(file);
              if (info != null) {
                CodeStyleManager.getInstance(myProject).reformatTextWithContext(file, info);
              }
            } else {
              Collection<TextRange> ranges = getRangesToFormat(file);
              CodeStyleManager.getInstance(myProject).reformatText(file, ranges);
            }

            caretPositionKeeper.restoreOriginalLocation();

            if (before != null) {
              prepareUserNotificationMessage(document, before);
            }

            return !FormattingProgressTask.FORMATTING_CANCELLED_FLAG.get();
          } catch (FilesTooBigForDiffException e) {
            handleFileTooBigException(LOG, e, file);
            return false;
          } catch (IncorrectOperationException e) {
            LOG.error(e);
            return false;
          } finally {
            myRanges.clear();
          }
        });
  }
コード例 #5
0
  @Override
  public PsiElement getMirror() {
    TreeElement mirrorTreeElement = myMirrorFileElement;
    if (mirrorTreeElement == null) {
      synchronized (myMirrorLock) {
        mirrorTreeElement = myMirrorFileElement;
        if (mirrorTreeElement == null) {
          VirtualFile file = getVirtualFile();
          PsiClass[] classes = getClasses();
          String fileName =
              (classes.length > 0 ? classes[0].getName() : file.getNameWithoutExtension())
                  + JavaFileType.DOT_DEFAULT_EXTENSION;

          final Document document = FileDocumentManager.getInstance().getDocument(file);
          assert document != null : file.getUrl();

          CharSequence mirrorText = document.getImmutableCharSequence();
          boolean internalDecompiler = StringUtil.startsWith(mirrorText, BANNER);
          PsiFileFactory factory = PsiFileFactory.getInstance(getManager().getProject());
          PsiFile mirror =
              factory.createFileFromText(fileName, JavaLanguage.INSTANCE, mirrorText, false, false);
          mirror.putUserData(PsiUtil.FILE_LANGUAGE_LEVEL_KEY, getLanguageLevel());

          mirrorTreeElement = SourceTreeToPsiMap.psiToTreeNotNull(mirror);
          try {
            final TreeElement finalMirrorTreeElement = mirrorTreeElement;
            ProgressManager.getInstance()
                .executeNonCancelableSection(
                    new Runnable() {
                      @Override
                      public void run() {
                        setMirror(finalMirrorTreeElement);
                        putUserData(CLS_DOCUMENT_LINK_KEY, document);
                      }
                    });
          } catch (InvalidMirrorException e) {
            //noinspection ThrowableResultOfMethodCallIgnored
            LOG.error(file.getUrl(), internalDecompiler ? e : wrapException(e, file));
          }

          ((PsiFileImpl) mirror).setOriginalFile(this);
          myMirrorFileElement = mirrorTreeElement;
        }
      }
    }
    return mirrorTreeElement.getPsi();
  }
コード例 #6
0
  @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);
  }
コード例 #7
0
  @Nullable
  public Runnable prepareTemplate(
      final Editor editor,
      char shortcutChar,
      @Nullable final PairProcessor<String, String> processor) {
    if (editor.getSelectionModel().hasSelection()) {
      return null;
    }

    PsiFile file = PsiUtilBase.getPsiFileInEditor(editor, myProject);
    if (file == null) return null;

    Map<TemplateImpl, String> template2argument =
        findMatchingTemplates(file, editor, shortcutChar, TemplateSettings.getInstance());

    List<CustomLiveTemplate> customCandidates =
        ContainerUtil.findAll(
            CustomLiveTemplate.EP_NAME.getExtensions(),
            customLiveTemplate ->
                shortcutChar == customLiveTemplate.getShortcut()
                    && (editor.getCaretModel().getCaretCount() <= 1
                        || supportsMultiCaretMode(customLiveTemplate)));
    if (!customCandidates.isEmpty()) {
      int caretOffset = editor.getCaretModel().getOffset();
      PsiFile fileCopy = insertDummyIdentifierIfNeeded(file, caretOffset, caretOffset, "");
      Document document = editor.getDocument();

      for (final CustomLiveTemplate customLiveTemplate : customCandidates) {
        if (isApplicable(customLiveTemplate, editor, fileCopy)) {
          final String key =
              customLiveTemplate.computeTemplateKey(new CustomTemplateCallback(editor, fileCopy));
          if (key != null) {
            int offsetBeforeKey = caretOffset - key.length();
            CharSequence text = document.getImmutableCharSequence();
            if (template2argument == null
                || !containsTemplateStartingBefore(
                    template2argument, offsetBeforeKey, caretOffset, text)) {
              return () -> customLiveTemplate.expand(key, new CustomTemplateCallback(editor, file));
            }
          }
        }
      }
    }

    return startNonCustomTemplates(template2argument, editor, processor);
  }
コード例 #8
0
 @NotNull
 public static IpnbFile parseIpnbFile(
     @NotNull Document document, @NotNull final VirtualFile virtualFile) throws IOException {
   return parseIpnbFile(document.getImmutableCharSequence(), virtualFile);
 }
コード例 #9
0
  private void paintTextWithEffects(
      Graphics2D g, Rectangle clip, int startVisualLine, int endVisualLine) {
    final CharSequence text = myDocument.getImmutableCharSequence();
    final EditorImpl.LineWhitespacePaintingStrategy whitespacePaintingStrategy =
        myEditor.new LineWhitespacePaintingStrategy();
    int lineCount = myEditor.getVisibleLineCount();
    for (int visualLine = startVisualLine; visualLine <= endVisualLine; visualLine++) {
      int y = myView.visualLineToY(visualLine) + myView.getAscent();
      LineLayout prefixLayout = myView.getPrefixLayout();
      if (visualLine == 0 && prefixLayout != null) {
        g.setColor(myView.getPrefixAttributes().getForegroundColor());
        paintLineLayoutWithEffect(
            g,
            prefixLayout,
            0,
            y,
            myView.getPrefixAttributes().getEffectColor(),
            myView.getPrefixAttributes().getEffectType());
      }
      if (visualLine >= lineCount) break;

      final int[] currentLogicalLine = new int[] {-1};

      paintLineFragments(
          g,
          clip,
          visualLine,
          y,
          new LineFragmentPainter() {
            @Override
            public void paintBeforeLineStart(
                Graphics2D g, TextAttributes attributes, int columnEnd, float xEnd, int y) {
              SoftWrapModelImpl softWrapModel = myEditor.getSoftWrapModel();
              int symbolWidth =
                  softWrapModel.getMinDrawingWidthInPixels(SoftWrapDrawingType.AFTER_SOFT_WRAP);
              softWrapModel.paint(
                  g,
                  SoftWrapDrawingType.AFTER_SOFT_WRAP,
                  (int) xEnd - symbolWidth,
                  y - myView.getAscent(),
                  myView.getLineHeight());
            }

            @Override
            public void paint(
                Graphics2D g,
                VisualLineFragmentsIterator.Fragment fragment,
                int start,
                int end,
                TextAttributes attributes,
                float xStart,
                float xEnd,
                int y) {
              if (attributes != null && attributes.getForegroundColor() != null) {
                g.setColor(attributes.getForegroundColor());
                fragment.draw(g, xStart, y, start, end);
              }
              if (fragment.getCurrentFoldRegion() == null) {
                int logicalLine = fragment.getStartLogicalLine();
                if (logicalLine != currentLogicalLine[0]) {
                  whitespacePaintingStrategy.update(
                      text,
                      myDocument.getLineStartOffset(logicalLine),
                      myDocument.getLineEndOffset(logicalLine));
                  currentLogicalLine[0] = logicalLine;
                }
                paintWhitespace(
                    g, text, xStart, y, start, end, whitespacePaintingStrategy, fragment);
              }
              if (attributes != null
                  && hasTextEffect(attributes.getEffectColor(), attributes.getEffectType())) {
                paintTextEffect(
                    g, xStart, xEnd, y, attributes.getEffectColor(), attributes.getEffectType());
              }
            }

            @Override
            public void paintAfterLineEnd(
                Graphics2D g,
                Rectangle clip,
                IterationState iterationState,
                int columnStart,
                float x,
                int y) {
              int offset = iterationState.getEndOffset();
              SoftWrapModelImpl softWrapModel = myEditor.getSoftWrapModel();
              if (softWrapModel.getSoftWrap(offset) == null) {
                int logicalLine = myDocument.getLineNumber(offset);
                paintLineExtensions(g, logicalLine, x, y);
              } else {
                softWrapModel.paint(
                    g,
                    SoftWrapDrawingType.BEFORE_SOFT_WRAP_LINE_FEED,
                    (int) x,
                    y - myView.getAscent(),
                    myView.getLineHeight());
              }
            }
          });
    }
  }
コード例 #10
0
 @Override
 @NotNull
 public CharSequence getLastCommittedText(@NotNull Document document) {
   Pair<CharSequence, Long> pair = myLastCommittedTexts.get(document);
   return pair != null ? pair.first : document.getImmutableCharSequence();
 }
コード例 #11
0
 DocumentChangeTransaction(@NotNull Document doc, @NotNull PsiFile scope) {
   myChangeScope = scope;
   myPsiText = CharArrayUtil.createImmutableCharSequence(doc.getImmutableCharSequence());
 }