Fixed operator references search for functions declared in Java
This commit is contained in:
@@ -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
|
||||
}
|
||||
+20
-4
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
+3
-4
@@ -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()
|
||||
}
|
||||
|
||||
+1
-2
@@ -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>,
|
||||
|
||||
+5
-2
@@ -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
|
||||
|
||||
+12
-1
@@ -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()
|
||||
|
||||
+40
-16
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -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,
|
||||
|
||||
+1
-17
@@ -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)
|
||||
|
||||
+43
-36
@@ -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 {
|
||||
|
||||
+1
-1
@@ -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>,
|
||||
|
||||
+27
-6
@@ -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,
|
||||
|
||||
+1
-1
@@ -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
|
||||
Reference in New Issue
Block a user