Fixed operator references search for functions declared in Java

This commit is contained in:
Valentin Kipyatkov
2016-09-02 20:46:22 +03:00
parent f6fbd0b623
commit 0158ff46f3
14 changed files with 161 additions and 91 deletions
@@ -18,8 +18,10 @@ package org.jetbrains.kotlin.caches.resolve
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiFile
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.resolve.TargetPlatform
import org.jetbrains.kotlin.resolve.diagnostics.KotlinSuppressCache
interface KotlinCacheService {
@@ -28,6 +30,7 @@ interface KotlinCacheService {
}
fun getResolutionFacade(elements: List<KtElement>): ResolutionFacade
fun getResolutionFacadeByFile(file: PsiFile, platform: TargetPlatform): ResolutionFacade
fun getSuppressionCache(): KotlinSuppressCache
}
@@ -21,6 +21,8 @@ import com.intellij.openapi.project.Project
import com.intellij.openapi.projectRoots.Sdk
import com.intellij.openapi.roots.ProjectRootModificationTracker
import com.intellij.openapi.util.ModificationTracker
import com.intellij.psi.PsiCodeFragment
import com.intellij.psi.PsiFile
import com.intellij.psi.util.CachedValue
import com.intellij.psi.util.CachedValueProvider
import com.intellij.psi.util.CachedValuesManager
@@ -48,8 +50,9 @@ import org.jetbrains.kotlin.resolve.diagnostics.KotlinSuppressCache
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import org.jetbrains.kotlin.utils.addToStdlib.singletonOrEmptyList
import org.jetbrains.kotlin.utils.addToStdlib.sumByLong
import java.lang.AssertionError
import java.lang.IllegalStateException
internal val LOG = Logger.getInstance(KotlinCacheService::class.java)
@@ -309,12 +312,25 @@ class KotlinCacheServiceImpl(val project: Project) : KotlinCacheService {
val syntheticFiles = findSyntheticFiles(files)
val file = files.first()
val moduleInfo = file.getModuleInfo()
val projectFacade = if (syntheticFiles.isNotEmpty()) {
getFacadeForSyntheticFiles(syntheticFiles)
if (syntheticFiles.isNotEmpty()) {
val projectFacade = getFacadeForSyntheticFiles(syntheticFiles)
return ResolutionFacadeImpl(projectFacade, moduleInfo)
}
else {
globalFacade(TargetPlatformDetector.getPlatform(file), moduleInfo.sdk)
val platform = TargetPlatformDetector.getPlatform(file)
return getResolutionFacadeByModuleInfo(moduleInfo, platform)
}
}
override fun getResolutionFacadeByFile(file: PsiFile, platform: TargetPlatform): ResolutionFacade {
assert(file !is PsiCodeFragment)
assert(ProjectRootsUtil.isInProjectSource(file))
val moduleInfo = file.getModuleInfo()
return getResolutionFacadeByModuleInfo(moduleInfo, platform)
}
private fun getResolutionFacadeByModuleInfo(moduleInfo: IdeaModuleInfo, platform: TargetPlatform): ResolutionFacade {
val projectFacade = globalFacade(platform, moduleInfo.sdk)
return ResolutionFacadeImpl(projectFacade, moduleInfo)
}
@@ -120,9 +120,8 @@ class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, ReferencesSearc
searchLightElements(queryParameters, element, consumer)
}
//TODO: operator functions from Java
if (element is KtFunction) {
val referenceSearcher = OperatorReferenceSearcher.createForKtFunction(
if (element is KtFunction || element is PsiMethod) {
val referenceSearcher = OperatorReferenceSearcher.create(
element, effectiveSearchScope, consumer, queryParameters.optimizer, kotlinOptions)
referenceSearcher?.run()
}
@@ -247,7 +246,7 @@ class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, ReferencesSearc
}
if (componentFunction != null) {
searchNamedElement(queryParameters, componentFunction)
val searcher = OperatorReferenceSearcher.createForPsiMethod(
val searcher = OperatorReferenceSearcher.create(
componentFunction, queryParameters.effectiveSearchScope, consumer, queryParameters.optimizer, kotlinOptions)
searcher!!.run()
}
@@ -25,11 +25,10 @@ import org.jetbrains.kotlin.idea.references.KtSimpleNameReference
import org.jetbrains.kotlin.lexer.KtSingleValueToken
import org.jetbrains.kotlin.psi.KtBinaryExpression
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtFunction
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
class BinaryOperatorReferenceSearcher(
targetFunction: KtFunction,
targetFunction: PsiElement,
private val operationTokens: List<KtSingleValueToken>,
searchScope: SearchScope,
consumer: Processor<PsiReference>,
@@ -23,11 +23,14 @@ import com.intellij.psi.search.SearchScope
import com.intellij.util.Processor
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.KtBinaryExpression
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtOperationReferenceExpression
import org.jetbrains.kotlin.psi.KtWhenConditionInRange
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
class ContainsOperatorReferenceSearcher(
targetFunction: KtFunction,
targetFunction: PsiElement,
searchScope: SearchScope,
consumer: Processor<PsiReference>,
optimizer: SearchRequestCollector
@@ -22,18 +22,20 @@ import com.intellij.psi.search.SearchRequestCollector
import com.intellij.psi.search.SearchScope
import com.intellij.util.Processor
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.idea.references.KtDestructuringDeclarationReference
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.dataClassUtils.getComponentIndex
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
class DestructuringDeclarationReferenceSearcher(
targetDeclaration: KtDeclaration,
targetDeclaration: PsiElement,
searchScope: SearchScope,
consumer: Processor<PsiReference>,
optimizer: SearchRequestCollector
) : OperatorReferenceSearcher<KtDestructuringDeclaration>(targetDeclaration, searchScope, consumer, optimizer, wordsToSearch = listOf("(")) {
//TODO
private val componentIndex = when (targetDeclaration) {
is KtParameter -> targetDeclaration.dataClassComponentFunction()?.name?.asString()?.let { getComponentIndex(it) }
is KtFunction -> targetDeclaration.name?.let { getComponentIndex(it) }
@@ -41,6 +43,15 @@ class DestructuringDeclarationReferenceSearcher(
else -> null
}
override fun resolveTargetToDescriptor(): FunctionDescriptor? {
if (targetDeclaration is KtParameter) {
return targetDeclaration.dataClassComponentFunction()
}
else {
return super.resolveTargetToDescriptor()
}
}
override fun run() {
if (componentIndex == null) return
super.run()
@@ -20,6 +20,8 @@ import com.intellij.ide.highlighter.JavaFileType
import com.intellij.lang.java.JavaLanguage
import com.intellij.lang.xml.XMLLanguage
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.ProjectRootManager
import com.intellij.psi.*
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.search.LocalSearchScope
@@ -30,6 +32,7 @@ import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.caches.resolve.KotlinCacheService
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
@@ -39,7 +42,6 @@ import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName
import org.jetbrains.kotlin.idea.references.KtDestructuringDeclarationReference
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchOptions
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchParameters
import org.jetbrains.kotlin.idea.search.restrictToKotlinSources
@@ -51,6 +53,7 @@ import org.jetbrains.kotlin.load.java.sam.SingleAbstractMethodUtils
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.*
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
import org.jetbrains.kotlin.types.KotlinType
import java.util.*
@@ -59,9 +62,9 @@ import java.util.*
class ExpressionsOfTypeProcessor(
private val typeToSearch: FuzzyType,
private val searchScope: SearchScope,
private val project: Project,
private val suspiciousExpressionHandler: (KtExpression) -> Unit,
private val suspiciousScopeHandler: (SearchScope) -> Unit,
private val resolutionFacade: ResolutionFacade
private val suspiciousScopeHandler: (SearchScope) -> Unit
) {
enum class Mode {
ALWAYS_SMART,
@@ -89,9 +92,20 @@ class ExpressionsOfTypeProcessor(
else -> fqName
}
}
}
private val project = resolutionFacade.project
private fun SearchScope.isEmpty(): Boolean {
when (this) {
GlobalSearchScope.EMPTY_SCOPE -> return true
is GlobalSearchScope -> {
val rootManager = ProjectRootManager.getInstance(project!!)
return rootManager.fileIndex.iterateContent { it.isDirectory || it !in this }
}
else -> return (this as LocalSearchScope).scope.isEmpty()
}
}
}
// note: a Task must define equals & hashCode!
private interface Task {
@@ -104,6 +118,8 @@ class ExpressionsOfTypeProcessor(
private val scopesToUsePlainSearch = LinkedHashMap<KtFile, ArrayList<PsiElement>>()
fun run() {
if (searchScope.restrictToKotlinSources().isEmpty()) return // optimization
val classDescriptor = typeToSearch.type.constructor.declarationDescriptor ?: return
val classDeclaration = DescriptorToSourceUtilsIde.getAnyDeclaration(project, classDescriptor)
val psiClass = when (classDeclaration) {
@@ -123,7 +139,9 @@ class ExpressionsOfTypeProcessor(
processTasks()
val scopeElements = scopesToUsePlainSearch.values.flatMap { it }.toTypedArray()
suspiciousScopeHandler(LocalSearchScope(scopeElements))
if (scopeElements.isNotEmpty()) {
suspiciousScopeHandler(LocalSearchScope(scopeElements))
}
}
private fun addTask(task: Task) {
@@ -439,6 +457,7 @@ class ExpressionsOfTypeProcessor(
if (psiClass != null) {
testLog?.add("Resolved java class to descriptor: ${psiClass.qualifiedName}")
val resolutionFacade = KotlinCacheService.getInstance(project).getResolutionFacadeByFile(psiClass.containingFile, JvmPlatform)
val classDescriptor = psiClass.resolveToDescriptor(resolutionFacade)
if (classDescriptor != null && SingleAbstractMethodUtils.getSingleAbstractMethodOrNull(classDescriptor) != null) {
addSamInterfaceToProcess(psiClass)
@@ -541,18 +560,23 @@ class ExpressionsOfTypeProcessor(
private fun usePlainSearch(scope: KtElement) {
val file = scope.getContainingKtFile()
val restricted = LocalSearchScope(scope).intersectWith(searchScope) as LocalSearchScope
ScopeLoop@
for (element in restricted.scope) {
val prevElements = scopesToUsePlainSearch.getOrPut(file) { ArrayList() }
for ((index, prevElement) in prevElements.withIndex()) {
if (prevElement.isAncestor(element, strict = false)) continue@ScopeLoop
if (element.isAncestor(prevElement)) {
prevElements[index] = element
continue@ScopeLoop
val restricted = LocalSearchScope(scope).intersectWith(searchScope)
if (restricted is LocalSearchScope) {
ScopeLoop@
for (element in restricted.scope) {
val prevElements = scopesToUsePlainSearch.getOrPut(file) { ArrayList() }
for ((index, prevElement) in prevElements.withIndex()) {
if (prevElement.isAncestor(element, strict = false)) continue@ScopeLoop
if (element.isAncestor(prevElement)) {
prevElements[index] = element
continue@ScopeLoop
}
}
prevElements.add(element)
}
prevElements.add(element)
}
else {
assert(restricted == GlobalSearchScope.EMPTY_SCOPE)
}
}
@@ -29,7 +29,7 @@ import org.jetbrains.kotlin.psi.KtFunction
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
class IndexingOperatorReferenceSearcher(
targetFunction: KtFunction,
targetFunction: PsiElement,
searchScope: SearchScope,
consumer: Processor<PsiReference>,
optimizer: SearchRequestCollector,
@@ -17,38 +17,22 @@
package org.jetbrains.kotlin.idea.search.usagesSearch
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiReference
import com.intellij.psi.search.SearchRequestCollector
import com.intellij.psi.search.SearchScope
import com.intellij.util.Processor
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.idea.references.KtInvokeFunctionReference
import org.jetbrains.kotlin.psi.KtCallExpression
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtFunction
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
class InvokeOperatorReferenceSearcher(
targetFunction: KtFunction,
targetFunction: PsiElement,
searchScope: SearchScope,
consumer: Processor<PsiReference>,
optimizer: SearchRequestCollector
) : OperatorReferenceSearcher<KtCallExpression>(targetFunction, searchScope, consumer, optimizer, wordsToSearch = emptyList()) {
companion object {
fun runForPsiMethod(
invokeFunction: PsiMethod,
scope: SearchScope,
consumer: Processor<PsiReference>,
optimizer: SearchRequestCollector
) {
if (invokeFunction !is KtLightMethod) return //TODO
val ktFunction = invokeFunction.kotlinOrigin as? KtFunction ?: return //TODO?
InvokeOperatorReferenceSearcher(ktFunction, scope, consumer, optimizer).run()
}
}
override fun processSuspiciousExpression(expression: KtExpression) {
val callExpression = expression.parent as? KtCallExpression ?: return
processReferenceElement(callExpression)
@@ -22,10 +22,9 @@ import com.intellij.psi.search.*
import com.intellij.util.Processor
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.asJava.namedUnwrappedElement
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
import org.jetbrains.kotlin.idea.caches.resolve.getJavaOrKotlinMemberDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchOptions
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinRequestResultProcessor
@@ -44,7 +43,7 @@ import org.jetbrains.kotlin.util.isValidOperator
import java.util.*
abstract class OperatorReferenceSearcher<TReferenceElement : KtElement>(
private val targetDeclaration: KtDeclaration,
protected val targetDeclaration: PsiElement,
private val searchScope: SearchScope,
private val consumer: Processor<PsiReference>,
private val optimizer: SearchRequestCollector,
@@ -70,47 +69,46 @@ abstract class OperatorReferenceSearcher<TReferenceElement : KtElement>(
}
companion object {
fun createForKtFunction(
function: KtFunction,
fun create(
declaration: PsiElement,
searchScope: SearchScope,
consumer: Processor<PsiReference>,
optimizer: SearchRequestCollector,
options: KotlinReferencesSearchOptions
): OperatorReferenceSearcher<*>? {
val name = function.name ?: return null
return create(function, name, searchScope, consumer, optimizer, options)
}
val functionName = when (declaration) {
is KtNamedFunction -> declaration.name
is PsiMethod -> declaration.name
else -> null
} ?: return null
fun createForPsiMethod(
psiMethod: PsiMethod,
searchScope: SearchScope,
consumer: Processor<PsiReference>,
optimizer: SearchRequestCollector,
options: KotlinReferencesSearchOptions
): OperatorReferenceSearcher<*>? {
if (psiMethod !is KtLightMethod) return null //TODO?
val ktDeclaration = psiMethod.kotlinOrigin as? KtDeclaration ?: return null //TODO?
return create(ktDeclaration, psiMethod.name, searchScope, consumer, optimizer, options)
}
private fun create(
declaration: KtDeclaration,
functionName: String,
searchScope: SearchScope,
consumer: Processor<PsiReference>,
optimizer: SearchRequestCollector,
options: KotlinReferencesSearchOptions
): OperatorReferenceSearcher<*>? {
if (!Name.isValidIdentifier(functionName)) return null
val name = Name.identifier(functionName)
val declarationToUse = if (declaration is KtLightMethod) {
declaration.kotlinOrigin ?: return null
}
else {
declaration
}
return create(declarationToUse, name, consumer, optimizer, options, searchScope)
}
private fun create(
declaration: PsiElement,
name: Name,
consumer: Processor<PsiReference>,
optimizer: SearchRequestCollector,
options: KotlinReferencesSearchOptions,
searchScope: SearchScope
): OperatorReferenceSearcher<*>? {
if (isComponentLike(name)) {
if (!options.searchForComponentConventions) return null
return DestructuringDeclarationReferenceSearcher(declaration, searchScope, consumer, optimizer)
}
if (!options.searchForOperatorConventions) return null
if (declaration !is KtFunction) return null
if (name == OperatorNameConventions.INVOKE) {
return InvokeOperatorReferenceSearcher(declaration, searchScope, consumer, optimizer)
@@ -148,16 +146,28 @@ abstract class OperatorReferenceSearcher<TReferenceElement : KtElement>(
return null
}
private object SearchesInProgress : ThreadLocal<HashSet<KtDeclaration>>() {
override fun initialValue() = HashSet<KtDeclaration>()
//TODO: check no light elements here
private object SearchesInProgress : ThreadLocal<HashSet<PsiElement>>() {
override fun initialValue() = HashSet<PsiElement>()
}
}
open protected fun resolveTargetToDescriptor(): FunctionDescriptor? {
return when (targetDeclaration) {
is KtDeclaration -> targetDeclaration.resolveToDescriptor()
is PsiMember -> targetDeclaration.getJavaOrKotlinMemberDescriptor()
else -> null
} as? FunctionDescriptor
}
open fun run() {
val inProgress = SearchesInProgress.get()
if (!inProgress.add(targetDeclaration)) return //TODO: it's not quite correct
try {
val descriptor = resolveTargetToDescriptor() ?: return
if (!descriptor.isValidOperator()) return
val usePlainSearch = when (ExpressionsOfTypeProcessor.mode) {
ExpressionsOfTypeProcessor.Mode.ALWAYS_SMART -> false
ExpressionsOfTypeProcessor.Mode.ALWAYS_PLAIN -> true
@@ -168,9 +178,6 @@ abstract class OperatorReferenceSearcher<TReferenceElement : KtElement>(
return
}
val descriptor = targetDeclaration.resolveToDescriptor() as? CallableDescriptor ?: return
if (descriptor is FunctionDescriptor && !descriptor.isValidOperator()) return
val dataType = if (descriptor.isExtension) {
descriptor.fuzzyExtensionReceiverType()!!
}
@@ -182,9 +189,9 @@ abstract class OperatorReferenceSearcher<TReferenceElement : KtElement>(
ExpressionsOfTypeProcessor(
dataType,
searchScope,
project,
suspiciousExpressionHandler = { expression -> processSuspiciousExpression(expression) },
suspiciousScopeHandler = { searchScope -> doPlainSearch(searchScope) },
resolutionFacade = targetDeclaration.getResolutionFacade()
suspiciousScopeHandler = { searchScope -> doPlainSearch(searchScope) }
).run()
}
finally {
@@ -29,7 +29,7 @@ import org.jetbrains.kotlin.psi.KtUnaryExpression
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
class UnaryOperatorReferenceSearcher(
targetFunction: KtFunction,
targetFunction: PsiElement,
private val operationToken: KtSingleValueToken,
searchScope: SearchScope,
consumer: Processor<PsiReference>,
@@ -22,8 +22,11 @@ import com.intellij.find.findUsages.AbstractFindUsagesDialog
import com.intellij.find.findUsages.FindUsagesOptions
import com.intellij.find.impl.FindManagerImpl
import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.fileTypes.FileTypeManager
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiReference
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.search.LocalSearchScope
import com.intellij.psi.search.SearchScope
import com.intellij.psi.search.searches.MethodReferencesSearch
import com.intellij.psi.search.searches.ReferencesSearch
@@ -32,6 +35,7 @@ import com.intellij.util.*
import org.jetbrains.kotlin.asJava.toLightMethods
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ParameterDescriptor
import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
import org.jetbrains.kotlin.idea.findUsages.KotlinCallableFindUsagesOptions
import org.jetbrains.kotlin.idea.findUsages.KotlinFindUsagesHandlerFactory
@@ -44,11 +48,10 @@ import org.jetbrains.kotlin.idea.search.declarationsSearch.searchOverriders
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.dataClassComponentFunction
import org.jetbrains.kotlin.idea.search.usagesSearch.isImportUsage
import org.jetbrains.kotlin.idea.util.application.runReadAction
import org.jetbrains.kotlin.psi.KtCallableDeclaration
import org.jetbrains.kotlin.psi.KtFunction
import org.jetbrains.kotlin.psi.KtNamedDeclaration
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.findOriginalTopMostOverriddenDescriptors
import org.jetbrains.kotlin.resolve.source.getPsi
@@ -131,9 +134,7 @@ abstract class KotlinFindMemberUsagesHandler<T : KtNamedDeclaration>
val uniqueProcessor = CommonProcessors.UniqueProcessor(processor)
if (options.isUsages) {
// we disable searchForComponentConventions and searchForOperatorConventions for ReferencesSearch because they will be searched by MethodReferencesSearch
val kotlinSearchOptions = createKotlinReferencesSearchOptions(options)
.copy(searchForComponentConventions = false, searchForOperatorConventions = false)
val searchParameters = KotlinReferencesSearchParameters(element, options.searchScope, kotlinOptions = kotlinSearchOptions)
with(applyQueryFilters(element, options, ReferencesSearch.search(searchParameters))) {
@@ -141,7 +142,12 @@ abstract class KotlinFindMemberUsagesHandler<T : KtNamedDeclaration>
}
for (psiMethod in runReadAction { element.toLightMethods() }) {
with(applyQueryFilters(element, options, MethodReferencesSearch.search(psiMethod, options.searchScope, true))) {
var searchScope = options.searchScope
// TODO: very bad code!! ReferencesSearch does not work correctly for constructors and annotation parameters
if (element is KtNamedFunction || (element is KtParameter && element.dataClassComponentFunction() != null)) {
searchScope = searchScope.excludeKotlinSources()
}
with(applyQueryFilters(element, options, MethodReferencesSearch.search(psiMethod, searchScope, true))) {
if (!forEach(referenceProcessor)) return false
}
}
@@ -156,6 +162,21 @@ abstract class KotlinFindMemberUsagesHandler<T : KtNamedDeclaration>
return true
}
private fun SearchScope.excludeKotlinSources(): SearchScope {
if (this is GlobalSearchScope) {
val fileTypes = FileTypeManager.getInstance().registeredFileTypes.filter { it != KotlinFileType.INSTANCE }.toTypedArray()
return GlobalSearchScope.getScopeRestrictedByFileTypes(this, *fileTypes)
}
else {
this as LocalSearchScope
val filteredElements = scope.filter { it.containingFile !is KtFile }
return if (filteredElements.isNotEmpty())
LocalSearchScope(filteredElements.toTypedArray())
else
GlobalSearchScope.EMPTY_SCOPE
}
}
protected abstract fun createKotlinReferencesSearchOptions(options: FindUsagesOptions): KotlinReferencesSearchOptions
protected abstract fun applyQueryFilters(element: PsiElement,
@@ -35,7 +35,7 @@ class KotlinConventionMethodReferencesSearcher() : QueryExecutorBase<PsiReferenc
if (!Name.isValidIdentifier(name)) return
val identifier = Name.identifier(name)
val operatorSearcher = OperatorReferenceSearcher.createForPsiMethod(
val operatorSearcher = OperatorReferenceSearcher.create(
method, queryParameters.effectiveSearchScope, consumer, queryParameters.optimizer, KotlinReferencesSearchOptions.Empty)
if (operatorSearcher != null) {
operatorSearcher.run()
@@ -0,0 +1,3 @@
Resolved in
Searched references to Small
Searched references to parameter small of some(small: Small) in Kotlin files