replace UsagesSearch with ReferencesSearch in Find Usages

This commit is contained in:
Dmitry Jemerov
2015-08-31 14:03:30 +02:00
parent f76520c771
commit 0bc9ef5c0b
4 changed files with 264 additions and 88 deletions
@@ -22,7 +22,6 @@ import com.intellij.psi.*
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
import org.jetbrains.kotlin.asJava.KotlinLightMethod
import org.jetbrains.kotlin.asJava.KotlinLightParameter
@@ -31,24 +30,37 @@ 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.dataClassComponentFunction
import org.jetbrains.kotlin.idea.search.usagesSearch.getClassNameForCompanionObject
import org.jetbrains.kotlin.idea.search.usagesSearch.getSpecialNamesToSearch
import org.jetbrains.kotlin.idea.search.usagesSearch.*
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.*
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.psi.psiUtil.parents
data class KotlinReferencesSearchOptions(val acceptCallableOverrides: Boolean,
val acceptOverloads: Boolean,
val acceptExtensionsOfDeclarationClass: Boolean) {
fun anyEnabled(): Boolean = acceptCallableOverrides || acceptOverloads || acceptExtensionsOfDeclarationClass
companion object {
val Empty = KotlinReferencesSearchOptions(false, false, false)
}
}
public class KotlinReferencesSearchParameters(elementToSearch: PsiElement,
scope: SearchScope,
ignoreAccessScope: Boolean,
optimizer: SearchRequestCollector?,
val kotlinOptions: KotlinReferencesSearchOptions)
: ReferencesSearch.SearchParameters(elementToSearch, scope, ignoreAccessScope, optimizer) {
}
public class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, ReferencesSearch.SearchParameters>() {
override fun processQuery(queryParameters: ReferencesSearch.SearchParameters, consumer: Processor<PsiReference>) {
val element = queryParameters.getElementToSearch()
val unwrappedElement = element.namedUnwrappedElement
if (unwrappedElement == null || !ProjectRootsUtil.isInProjectOrLibSource(unwrappedElement)) return
val unwrappedElement = element.namedUnwrappedElement ?: return
val classNameForCompanionObject = unwrappedElement.getClassNameForCompanionObject()
val words = unwrappedElement.getSpecialNamesToSearch() +
@@ -61,10 +73,22 @@ public class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, Referenc
else
({true})
val kotlinOptions = (queryParameters as? KotlinReferencesSearchParameters)?.kotlinOptions
?: KotlinReferencesSearchOptions.Empty
val resultProcessor = MyRequestResultProcessor(unwrappedElement, refFilter, kotlinOptions)
if (kotlinOptions.anyEnabled()) {
val name = unwrappedElement.name
if (name != null) {
queryParameters.optimizer.searchWord(name, effectiveSearchScope, UsageSearchContext.IN_CODE, true, unwrappedElement,
resultProcessor)
}
}
words.forEach { word ->
queryParameters.optimizer.searchWord(word, effectiveSearchScope,
UsagesSearchLocation.EVERYWHERE.searchContext, true, unwrappedElement,
MyRequestResultProcessor(unwrappedElement, refFilter))
resultProcessor)
}
if (unwrappedElement is JetParameter) {
@@ -91,12 +115,13 @@ public class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, Referenc
namedArgsScope = GlobalSearchScope.filesScope(project, filesWithFunctionName.asList())
}
val processor = MyRequestResultProcessor(parameter, { it.isNamedArgumentReference() }, KotlinReferencesSearchOptions.Empty)
queryParameters.optimizer.searchWord(parameterName,
namedArgsScope,
KOTLIN_NAMED_ARGUMENT_SEARCH_CONTEXT,
true,
parameter,
MyRequestResultProcessor(parameter) { it.isNamedArgumentReference() })
processor)
}
private fun PsiReference.isNamedArgumentReference(): Boolean {
@@ -105,7 +130,8 @@ public class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, Referenc
private class MyRequestResultProcessor(
private val unwrappedElement: PsiElement,
private val filter: (PsiReference) -> Boolean
private val filter: (PsiReference) -> Boolean,
private val options: KotlinReferencesSearchOptions
) : RequestResultProcessor() {
private val referenceService = PsiReferenceService.getService()
@@ -116,11 +142,29 @@ public class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, Referenc
when {
!filter(ref) -> true
!ReferenceRange.containsOffsetInElement(ref, offsetInElement) -> true
!ref.isReferenceTo(unwrappedElement) -> true
!ref.isReferenceToTarget(unwrappedElement) -> true
else -> consumer.process(ref)
}
}
}
private fun PsiReference.isReferenceToTarget(element: PsiElement): Boolean {
if (isReferenceTo(element)) {
return true
}
if (element is JetNamedDeclaration) {
if (options.acceptCallableOverrides && isCallableOverrideUsage(element)) {
return true
}
if (options.acceptOverloads && isUsageInContainingDeclaration(element)) {
return true
}
if (options.acceptExtensionsOfDeclarationClass && isExtensionOfDeclarationClassUsage(element)) {
return true
}
}
return false
}
}
companion object {
@@ -194,7 +238,8 @@ public class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, Referenc
searchNamedElement(queryParameters, declaration as PsiNamedElement)
}
else if (declaration is JetPropertyAccessor) {
searchNamedElement(queryParameters, PsiTreeUtil.getParentOfType<JetProperty>(declaration, javaClass<JetProperty>()))
val property = declaration.getStrictParentOfType<JetProperty>()
searchNamedElement(queryParameters, property)
}
else if (declaration is JetFunction) {
val staticFromCompanionObject = findStaticMethodFromCompanionObject(declaration)
@@ -225,11 +270,16 @@ public class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, Referenc
private fun isOnlyKotlinSearch(searchScope: SearchScope) =
searchScope is LocalSearchScope && searchScope.getScope().all { it.getContainingFile().getFileType() == JetFileType.INSTANCE }
private fun searchNamedElement(queryParameters: ReferencesSearch.SearchParameters, element: PsiNamedElement?,
private fun searchNamedElement(queryParameters: ReferencesSearch.SearchParameters,
element: PsiNamedElement?,
name: String? = element?.getName()) {
if (name != null && element != null) {
val scope = runReadAction { queryParameters.getEffectiveSearchScope() }
queryParameters.getOptimizer().searchWord(name, scope, true, element)
val context = UsageSearchContext.IN_CODE + UsageSearchContext.IN_FOREIGN_LANGUAGES + UsageSearchContext.IN_COMMENTS
val kotlinOptions = (queryParameters as? KotlinReferencesSearchParameters)?.kotlinOptions
?: KotlinReferencesSearchOptions.Empty
queryParameters.getOptimizer().searchWord(name, scope, context.toShort(), true, element,
MyRequestResultProcessor(element, { true }, kotlinOptions))
}
}
}
@@ -18,35 +18,39 @@ package org.jetbrains.kotlin.idea.findUsages.handlers
import com.intellij.find.findUsages.AbstractFindUsagesDialog
import com.intellij.find.findUsages.FindUsagesOptions
import com.intellij.find.findUsages.JavaFindUsagesHandler
import com.intellij.find.findUsages.JavaFindUsagesHandlerFactory
import com.intellij.openapi.actionSystem.DataContext
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiReference
import com.intellij.psi.search.PsiElementProcessor
import com.intellij.psi.search.PsiElementProcessorAdapter
import com.intellij.psi.search.searches.ReferencesSearch
import com.intellij.usageView.UsageInfo
import com.intellij.util.FilteredQuery
import com.intellij.util.Processor
import org.jetbrains.kotlin.asJava.KotlinLightMethod
import org.jetbrains.kotlin.asJava.LightClassUtil
import org.jetbrains.kotlin.psi.JetClassOrObject
import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.findUsages.KotlinClassFindUsagesOptions
import org.jetbrains.kotlin.idea.findUsages.KotlinFindUsagesHandlerFactory
import org.jetbrains.kotlin.idea.findUsages.dialogs.KotlinFindClassUsagesDialog
import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.idea.search.declarationsSearch.HierarchySearchRequest
import org.jetbrains.kotlin.idea.search.declarationsSearch.searchInheritors
import org.jetbrains.kotlin.idea.findUsages.toSearchTarget
import org.jetbrains.kotlin.idea.findUsages.toClassHelper
import org.jetbrains.kotlin.idea.findUsages.toClassDeclarationsHelper
import org.jetbrains.kotlin.idea.search.usagesSearch.search
import org.jetbrains.kotlin.idea.util.application.runReadAction
import java.util.Collections
import com.intellij.find.findUsages.JavaFindUsagesHandler
import com.intellij.find.findUsages.JavaFindUsagesHandlerFactory
import com.intellij.psi.*
import com.intellij.psi.search.searches.MethodReferencesSearch
import com.intellij.util.CommonProcessors
import org.jetbrains.kotlin.asJava.KotlinLightMethod
import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor
import org.jetbrains.kotlin.idea.search.usagesSearch.isConstructorUsage
import org.jetbrains.kotlin.idea.search.usagesSearch.isImportUsage
import org.jetbrains.kotlin.idea.search.usagesSearch.processDelegationCallConstructorUsages
import org.jetbrains.kotlin.psi.JetClass
import org.jetbrains.kotlin.psi.psiUtil.isInheritable
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.effectiveDeclarations
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.scopes.receivers.ClassReceiver
import java.util.*
public class KotlinFindClassUsagesHandler(
jetClass: JetClassOrObject,
@@ -73,9 +77,9 @@ public class KotlinFindClassUsagesHandler(
PsiElementProcessorAdapter(
object : PsiElementProcessor<PsiClass> {
public override fun execute(element: PsiClass): Boolean {
val traitOrInterface = element.isInterface()
val isInterface = element.isInterface()
return when {
traitOrInterface && options.isDerivedInterfaces, !traitOrInterface && options.isDerivedClasses ->
isInterface && options.isDerivedInterfaces, !isInterface && options.isDerivedClasses ->
KotlinFindUsagesHandler.processUsage(processor, element.getNavigationElement())
else -> true
}
@@ -86,26 +90,94 @@ public class KotlinFindClassUsagesHandler(
}
val classOrObject = element as JetClassOrObject
val referenceProcessor = KotlinFindUsagesHandler.createReferenceProcessor(processor)
val uniqueProcessor = CommonProcessors.UniqueProcessor(processor)
if (kotlinOptions.isUsages || kotlinOptions.searchConstructorUsages) {
if (!processClassReferences(classOrObject, kotlinOptions, referenceProcessor)) return false
}
return runReadAction {
val target = kotlinOptions.toSearchTarget(classOrObject, true)
val classUsages = kotlinOptions.toClassHelper().newRequest(target).search()
val declarationUsages = kotlinOptions.toClassDeclarationsHelper().newRequest(target).search()
if (kotlinOptions.isFieldsUsages || kotlinOptions.isMethodsUsages) {
if (!processMemberReferences(classOrObject, kotlinOptions, referenceProcessor)) return false
}
if (kotlinOptions.searchConstructorUsages) {
val constructors = classOrObject.toLightClass()?.getConstructors() ?: PsiMethod.EMPTY_ARRAY
for (constructor in constructors) {
if (constructor !is KotlinLightMethod) continue
constructor.processDelegationCallConstructorUsages(constructor.getUseScope()) {
it.getCalleeExpression()?.mainReference?.let { KotlinFindUsagesHandler.processUsage(uniqueProcessor, it) }
if (kotlinOptions.isUsages && classOrObject is JetObjectDeclaration && classOrObject.isCompanion()) {
if (!processClassObjectInternalReferences(classOrObject, referenceProcessor)) {
return false
}
}
if (kotlinOptions.searchConstructorUsages) {
val constructors = classOrObject.toLightClass()?.getConstructors() ?: PsiMethod.EMPTY_ARRAY
for (constructor in constructors) {
if (constructor !is KotlinLightMethod) continue
constructor.processDelegationCallConstructorUsages(constructor.getUseScope()) {
it.getCalleeExpression()?.mainReference?.let { referenceProcessor.process(it) }
}
}
}
if (options.isDerivedClasses || options.isDerivedInterfaces) {
if (!processInheritors()) return false
}
return true
}
private fun processClassReferences(classOrObject: JetClassOrObject,
options: KotlinClassFindUsagesOptions,
processor: Processor<PsiReference>): Boolean {
var usagesQuery = ReferencesSearch.search(classOrObject)
if (options.isSkipImportStatements) {
usagesQuery = FilteredQuery(usagesQuery) { !it.isImportUsage() }
}
if (!options.searchConstructorUsages) {
usagesQuery = FilteredQuery(usagesQuery) { !it.isConstructorUsage(classOrObject) }
}
else if (!options.isUsages) {
usagesQuery = FilteredQuery(usagesQuery) { it.isConstructorUsage(classOrObject) }
}
return usagesQuery.forEach(processor)
}
private fun processClassObjectInternalReferences(classObject: JetObjectDeclaration,
processor: Processor<PsiReference>): Boolean {
val klass = classObject.getStrictParentOfType<JetClass>() ?: return true
val companionObjectDescriptor = classObject.descriptor
var stop: Boolean = false
klass.acceptChildren(object : JetVisitorVoid() {
override fun visitJetElement(element: JetElement) {
if (element == classObject) return // skip companion object itself
if (stop) return
element.acceptChildren(this)
val bindingContext = element.analyze()
val call = bindingContext[BindingContext.CALL, element] ?: return
val resolvedCall = bindingContext[BindingContext.RESOLVED_CALL, call] ?: return
if ((resolvedCall.getDispatchReceiver() as? ClassReceiver)?.getDeclarationDescriptor() == companionObjectDescriptor
|| (resolvedCall.getExtensionReceiver() as? ClassReceiver)?.getDeclarationDescriptor() == companionObjectDescriptor) {
element.getReferences().forEach {
if (!stop && !processor.process(it)) {
stop = true
}
}
}
}
})
return !stop
}
(classUsages + declarationUsages).all { KotlinFindUsagesHandler.processUsage(uniqueProcessor, it)} && processInheritors()
private fun processMemberReferences(classOrObject: JetClassOrObject,
options: KotlinClassFindUsagesOptions,
processor: Processor<PsiReference>): Boolean {
for (decl in classOrObject.effectiveDeclarations()) {
if ((decl is JetNamedFunction && options.isMethodsUsages) ||
((decl is JetProperty || decl is JetParameter) && options.isFieldsUsages)) {
if (!ReferencesSearch.search(decl).forEach(processor)) return false
}
}
return true
}
protected override fun getStringsToSearch(element: PsiElement): Collection<String> {
@@ -16,29 +16,35 @@
package org.jetbrains.kotlin.idea.findUsages.handlers
import com.intellij.codeInsight.highlighting.ReadWriteAccessDetector
import com.intellij.find.findUsages.AbstractFindUsagesDialog
import com.intellij.find.findUsages.FindUsagesOptions
import com.intellij.openapi.actionSystem.DataContext
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiReference
import com.intellij.psi.search.searches.MethodReferencesSearch
import com.intellij.psi.search.searches.ReferencesSearch
import com.intellij.usageView.UsageInfo
import com.intellij.util.CommonProcessors
import com.intellij.util.Processor
import com.intellij.util.*
import org.jetbrains.kotlin.asJava.LightClassUtil
import org.jetbrains.kotlin.asJava.toLightMethods
import org.jetbrains.kotlin.idea.findUsages.*
import org.jetbrains.kotlin.idea.findUsages.KotlinCallableFindUsagesOptions
import org.jetbrains.kotlin.idea.findUsages.KotlinFindUsagesHandlerFactory
import org.jetbrains.kotlin.idea.findUsages.KotlinFunctionFindUsagesOptions
import org.jetbrains.kotlin.idea.findUsages.KotlinPropertyFindUsagesOptions
import org.jetbrains.kotlin.idea.findUsages.dialogs.KotlinFindFunctionUsagesDialog
import org.jetbrains.kotlin.idea.findUsages.dialogs.KotlinFindPropertyUsagesDialog
import org.jetbrains.kotlin.idea.search.allScope
import org.jetbrains.kotlin.idea.search.declarationsSearch.HierarchySearchRequest
import org.jetbrains.kotlin.idea.search.declarationsSearch.searchOverriders
import org.jetbrains.kotlin.idea.search.usagesSearch.UsagesSearch
import org.jetbrains.kotlin.idea.search.usagesSearch.UsagesSearchHelper
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReadWriteAccessDetector
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchOptions
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchParameters
import org.jetbrains.kotlin.idea.search.usagesSearch.isImportUsage
import org.jetbrains.kotlin.idea.util.application.runReadAction
import org.jetbrains.kotlin.psi.JetConstructor
import org.jetbrains.kotlin.psi.JetFunction
import org.jetbrains.kotlin.psi.JetNamedDeclaration
import org.jetbrains.kotlin.psi.JetParameter
public abstract class KotlinFindMemberUsagesHandler<T : JetNamedDeclaration>
protected constructor(declaration: T, elementsToSearch: Collection<PsiElement>, factory: KotlinFindUsagesHandlerFactory)
@@ -48,10 +54,6 @@ public abstract class KotlinFindMemberUsagesHandler<T : JetNamedDeclaration>
elementsToSearch: Collection<PsiElement>,
factory: KotlinFindUsagesHandlerFactory) : KotlinFindMemberUsagesHandler<JetFunction>(declaration, elementsToSearch, factory) {
override fun getSearchHelper(options: KotlinCallableFindUsagesOptions): UsagesSearchHelper<JetFunction> {
return (options as KotlinFunctionFindUsagesOptions).toHelper()
}
override fun getFindUsagesOptions(dataContext: DataContext?): FindUsagesOptions = factory.findFunctionOptions
override fun getFindUsagesDialog(isSingleFile: Boolean, toShowInNewTab: Boolean, mustOpenInNewTab: Boolean): AbstractFindUsagesDialog {
@@ -63,50 +65,83 @@ public abstract class KotlinFindMemberUsagesHandler<T : JetNamedDeclaration>
return super.getFindUsagesDialog(isSingleFile, toShowInNewTab, mustOpenInNewTab)
}
override fun createKotlinReferencesSearchOptions(options: FindUsagesOptions): KotlinReferencesSearchOptions {
val kotlinOptions = options as KotlinFunctionFindUsagesOptions
return KotlinReferencesSearchOptions(true,
kotlinOptions.isIncludeOverloadUsages,
kotlinOptions.isIncludeOverloadUsages)
}
override fun applyQueryFilters(element: PsiElement, options: FindUsagesOptions, query: Query<PsiReference>): Query<PsiReference> {
val kotlinOptions = options as KotlinFunctionFindUsagesOptions
return query
.applyFilter(kotlinOptions.isSkipImportStatements) { !it.isImportUsage() }
}
}
private class Property(declaration: JetNamedDeclaration, elementsToSearch: Collection<PsiElement>, factory: KotlinFindUsagesHandlerFactory) : KotlinFindMemberUsagesHandler<JetNamedDeclaration>(declaration, elementsToSearch, factory) {
override fun getSearchHelper(options: KotlinCallableFindUsagesOptions): UsagesSearchHelper<JetNamedDeclaration> {
return (options as KotlinPropertyFindUsagesOptions).toHelper()
}
override fun getFindUsagesOptions(dataContext: DataContext?): FindUsagesOptions = factory.findPropertyOptions
override fun getFindUsagesDialog(isSingleFile: Boolean, toShowInNewTab: Boolean, mustOpenInNewTab: Boolean): AbstractFindUsagesDialog {
return KotlinFindPropertyUsagesDialog(getElement(), getProject(), factory.findPropertyOptions, toShowInNewTab, mustOpenInNewTab, isSingleFile, this)
}
}
protected abstract fun getSearchHelper(options: KotlinCallableFindUsagesOptions): UsagesSearchHelper<T>
override fun applyQueryFilters(element: PsiElement, options: FindUsagesOptions, query: Query<PsiReference>): Query<PsiReference> {
var kotlinOptions = options as KotlinPropertyFindUsagesOptions
if (!kotlinOptions.isReadAccess && !kotlinOptions.isWriteAccess) {
return EmptyQuery()
}
val result = query
.applyFilter(kotlinOptions.isSkipImportStatements) { !it.isImportUsage() }
if (!kotlinOptions.isReadAccess || !kotlinOptions.isWriteAccess) {
val detector = KotlinReadWriteAccessDetector()
return FilteredQuery(result) {
val access = detector.getReferenceAccess(element, it)
when (access) {
ReadWriteAccessDetector.Access.Read -> kotlinOptions.isReadAccess
ReadWriteAccessDetector.Access.Write -> kotlinOptions.isWriteAccess
ReadWriteAccessDetector.Access.ReadWrite -> true
}
}
}
return result
}
override fun createKotlinReferencesSearchOptions(options: FindUsagesOptions): KotlinReferencesSearchOptions {
return KotlinReferencesSearchOptions(true, false, false)
}
}
override fun searchReferences(element: PsiElement, processor: Processor<UsageInfo>, options: FindUsagesOptions): Boolean {
val kotlinOptions = options as KotlinCallableFindUsagesOptions
val request = runReadAction {
@suppress("UNCHECKED_CAST")
val searchTarget = if (element is JetParameter)
options.toSearchTarget<T>(element as T, restrictByTarget = false) // named argument usages are outside getUseScope for JetParameter
else
options.toSearchTarget<T>(element as T, restrictByTarget = true)
getSearchHelper(kotlinOptions).newRequest(searchTarget)
}
val referenceProcessor = KotlinFindUsagesHandler.createReferenceProcessor(processor)
val uniqueProcessor = CommonProcessors.UniqueProcessor(processor)
for (ref in UsagesSearch.search(request)) {
KotlinFindUsagesHandler.processUsage(uniqueProcessor, ref)
}
if (options.isUsages) {
val searchParameters = KotlinReferencesSearchParameters(element,
element.project.allScope(),
ignoreAccessScope = false,
optimizer = null,
kotlinOptions = createKotlinReferencesSearchOptions(options))
val psiMethod: PsiMethod? = when (element) {
is PsiMethod -> element
is JetConstructor<*> -> runReadAction { LightClassUtil.getLightClassMethod(element as JetFunction) }
else -> null
}
if (psiMethod != null) {
for (ref in MethodReferencesSearch.search(psiMethod, options.searchScope, true)) {
KotlinFindUsagesHandler.processUsage(uniqueProcessor, ref)
val query = applyQueryFilters(element, options, ReferencesSearch.search(searchParameters))
if (!query.forEach(referenceProcessor)) return false
val psiMethod: PsiMethod? = when (element) {
is PsiMethod -> element
is JetFunction -> runReadAction { LightClassUtil.getLightClassMethod(element) }
else -> null
}
if (psiMethod != null) {
val query = applyQueryFilters(element, options, MethodReferencesSearch.search(psiMethod, options.searchScope, true))
if (!query.forEach(referenceProcessor)) return false
}
}
@@ -119,6 +154,12 @@ public abstract class KotlinFindMemberUsagesHandler<T : JetNamedDeclaration>
return true
}
protected abstract fun createKotlinReferencesSearchOptions(options: FindUsagesOptions): KotlinReferencesSearchOptions
protected abstract fun applyQueryFilters(element: PsiElement,
options: FindUsagesOptions,
query: Query<PsiReference>): Query<PsiReference>
override fun isSearchForTextOccurencesAvailable(psiElement: PsiElement, isSingleFile: Boolean): Boolean = !isSingleFile
companion object {
@@ -133,3 +174,8 @@ public abstract class KotlinFindMemberUsagesHandler<T : JetNamedDeclaration>
}
}
}
fun Query<PsiReference>.applyFilter(flag: Boolean, condition: (PsiReference) -> Boolean): Query<PsiReference> {
return if (flag) FilteredQuery(this, condition) else this
}
@@ -18,19 +18,17 @@ package org.jetbrains.kotlin.idea.findUsages.handlers
import com.intellij.find.findUsages.FindUsagesHandler
import com.intellij.find.findUsages.FindUsagesOptions
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiReference
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.search.SearchScope
import com.intellij.usageView.UsageInfo
import com.intellij.util.CommonProcessors
import com.intellij.util.Processor
import org.jetbrains.kotlin.idea.findUsages.KotlinFindUsagesHandlerFactory
import org.jetbrains.kotlin.idea.findUsages.KotlinReferenceUsageInfo
import org.jetbrains.kotlin.idea.util.application.runReadAction
import java.util.ArrayList
import java.util.Collections
import java.util.*
public abstract class KotlinFindUsagesHandler<T : PsiElement>(psiElement: T,
private val elementsToSearch: Collection<PsiElement>,
@@ -100,5 +98,15 @@ public abstract class KotlinFindUsagesHandler<T : PsiElement>(psiElement: T,
val usageInfo = runReadAction(callback)
return if (usageInfo != null) process(usageInfo) else true
}
protected fun createReferenceProcessor(usageInfoProcessor: Processor<UsageInfo>): Processor<PsiReference> {
val uniqueProcessor = CommonProcessors.UniqueProcessor(usageInfoProcessor)
return object: Processor<PsiReference> {
override fun process(t: PsiReference): Boolean {
return KotlinFindUsagesHandler.processUsage(uniqueProcessor, t)
}
}
}
}
}