diff --git a/platform/platform-impl/src/com/intellij/ide/actions/RecentLocationManager.java b/platform/platform-impl/src/com/intellij/ide/actions/RecentLocationManager.java index 710f8e874a1a..2f44c4a58f2c 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/RecentLocationManager.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/RecentLocationManager.java @@ -8,16 +8,16 @@ import com.intellij.openapi.editor.LogicalPosition; import com.intellij.openapi.editor.RangeMarker; import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.impl.EditorComponentImpl; -import com.intellij.openapi.fileEditor.FileEditor; -import com.intellij.openapi.fileEditor.FileEditorState; -import com.intellij.openapi.fileEditor.TextEditor; +import com.intellij.openapi.fileEditor.*; import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx; +import com.intellij.openapi.fileEditor.ex.FileEditorWithProvider; import com.intellij.openapi.fileEditor.impl.EditorWindow; import com.intellij.openapi.fileEditor.impl.EditorWithProviderComposite; import com.intellij.openapi.fileEditor.impl.IdeDocumentHistoryImpl; import com.intellij.openapi.fileEditor.impl.IdeDocumentHistoryImpl.PlaceInfo; import com.intellij.openapi.fileEditor.impl.text.TextEditorState; import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.openapi.vfs.newvfs.BulkFileListener; import com.intellij.openapi.vfs.newvfs.events.VFileEvent; @@ -52,6 +52,38 @@ public class RecentLocationManager implements ProjectComponent { subscribeRecentPlaces(connection); subscribeOnExternalChange(connection); + subscribeOnEditorClose(connection); + } + + private void subscribeOnEditorClose(@NotNull MessageBusConnection connection) { + connection.subscribe(FileEditorManagerListener.Before.FILE_EDITOR_MANAGER, new FileEditorManagerListener.Before() { + @Override + public void beforeFileClosed(@NotNull FileEditorManager source, @NotNull VirtualFile file) { + FileEditor fileEditor = source.getSelectedEditor(file); + Editor editor = getEditor(fileEditor); + if (editor == null) { + return; + } + + FileEditorManagerEx editorManagerEx = FileEditorManagerEx.getInstanceEx(myProject); + FileEditorWithProvider selectedEditorWithProvider = editorManagerEx.getSelectedEditorWithProvider(file); + + if (selectedEditorWithProvider == null) { + return; + } + + PlaceInfo placeInfo = new PlaceInfo(file, + fileEditor.getState(FileEditorStateLevel.NAVIGATION), + selectedEditorWithProvider.getProvider().getEditorTypeId(), + editorManagerEx.getCurrentWindow()); + + int offset = editor.getCaretModel().getOffset(); + PlaceInfoPersistentItem placeInfoPersistentItem = + new PlaceInfoPersistentItem(editor.getDocument().createRangeMarker(offset, offset), editor.getColorsScheme()); + + myRecentItems.put(placeInfo, placeInfoPersistentItem); + } + }); } @Nullable @@ -88,7 +120,30 @@ public class RecentLocationManager implements ProjectComponent { connection.subscribe(IdeDocumentHistoryImpl.RecentPlacesListener.TOPIC, new IdeDocumentHistoryImpl.RecentPlacesListener() { @Override public void recentPlaceAdded(@NotNull PlaceInfo changePlace, boolean isChanged) { - update(changePlace, myProject, getItems(isChanged)); + Editor editor = findEditor(myProject, changePlace); + if (editor == null) { + myRecentItems + .keySet() + .stream() + .filter(info -> arePlacesEqual(changePlace, info)) + .findFirst() + .ifPresent(placeInfo -> { + //correct old key + PlaceInfoPersistentItem item = myRecentItems.remove(placeInfo); + myRecentItems.put(changePlace, item); + }); + + return; + } + + LogicalPosition logicalPosition = getLogicalPosition(changePlace); + if (logicalPosition == null) { + return; + } + + int offset = editor.logicalPositionToOffset(logicalPosition); + getItems(isChanged).put(changePlace, new PlaceInfoPersistentItem(editor.getDocument().createRangeMarker(offset, offset), + editor.getColorsScheme())); } @Override @@ -103,25 +158,15 @@ public class RecentLocationManager implements ProjectComponent { }); } - private static void removePlace(@NotNull PlaceInfo placeToRemove, @NotNull Map items) { - items.remove(placeToRemove); + private static boolean arePlacesEqual(@NotNull PlaceInfo info1, @NotNull PlaceInfo info2) { + return info2.getFile().equals(info1.getFile()) && + info2.getEditorTypeId().equals(info1.getEditorTypeId()) + && info2.getNavigationState().equals(info1.getNavigationState()) && + info2.getWindow().equals(info1.getWindow()); } - private static void update(@NotNull PlaceInfo changePlace, - @NotNull Project project, - @NotNull Map items) { - Editor editor = findEditor(project, changePlace); - if (editor == null) { - return; - } - - LogicalPosition logicalPosition = getLogicalPosition(changePlace); - if (logicalPosition == null) { - return; - } - - int offset = editor.logicalPositionToOffset(logicalPosition); - items.put(changePlace, new PlaceInfoPersistentItem(editor.getDocument().createRangeMarker(offset, offset), editor.getColorsScheme())); + private static void removePlace(@NotNull PlaceInfo placeToRemove, @NotNull Map items) { + items.remove(placeToRemove); } @Nullable @@ -162,12 +207,12 @@ public class RecentLocationManager implements ProjectComponent { return null; } - FileEditor fileEditor = composite.getSelectedWithProvider().getFileEditor(); - if (!(fileEditor instanceof TextEditor)) { - return null; - } + return getEditor(composite.getSelectedWithProvider().getFileEditor()); + } - return ((TextEditor)fileEditor).getEditor(); + @Nullable + private static Editor getEditor(@Nullable FileEditor fileEditor) { + return !(fileEditor instanceof TextEditor) ? null : ((TextEditor)fileEditor).getEditor(); } @NotNull