mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
smart pointers should survive on DocumentEx.moveText
This commit is contained in:
+28
@@ -27,6 +27,7 @@ import com.intellij.openapi.editor.EditorFactory;
|
||||
import com.intellij.openapi.editor.event.DocumentEvent;
|
||||
import com.intellij.openapi.editor.event.DocumentListener;
|
||||
import com.intellij.openapi.editor.event.EditorEventMulticaster;
|
||||
import com.intellij.openapi.editor.ex.DocumentEx;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.fileTypes.PlainTextFileType;
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
@@ -716,6 +717,33 @@ public class SmartPsiElementPointersTest extends CodeInsightTestCase {
|
||||
assertEquals(TextRange.create(1, 2), range2.getRange());
|
||||
}
|
||||
|
||||
public void testMoveText() {
|
||||
PsiJavaFile file = (PsiJavaFile)configureByText(JavaFileType.INSTANCE, "class C1{}\nclass C2 {}");
|
||||
DocumentEx document = (DocumentEx)file.getViewProvider().getDocument();
|
||||
|
||||
SmartPsiElementPointer<PsiClass> pointer1 =
|
||||
SmartPointerManager.getInstance(myProject).createSmartPsiElementPointer(file.getClasses()[0]);
|
||||
SmartPsiElementPointer<PsiClass> pointer2 =
|
||||
SmartPointerManager.getInstance(myProject).createSmartPsiElementPointer(file.getClasses()[1]);
|
||||
assertEquals("C1", pointer1.getElement().getName());
|
||||
assertEquals("C2", pointer2.getElement().getName());
|
||||
|
||||
PlatformTestUtil.tryGcSoftlyReachableObjects();
|
||||
assertNull(((SmartPointerEx) pointer1).getCachedElement());
|
||||
assertNull(((SmartPointerEx) pointer2).getCachedElement());
|
||||
|
||||
TextRange range = file.getClasses()[1].getTextRange();
|
||||
document.moveText(range.getStartOffset(), range.getEndOffset(), 0);
|
||||
|
||||
System.out.println(pointer1.getRange());
|
||||
System.out.println(pointer2.getRange());
|
||||
|
||||
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
|
||||
|
||||
assertEquals("C1", pointer1.getElement().getName());
|
||||
assertEquals("C2", pointer2.getElement().getName());
|
||||
}
|
||||
|
||||
public void testNonPhysicalFile() {
|
||||
PsiJavaFile file = (PsiJavaFile)myJavaFacade.findClass("AClass", GlobalSearchScope.allScope(getProject())).getContainingFile().copy();
|
||||
SmartPsiFileRange pointer = SmartPointerManager.getInstance(myProject).createSmartPsiFileRangePointer(file, TextRange.create(1, 2));
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package com.intellij.openapi.editor.impl;
|
||||
|
||||
import com.intellij.openapi.editor.event.DocumentEvent;
|
||||
import com.intellij.openapi.editor.impl.event.RetargetRangeMarkers;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.ProperTextRange;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -57,6 +58,14 @@ public class ManualRangeMarker {
|
||||
|
||||
@Nullable
|
||||
private Pair<ProperTextRange, PersistentRangeMarker.LinesCols> getUpdatedState(@NotNull DocumentEvent event) {
|
||||
if (event instanceof RetargetRangeMarkers) {
|
||||
int start = ((RetargetRangeMarkers)event).getStartOffset();
|
||||
if (myRange.getStartOffset() >= start && myRange.getEndOffset() <= ((RetargetRangeMarkers)event).getEndOffset()) {
|
||||
ProperTextRange range = myRange.shiftRight(((RetargetRangeMarkers)event).getMoveDestinationOffset() - start);
|
||||
return Pair.create(range, myLinesCols == null ? null : PersistentRangeMarker.storeLinesAndCols(range, event.getDocument()));
|
||||
}
|
||||
}
|
||||
|
||||
if (myLinesCols != null) {
|
||||
return PersistentRangeMarker
|
||||
.applyChange(event, myRange, myRange.getStartOffset(), myRange.getEndOffset(), myGreedyLeft, myGreedyRight, myLinesCols);
|
||||
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.editor.impl.event;
|
||||
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class RetargetRangeMarkers extends DocumentEventImpl {
|
||||
private final int myStartOffset;
|
||||
private final int myEndOffset;
|
||||
private final int myMoveDestinationOffset;
|
||||
|
||||
public RetargetRangeMarkers(@NotNull Document document,
|
||||
int startOffset, int endOffset, int moveDestinationOffset) {
|
||||
super(document, startOffset, "", "", 0, false);
|
||||
myStartOffset = startOffset;
|
||||
myEndOffset = endOffset;
|
||||
myMoveDestinationOffset = moveDestinationOffset;
|
||||
}
|
||||
|
||||
public int getStartOffset() {
|
||||
return myStartOffset;
|
||||
}
|
||||
|
||||
public int getEndOffset() {
|
||||
return myEndOffset;
|
||||
}
|
||||
|
||||
public int getMoveDestinationOffset() {
|
||||
return myMoveDestinationOffset;
|
||||
}
|
||||
}
|
||||
@@ -24,11 +24,15 @@ import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.impl.ApplicationInfoImpl;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.event.DocumentAdapter;
|
||||
import com.intellij.openapi.editor.event.DocumentEvent;
|
||||
import com.intellij.openapi.editor.event.DocumentListener;
|
||||
import com.intellij.openapi.editor.ex.DocumentEx;
|
||||
import com.intellij.openapi.editor.ex.PrioritizedInternalDocumentListener;
|
||||
import com.intellij.openapi.editor.impl.DocumentImpl;
|
||||
import com.intellij.openapi.editor.impl.EditorDocumentPriorities;
|
||||
import com.intellij.openapi.editor.impl.FrozenDocument;
|
||||
import com.intellij.openapi.editor.impl.event.RetargetRangeMarkers;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
@@ -667,10 +671,6 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen
|
||||
if (myStopTrackingDocuments || myProject.isDisposed()) return;
|
||||
|
||||
final Document document = event.getDocument();
|
||||
if (document instanceof DocumentImpl) {
|
||||
myUncommittedInfos.get(document).myEvents.add(event);
|
||||
}
|
||||
|
||||
VirtualFile virtualFile = FileDocumentManager.getInstance().getFile(document);
|
||||
boolean isRelevant = virtualFile != null && isRelevant(virtualFile);
|
||||
|
||||
@@ -767,6 +767,7 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen
|
||||
UncommittedInfo info = myUncommittedInfos.remove(document);
|
||||
if (info != null) {
|
||||
((SmartPointerManagerImpl)SmartPointerManager.getInstance(myProject)).updatePointers(document, info.myFrozen, info.myEvents);
|
||||
Disposer.dispose(info);
|
||||
}
|
||||
return info;
|
||||
}
|
||||
@@ -841,6 +842,9 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen
|
||||
|
||||
@TestOnly
|
||||
public void clearUncommittedDocuments() {
|
||||
for (UncommittedInfo info : myUncommittedInfos.values()) {
|
||||
Disposer.dispose(info);
|
||||
}
|
||||
myUncommittedInfos.clear();
|
||||
myUncommittedDocuments.clear();
|
||||
mySynchronizer.cleanupForNextTest();
|
||||
@@ -863,7 +867,7 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen
|
||||
return mySynchronizer;
|
||||
}
|
||||
|
||||
private static class UncommittedInfo {
|
||||
private static class UncommittedInfo extends DocumentAdapter implements PrioritizedInternalDocumentListener, Disposable {
|
||||
final DocumentImpl myOriginal;
|
||||
final FrozenDocument myFrozen;
|
||||
final List<DocumentEvent> myEvents = ContainerUtil.newArrayList();
|
||||
@@ -871,8 +875,27 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen
|
||||
public UncommittedInfo(DocumentImpl original) {
|
||||
myOriginal = original;
|
||||
myFrozen = original.freeze();
|
||||
myOriginal.addDocumentListener(this, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return EditorDocumentPriorities.RANGE_MARKER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void documentChanged(DocumentEvent e) {
|
||||
myEvents.add(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveTextHappened(int start, int end, int base) {
|
||||
myEvents.add(new RetargetRangeMarkers(myOriginal, start, end, base));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import com.intellij.openapi.editor.event.DocumentEvent;
|
||||
import com.intellij.openapi.editor.impl.FrozenDocument;
|
||||
import com.intellij.openapi.editor.impl.ManualRangeMarker;
|
||||
import com.intellij.openapi.editor.impl.event.DocumentEventImpl;
|
||||
import com.intellij.openapi.editor.impl.event.RetargetRangeMarkers;
|
||||
import com.intellij.openapi.util.ProperTextRange;
|
||||
import com.intellij.openapi.util.Trinity;
|
||||
import com.intellij.util.NullableFunction;
|
||||
@@ -114,10 +115,17 @@ class MarkerCache {
|
||||
@NotNull List<DocumentEvent> events,
|
||||
Map<RangeKey, ManualRangeMarker> map) {
|
||||
for (DocumentEvent event : events) {
|
||||
frozen = frozen.applyEvent(event, 0);
|
||||
final DocumentEvent corrected =
|
||||
new DocumentEventImpl(frozen, event.getOffset(), event.getOldFragment(), event.getNewFragment(), event.getOldTimeStamp(),
|
||||
event.isWholeTextReplaced());
|
||||
DocumentEvent corrected;
|
||||
if ((event instanceof RetargetRangeMarkers)) {
|
||||
RetargetRangeMarkers retarget = (RetargetRangeMarkers)event;
|
||||
corrected = new RetargetRangeMarkers(frozen, retarget.getStartOffset(), retarget.getEndOffset(), retarget.getMoveDestinationOffset());
|
||||
}
|
||||
else {
|
||||
frozen = frozen.applyEvent(event, 0);
|
||||
corrected = new DocumentEventImpl(frozen, event.getOffset(), event.getOldFragment(), event.getNewFragment(), event.getOldTimeStamp(),
|
||||
event.isWholeTextReplaced());
|
||||
}
|
||||
|
||||
for (Map.Entry<RangeKey, ManualRangeMarker> entry : map.entrySet()) {
|
||||
ManualRangeMarker currentRange = entry.getValue();
|
||||
if (currentRange != null) {
|
||||
|
||||
Reference in New Issue
Block a user