mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-03-22 06:50:54 +07:00
[platform UI][se] IJPL-223925 Find and apply scope to FilesTabSEContributor
(cherry picked from commit 76af54e96c2370df727bd458c601e3a56d325b38) IJ-CR-193777 GitOrigin-RevId: 7429a00fd3c7b591b9a6aa992dfe65c11e04dbb3
This commit is contained in:
committed by
intellij-monorepo-bot
parent
8d2a8bcf74
commit
a8c8727a82
@@ -170,6 +170,15 @@ abstract class AbstractGotoSEContributor @ApiStatus.Internal protected construct
|
||||
}
|
||||
return current
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
fun createScopes(project: Project, psiContext: SmartPsiElementPointer<PsiElement?>?): List<ScopeDescriptor> {
|
||||
@Suppress("DEPRECATION")
|
||||
return project.getService(ScopeService::class.java)
|
||||
.createModel(EnumSet.of(ScopeOption.LIBRARIES, ScopeOption.EMPTY_SCOPES))
|
||||
.getScopesImmediately(createContext(project, psiContext))
|
||||
.scopeDescriptors
|
||||
}
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
@@ -190,10 +199,7 @@ abstract class AbstractGotoSEContributor @ApiStatus.Internal protected construct
|
||||
|
||||
protected open fun createScopes(): List<ScopeDescriptor> {
|
||||
@Suppress("DEPRECATION")
|
||||
return myProject.getService(ScopeService::class.java)
|
||||
.createModel(EnumSet.of(ScopeOption.LIBRARIES, ScopeOption.EMPTY_SCOPES))
|
||||
.getScopesImmediately(createContext(myProject, myPsiContext))
|
||||
.scopeDescriptors
|
||||
return createScopes(myProject, myPsiContext)
|
||||
}
|
||||
|
||||
override fun getSearchProviderId(): String = javaClass.simpleName
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
package com.intellij.ide.actions.searcheverywhere
|
||||
|
||||
import com.intellij.ide.IdeBundle
|
||||
import com.intellij.ide.actions.GotoActionBase
|
||||
import com.intellij.ide.actions.GotoFileItemProvider
|
||||
import com.intellij.ide.actions.SearchEverywherePsiRenderer
|
||||
import com.intellij.ide.actions.searcheverywhere.footer.createPsiExtendedInfo
|
||||
@@ -10,6 +11,7 @@ import com.intellij.ide.util.scopeChooser.ScopeDescriptor
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.application.ReadAction
|
||||
import com.intellij.openapi.application.runReadAction
|
||||
import com.intellij.openapi.application.runReadActionBlocking
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.progress.ProgressIndicator
|
||||
import com.intellij.openapi.project.DumbAware
|
||||
@@ -22,6 +24,8 @@ import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.PsiFileSystemItem
|
||||
import com.intellij.psi.PsiManager
|
||||
import com.intellij.psi.SmartPointerManager
|
||||
import com.intellij.psi.SmartPsiElementPointer
|
||||
import com.intellij.psi.codeStyle.NameUtil
|
||||
import com.intellij.util.Processor
|
||||
import com.intellij.util.indexing.FilesDeque
|
||||
@@ -39,6 +43,9 @@ import kotlin.concurrent.atomics.ExperimentalAtomicApi
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
interface FilesTabSEContributor {
|
||||
val psiContext: SmartPsiElementPointer<PsiElement?>?
|
||||
val project: Project
|
||||
|
||||
fun setScope(scope: ScopeDescriptor)
|
||||
fun setHiddenTypes(hiddenTypes: List<FileTypeRef>)
|
||||
|
||||
@@ -73,11 +80,14 @@ class NonIndexableFilesSEContributor(event: AnActionEvent) : WeightedSearchEvery
|
||||
DumbAware,
|
||||
FilesTabSEContributor,
|
||||
SearchEverywhereExtendedInfoProvider {
|
||||
private val project: Project = event.project!!
|
||||
override val project: Project = event.project!!
|
||||
private val navigationHandler: SearchEverywhereNavigationHandler = FileSearchEverywhereNavigationContributionHandler(project)
|
||||
|
||||
private val scope: AtomicReference<ScopeDescriptor?> = AtomicReference(null)
|
||||
private val hiddenTypes: AtomicReference<Set<FileTypeRef>> = AtomicReference(emptySet())
|
||||
override val psiContext: SmartPsiElementPointer<PsiElement?>? = GotoActionBase.getPsiContext(event)?.let { context ->
|
||||
SmartPointerManager.getInstance(project).createSmartPsiElementPointer(context)
|
||||
}
|
||||
|
||||
override fun getSearchProviderId(): String = ID
|
||||
|
||||
@@ -137,7 +147,7 @@ class NonIndexableFilesSEContributor(event: AnActionEvent) : WeightedSearchEvery
|
||||
*/
|
||||
val pathMatcher = GotoFileItemProvider.getQualifiedNameMatcher(pathPattern)
|
||||
|
||||
val nameMatcher = NameUtil.buildMatcher("*" + namePattern)
|
||||
val nameMatcher = NameUtil.buildMatcher("*$namePattern")
|
||||
.withMatchingMode(MatchingMode.IGNORE_CASE)
|
||||
.preferringStartMatches()
|
||||
.build()
|
||||
@@ -163,7 +173,7 @@ class NonIndexableFilesSEContributor(event: AnActionEvent) : WeightedSearchEvery
|
||||
if (file == null) break
|
||||
|
||||
val workspaceFileIndex = WorkspaceFileIndexEx.getInstance(project)
|
||||
val nonIndexableRoot = runReadAction { workspaceFileIndex.findNonIndexableFileSet(file) }?.root
|
||||
val nonIndexableRoot = runReadActionBlocking { workspaceFileIndex.findNonIndexableFileSet(file) }?.root
|
||||
// path includes root
|
||||
val pathFromNonIndexableRoot = file.path.removePrefix(nonIndexableRoot?.parent?.path ?: "").removePrefix("/")
|
||||
|
||||
|
||||
@@ -74,11 +74,7 @@ class SeTargetsProviderDelegate(private val contributorWrapper: SeAsyncContribut
|
||||
|
||||
scopeProviderDelegate?.let { scopeProviderDelegate ->
|
||||
SeEverywhereFilter.isEverywhere(params.filter)?.let { isEverywhere ->
|
||||
val selectedScopeId = scopeProviderDelegate.searchScopesInfo.getValue()?.let { searchScopesInfo ->
|
||||
if (isEverywhere) searchScopesInfo.everywhereScopeId else searchScopesInfo.projectScopeId
|
||||
} ?: return@let
|
||||
|
||||
scopeProviderDelegate.applyScope(selectedScopeId, false)
|
||||
scopeProviderDelegate.applyScope(isEverywhere, false)
|
||||
} ?: run {
|
||||
val targetsFilter = SeTargetsFilter.from(params.filter)
|
||||
SeTypeVisibilityStateProviderDelegate.applyTypeVisibilityStates<T>(contributor, targetsFilter.hiddenTypes)
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
// 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.searchEverywhere.providers
|
||||
|
||||
import com.intellij.ide.actions.searcheverywhere.AbstractGotoSEContributor
|
||||
import com.intellij.ide.actions.searcheverywhere.FilesTabSEContributor
|
||||
import com.intellij.ide.actions.searcheverywhere.FilesTabSEContributor.Companion.unwrapFilesTabContributorIfPossible
|
||||
import com.intellij.ide.actions.searcheverywhere.ScopeChooserAction
|
||||
import com.intellij.ide.util.scopeChooser.ScopeDescriptor
|
||||
import com.intellij.ide.util.scopeChooser.ScopeIdMapper
|
||||
import com.intellij.openapi.application.readAction
|
||||
import com.intellij.openapi.application.runReadActionBlocking
|
||||
import com.intellij.platform.scopes.SearchScopeData
|
||||
import com.intellij.platform.scopes.SearchScopesInfo
|
||||
import com.intellij.platform.searchEverywhere.utils.SuspendLazyProperty
|
||||
import com.intellij.platform.searchEverywhere.utils.suspendLazy
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import java.util.UUID
|
||||
import kotlin.concurrent.atomics.AtomicReference
|
||||
@@ -19,11 +25,13 @@ class ScopeChooserActionProviderDelegate private constructor(private val contrib
|
||||
|
||||
val searchScopesInfo: SuspendLazyProperty<SearchScopesInfo?> = suspendLazy { getSearchScopesInfo() }
|
||||
|
||||
@Volatile
|
||||
private var scopeIdToScope: AtomicReference<Map<String, ScopeDescriptor>> = AtomicReference(emptyMap())
|
||||
private val availableScopes: AtomicReference<SeScopeById> =
|
||||
contributorWrapper.contributor.unwrapFilesTabContributorIfPossible()?.let { filesTabContributor ->
|
||||
AtomicReference(SeScopeByIdFiles(filesTabContributor))
|
||||
} ?: AtomicReference(SeScopeByIdAtomicMap(emptyMap(), null, null))
|
||||
|
||||
suspend fun getSearchScopesInfo(): SearchScopesInfo? {
|
||||
val scopeChooserAction: ScopeChooserAction = contributorWrapper.contributor.getActions({ }).filterIsInstance<ScopeChooserAction>().firstOrNull()
|
||||
private suspend fun getSearchScopesInfo(): SearchScopesInfo? {
|
||||
val scopeChooserAction: ScopeChooserAction = contributorWrapper.contributor.getActions { }.filterIsInstance<ScopeChooserAction>().firstOrNull()
|
||||
?: return null
|
||||
|
||||
|
||||
@@ -33,54 +41,103 @@ class ScopeChooserActionProviderDelegate private constructor(private val contrib
|
||||
val scopeDataList = readAction {
|
||||
scopeChooserAction.scopesWithSeparators
|
||||
}.mapNotNull { scope ->
|
||||
val key = UUID.randomUUID().toString()
|
||||
val data = SearchScopeData.Companion.from(scope, key)
|
||||
val key = scope.displayName?.let {
|
||||
"${UUID.randomUUID()}$SCOPE_ID_SEPARATOR${ScopeIdMapper.instance.getScopeSerializationId(it)}"
|
||||
} ?: return@mapNotNull null
|
||||
|
||||
val data = SearchScopeData.from(scope, key)
|
||||
if (data != null) all[key] = scope
|
||||
data
|
||||
}
|
||||
scopeIdToScope.store(all)
|
||||
|
||||
val selectedScopeId = selectedScope.scope?.displayName.let { name ->
|
||||
scopeDataList.firstOrNull {
|
||||
@Suppress("HardCodedStringLiteral")
|
||||
it.name == name
|
||||
}?.scopeId
|
||||
}
|
||||
|
||||
val everywhereScopeId = scopeChooserAction.everywhereScopeName?.let { name ->
|
||||
scopeDataList.firstOrNull {
|
||||
@Suppress("HardCodedStringLiteral")
|
||||
it.name == name
|
||||
}?.scopeId
|
||||
}
|
||||
|
||||
val projectScopeId = scopeChooserAction.projectScopeName?.let { name ->
|
||||
scopeDataList.firstOrNull {
|
||||
@Suppress("HardCodedStringLiteral")
|
||||
it.name == name
|
||||
}?.scopeId
|
||||
}
|
||||
|
||||
availableScopes.store(SeScopeByIdAtomicMap(all, everywhereScopeId = everywhereScopeId, projectScopeId = projectScopeId))
|
||||
|
||||
return SearchScopesInfo(scopeDataList,
|
||||
selectedScopeId,
|
||||
projectScopeId,
|
||||
everywhereScopeId)
|
||||
}
|
||||
|
||||
fun applyScope(isEverywhere: Boolean, isAutoTogglePossible: Boolean) {
|
||||
val scope = availableScopes.load()[isEverywhere] ?: return
|
||||
applyScope(scope, isAutoTogglePossible)
|
||||
}
|
||||
|
||||
fun applyScope(scopeId: String?, isAutoTogglePossible: Boolean) {
|
||||
if (scopeId == null) return
|
||||
val scope = scopeIdToScope.load()[scopeId] ?: return
|
||||
val scope = availableScopes.load()[scopeId] ?: return
|
||||
applyScope(scope, isAutoTogglePossible)
|
||||
}
|
||||
|
||||
fun applyScope(scope: ScopeDescriptor, isAutoTogglePossible: Boolean) {
|
||||
contributorWrapper.contributor.getActions { }.filterIsInstance<ScopeChooserAction>().firstOrNull()?.let {
|
||||
it.setScopeIsDefaultAndAutoSet(isAutoTogglePossible)
|
||||
it.onScopeSelected(scope)
|
||||
}
|
||||
?: contributorWrapper.contributor.unwrapFilesTabContributorIfPossible()?.setScope(scope)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun createOrNull(contributorWrapper: SeAsyncContributorWrapper<Any>): ScopeChooserActionProviderDelegate? =
|
||||
if (contributorWrapper.contributor.getActions { }.any { it is ScopeChooserAction })
|
||||
if (contributorWrapper.contributor.unwrapFilesTabContributorIfPossible() != null ||
|
||||
contributorWrapper.contributor.getActions { }.any { it is ScopeChooserAction })
|
||||
ScopeChooserActionProviderDelegate(contributorWrapper)
|
||||
else null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private const val SCOPE_ID_SEPARATOR = '_'
|
||||
|
||||
private interface SeScopeById {
|
||||
operator fun get(isEverywhere: Boolean): ScopeDescriptor?
|
||||
operator fun get(scopeId: String): ScopeDescriptor?
|
||||
}
|
||||
|
||||
private class SeScopeByIdAtomicMap(
|
||||
private val scopeIdToScope: Map<String, ScopeDescriptor>,
|
||||
private val everywhereScopeId: String?,
|
||||
private val projectScopeId: String?,
|
||||
) : SeScopeById {
|
||||
override fun get(isEverywhere: Boolean): ScopeDescriptor? =
|
||||
(if (isEverywhere) everywhereScopeId else projectScopeId)?.let { scopeIdToScope[it] }
|
||||
|
||||
override fun get(scopeId: String): ScopeDescriptor? = scopeIdToScope[scopeId]
|
||||
}
|
||||
|
||||
private class SeScopeByIdFiles(filesContributor: FilesTabSEContributor): SeScopeById {
|
||||
private val scopes = runReadActionBlocking {
|
||||
AbstractGotoSEContributor.createScopes(filesContributor.project, filesContributor.psiContext).mapNotNull {
|
||||
val name = it.displayName ?: return@mapNotNull null
|
||||
ScopeIdMapper.instance.getScopeSerializationId(name) to it
|
||||
}.toMap()
|
||||
}
|
||||
|
||||
private val projectScopeId: String = GlobalSearchScope.projectScope(filesContributor.project).displayName.let {
|
||||
ScopeIdMapper.instance.getScopeSerializationId(it)
|
||||
}
|
||||
|
||||
private val everywhereScopeId: String = GlobalSearchScope.everythingScope(filesContributor.project).displayName.let {
|
||||
ScopeIdMapper.instance.getScopeSerializationId(it)
|
||||
}
|
||||
|
||||
override fun get(isEverywhere: Boolean): ScopeDescriptor? = (if (isEverywhere) everywhereScopeId else projectScopeId).let { scopes[it] }
|
||||
override fun get(scopeId: String): ScopeDescriptor? = scopes[scopeId.substringAfter(SCOPE_ID_SEPARATOR)]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user