mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[recent files + diff] IJ-MR-209657 IJPL-242683 Use shared recent files filtering code on both fe and be sides to simplify and unify filtering approach
(cherry picked from commit 6cd3a5a5048434ff77184f707a2687538a88097f) GitOrigin-RevId: 3d15129cd2cb8991930e2a3dc6b271e03a931602
This commit is contained in:
committed by
intellij-monorepo-bot
parent
1620fd53ef
commit
ed5180618d
+12
-12
@@ -33,6 +33,7 @@ import com.intellij.platform.recentFiles.shared.RecentFileKind
|
||||
import com.intellij.platform.recentFiles.shared.RecentFilesBackendRequest
|
||||
import com.intellij.platform.recentFiles.shared.RecentFilesEvent
|
||||
import com.intellij.platform.recentFiles.shared.SwitcherRpcDto
|
||||
import com.intellij.platform.recentFiles.shared.isAllowedInRecentFilesModel
|
||||
import com.intellij.problems.ProblemListener
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.awaitCancellation
|
||||
@@ -114,7 +115,7 @@ internal class BackendRecentFileEventsModel(private val project: Project, corout
|
||||
val metadata =
|
||||
metadataRequest.frontendRecentFiles
|
||||
.mapNotNull { frontendFileId -> frontendFileId.virtualFile() }
|
||||
.filter { isAllowedInRecentFilesModel(project, it) }
|
||||
.filter { isAllowedInRecentFilesModel(project, metadataRequest.filesKind, it) }
|
||||
.map { frontendFile ->
|
||||
readAction {
|
||||
createRecentFileViewModel(frontendFile, project)
|
||||
@@ -184,10 +185,11 @@ internal class BackendRecentFileEventsModel(private val project: Project, corout
|
||||
private suspend fun processOrderChangeEvent(event: OrderChangeEvent) {
|
||||
when (event.changeKind) {
|
||||
FileChangeKind.ADDED -> {
|
||||
val models = createRecentFilesViewModels(event.files.filter { isAllowedInRecentFilesModel(project, it) })
|
||||
val fileEvent = BackendRecentFilesEvent.ItemsAdded(models)
|
||||
|
||||
for (fileKind in RecentFileKind.entries) {
|
||||
val models = createRecentFilesViewModels(
|
||||
event.files.filter { isAllowedInRecentFilesModel(project, fileKind, it) }
|
||||
)
|
||||
val fileEvent = BackendRecentFilesEvent.ItemsAdded(models)
|
||||
chooseTargetFlow(fileKind).emit(fileEvent)
|
||||
}
|
||||
}
|
||||
@@ -213,16 +215,14 @@ internal class BackendRecentFileEventsModel(private val project: Project, corout
|
||||
BackendRecentFilesModel.getInstance(project).getFilesByKind(fileKind).toSet()
|
||||
}
|
||||
|
||||
val filesToUpdate = files.filter { file ->
|
||||
isAllowedInRecentFilesModel(project, file) && knownFilesByKind.values.any { known -> known.contains(file) }
|
||||
}
|
||||
|
||||
val models = createRecentFilesViewModels(filesToUpdate)
|
||||
assert(models.size == filesToUpdate.size)
|
||||
val filesToUpdate = files.filter { file -> knownFilesByKind.values.any { known -> known.contains(file) } }
|
||||
|
||||
for (fileKind in RecentFileKind.entries) {
|
||||
val knownFiles = knownFilesByKind[fileKind]!!
|
||||
val eventModels = models.filterIndexed { index, _ -> knownFiles.contains(filesToUpdate[index]) }
|
||||
val filesForKind = filesToUpdate.filter { file ->
|
||||
knownFiles.contains(file) && isAllowedInRecentFilesModel(project, fileKind, file)
|
||||
}
|
||||
val eventModels = createRecentFilesViewModels(filesForKind)
|
||||
|
||||
val fileEvent = BackendRecentFilesEvent.ItemsUpdated(eventModels, putOnTop)
|
||||
chooseTargetFlow(fileKind).emit(fileEvent)
|
||||
@@ -269,7 +269,7 @@ internal class BackendRecentFileEventsModel(private val project: Project, corout
|
||||
getFilesToShow(project = project,
|
||||
recentFileKind = filter.filesKind,
|
||||
filesFromFrontendEditorSelectionHistory = filter.frontendEditorSelectionHistory.mapNotNull(VirtualFileId::virtualFile))
|
||||
.filter { isAllowedInRecentFilesModel(project, it) }
|
||||
.filter { isAllowedInRecentFilesModel(project, filter.filesKind, it) }
|
||||
.map {
|
||||
readAction {
|
||||
createRecentFileViewModel(it, project)
|
||||
|
||||
-9
@@ -1,22 +1,13 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.platform.recentFiles.backend
|
||||
|
||||
import com.intellij.openapi.fileEditor.impl.IdeDocumentHistoryImpl
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.platform.recentFiles.shared.RecentFileKind
|
||||
import com.intellij.platform.recentFiles.shared.RecentFilesMutableState
|
||||
|
||||
internal class BackendRecentFilesMutableState(project: Project) : RecentFilesMutableState<VirtualFile>(project) {
|
||||
override fun isAllowedInModel(targetFilesKind: RecentFileKind, model: VirtualFile): Boolean {
|
||||
return isAllowedInRecentFilesModel(project, model)
|
||||
}
|
||||
|
||||
fun getFilesByKind(filesKind: RecentFileKind): List<VirtualFile> {
|
||||
return chooseStateToWriteTo(filesKind).value.entries
|
||||
}
|
||||
}
|
||||
|
||||
internal fun isAllowedInRecentFilesModel(project: Project, file: VirtualFile): Boolean {
|
||||
return file.isValid && (file !is IdeDocumentHistoryImpl.OptionallyIncluded || file.isIncludedInDocumentHistory(project))
|
||||
}
|
||||
@@ -31,9 +31,6 @@
|
||||
<extensionPoint interface="com.intellij.platform.recentFiles.frontend.RecentFilesNavigator"
|
||||
qualifiedName="com.intellij.recentFiles.navigator"
|
||||
dynamic="true"/>
|
||||
<extensionPoint interface="com.intellij.platform.recentFiles.frontend.RecentFilesExcluder"
|
||||
qualifiedName="com.intellij.recentFiles.excluder"
|
||||
dynamic="true"/>
|
||||
</extensionPoints>
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<registryKey key="switcher.use.fallback.in.monolith" defaultValue="false"
|
||||
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.platform.recentFiles.frontend
|
||||
|
||||
import com.intellij.openapi.extensions.ExtensionPointName
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.platform.recentFiles.shared.RecentFileKind
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
|
||||
@ApiStatus.Internal
|
||||
interface RecentFilesExcluder {
|
||||
fun isExcludedFromRecentlyOpened(project: Project, file: VirtualFile): Boolean
|
||||
|
||||
fun isExcludedFromRecentlyEdited(project: Project, file: VirtualFile): Boolean = false
|
||||
|
||||
companion object {
|
||||
@JvmField
|
||||
val EP_NAME: ExtensionPointName<RecentFilesExcluder> = ExtensionPointName<RecentFilesExcluder>("com.intellij.recentFiles.excluder")
|
||||
}
|
||||
}
|
||||
|
||||
internal fun isExcludedFromRecentFiles(project: Project, fileKind: RecentFileKind, file: VirtualFile): Boolean {
|
||||
return RecentFilesExcluder.EP_NAME.findFirstSafe { ext ->
|
||||
when (fileKind) {
|
||||
RecentFileKind.RECENTLY_EDITED -> ext.isExcludedFromRecentlyEdited(project, file)
|
||||
RecentFileKind.RECENTLY_OPENED, RecentFileKind.RECENTLY_OPENED_UNPINNED -> ext.isExcludedFromRecentlyOpened(project, file)
|
||||
}
|
||||
} != null
|
||||
}
|
||||
+2
-1
@@ -10,6 +10,7 @@ import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.platform.recentFiles.frontend.model.FrontendRecentFilesModel
|
||||
import com.intellij.platform.recentFiles.shared.FileChangeKind
|
||||
import com.intellij.platform.recentFiles.shared.RecentFileKind
|
||||
import com.intellij.platform.recentFiles.shared.isAllowedInRecentFilesModel
|
||||
|
||||
private class RecentlySelectedEditorListener : FileEditorManagerListener {
|
||||
override fun fileOpened(source: FileEditorManager, file: VirtualFile) {
|
||||
@@ -25,7 +26,7 @@ private class RecentlySelectedEditorListener : FileEditorManagerListener {
|
||||
if (source.getEditors(file).isEmpty()) {
|
||||
thisLogger().trace { "Do remove closed frontend file from model: ${file.name}" }
|
||||
frontendRecentFilesModel.applyFrontendChanges(RecentFileKind.RECENTLY_OPENED_UNPINNED, listOf(file), FileChangeKind.REMOVED)
|
||||
if (isExcludedFromRecentFiles(source.project, RecentFileKind.RECENTLY_OPENED, file)) {
|
||||
if (!isAllowedInRecentFilesModel(source.project, RecentFileKind.RECENTLY_OPENED, file)) {
|
||||
frontendRecentFilesModel.applyFrontendChanges(RecentFileKind.RECENTLY_OPENED, listOf(file), FileChangeKind.REMOVED)
|
||||
}
|
||||
}
|
||||
|
||||
+9
-3
@@ -19,7 +19,6 @@ import com.intellij.platform.recentFiles.frontend.SwitcherVirtualFile
|
||||
import com.intellij.platform.recentFiles.frontend.createFilesSearchRequestRequest
|
||||
import com.intellij.platform.recentFiles.frontend.createFilesUpdateRequest
|
||||
import com.intellij.platform.recentFiles.frontend.createHideFilesRequest
|
||||
import com.intellij.platform.recentFiles.frontend.isExcludedFromRecentFiles
|
||||
import com.intellij.platform.recentFiles.shared.FileChangeKind
|
||||
import com.intellij.platform.recentFiles.shared.FileSwitcherApi
|
||||
import com.intellij.platform.recentFiles.shared.RecentFileKind
|
||||
@@ -27,6 +26,7 @@ import com.intellij.platform.recentFiles.shared.RecentFilesCoroutineScopeProvide
|
||||
import com.intellij.platform.recentFiles.shared.RecentFilesEvent
|
||||
import com.intellij.platform.recentFiles.shared.RecentFilesState
|
||||
import com.intellij.platform.recentFiles.shared.SwitcherRpcDto
|
||||
import com.intellij.platform.recentFiles.shared.isAllowedInRecentFilesModel
|
||||
import com.intellij.platform.util.coroutines.childScope
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -76,7 +76,10 @@ class FrontendRecentFilesModel(private val project: Project) {
|
||||
|
||||
fun applyFrontendChanges(filesKind: RecentFileKind, files: List<VirtualFile>, changeKind: FileChangeKind) {
|
||||
if (files.isEmpty()) return
|
||||
val filesToApply = if (changeKind == FileChangeKind.REMOVED) files else files.filterNot { isExcludedFromRecentFiles(project, filesKind, it) }
|
||||
val filesToApply = if (changeKind == FileChangeKind.REMOVED) files
|
||||
else files.filter {
|
||||
isAllowedInRecentFilesModel(project, filesKind, it)
|
||||
}
|
||||
if (changeKind != FileChangeKind.REMOVED) {
|
||||
val filesToRemove = files - filesToApply.toSet()
|
||||
if (filesToRemove.isNotEmpty()) {
|
||||
@@ -113,7 +116,10 @@ class FrontendRecentFilesModel(private val project: Project) {
|
||||
oldList.entries
|
||||
}
|
||||
}
|
||||
RecentFilesState(updatedEntries.filter { modelState.isAllowedInModel(filesKind, it) })
|
||||
RecentFilesState(updatedEntries.filter { fileModel ->
|
||||
val file = fileModel.virtualFile ?: return@filter true
|
||||
isAllowedInRecentFilesModel(project, filesKind, file)
|
||||
})
|
||||
}
|
||||
|
||||
when (changeKind) {
|
||||
|
||||
-6
@@ -7,7 +7,6 @@ import com.intellij.openapi.fileEditor.FileEditorManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.platform.recentFiles.frontend.SwitcherVirtualFile
|
||||
import com.intellij.platform.recentFiles.frontend.isExcludedFromRecentFiles
|
||||
import com.intellij.platform.recentFiles.shared.RecentFileKind
|
||||
import com.intellij.platform.recentFiles.shared.RecentFilesMutableState
|
||||
import com.intellij.platform.recentFiles.shared.RecentFilesState
|
||||
@@ -15,11 +14,6 @@ import com.intellij.util.IconUtil
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
||||
internal class FrontendRecentFilesMutableState(project: Project) : RecentFilesMutableState<SwitcherVirtualFile>(project) {
|
||||
override fun isAllowedInModel(targetFilesKind: RecentFileKind, model: SwitcherVirtualFile): Boolean {
|
||||
val file = model.virtualFile ?: return true
|
||||
return file.isValid && !isExcludedFromRecentFiles(project, targetFilesKind, file)
|
||||
}
|
||||
|
||||
fun chooseStateToReadFrom(filesKind: RecentFileKind): MutableStateFlow<RecentFilesState<SwitcherVirtualFile>> {
|
||||
return when (filesKind) {
|
||||
RecentFileKind.RECENTLY_EDITED -> recentlyEditedFilesState
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<idea-plugin>
|
||||
<idea-plugin visibility="internal">
|
||||
<!-- region Generated dependencies - run `Generate Product Layouts` to regenerate -->
|
||||
<dependencies>
|
||||
<module name="fleet.rhizomedb"/>
|
||||
@@ -14,4 +14,10 @@
|
||||
<module name="intellij.platform.util.ui"/>
|
||||
</dependencies>
|
||||
<!-- endregion -->
|
||||
|
||||
<extensionPoints>
|
||||
<extensionPoint interface="com.intellij.platform.recentFiles.shared.RecentFilesExcluder"
|
||||
qualifiedName="com.intellij.recentFiles.excluder"
|
||||
dynamic="true"/>
|
||||
</extensionPoints>
|
||||
</idea-plugin>
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.platform.recentFiles.shared
|
||||
|
||||
import com.intellij.openapi.extensions.ExtensionPointName
|
||||
import com.intellij.openapi.fileEditor.impl.IdeDocumentHistoryImpl
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
|
||||
@ApiStatus.Internal
|
||||
interface RecentFilesExcluder {
|
||||
fun isExcludedFromRecentlyOpened(project: Project, file: VirtualFile): Boolean
|
||||
|
||||
fun isExcludedFromRecentlyEdited(project: Project, file: VirtualFile): Boolean = false
|
||||
|
||||
companion object {
|
||||
@JvmField
|
||||
val EP_NAME: ExtensionPointName<RecentFilesExcluder> = ExtensionPointName("com.intellij.recentFiles.excluder")
|
||||
}
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
fun isAllowedInRecentFilesModel(project: Project, fileKind: RecentFileKind, file: VirtualFile): Boolean {
|
||||
return file.isValid &&
|
||||
(file !is IdeDocumentHistoryImpl.OptionallyIncluded || file.isIncludedInDocumentHistory(project)) &&
|
||||
RecentFilesExcluder.EP_NAME.findFirstSafe { ext ->
|
||||
when (fileKind) {
|
||||
RecentFileKind.RECENTLY_EDITED -> ext.isExcludedFromRecentlyEdited(project, file)
|
||||
RecentFileKind.RECENTLY_OPENED, RecentFileKind.RECENTLY_OPENED_UNPINNED -> ext.isExcludedFromRecentlyOpened(project, file)
|
||||
}
|
||||
} == null
|
||||
}
|
||||
+6
-9
@@ -13,13 +13,11 @@ private val LOG by lazy { fileLogger() }
|
||||
class RecentFilesState<T>(val entries: List<T> = listOf())
|
||||
|
||||
@ApiStatus.Internal
|
||||
abstract class RecentFilesMutableState<T>(protected val project: Project) {
|
||||
open class RecentFilesMutableState<T>(protected val project: Project) {
|
||||
protected val recentlyOpenedFilesState: MutableStateFlow<RecentFilesState<T>> = MutableStateFlow(RecentFilesState())
|
||||
protected val recentlyEditedFilesState: MutableStateFlow<RecentFilesState<T>> = MutableStateFlow(RecentFilesState())
|
||||
protected val recentlyOpenedPinnedFilesState: MutableStateFlow<RecentFilesState<T>> = MutableStateFlow(RecentFilesState())
|
||||
|
||||
abstract fun isAllowedInModel(targetFilesKind: RecentFileKind, model: T): Boolean
|
||||
|
||||
fun chooseStateToWriteTo(targetFilesKind: RecentFileKind): MutableStateFlow<RecentFilesState<T>> {
|
||||
return when (targetFilesKind) {
|
||||
RecentFileKind.RECENTLY_EDITED -> recentlyEditedFilesState
|
||||
@@ -30,11 +28,10 @@ abstract class RecentFilesMutableState<T>(protected val project: Project) {
|
||||
|
||||
fun addEvent(targetFilesKind: RecentFileKind, batch: List<T>) {
|
||||
val targetModel = chooseStateToWriteTo(targetFilesKind)
|
||||
val toAdd = batch
|
||||
LOG.debug("Adding ${batch.size} items to $targetFilesKind frontend model")
|
||||
targetModel.update { oldList ->
|
||||
val updatedState = toAdd + (oldList.entries - toAdd.toSet())
|
||||
RecentFilesState(updatedState.filter { isAllowedInModel(targetFilesKind, it) })
|
||||
val updatedState = batch + (oldList.entries - batch.toSet())
|
||||
RecentFilesState(updatedState)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,11 +46,11 @@ abstract class RecentFilesMutableState<T>(protected val project: Project) {
|
||||
val newValuesToPutIntoFirstPosition = oldList.entries.mapNotNull { oldItem -> itemsToMergeWithExisting[oldItem] }
|
||||
val restOfExistingValues = oldList.entries - newValuesToPutIntoFirstPosition.toSet()
|
||||
val updatedState = newValuesToPutIntoFirstPosition + restOfExistingValues
|
||||
RecentFilesState(updatedState.filter { isAllowedInModel(targetFilesKind, it) })
|
||||
RecentFilesState(updatedState)
|
||||
}
|
||||
else {
|
||||
val effectiveModelsToInsert = oldList.entries.map { oldItem -> itemsToMergeWithExisting[oldItem] ?: oldItem }
|
||||
RecentFilesState(effectiveModelsToInsert.filter { isAllowedInModel(targetFilesKind, it) })
|
||||
RecentFilesState(effectiveModelsToInsert)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -63,7 +60,7 @@ abstract class RecentFilesMutableState<T>(protected val project: Project) {
|
||||
LOG.debug("Removing ${batch.size} items from $targetFilesKind frontend model")
|
||||
targetModel.update { oldList ->
|
||||
val updatedState = oldList.entries - batch.toSet()
|
||||
RecentFilesState(updatedState.filter { isAllowedInModel(targetFilesKind, it) })
|
||||
RecentFilesState(updatedState)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -6,10 +6,10 @@ import com.intellij.openapi.application.EDT
|
||||
import com.intellij.openapi.fileEditor.impl.IdeDocumentHistoryImpl
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.platform.recentFiles.frontend.RecentFilesExcluder
|
||||
import com.intellij.platform.recentFiles.frontend.model.FrontendRecentFilesModel
|
||||
import com.intellij.platform.recentFiles.shared.FileChangeKind
|
||||
import com.intellij.platform.recentFiles.shared.RecentFileKind
|
||||
import com.intellij.platform.recentFiles.shared.RecentFilesExcluder
|
||||
import com.intellij.testFramework.LightVirtualFile
|
||||
import com.intellij.testFramework.junit5.TestApplication
|
||||
import com.intellij.testFramework.junit5.TestDisposable
|
||||
|
||||
@@ -40,6 +40,7 @@ jvm_library(
|
||||
"//platform/util/coroutines",
|
||||
"//libraries/kotlinx/serialization/core",
|
||||
"//libraries/kotlinx/serialization/json",
|
||||
"//platform/recentFiles/shared:recentFiles",
|
||||
"//platform/recentFiles/frontend",
|
||||
"//platform/analysis-api:analysis",
|
||||
"//platform/vcs-api/shared",
|
||||
@@ -83,6 +84,7 @@ jvm_library(
|
||||
"//platform/util/coroutines:coroutines_test_lib",
|
||||
"//libraries/kotlinx/serialization/core:core_test_lib",
|
||||
"//libraries/kotlinx/serialization/json:json_test_lib",
|
||||
"//platform/recentFiles/shared:recentFiles_test_lib",
|
||||
"//platform/recentFiles/frontend:frontend_test_lib",
|
||||
"//platform/analysis-api:analysis_test_lib",
|
||||
"//platform/vcs-api/shared:shared_test_lib",
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
<orderEntry type="module" module-name="intellij.platform.util.coroutines" />
|
||||
<orderEntry type="module" module-name="intellij.libraries.kotlinx.serialization.core" />
|
||||
<orderEntry type="module" module-name="intellij.libraries.kotlinx.serialization.json" />
|
||||
<orderEntry type="module" module-name="intellij.platform.recentFiles" />
|
||||
<orderEntry type="module" module-name="intellij.platform.recentFiles.frontend" />
|
||||
<orderEntry type="module" module-name="intellij.platform.analysis" />
|
||||
<orderEntry type="module" module-name="intellij.platform.vcs.shared" />
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
<module name="intellij.platform.lang.core"/>
|
||||
<module name="intellij.platform.lang.impl"/>
|
||||
<module name="intellij.platform.projectModel"/>
|
||||
<module name="intellij.platform.recentFiles"/>
|
||||
<module name="intellij.platform.recentFiles.frontend"/>
|
||||
<module name="intellij.platform.rpc.topics"/>
|
||||
<module name="intellij.platform.util.coroutines"/>
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ import com.intellij.diff.impl.DiffSettingsHolder
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.platform.recentFiles.frontend.RecentFilesExcluder
|
||||
import com.intellij.platform.recentFiles.shared.RecentFilesExcluder
|
||||
|
||||
internal class DiffRecentFilesExcluder : RecentFilesExcluder {
|
||||
override fun isExcludedFromRecentlyOpened(project: Project, file: VirtualFile): Boolean {
|
||||
|
||||
Reference in New Issue
Block a user