replace UsagesSearch with ReferencesSearch in Find Usages
This commit is contained in:
+65
-15
@@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+103
-31
@@ -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> {
|
||||
|
||||
+84
-38
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user