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.impl.cache.CacheManager
|
||||||
import com.intellij.psi.search.*
|
import com.intellij.psi.search.*
|
||||||
import com.intellij.psi.search.searches.ReferencesSearch
|
import com.intellij.psi.search.searches.ReferencesSearch
|
||||||
import com.intellij.psi.util.PsiTreeUtil
|
|
||||||
import com.intellij.util.Processor
|
import com.intellij.util.Processor
|
||||||
import org.jetbrains.kotlin.asJava.KotlinLightMethod
|
import org.jetbrains.kotlin.asJava.KotlinLightMethod
|
||||||
import org.jetbrains.kotlin.asJava.KotlinLightParameter
|
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.JetFileType
|
||||||
import org.jetbrains.kotlin.idea.references.JetSimpleNameReference
|
import org.jetbrains.kotlin.idea.references.JetSimpleNameReference
|
||||||
import org.jetbrains.kotlin.idea.search.KOTLIN_NAMED_ARGUMENT_SEARCH_CONTEXT
|
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.*
|
||||||
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.stubindex.JetSourceFilterScope
|
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.idea.util.application.runReadAction
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.parents
|
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>() {
|
public class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, ReferencesSearch.SearchParameters>() {
|
||||||
|
|
||||||
override fun processQuery(queryParameters: ReferencesSearch.SearchParameters, consumer: Processor<PsiReference>) {
|
override fun processQuery(queryParameters: ReferencesSearch.SearchParameters, consumer: Processor<PsiReference>) {
|
||||||
val element = queryParameters.getElementToSearch()
|
val element = queryParameters.getElementToSearch()
|
||||||
|
|
||||||
val unwrappedElement = element.namedUnwrappedElement
|
val unwrappedElement = element.namedUnwrappedElement ?: return
|
||||||
if (unwrappedElement == null || !ProjectRootsUtil.isInProjectOrLibSource(unwrappedElement)) return
|
|
||||||
|
|
||||||
val classNameForCompanionObject = unwrappedElement.getClassNameForCompanionObject()
|
val classNameForCompanionObject = unwrappedElement.getClassNameForCompanionObject()
|
||||||
val words = unwrappedElement.getSpecialNamesToSearch() +
|
val words = unwrappedElement.getSpecialNamesToSearch() +
|
||||||
@@ -61,10 +73,22 @@ public class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, Referenc
|
|||||||
else
|
else
|
||||||
({true})
|
({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 ->
|
words.forEach { word ->
|
||||||
queryParameters.optimizer.searchWord(word, effectiveSearchScope,
|
queryParameters.optimizer.searchWord(word, effectiveSearchScope,
|
||||||
UsagesSearchLocation.EVERYWHERE.searchContext, true, unwrappedElement,
|
UsagesSearchLocation.EVERYWHERE.searchContext, true, unwrappedElement,
|
||||||
MyRequestResultProcessor(unwrappedElement, refFilter))
|
resultProcessor)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unwrappedElement is JetParameter) {
|
if (unwrappedElement is JetParameter) {
|
||||||
@@ -91,12 +115,13 @@ public class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, Referenc
|
|||||||
namedArgsScope = GlobalSearchScope.filesScope(project, filesWithFunctionName.asList())
|
namedArgsScope = GlobalSearchScope.filesScope(project, filesWithFunctionName.asList())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val processor = MyRequestResultProcessor(parameter, { it.isNamedArgumentReference() }, KotlinReferencesSearchOptions.Empty)
|
||||||
queryParameters.optimizer.searchWord(parameterName,
|
queryParameters.optimizer.searchWord(parameterName,
|
||||||
namedArgsScope,
|
namedArgsScope,
|
||||||
KOTLIN_NAMED_ARGUMENT_SEARCH_CONTEXT,
|
KOTLIN_NAMED_ARGUMENT_SEARCH_CONTEXT,
|
||||||
true,
|
true,
|
||||||
parameter,
|
parameter,
|
||||||
MyRequestResultProcessor(parameter) { it.isNamedArgumentReference() })
|
processor)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun PsiReference.isNamedArgumentReference(): Boolean {
|
private fun PsiReference.isNamedArgumentReference(): Boolean {
|
||||||
@@ -105,7 +130,8 @@ public class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, Referenc
|
|||||||
|
|
||||||
private class MyRequestResultProcessor(
|
private class MyRequestResultProcessor(
|
||||||
private val unwrappedElement: PsiElement,
|
private val unwrappedElement: PsiElement,
|
||||||
private val filter: (PsiReference) -> Boolean
|
private val filter: (PsiReference) -> Boolean,
|
||||||
|
private val options: KotlinReferencesSearchOptions
|
||||||
) : RequestResultProcessor() {
|
) : RequestResultProcessor() {
|
||||||
private val referenceService = PsiReferenceService.getService()
|
private val referenceService = PsiReferenceService.getService()
|
||||||
|
|
||||||
@@ -116,11 +142,29 @@ public class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, Referenc
|
|||||||
when {
|
when {
|
||||||
!filter(ref) -> true
|
!filter(ref) -> true
|
||||||
!ReferenceRange.containsOffsetInElement(ref, offsetInElement) -> true
|
!ReferenceRange.containsOffsetInElement(ref, offsetInElement) -> true
|
||||||
!ref.isReferenceTo(unwrappedElement) -> true
|
!ref.isReferenceToTarget(unwrappedElement) -> true
|
||||||
else -> consumer.process(ref)
|
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 {
|
companion object {
|
||||||
@@ -194,7 +238,8 @@ public class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, Referenc
|
|||||||
searchNamedElement(queryParameters, declaration as PsiNamedElement)
|
searchNamedElement(queryParameters, declaration as PsiNamedElement)
|
||||||
}
|
}
|
||||||
else if (declaration is JetPropertyAccessor) {
|
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) {
|
else if (declaration is JetFunction) {
|
||||||
val staticFromCompanionObject = findStaticMethodFromCompanionObject(declaration)
|
val staticFromCompanionObject = findStaticMethodFromCompanionObject(declaration)
|
||||||
@@ -225,11 +270,16 @@ public class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, Referenc
|
|||||||
private fun isOnlyKotlinSearch(searchScope: SearchScope) =
|
private fun isOnlyKotlinSearch(searchScope: SearchScope) =
|
||||||
searchScope is LocalSearchScope && searchScope.getScope().all { it.getContainingFile().getFileType() == JetFileType.INSTANCE }
|
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()) {
|
name: String? = element?.getName()) {
|
||||||
if (name != null && element != null) {
|
if (name != null && element != null) {
|
||||||
val scope = runReadAction { queryParameters.getEffectiveSearchScope() }
|
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.AbstractFindUsagesDialog
|
||||||
import com.intellij.find.findUsages.FindUsagesOptions
|
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.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.PsiElementProcessor
|
||||||
import com.intellij.psi.search.PsiElementProcessorAdapter
|
import com.intellij.psi.search.PsiElementProcessorAdapter
|
||||||
|
import com.intellij.psi.search.searches.ReferencesSearch
|
||||||
import com.intellij.usageView.UsageInfo
|
import com.intellij.usageView.UsageInfo
|
||||||
|
import com.intellij.util.FilteredQuery
|
||||||
import com.intellij.util.Processor
|
import com.intellij.util.Processor
|
||||||
|
import org.jetbrains.kotlin.asJava.KotlinLightMethod
|
||||||
import org.jetbrains.kotlin.asJava.LightClassUtil
|
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.KotlinClassFindUsagesOptions
|
||||||
import org.jetbrains.kotlin.idea.findUsages.KotlinFindUsagesHandlerFactory
|
import org.jetbrains.kotlin.idea.findUsages.KotlinFindUsagesHandlerFactory
|
||||||
import org.jetbrains.kotlin.idea.findUsages.dialogs.KotlinFindClassUsagesDialog
|
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.HierarchySearchRequest
|
||||||
import org.jetbrains.kotlin.idea.search.declarationsSearch.searchInheritors
|
import org.jetbrains.kotlin.idea.search.declarationsSearch.searchInheritors
|
||||||
import org.jetbrains.kotlin.idea.findUsages.toSearchTarget
|
import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor
|
||||||
import org.jetbrains.kotlin.idea.findUsages.toClassHelper
|
import org.jetbrains.kotlin.idea.search.usagesSearch.isConstructorUsage
|
||||||
import org.jetbrains.kotlin.idea.findUsages.toClassDeclarationsHelper
|
import org.jetbrains.kotlin.idea.search.usagesSearch.isImportUsage
|
||||||
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.processDelegationCallConstructorUsages
|
import org.jetbrains.kotlin.idea.search.usagesSearch.processDelegationCallConstructorUsages
|
||||||
import org.jetbrains.kotlin.psi.JetClass
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.isInheritable
|
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(
|
public class KotlinFindClassUsagesHandler(
|
||||||
jetClass: JetClassOrObject,
|
jetClass: JetClassOrObject,
|
||||||
@@ -73,9 +77,9 @@ public class KotlinFindClassUsagesHandler(
|
|||||||
PsiElementProcessorAdapter(
|
PsiElementProcessorAdapter(
|
||||||
object : PsiElementProcessor<PsiClass> {
|
object : PsiElementProcessor<PsiClass> {
|
||||||
public override fun execute(element: PsiClass): Boolean {
|
public override fun execute(element: PsiClass): Boolean {
|
||||||
val traitOrInterface = element.isInterface()
|
val isInterface = element.isInterface()
|
||||||
return when {
|
return when {
|
||||||
traitOrInterface && options.isDerivedInterfaces, !traitOrInterface && options.isDerivedClasses ->
|
isInterface && options.isDerivedInterfaces, !isInterface && options.isDerivedClasses ->
|
||||||
KotlinFindUsagesHandler.processUsage(processor, element.getNavigationElement())
|
KotlinFindUsagesHandler.processUsage(processor, element.getNavigationElement())
|
||||||
else -> true
|
else -> true
|
||||||
}
|
}
|
||||||
@@ -86,26 +90,94 @@ public class KotlinFindClassUsagesHandler(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val classOrObject = element as JetClassOrObject
|
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 {
|
if (kotlinOptions.isFieldsUsages || kotlinOptions.isMethodsUsages) {
|
||||||
val target = kotlinOptions.toSearchTarget(classOrObject, true)
|
if (!processMemberReferences(classOrObject, kotlinOptions, referenceProcessor)) return false
|
||||||
val classUsages = kotlinOptions.toClassHelper().newRequest(target).search()
|
}
|
||||||
val declarationUsages = kotlinOptions.toClassDeclarationsHelper().newRequest(target).search()
|
|
||||||
|
|
||||||
if (kotlinOptions.searchConstructorUsages) {
|
if (kotlinOptions.isUsages && classOrObject is JetObjectDeclaration && classOrObject.isCompanion()) {
|
||||||
val constructors = classOrObject.toLightClass()?.getConstructors() ?: PsiMethod.EMPTY_ARRAY
|
if (!processClassObjectInternalReferences(classOrObject, referenceProcessor)) {
|
||||||
for (constructor in constructors) {
|
return false
|
||||||
if (constructor !is KotlinLightMethod) continue
|
}
|
||||||
constructor.processDelegationCallConstructorUsages(constructor.getUseScope()) {
|
}
|
||||||
it.getCalleeExpression()?.mainReference?.let { KotlinFindUsagesHandler.processUsage(uniqueProcessor, it) }
|
|
||||||
|
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> {
|
protected override fun getStringsToSearch(element: PsiElement): Collection<String> {
|
||||||
|
|||||||
+84
-38
@@ -16,29 +16,35 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.findUsages.handlers
|
package org.jetbrains.kotlin.idea.findUsages.handlers
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.highlighting.ReadWriteAccessDetector
|
||||||
import com.intellij.find.findUsages.AbstractFindUsagesDialog
|
import com.intellij.find.findUsages.AbstractFindUsagesDialog
|
||||||
import com.intellij.find.findUsages.FindUsagesOptions
|
import com.intellij.find.findUsages.FindUsagesOptions
|
||||||
import com.intellij.openapi.actionSystem.DataContext
|
import com.intellij.openapi.actionSystem.DataContext
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.PsiMethod
|
import com.intellij.psi.PsiMethod
|
||||||
|
import com.intellij.psi.PsiReference
|
||||||
import com.intellij.psi.search.searches.MethodReferencesSearch
|
import com.intellij.psi.search.searches.MethodReferencesSearch
|
||||||
|
import com.intellij.psi.search.searches.ReferencesSearch
|
||||||
import com.intellij.usageView.UsageInfo
|
import com.intellij.usageView.UsageInfo
|
||||||
import com.intellij.util.CommonProcessors
|
import com.intellij.util.*
|
||||||
import com.intellij.util.Processor
|
|
||||||
import org.jetbrains.kotlin.asJava.LightClassUtil
|
import org.jetbrains.kotlin.asJava.LightClassUtil
|
||||||
import org.jetbrains.kotlin.asJava.toLightMethods
|
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.KotlinFindFunctionUsagesDialog
|
||||||
import org.jetbrains.kotlin.idea.findUsages.dialogs.KotlinFindPropertyUsagesDialog
|
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.HierarchySearchRequest
|
||||||
import org.jetbrains.kotlin.idea.search.declarationsSearch.searchOverriders
|
import org.jetbrains.kotlin.idea.search.declarationsSearch.searchOverriders
|
||||||
import org.jetbrains.kotlin.idea.search.usagesSearch.UsagesSearch
|
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReadWriteAccessDetector
|
||||||
import org.jetbrains.kotlin.idea.search.usagesSearch.UsagesSearchHelper
|
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.idea.util.application.runReadAction
|
||||||
import org.jetbrains.kotlin.psi.JetConstructor
|
|
||||||
import org.jetbrains.kotlin.psi.JetFunction
|
import org.jetbrains.kotlin.psi.JetFunction
|
||||||
import org.jetbrains.kotlin.psi.JetNamedDeclaration
|
import org.jetbrains.kotlin.psi.JetNamedDeclaration
|
||||||
import org.jetbrains.kotlin.psi.JetParameter
|
|
||||||
|
|
||||||
public abstract class KotlinFindMemberUsagesHandler<T : JetNamedDeclaration>
|
public abstract class KotlinFindMemberUsagesHandler<T : JetNamedDeclaration>
|
||||||
protected constructor(declaration: T, elementsToSearch: Collection<PsiElement>, factory: KotlinFindUsagesHandlerFactory)
|
protected constructor(declaration: T, elementsToSearch: Collection<PsiElement>, factory: KotlinFindUsagesHandlerFactory)
|
||||||
@@ -48,10 +54,6 @@ public abstract class KotlinFindMemberUsagesHandler<T : JetNamedDeclaration>
|
|||||||
elementsToSearch: Collection<PsiElement>,
|
elementsToSearch: Collection<PsiElement>,
|
||||||
factory: KotlinFindUsagesHandlerFactory) : KotlinFindMemberUsagesHandler<JetFunction>(declaration, elementsToSearch, factory) {
|
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 getFindUsagesOptions(dataContext: DataContext?): FindUsagesOptions = factory.findFunctionOptions
|
||||||
|
|
||||||
override fun getFindUsagesDialog(isSingleFile: Boolean, toShowInNewTab: Boolean, mustOpenInNewTab: Boolean): AbstractFindUsagesDialog {
|
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)
|
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) {
|
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 getFindUsagesOptions(dataContext: DataContext?): FindUsagesOptions = factory.findPropertyOptions
|
||||||
|
|
||||||
override fun getFindUsagesDialog(isSingleFile: Boolean, toShowInNewTab: Boolean, mustOpenInNewTab: Boolean): AbstractFindUsagesDialog {
|
override fun getFindUsagesDialog(isSingleFile: Boolean, toShowInNewTab: Boolean, mustOpenInNewTab: Boolean): AbstractFindUsagesDialog {
|
||||||
return KotlinFindPropertyUsagesDialog(getElement(), getProject(), factory.findPropertyOptions, toShowInNewTab, mustOpenInNewTab, isSingleFile, this)
|
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 {
|
override fun searchReferences(element: PsiElement, processor: Processor<UsageInfo>, options: FindUsagesOptions): Boolean {
|
||||||
val kotlinOptions = options as KotlinCallableFindUsagesOptions
|
val kotlinOptions = options as KotlinCallableFindUsagesOptions
|
||||||
|
|
||||||
val request = runReadAction {
|
val referenceProcessor = KotlinFindUsagesHandler.createReferenceProcessor(processor)
|
||||||
@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 uniqueProcessor = CommonProcessors.UniqueProcessor(processor)
|
val uniqueProcessor = CommonProcessors.UniqueProcessor(processor)
|
||||||
|
|
||||||
for (ref in UsagesSearch.search(request)) {
|
if (options.isUsages) {
|
||||||
KotlinFindUsagesHandler.processUsage(uniqueProcessor, ref)
|
val searchParameters = KotlinReferencesSearchParameters(element,
|
||||||
}
|
element.project.allScope(),
|
||||||
|
ignoreAccessScope = false,
|
||||||
|
optimizer = null,
|
||||||
|
kotlinOptions = createKotlinReferencesSearchOptions(options))
|
||||||
|
|
||||||
val psiMethod: PsiMethod? = when (element) {
|
val query = applyQueryFilters(element, options, ReferencesSearch.search(searchParameters))
|
||||||
is PsiMethod -> element
|
if (!query.forEach(referenceProcessor)) return false
|
||||||
is JetConstructor<*> -> runReadAction { LightClassUtil.getLightClassMethod(element as JetFunction) }
|
|
||||||
else -> null
|
val psiMethod: PsiMethod? = when (element) {
|
||||||
}
|
is PsiMethod -> element
|
||||||
if (psiMethod != null) {
|
is JetFunction -> runReadAction { LightClassUtil.getLightClassMethod(element) }
|
||||||
for (ref in MethodReferencesSearch.search(psiMethod, options.searchScope, true)) {
|
else -> null
|
||||||
KotlinFindUsagesHandler.processUsage(uniqueProcessor, ref)
|
}
|
||||||
|
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
|
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
|
override fun isSearchForTextOccurencesAvailable(psiElement: PsiElement, isSingleFile: Boolean): Boolean = !isSingleFile
|
||||||
|
|
||||||
companion object {
|
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.FindUsagesHandler
|
||||||
import com.intellij.find.findUsages.FindUsagesOptions
|
import com.intellij.find.findUsages.FindUsagesOptions
|
||||||
import com.intellij.openapi.util.TextRange
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.PsiReference
|
import com.intellij.psi.PsiReference
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import com.intellij.psi.search.SearchScope
|
import com.intellij.psi.search.SearchScope
|
||||||
import com.intellij.usageView.UsageInfo
|
import com.intellij.usageView.UsageInfo
|
||||||
|
import com.intellij.util.CommonProcessors
|
||||||
import com.intellij.util.Processor
|
import com.intellij.util.Processor
|
||||||
import org.jetbrains.kotlin.idea.findUsages.KotlinFindUsagesHandlerFactory
|
import org.jetbrains.kotlin.idea.findUsages.KotlinFindUsagesHandlerFactory
|
||||||
import org.jetbrains.kotlin.idea.findUsages.KotlinReferenceUsageInfo
|
import org.jetbrains.kotlin.idea.findUsages.KotlinReferenceUsageInfo
|
||||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||||
|
import java.util.*
|
||||||
import java.util.ArrayList
|
|
||||||
import java.util.Collections
|
|
||||||
|
|
||||||
public abstract class KotlinFindUsagesHandler<T : PsiElement>(psiElement: T,
|
public abstract class KotlinFindUsagesHandler<T : PsiElement>(psiElement: T,
|
||||||
private val elementsToSearch: Collection<PsiElement>,
|
private val elementsToSearch: Collection<PsiElement>,
|
||||||
@@ -100,5 +98,15 @@ public abstract class KotlinFindUsagesHandler<T : PsiElement>(psiElement: T,
|
|||||||
val usageInfo = runReadAction(callback)
|
val usageInfo = runReadAction(callback)
|
||||||
return if (usageInfo != null) process(usageInfo) else true
|
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