ReferenceSearch searches references to parameters using optimized way too

#KT-8625 Fixed
This commit is contained in:
Valentin Kipyatkov
2015-07-31 16:50:34 +03:00
parent d6f724c55d
commit 397e48a11d
7 changed files with 74 additions and 88 deletions
@@ -19,9 +19,8 @@ package org.jetbrains.kotlin.idea.search.ideaExtensions
import com.intellij.openapi.application.QueryExecutorBase
import com.intellij.openapi.progress.ProgressManager
import com.intellij.psi.*
import com.intellij.psi.search.LocalSearchScope
import com.intellij.psi.search.RequestResultProcessor
import com.intellij.psi.search.SearchScope
import com.intellij.psi.impl.cache.CacheManager
import com.intellij.psi.search.*
import com.intellij.psi.search.searches.ReferencesSearch
import com.intellij.psi.util.PsiTreeUtil
import com.intellij.util.Processor
@@ -29,8 +28,11 @@ import org.jetbrains.kotlin.asJava.KotlinLightMethod
import org.jetbrains.kotlin.asJava.LightClassUtil
import org.jetbrains.kotlin.asJava.namedUnwrappedElement
import org.jetbrains.kotlin.idea.JetFileType
import org.jetbrains.kotlin.idea.references.JetSimpleNameReference
import org.jetbrains.kotlin.idea.search.KOTLIN_NAMED_ARGUMENT_SEARCH_CONTEXT
import org.jetbrains.kotlin.idea.search.usagesSearch.UsagesSearchLocation
import org.jetbrains.kotlin.idea.search.usagesSearch.getSpecialNamesToSearch
import org.jetbrains.kotlin.idea.stubindex.JetSourceFilterScope
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
import org.jetbrains.kotlin.idea.util.application.runReadAction
import org.jetbrains.kotlin.psi.*
@@ -45,28 +47,16 @@ public class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, Referenc
val words = unwrappedElement.getSpecialNamesToSearch()
val resultProcessor = object : RequestResultProcessor() {
private val referenceService = PsiReferenceService.getService()
override fun processTextOccurrence(element: PsiElement, offsetInElement: Int, consumer: Processor<PsiReference>): Boolean {
return referenceService.getReferences(element, PsiReferenceService.Hints.NO_HINTS).all { ref ->
ProgressManager.checkCanceled()
when {
!ReferenceRange.containsOffsetInElement(ref, offsetInElement) -> true
!ref.isReferenceTo(unwrappedElement) -> true
else -> consumer.process(ref)
}
}
}
}
val effectiveSearchScope = runReadAction { queryParameters.effectiveSearchScope }
words.forEach { word ->
queryParameters.getOptimizer().searchWord(word, effectiveSearchScope,
UsagesSearchLocation.EVERYWHERE.searchContext, true, unwrappedElement,
resultProcessor)
queryParameters.optimizer.searchWord(word, effectiveSearchScope,
UsagesSearchLocation.EVERYWHERE.searchContext, true, unwrappedElement,
MyRequestResultProcessor(unwrappedElement) { !it.isNamedArgumentReference()/* they are processed later*/ })
}
if (unwrappedElement is JetParameter) {
runReadAction { searchNamedArguments(unwrappedElement, queryParameters) }
}
if (!(unwrappedElement is JetElement && isOnlyKotlinSearch(effectiveSearchScope))) {
@@ -74,6 +64,52 @@ public class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, Referenc
}
}
private fun searchNamedArguments(parameter: JetParameter, queryParameters: ReferencesSearch.SearchParameters) {
val function = parameter.ownerFunction ?: return
if (function.nameAsName?.isSpecial ?: true) return
val project = function.project
var namedArgsScope = function.useScope.intersectWith(queryParameters.scopeDeterminedByUser)
if (namedArgsScope is GlobalSearchScope) {
namedArgsScope = JetSourceFilterScope.kotlinSources(namedArgsScope, project)
val filesWithFunctionName = CacheManager.SERVICE.getInstance(project).getVirtualFilesWithWord(
function.name!!, UsageSearchContext.IN_CODE, namedArgsScope, true)
namedArgsScope = GlobalSearchScope.filesScope(project, filesWithFunctionName.asList())
}
queryParameters.optimizer.searchWord(parameter.name!!,
namedArgsScope,
KOTLIN_NAMED_ARGUMENT_SEARCH_CONTEXT,
true,
parameter,
MyRequestResultProcessor(parameter) { it.isNamedArgumentReference() })
}
private fun PsiReference.isNamedArgumentReference(): Boolean {
return this is JetSimpleNameReference && expression.parent is JetValueArgumentName
}
private class MyRequestResultProcessor(
private val unwrappedElement: PsiElement,
private val filter: (PsiReference) -> Boolean
) : RequestResultProcessor() {
private val referenceService = PsiReferenceService.getService()
override fun processTextOccurrence(element: PsiElement, offsetInElement: Int, consumer: Processor<PsiReference>): Boolean {
return referenceService.getReferences(element, PsiReferenceService.Hints.NO_HINTS).all { ref ->
ProgressManager.checkCanceled()
when {
!filter(ref) -> true
!ReferenceRange.containsOffsetInElement(ref, offsetInElement) -> true
!ref.isReferenceTo(unwrappedElement) -> true
else -> consumer.process(ref)
}
}
}
}
companion object {
public fun processJetClassOrObject(element: JetClassOrObject, queryParameters: ReferencesSearch.SearchParameters) {
val className = element.getName()
@@ -251,8 +251,8 @@ class PropertyUsagesSearchHelper(
override fun makeItemList(target: UsagesSearchTarget<JetNamedDeclaration>): List<UsagesSearchRequestItem> {
val element = target.element
if (element is JetParameter) {
val realUsagesScope = element.useScopeExceptNamedArguments
val realUsagesTarget = target.withScope(realUsagesScope and target.effectiveScope)
val realUsagesScope = element.useScope and target.effectiveScope
val realUsagesTarget = target.withScope(realUsagesScope)
val realUsagesFilter = makeFilter(target) and !(PsiReference::isNamedArgumentUsage).searchFilter
val realUsagesRequest = UsagesSearchRequestItem(realUsagesTarget, makeWordList(target), realUsagesFilter, makeAdditionalSearchDelegate(target.element))
@@ -266,7 +266,7 @@ class PropertyUsagesSearchHelper(
return listOf(realUsagesRequest)
}
var scope = target.effectiveScope
var scope = function.useScope and target.effectiveScope
if (scope is GlobalSearchScope) {
scope = JetSourceFilterScope.kotlinSources(scope, element.project)
}
@@ -96,7 +96,7 @@ public class UsagesSearchRequestItem(
val additionalFileFilters: Collection<AdditionalFileFilter> = emptyList()
)
public data class AdditionalFileFilter(
public class AdditionalFileFilter(
val word: String,
val searchContext: Short,
val caseSensitively: Boolean