@Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (o == null || getClass() != o.getClass()) {
      return false;
    }

    DocumentFoldingInfo info = (DocumentFoldingInfo) o;

    if (myFile != null ? !myFile.equals(info.myFile) : info.myFile != null) {
      return false;
    }
    if (!myProject.equals(info.myProject)
        || !myPsiElements.equals(info.myPsiElements)
        || !mySerializedElements.equals(info.mySerializedElements)) {
      return false;
    }

    if (myRangeMarkers.size() != info.myRangeMarkers.size()) return false;
    for (int i = 0; i < myRangeMarkers.size(); i++) {
      RangeMarker marker = myRangeMarkers.get(i);
      RangeMarker other = info.myRangeMarkers.get(i);
      if (marker == other || !marker.isValid() || !other.isValid()) {
        continue;
      }
      if (!TextRange.areSegmentsEqual(marker, other)) return false;

      FoldingInfo fi = marker.getUserData(FOLDING_INFO_KEY);
      FoldingInfo ofi = other.getUserData(FOLDING_INFO_KEY);
      if (!Comparing.equal(fi, ofi)) return false;
    }
    return true;
  }
  public void testPersistentMarkerDoesntImpactNormalMarkers() {
    Document doc = new DocumentImpl("text");
    RangeMarker normal = doc.createRangeMarker(1, 3);
    RangeMarker persistent = doc.createRangeMarker(1, 3, true);

    doc.replaceString(0, 4, "before\ntext\nafter");

    assertTrue(persistent.isValid());
    assertFalse(normal.isValid());
  }
  public void testUpdateInvalid() throws Exception {
    RangeMarker marker = createMarker("01[]23456789");

    marker.getDocument().deleteString(1, 3);
    assertFalse(marker.isValid());

    marker.getDocument().insertString(2, "xxx");

    assertEquals(2, marker.getStartOffset());
    assertEquals(2, marker.getEndOffset());
    assertFalse(marker.isValid());
  }
  public void testRangeHighlighterDisposeVsRemoveAllConflict() throws Exception {
    Document document = EditorFactory.getInstance().createDocument("[xxxxxxxxxxxxxx]");

    MarkupModel markupModel = DocumentMarkupModel.forDocument(document, ourProject, true);
    RangeMarker m =
        markupModel.addRangeHighlighter(1, 6, 0, null, HighlighterTargetArea.EXACT_RANGE);
    assertTrue(m.isValid());
    markupModel.removeAllHighlighters();
    assertFalse(m.isValid());
    assertEmpty(markupModel.getAllHighlighters());
    m.dispose();
    assertFalse(m.isValid());
  }
  private static void restoreBlockSelection(
      Editor editor, List<RangeMarker> caretsAfter, int caretLine) {
    int column = -1;
    int minLine = Integer.MAX_VALUE;
    int maxLine = -1;
    for (RangeMarker marker : caretsAfter) {
      if (marker.isValid()) {
        LogicalPosition lp = editor.offsetToLogicalPosition(marker.getStartOffset());
        if (column == -1) {
          column = lp.column;
        } else if (column != lp.column) {
          return;
        }
        minLine = Math.min(minLine, lp.line);
        maxLine = Math.max(maxLine, lp.line);

        if (lp.line == caretLine) {
          editor.getCaretModel().moveToLogicalPosition(lp);
        }
      }
    }
    editor
        .getSelectionModel()
        .setBlockSelection(
            new LogicalPosition(minLine, column), new LogicalPosition(maxLine, column));
  }
  public void testCreation() throws Exception {
    RangeMarker marker = createMarker("0123456789", 2, 5);

    assertEquals(2, marker.getStartOffset());
    assertEquals(5, marker.getEndOffset());
    assertTrue(marker.isValid());
  }
  public void testDeletePoint() throws Exception {
    RangeMarker marker = createMarker("0123456789", 2, 2);

    marker.getDocument().deleteString(1, 3);

    assertFalse(marker.isValid());
  }
  public void testDeleteRangeInside() throws Exception {
    RangeMarker marker = createMarker("0123456789", 1, 7);

    marker.getDocument().deleteString(2, 5);

    assertTrue(marker.isValid());
  }
  public void testReplaceRangeToSingleChar() throws Exception {
    RangeMarker marker = createMarker("0123456789", 1, 7);

    marker.getDocument().replaceString(2, 5, " ");

    assertTrue(marker.isValid());
  }
 @Override
 public void documentChanged(DocumentEvent e) {
   UndoManager undoManager = UndoManager.getInstance(myProject);
   boolean undoOrRedo = undoManager.isUndoInProgress() || undoManager.isRedoInProgress();
   if (undoOrRedo) {
     // allow undo/redo up until 'creation stamp' back in time
     // and check it after action is completed
     if (e.getDocument() == myOrigDocument) {
       //noinspection SSBasedInspection
       SwingUtilities.invokeLater(
           () -> {
             if (myOrigCreationStamp > myOrigDocument.getModificationStamp()) {
               closeEditor();
             }
           });
     }
   } else if (e.getDocument() == myNewDocument) {
     commitToOriginal(e);
     if (!isValid()) {
       ApplicationManager.getApplication()
           .invokeLater(() -> closeEditor(), myProject.getDisposed());
     }
   } else if (e.getDocument() == myOrigDocument) {
     if (myCommittingToOriginal || myAltFullRange != null && myAltFullRange.isValid()) return;
     ApplicationManager.getApplication().invokeLater(() -> closeEditor(), myProject.getDisposed());
   }
 }
 @Override
 protected void moveOffsetAfter(boolean success) {
   if (getLocalVariable() != null && getLocalVariable().isValid()) {
     myEditor.getCaretModel().moveToOffset(getLocalVariable().getTextOffset());
     myEditor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
   } else if (getExprMarker() != null) {
     final RangeMarker exprMarker = getExprMarker();
     if (exprMarker.isValid()) {
       myEditor.getCaretModel().moveToOffset(exprMarker.getStartOffset());
       myEditor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
     }
   }
   super.moveOffsetAfter(success);
   if (myLocalMarker != null && !isRestart()) {
     myLocalMarker.dispose();
   }
   if (success) {
     performPostIntroduceTasks();
     final String refactoringId = getRefactoringId();
     if (refactoringId != null) {
       final RefactoringEventData afterData = new RefactoringEventData();
       afterData.addElement(getVariable());
       myProject
           .getMessageBus()
           .syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC)
           .refactoringDone(refactoringId, afterData);
     }
   }
 }
  public void testRangeMarkersAreLazyCreated() throws Exception {
    final Document document = EditorFactory.getInstance().createDocument("[xxxxxxxxxxxxxx]");
    RangeMarker m1 = document.createRangeMarker(2, 4);
    RangeMarker m2 = document.createRangeMarker(2, 4);

    assertEquals(2, ((DocumentImpl) document).getRangeMarkersSize());
    assertEquals(1, ((DocumentImpl) document).getRangeMarkersNodeSize());

    RangeMarker m3 = document.createRangeMarker(2, 5);
    assertEquals(2, ((DocumentImpl) document).getRangeMarkersNodeSize());
    document.deleteString(4, 5);
    assertTrue(m1.isValid());
    assertTrue(m2.isValid());
    assertTrue(m3.isValid());
    assertEquals(1, ((DocumentImpl) document).getRangeMarkersNodeSize());

    m1.setGreedyToLeft(true);
    assertTrue(m1.isValid());
    assertEquals(3, ((DocumentImpl) document).getRangeMarkersSize());
    assertEquals(2, ((DocumentImpl) document).getRangeMarkersNodeSize());

    m3.dispose();
    assertTrue(m1.isValid());
    assertTrue(m2.isValid());
    assertFalse(m3.isValid());
    assertEquals(2, ((DocumentImpl) document).getRangeMarkersSize());
    assertEquals(2, ((DocumentImpl) document).getRangeMarkersNodeSize());
  }
 @Override
 public void dispose() {
   for (Pair<Integer, RangeMarker> pair : myRangesToReindent) {
     RangeMarker marker = pair.second;
     if (marker.isValid()) {
       marker.dispose();
     }
   }
 }
  public void testDeleteBeforeStart() throws Exception {
    RangeMarker marker = createMarker("01[234]56789");

    marker.getDocument().deleteString(0, 1);

    assertEquals(1, marker.getStartOffset());
    assertEquals(4, marker.getEndOffset());
    assertTrue(marker.isValid());
  }
  public void testInsertIntoEnd() throws Exception {
    RangeMarker marker = createMarker("0123456789", 2, 5);

    marker.getDocument().insertString(5, "xxx");

    assertEquals(2, marker.getStartOffset());
    assertEquals(5, marker.getEndOffset());
    assertTrue(marker.isValid());
  }
  public void testInsertIntoStartExpandToLeft() throws Exception {
    RangeMarker marker = createMarker("0123456789", 2, 5);

    marker.setGreedyToLeft(true);

    marker.getDocument().insertString(2, "xxx");

    assertEquals(2, marker.getStartOffset());
    assertEquals(8, marker.getEndOffset());
    assertTrue(marker.isValid());
  }
 protected void onOriginalChanged(DocumentEvent event, Document copy) {
   if (!myRangeMarker.isValid()) {
     fireContentInvalid();
     return;
   }
   replaceString(
       copy,
       0,
       copy.getTextLength(),
       subText(event.getDocument(), myRangeMarker.getStartOffset(), getLength()));
 }
  public void testPersistent() throws Exception {
    String text = "xxx\nzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz";
    Document document = EditorFactory.getInstance().createDocument(text);
    int startOffset = text.indexOf('z');
    int endOffset = text.lastIndexOf('z');
    RangeMarker marker = document.createRangeMarker(startOffset, endOffset, true);

    document.replaceString(startOffset + 1, endOffset - 1, "ccc");

    assertTrue(marker.isValid());
  }
 public boolean isValid() {
   boolean valid =
       myNewVirtualFile.isValid()
           && (myAltFullRange == null && myInjectedFile.isValid()
               || myAltFullRange != null && myAltFullRange.isValid());
   if (valid) {
     for (Trinity<RangeMarker, RangeMarker, SmartPsiElementPointer> t : myMarkers) {
       if (!t.first.isValid() || !t.second.isValid() || t.third.getElement() == null) {
         valid = false;
         break;
       }
     }
   }
   return valid;
 }
  public boolean startsOnTheSameElement(E expr, V localVariable) {
    if (myExprMarker != null
        && myExprMarker.isValid()
        && expr != null
        && myExprMarker.getStartOffset() == expr.getTextOffset()) {
      return true;
    }

    if (myLocalMarker != null
        && myLocalMarker.isValid()
        && localVariable != null
        && myLocalMarker.getStartOffset() == localVariable.getTextOffset()) {
      return true;
    }
    return isRestart();
  }
 @Override
 protected void moveOffsetAfter(boolean success) {
   RangeMarker exprMarker = getExprMarker();
   final AccessToken accessToken = WriteAction.start();
   try {
     Document document = myEditor.getDocument();
     // todo restore original expression if not success
     PsiDocumentManager.getInstance(myProject).commitDocument(document);
     if (exprMarker != null && exprMarker.isValid()) {
       myEditor.getCaretModel().moveToOffset(exprMarker.getStartOffset());
       myEditor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
       exprMarker.dispose();
     }
   } finally {
     accessToken.finish();
   }
 }
 @NotNull
 private static RangeMarker combineScopes(
     RangeMarker old, @NotNull TextRange scope, int textLength, @NotNull Document document) {
   if (old == null) {
     if (scope.equalsToRange(0, textLength)) return WHOLE_FILE_DIRTY_MARKER;
     return document.createRangeMarker(scope);
   }
   if (old == WHOLE_FILE_DIRTY_MARKER) return old;
   TextRange oldRange = TextRange.create(old);
   TextRange union = scope.union(oldRange);
   if (old.isValid() && union.equals(oldRange)) {
     return old;
   }
   if (union.getEndOffset() > textLength) {
     union = union.intersection(new TextRange(0, textLength));
   }
   assert union != null;
   return document.createRangeMarker(union);
 }
 private static boolean isOffsetInsideHighlightInfo(
     int offset, HighlightInfo info, boolean includeFixRange) {
   RangeHighlighterEx highlighter = info.highlighter;
   if (highlighter == null || !highlighter.isValid()) return false;
   int startOffset = highlighter.getStartOffset();
   int endOffset = highlighter.getEndOffset();
   if (startOffset <= offset && offset <= endOffset) {
     return true;
   }
   if (!includeFixRange) return false;
   RangeMarker fixMarker = info.fixMarker;
   if (fixMarker != null) { // null means its range is the same as highlighter
     if (!fixMarker.isValid()) return false;
     startOffset = fixMarker.getStartOffset();
     endOffset = fixMarker.getEndOffset();
     return startOffset <= offset && offset <= endOffset;
   }
   return false;
 }
 /**
  * @return null for processed file, whole file for untouched or entirely dirty file, range(usually
  *     code block) for dirty region (optimization)
  */
 @Nullable
 public TextRange getFileDirtyScope(@NotNull Document document, int passId) {
   synchronized (myDocumentToStatusMap) {
     PsiFile file = PsiDocumentManager.getInstance(myProject).getPsiFile(document);
     if (!ProblemHighlightFilter.shouldHighlightFile(file)) return null;
     FileStatus status = myDocumentToStatusMap.get(document);
     if (status == null) {
       return file == null ? null : file.getTextRange();
     }
     if (status.defensivelyMarked) {
       status.markWholeFileDirty(myProject);
       status.defensivelyMarked = false;
     }
     LOG.assertTrue(status.dirtyScopes.containsKey(passId), "Unknown pass " + passId);
     RangeMarker marker = status.dirtyScopes.get(passId);
     return marker == null
         ? null
         : marker.isValid()
             ? TextRange.create(marker)
             : new TextRange(0, document.getTextLength());
   }
 }
  public void testValidationBug() throws Exception {
    Document document = EditorFactory.getInstance().createDocument("[xxxxxxxxxxxxxx]");
    final Editor editor = EditorFactory.getInstance().createEditor(document);

    try {
      final FoldRegion[] fold = new FoldRegion[1];
      editor
          .getFoldingModel()
          .runBatchFoldingOperation(
              new Runnable() {
                @Override
                public void run() {
                  fold[0] = editor.getFoldingModel().addFoldRegion(0, 2, "");
                }
              });
      RangeMarker marker = document.createRangeMarker(0, 2);
      document.deleteString(1, 2);

      assertTrue(marker.isValid());
      // assertFalse(fold[0].isValid());
    } finally {
      EditorFactory.getInstance().releaseEditor(editor);
    }
  }
  @Override
  public void handleInsert(InsertionContext context) {
    PsiVariable variable = getObject();

    Document document = context.getDocument();
    document.replaceString(context.getStartOffset(), context.getTailOffset(), variable.getName());
    context.commitDocument();

    if (variable instanceof PsiField) {
      if (willBeImported()) {
        RangeMarker toDelete =
            JavaCompletionUtil.insertTemporary(context.getTailOffset(), document, " ");
        context.commitDocument();
        final PsiReferenceExpression ref =
            PsiTreeUtil.findElementOfClassAtOffset(
                context.getFile(), context.getStartOffset(), PsiReferenceExpression.class, false);
        if (ref != null) {
          ref.bindToElementViaStaticImport(((PsiField) variable).getContainingClass());
          PostprocessReformattingAspect.getInstance(ref.getProject()).doPostponedFormatting();
        }
        if (toDelete.isValid()) {
          document.deleteString(toDelete.getStartOffset(), toDelete.getEndOffset());
        }
        context.commitDocument();
      } else if (shouldQualify((PsiField) variable, context)) {
        qualifyFieldReference(context, (PsiField) variable);
      }
    }

    PsiReferenceExpression ref =
        PsiTreeUtil.findElementOfClassAtOffset(
            context.getFile(), context.getTailOffset() - 1, PsiReferenceExpression.class, false);
    if (ref != null) {
      JavaCodeStyleManager.getInstance(context.getProject()).shortenClassReferences(ref);
    }

    ref =
        PsiTreeUtil.findElementOfClassAtOffset(
            context.getFile(), context.getTailOffset() - 1, PsiReferenceExpression.class, false);
    makeVariableFinalIfNeeded(context, ref);

    final char completionChar = context.getCompletionChar();
    if (completionChar == '=') {
      context.setAddCompletionChar(false);
      TailType.EQ.processTail(context.getEditor(), context.getTailOffset());
    } else if (completionChar == ','
        && getAttribute(LookupItem.TAIL_TYPE_ATTR) != TailType.UNKNOWN) {
      context.setAddCompletionChar(false);
      TailType.COMMA.processTail(context.getEditor(), context.getTailOffset());
      AutoPopupController.getInstance(context.getProject())
          .autoPopupParameterInfo(context.getEditor(), null);
    } else if (completionChar == ':') {
      context.setAddCompletionChar(false);
      TailType.COND_EXPR_COLON.processTail(context.getEditor(), context.getTailOffset());
    } else if (completionChar == '.') {
      AutoPopupController.getInstance(context.getProject())
          .autoPopupMemberLookup(context.getEditor(), null);
    } else if (completionChar == '!' && PsiType.BOOLEAN.isAssignableFrom(variable.getType())) {
      context.setAddCompletionChar(false);
      if (ref != null) {
        FeatureUsageTracker.getInstance()
            .triggerFeatureUsed(CodeCompletionFeatures.EXCLAMATION_FINISH);
        document.insertString(ref.getTextRange().getStartOffset(), "!");
      }
    }
  }
  private static CompletionAssertions.WatchingInsertionContext insertItemHonorBlockSelection(
      final CompletionProgressIndicator indicator,
      final LookupElement item,
      final char completionChar,
      final List<LookupElement> items,
      final CompletionLookupArranger.StatisticsUpdate update) {
    final Editor editor = indicator.getEditor();

    final int caretOffset = editor.getCaretModel().getOffset();
    int idEndOffset = indicator.getIdentifierEndOffset();
    if (idEndOffset < 0) {
      idEndOffset = CompletionInitializationContext.calcDefaultIdentifierEnd(editor, caretOffset);
    }
    final int idEndOffsetDelta = idEndOffset - caretOffset;

    CompletionAssertions.WatchingInsertionContext context = null;
    if (editor.getSelectionModel().hasBlockSelection()
        && editor.getSelectionModel().getBlockSelectionEnds().length > 0) {
      List<RangeMarker> insertionPoints = new ArrayList<RangeMarker>();
      int idDelta = 0;
      Document document = editor.getDocument();
      int caretLine = document.getLineNumber(editor.getCaretModel().getOffset());

      for (int point : editor.getSelectionModel().getBlockSelectionEnds()) {
        insertionPoints.add(document.createRangeMarker(point, point));
        if (document.getLineNumber(point) == document.getLineNumber(idEndOffset)) {
          idDelta = idEndOffset - point;
        }
      }

      List<RangeMarker> caretsAfter = new ArrayList<RangeMarker>();
      for (RangeMarker marker : insertionPoints) {
        if (marker.isValid()) {
          int insertionPoint = marker.getStartOffset();
          context =
              insertItem(
                  indicator,
                  item,
                  completionChar,
                  items,
                  update,
                  editor,
                  indicator.getParameters().getOriginalFile(),
                  insertionPoint,
                  idDelta + insertionPoint);
          int offset = editor.getCaretModel().getOffset();
          caretsAfter.add(document.createRangeMarker(offset, offset));
        }
      }
      assert context != null;

      restoreBlockSelection(editor, caretsAfter, caretLine);

      for (RangeMarker insertionPoint : insertionPoints) {
        insertionPoint.dispose();
      }
      for (RangeMarker marker : caretsAfter) {
        marker.dispose();
      }

    } else if (editor.getCaretModel().supportsMultipleCarets()) {
      final List<CompletionAssertions.WatchingInsertionContext> contexts =
          new ArrayList<CompletionAssertions.WatchingInsertionContext>();
      final Editor hostEditor = InjectedLanguageUtil.getTopLevelEditor(editor);
      hostEditor
          .getCaretModel()
          .runForEachCaret(
              new CaretAction() {
                @Override
                public void perform(Caret caret) {
                  PsiFile hostFile =
                      InjectedLanguageUtil.getTopLevelFile(
                          indicator.getParameters().getOriginalFile());
                  PsiFile targetFile =
                      InjectedLanguageUtil.findInjectedPsiNoCommit(hostFile, caret.getOffset());
                  Editor targetEditor =
                      InjectedLanguageUtil.getInjectedEditorForInjectedFile(hostEditor, targetFile);
                  int targetCaretOffset = targetEditor.getCaretModel().getOffset();
                  CompletionAssertions.WatchingInsertionContext currentContext =
                      insertItem(
                          indicator,
                          item,
                          completionChar,
                          items,
                          update,
                          targetEditor,
                          targetFile == null ? hostFile : targetFile,
                          targetCaretOffset,
                          targetCaretOffset + idEndOffsetDelta);
                  contexts.add(currentContext);
                }
              },
              true);
      context = contexts.get(contexts.size() - 1);
      if (context.shouldAddCompletionChar()
          && context.getCompletionChar() != Lookup.COMPLETE_STATEMENT_SELECT_CHAR) {
        ApplicationManager.getApplication()
            .runWriteAction(
                new Runnable() {
                  @Override
                  public void run() {
                    DataContext dataContext =
                        DataManager.getInstance().getDataContext(editor.getContentComponent());
                    EditorActionManager.getInstance()
                        .getTypedAction()
                        .getHandler()
                        .execute(editor, completionChar, dataContext);
                  }
                });
      }
      for (CompletionAssertions.WatchingInsertionContext insertionContext : contexts) {
        insertionContext.stopWatching();
      }
    } else {
      context =
          insertItem(
              indicator,
              item,
              completionChar,
              items,
              update,
              editor,
              indicator.getParameters().getOriginalFile(),
              caretOffset,
              idEndOffset);
    }
    return context;
  }
  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;
  }
  @Override
  public void setToEditor(@NotNull final Editor editor) {
    assertDispatchThread();
    final PsiManager psiManager = PsiManager.getInstance(myProject);
    if (psiManager.isDisposed()) return;

    if (!myFile.isValid()) return;
    final PsiFile psiFile = psiManager.findFile(myFile);
    if (psiFile == null) return;

    if (!mySerializedElements.isEmpty()) {
      // Restore postponed state
      assert myPsiElements.isEmpty() : "Sequential deserialization";
      for (SerializedPsiElement entry : mySerializedElements) {
        PsiElement restoredElement =
            FoldingPolicy.restoreBySignature(psiFile, entry.mySerializedElement);
        if (restoredElement != null && restoredElement.isValid()) {
          myPsiElements.add(
              SmartPointerManager.getInstance(myProject)
                  .createSmartPsiElementPointer(restoredElement));
          restoredElement.putUserData(FOLDING_INFO_KEY, entry.myFoldingInfo);
        }
      }
      mySerializedElements.clear();
    }

    Map<PsiElement, FoldingDescriptor> ranges = null;
    for (SmartPsiElementPointer<PsiElement> ptr : myPsiElements) {
      PsiElement element = ptr.getElement();
      if (element == null || !element.isValid()) {
        continue;
      }

      if (ranges == null) {
        ranges = buildRanges(editor, psiFile);
      }
      FoldingDescriptor descriptor = ranges.get(element);
      if (descriptor == null) {
        continue;
      }

      TextRange range = descriptor.getRange();
      FoldRegion region =
          FoldingUtil.findFoldRegion(editor, range.getStartOffset(), range.getEndOffset());
      if (region != null) {
        FoldingInfo fi = element.getUserData(FOLDING_INFO_KEY);
        boolean state = fi != null && fi.expanded;
        region.setExpanded(state);
      }
    }
    for (RangeMarker marker : myRangeMarkers) {
      if (!marker.isValid()) {
        continue;
      }
      FoldRegion region =
          FoldingUtil.findFoldRegion(editor, marker.getStartOffset(), marker.getEndOffset());
      FoldingInfo info = marker.getUserData(FOLDING_INFO_KEY);
      if (region == null) {
        if (info != null) {
          region =
              editor
                  .getFoldingModel()
                  .addFoldRegion(marker.getStartOffset(), marker.getEndOffset(), info.placeHolder);
        }
        if (region == null) {
          return;
        }
      }

      boolean state = info != null && info.expanded;
      region.setExpanded(state);
    }
  }
 private static void assertValidMarker(@NotNull RangeMarker marker, int start, int end) {
   assertTrue(marker.isValid());
   assertEquals(start, marker.getStartOffset());
   assertEquals(end, marker.getEndOffset());
 }