[FIR IDE] Separate find usages logic from descriptors
This commit is contained in:
@@ -79,7 +79,6 @@ wrapped.into.a.reference.object.to.be.modified.when.captured.in.a.closure=Wrappe
|
||||
smart.cast.to.0.for.1.call=Smart cast to {0} (for {1} call)
|
||||
smart.cast.to.0=Smart cast to {0}
|
||||
replace.overloaded.operator.with.function.call=Replace overloaded operator with function call
|
||||
searching.for.implicit.usages=Searching for implicit usages...
|
||||
class.initializer=<class initializer>
|
||||
object.0=object{0}
|
||||
show.non.public=Show non-public
|
||||
|
||||
+32
-4
@@ -16,14 +16,14 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.search.usagesSearch
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiNamedElement
|
||||
import org.jetbrains.kotlin.asJava.LightClassUtil
|
||||
import org.jetbrains.kotlin.asJava.LightClassUtil.PropertyAccessorsPsiMethods
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToParameterDescriptorIfAny
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
@@ -31,6 +31,11 @@ import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DataClassDescriptorResolver
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.findOriginalTopMostOverriddenDescriptors
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
|
||||
import org.jetbrains.kotlin.resolve.source.getPsi
|
||||
import java.util.*
|
||||
|
||||
fun PsiNamedElement.getAccessorNames(readable: Boolean = true, writable: Boolean = true): List<String> {
|
||||
@@ -87,3 +92,26 @@ fun KtParameter.isDataClassProperty(): Boolean {
|
||||
return this.containingClassOrObject?.hasModifier(KtTokens.DATA_KEYWORD) ?: false
|
||||
}
|
||||
|
||||
fun getTopMostOverriddenElementsToHighlight(target: PsiElement): List<PsiElement> {
|
||||
val callableDescriptor = (target as? KtCallableDeclaration)?.resolveToDescriptorIfAny() as? CallableDescriptor
|
||||
val descriptorsToHighlight = if (callableDescriptor is ParameterDescriptor)
|
||||
listOf(callableDescriptor)
|
||||
else
|
||||
callableDescriptor?.findOriginalTopMostOverriddenDescriptors() ?: emptyList()
|
||||
|
||||
return descriptorsToHighlight.mapNotNull { it.source.getPsi() }.filter { it != target }
|
||||
}
|
||||
|
||||
val KtDeclaration.descriptor: DeclarationDescriptor?
|
||||
get() = if (this is KtParameter) this.descriptor else this.resolveToDescriptorIfAny(BodyResolveMode.FULL)
|
||||
|
||||
val KtParameter.descriptor: ValueParameterDescriptor?
|
||||
get() = this.resolveToParameterDescriptorIfAny(BodyResolveMode.FULL)
|
||||
|
||||
fun isCallReceiverRefersToCompanionObject(element: KtElement, companionObject: KtObjectDeclaration): Boolean {
|
||||
val companionObjectDescriptor = companionObject.descriptor
|
||||
val bindingContext = element.analyze()
|
||||
val resolvedCall = bindingContext[BindingContext.CALL, element]?.getResolvedCall(bindingContext) ?: return false
|
||||
return (resolvedCall.dispatchReceiver as? ImplicitClassReceiver)?.declarationDescriptor == companionObjectDescriptor ||
|
||||
(resolvedCall.extensionReceiver as? ImplicitClassReceiver)?.declarationDescriptor == companionObjectDescriptor
|
||||
}
|
||||
|
||||
@@ -35,7 +35,6 @@ import org.jetbrains.kotlin.idea.core.extension.KotlinIndicesHelperExtension
|
||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.resolve.frontendService
|
||||
import org.jetbrains.kotlin.idea.search.excludeKotlinSources
|
||||
import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor
|
||||
import org.jetbrains.kotlin.idea.stubindex.*
|
||||
import org.jetbrains.kotlin.idea.util.CallType
|
||||
import org.jetbrains.kotlin.idea.util.CallTypeAndReceiver
|
||||
|
||||
@@ -18,6 +18,7 @@ dependencies {
|
||||
compileOnly(project(":kotlin-reflect-api"))
|
||||
compileOnly(intellijCoreDep())
|
||||
compileOnly(intellijDep())
|
||||
compileOnly(project(":compiler:light-classes"))
|
||||
|
||||
Platform[191].orLower {
|
||||
compileOnly(intellijDep()) { includeJars("java-api", "java-impl") }
|
||||
@@ -29,8 +30,14 @@ dependencies {
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
"main" { projectDefault() }
|
||||
"main" {
|
||||
projectDefault()
|
||||
resources.srcDirs(
|
||||
"resources-en"
|
||||
)
|
||||
}
|
||||
"test" { projectDefault() }
|
||||
|
||||
}
|
||||
|
||||
testsJar()
|
||||
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
find.declaration.implementing.methods.checkbox=&Implementing functions
|
||||
find.declaration.overriding.methods.checkbox=Over&riding functions
|
||||
find.declaration.implementing.properties.checkbox=&Implementing properties
|
||||
find.declaration.overriding.properties.checkbox=Over&riding properties
|
||||
find.declaration.property.readers.checkbox=Readers
|
||||
find.declaration.property.writers.checkbox=Writers
|
||||
find.declaration.include.overloaded.methods.checkbox=Include o&verloaded functions and extensions
|
||||
find.declaration.functions.usages.checkbox=Usages of &functions
|
||||
find.declaration.properties.usages.checkbox=Usages of &properties
|
||||
find.declaration.constructor.usages.checkbox=Usages of &constructor
|
||||
find.declaration.derived.classes.checkbox=&Derived classes
|
||||
find.declaration.derived.interfaces.checkbox=Derived &interfaces
|
||||
|
||||
find.usages.class=class
|
||||
find.usages.companion.object=companion object
|
||||
find.usages.constructor=constructor
|
||||
find.usages.facade.class=facade class
|
||||
find.usages.for.property={0} for property
|
||||
find.usages.function=function
|
||||
find.usages.getter=getter
|
||||
find.usages.import.alias=import alias
|
||||
find.usages.interface=interface
|
||||
find.usages.label=label
|
||||
find.usages.lambda=lambda
|
||||
find.usages.object=object
|
||||
find.usages.parameter=parameter
|
||||
find.usages.property.accessor=property accessor
|
||||
find.usages.property=property
|
||||
find.usages.setter=setter
|
||||
find.usages.type.alias=type alias
|
||||
find.usages.type.parameter=type parameter
|
||||
find.usages.variable=variable
|
||||
find.usages.checkbox.name.expected.classes=Expected classes
|
||||
find.usages.class.name.anonymous=Anonymous
|
||||
find.usages.checkbox.name.expected.functions=Expected functions
|
||||
find.usages.text.find.usages.for.data.class.components.and.destruction.declarations=<p>Find usages for data class components and destructuring declarations<br/>could be <a href="{0}">disabled once</a> or <a href="{1}">disabled for a project</a>.</p>
|
||||
find.usages.tool.tip.text.disable.search.for.data.class.components.and.destruction.declarations.project.wide.setting=Disable search for data class components and destructuring declarations. (Project wide setting)
|
||||
find.usages.checkbox.text.fast.data.class.component.search=Fast data class component search
|
||||
find.usages.checkbox.name.expected.properties=Expected properties
|
||||
find.usages.action.text.find.usages.of=find usages of
|
||||
+1
@@ -0,0 +1 @@
|
||||
searching.for.implicit.usages=Searching for implicit usages...
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea
|
||||
|
||||
import com.intellij.DynamicBundle
|
||||
|
||||
abstract class AbstractKotlinBundleIndependent protected constructor(pathToBundle: String) : DynamicBundle(pathToBundle) {
|
||||
protected fun String.withHtml(): String = "<html>$this</html>"
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea
|
||||
|
||||
import com.intellij.AbstractBundle
|
||||
|
||||
abstract class AbstractKotlinBundleIndependent protected constructor(pathToBundle: String) : AbstractBundle(pathToBundle) {
|
||||
protected fun String.withHtml(): String = "<html>$this</html>"
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
package org.jetbrains.kotlin.idea
|
||||
|
||||
import org.jetbrains.annotations.NonNls
|
||||
import org.jetbrains.annotations.PropertyKey
|
||||
|
||||
@NonNls
|
||||
private const val BUNDLE = "messages.KotlinBundleIndependent"
|
||||
|
||||
//TODO Copy-pasted from KotlinBundle.kt
|
||||
object KotlinBundleIndependent : AbstractKotlinBundleIndependent(BUNDLE) {
|
||||
@JvmStatic
|
||||
fun message(@NonNls @PropertyKey(resourceBundle = BUNDLE) key: String, vararg params: Any): String = getMessage(key, *params)
|
||||
|
||||
@JvmStatic
|
||||
fun htmlMessage(@NonNls @PropertyKey(resourceBundle = BUNDLE) key: String, vararg params: Any): String =
|
||||
getMessage(key, *params).withHtml()
|
||||
|
||||
@JvmStatic
|
||||
fun lazyMessage(@PropertyKey(resourceBundle = BUNDLE) key: String, vararg params: Any): () -> String = { getMessage(key, *params) }
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
package org.jetbrains.kotlin.idea
|
||||
|
||||
import org.jetbrains.annotations.NonNls
|
||||
import org.jetbrains.annotations.PropertyKey
|
||||
|
||||
@NonNls
|
||||
private const val BUNDLE = "messages.KotlinIdeaAnalysisBundleIndependent"
|
||||
|
||||
object KotlinIdeaAnalysisBundleIndependent : AbstractKotlinBundleIndependent(BUNDLE) {
|
||||
@JvmStatic
|
||||
fun message(@NonNls @PropertyKey(resourceBundle = BUNDLE) key: String, vararg params: Any): String = getMessage(key, *params)
|
||||
|
||||
@JvmStatic
|
||||
fun htmlMessage(@NonNls @PropertyKey(resourceBundle = BUNDLE) key: String, vararg params: Any): String =
|
||||
getMessage(key, *params).withHtml()
|
||||
|
||||
@JvmStatic
|
||||
fun lazyMessage(@PropertyKey(resourceBundle = BUNDLE) key: String, vararg params: Any): () -> String = { getMessage(key, *params) }
|
||||
}
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.asJava
|
||||
|
||||
import com.intellij.openapi.components.ServiceManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.impl.light.AbstractLightClass
|
||||
import com.intellij.psi.impl.light.LightMethod
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightElement
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||
import org.jetbrains.kotlin.idea.search.KotlinSearchUsagesSupport
|
||||
import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||
|
||||
interface LightClassProvider {
|
||||
|
||||
fun getLightFieldForCompanionObject(companionObject: KtClassOrObject): PsiField?
|
||||
|
||||
fun getLightClassMethods(function: KtFunction): List<PsiMethod>
|
||||
|
||||
//getLightClassPropertyMethods.allDeclarations
|
||||
fun getLightClassParameterDeclarations(parameter: KtParameter): List<PsiNamedElement>
|
||||
|
||||
//getLightClassPropertyMethods.allDeclarations
|
||||
fun getLightClassPropertyDeclarations(property: KtProperty): List<PsiNamedElement>
|
||||
|
||||
fun toLightClassWithBuiltinMapping(classOrObject: KtClassOrObject): PsiClass?
|
||||
|
||||
fun toLightMethods(psiElement: PsiElement): List<PsiMethod>
|
||||
|
||||
fun toLightClass(classOrObject: KtClassOrObject): KtLightClass?
|
||||
|
||||
fun toLightElements(ktElement: KtElement): List<PsiNamedElement>
|
||||
|
||||
fun createKtFakeLightClass(kotlinOrigin: KtClassOrObject): PsiClass
|
||||
|
||||
fun getRepresentativeLightMethod(psiElement: PsiElement): PsiMethod?
|
||||
|
||||
fun isKtFakeLightClass(psiClass: PsiClass): Boolean
|
||||
|
||||
fun createKtFakeLightMethod(ktDeclaration: KtNamedDeclaration): PsiMethod?
|
||||
|
||||
companion object {
|
||||
|
||||
fun getInstance(project: Project): LightClassProvider {
|
||||
return ServiceManager.getService(project, LightClassProvider::class.java)
|
||||
}
|
||||
|
||||
fun providedGetLightFieldForCompanionObject(companionObject: KtClassOrObject): PsiField? =
|
||||
getInstance(companionObject.project).getLightFieldForCompanionObject(companionObject)
|
||||
|
||||
fun providedGetLightClassMethods(function: KtFunction): List<PsiMethod> =
|
||||
getInstance(function.project).getLightClassMethods(function)
|
||||
|
||||
//getLightClassPropertyMethods.allDeclarations
|
||||
fun providedGetLightClassParameterDeclarations(parameter: KtParameter): List<PsiNamedElement> =
|
||||
getInstance(parameter.project).getLightClassParameterDeclarations(parameter)
|
||||
|
||||
//getLightClassPropertyMethods.allDeclarations
|
||||
fun providedGetLightClassPropertyDeclarations(property: KtProperty): List<PsiNamedElement> =
|
||||
getInstance(property.project).getLightClassPropertyDeclarations(property)
|
||||
|
||||
fun KtClassOrObject.providedToLightClassWithBuiltinMapping(): PsiClass? =
|
||||
getInstance(project).toLightClassWithBuiltinMapping(this)
|
||||
|
||||
fun PsiElement.providedToLightMethods(): List<PsiMethod> =
|
||||
getInstance(project).toLightMethods(this)
|
||||
|
||||
fun KtClassOrObject.providedToLightClass(): KtLightClass? =
|
||||
getInstance(project).toLightClass(this)
|
||||
|
||||
fun KtElement.providedToLightElements(): List<PsiNamedElement> =
|
||||
getInstance(project).toLightElements(this)
|
||||
|
||||
fun providedCreateKtFakeLightClass(kotlinOrigin: KtClassOrObject): PsiClass? =
|
||||
getInstance(kotlinOrigin.project).createKtFakeLightClass(kotlinOrigin)
|
||||
|
||||
fun PsiClass.providedIsKtFakeLightClass(): Boolean =
|
||||
getInstance(project).isKtFakeLightClass(this)
|
||||
|
||||
fun providedCreateKtFakeLightMethod(ktDeclaration: KtNamedDeclaration): PsiMethod? =
|
||||
getInstance(ktDeclaration.project).createKtFakeLightMethod(ktDeclaration)
|
||||
|
||||
fun PsiElement.providedGetRepresentativeLightMethod(): PsiMethod? =
|
||||
getInstance(project).getRepresentativeLightMethod(this)
|
||||
}
|
||||
}
|
||||
+229
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.findUsages
|
||||
|
||||
import com.intellij.codeInsight.highlighting.HighlightUsagesDescriptionLocation
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.psi.ElementDescriptionLocation
|
||||
import com.intellij.psi.ElementDescriptionProvider
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiNamedElement
|
||||
import com.intellij.refactoring.util.CommonRefactoringUtil
|
||||
import com.intellij.refactoring.util.RefactoringDescriptionLocation
|
||||
import com.intellij.usageView.UsageViewLongNameLocation
|
||||
import com.intellij.usageView.UsageViewShortNameLocation
|
||||
import com.intellij.usageView.UsageViewTypeLocation
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
|
||||
import org.jetbrains.kotlin.asJava.unwrapped
|
||||
import org.jetbrains.kotlin.idea.KotlinBundleIndependent
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||
|
||||
open class KotlinElementDescriptionProviderBase : ElementDescriptionProvider {
|
||||
private tailrec fun KtNamedDeclaration.parentForFqName(): KtNamedDeclaration? {
|
||||
val parent = getStrictParentOfType<KtNamedDeclaration>() ?: return null
|
||||
if (parent is KtProperty && parent.isLocal) return parent.parentForFqName()
|
||||
return parent
|
||||
}
|
||||
|
||||
private fun KtNamedDeclaration.name() = nameAsName ?: Name.special("<no name provided>")
|
||||
|
||||
private fun KtNamedDeclaration.fqName(): FqNameUnsafe {
|
||||
containingClassOrObject?.let {
|
||||
if (it is KtObjectDeclaration && it.isCompanion()) {
|
||||
return it.fqName().child(name())
|
||||
}
|
||||
return FqNameUnsafe("${it.name()}.${name()}")
|
||||
}
|
||||
|
||||
val internalSegments = generateSequence(this) { it.parentForFqName() }
|
||||
.filterIsInstance<KtNamedDeclaration>()
|
||||
.map { it.name ?: "<no name provided>" }
|
||||
.toList()
|
||||
.asReversed()
|
||||
val packageSegments = containingKtFile.packageFqName.pathSegments()
|
||||
return FqNameUnsafe((packageSegments + internalSegments).joinToString("."))
|
||||
}
|
||||
|
||||
private fun KtTypeReference.renderShort(): String {
|
||||
return accept(
|
||||
object : KtVisitor<String, Unit>() {
|
||||
private val visitor get() = this
|
||||
|
||||
override fun visitTypeReference(typeReference: KtTypeReference, data: Unit): String {
|
||||
val typeText = typeReference.typeElement?.accept(this, data) ?: "???"
|
||||
return if (typeReference.hasParentheses()) "($typeText)" else typeText
|
||||
}
|
||||
|
||||
override fun visitDynamicType(type: KtDynamicType, data: Unit) = type.text
|
||||
|
||||
override fun visitFunctionType(type: KtFunctionType, data: Unit): String {
|
||||
return buildString {
|
||||
type.receiverTypeReference?.let { append(it.accept(visitor, data)).append('.') }
|
||||
type.parameters.joinTo(this, prefix = "(", postfix = ")") { it.accept(visitor, data) }
|
||||
append(" -> ")
|
||||
append(type.returnTypeReference?.accept(visitor, data) ?: "???")
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitNullableType(nullableType: KtNullableType, data: Unit): String {
|
||||
val innerTypeText = nullableType.innerType?.accept(this, data) ?: return "???"
|
||||
return "$innerTypeText?"
|
||||
}
|
||||
|
||||
override fun visitSelfType(type: KtSelfType, data: Unit) = type.text
|
||||
|
||||
override fun visitUserType(type: KtUserType, data: Unit): String {
|
||||
return buildString {
|
||||
append(type.referencedName ?: "???")
|
||||
|
||||
val arguments = type.typeArguments
|
||||
if (arguments.isNotEmpty()) {
|
||||
arguments.joinTo(this, prefix = "<", postfix = ">") {
|
||||
it.typeReference?.accept(visitor, data) ?: it.text
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitParameter(parameter: KtParameter, data: Unit) = parameter.typeReference?.accept(this, data) ?: "???"
|
||||
},
|
||||
Unit
|
||||
)
|
||||
}
|
||||
|
||||
//TODO Copied from stringUtil.kt
|
||||
private fun String.collapseSpaces(): String {
|
||||
val builder = StringBuilder()
|
||||
var haveSpaces = false
|
||||
for (c in this) {
|
||||
if (c.isWhitespace()) {
|
||||
haveSpaces = true
|
||||
} else {
|
||||
if (haveSpaces) {
|
||||
builder.append(" ")
|
||||
haveSpaces = false
|
||||
}
|
||||
builder.append(c)
|
||||
}
|
||||
}
|
||||
return builder.toString()
|
||||
}
|
||||
|
||||
//TODO: Implement in FIR
|
||||
protected open val PsiElement.isRenameJavaSyntheticPropertyHandler get() = false
|
||||
protected open val PsiElement.isRenameKotlinPropertyProcessor get() = false
|
||||
|
||||
override fun getElementDescription(element: PsiElement, location: ElementDescriptionLocation): String? {
|
||||
val shouldUnwrap = location !is UsageViewShortNameLocation && location !is UsageViewLongNameLocation
|
||||
val targetElement = if (shouldUnwrap) element.unwrapped ?: element else element
|
||||
|
||||
fun elementKind() = when (targetElement) {
|
||||
is KtClass -> if (targetElement.isInterface())
|
||||
KotlinBundleIndependent.message("find.usages.interface")
|
||||
else
|
||||
KotlinBundleIndependent.message("find.usages.class")
|
||||
is KtObjectDeclaration -> if (targetElement.isCompanion())
|
||||
KotlinBundleIndependent.message("find.usages.companion.object")
|
||||
else
|
||||
KotlinBundleIndependent.message("find.usages.object")
|
||||
is KtNamedFunction -> KotlinBundleIndependent.message("find.usages.function")
|
||||
is KtPropertyAccessor -> KotlinBundleIndependent.message(
|
||||
"find.usages.for.property",
|
||||
(if (targetElement.isGetter)
|
||||
KotlinBundleIndependent.message("find.usages.getter")
|
||||
else
|
||||
KotlinBundleIndependent.message("find.usages.setter"))
|
||||
) + " "
|
||||
is KtFunctionLiteral -> KotlinBundleIndependent.message("find.usages.lambda")
|
||||
is KtPrimaryConstructor, is KtSecondaryConstructor -> KotlinBundleIndependent.message("find.usages.constructor")
|
||||
is KtProperty -> if (targetElement.isLocal)
|
||||
KotlinBundleIndependent.message("find.usages.variable")
|
||||
else
|
||||
KotlinBundleIndependent.message("find.usages.property")
|
||||
is KtTypeParameter -> KotlinBundleIndependent.message("find.usages.type.parameter")
|
||||
is KtParameter -> KotlinBundleIndependent.message("find.usages.parameter")
|
||||
is KtDestructuringDeclarationEntry -> KotlinBundleIndependent.message("find.usages.variable")
|
||||
is KtTypeAlias -> KotlinBundleIndependent.message("find.usages.type.alias")
|
||||
is KtLabeledExpression -> KotlinBundleIndependent.message("find.usages.label")
|
||||
is KtImportAlias -> KotlinBundleIndependent.message("find.usages.import.alias")
|
||||
is KtLightClassForFacade -> KotlinBundleIndependent.message("find.usages.facade.class")
|
||||
else -> {
|
||||
//TODO Implement in FIR
|
||||
when {
|
||||
targetElement.isRenameJavaSyntheticPropertyHandler -> KotlinBundleIndependent.message("find.usages.property")
|
||||
targetElement.isRenameKotlinPropertyProcessor -> KotlinBundleIndependent.message("find.usages.property.accessor")
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val namedElement = if (targetElement is KtPropertyAccessor) {
|
||||
targetElement.parent as? KtProperty
|
||||
} else targetElement as? PsiNamedElement
|
||||
|
||||
@Suppress("FoldInitializerAndIfToElvis")
|
||||
if (namedElement == null) {
|
||||
return if (targetElement is KtElement) "'" + StringUtil.shortenTextWithEllipsis(
|
||||
targetElement.text.collapseSpaces(),
|
||||
53,
|
||||
0
|
||||
) + "'" else null
|
||||
}
|
||||
|
||||
if (namedElement.language != KotlinLanguage.INSTANCE) return null
|
||||
|
||||
return when (location) {
|
||||
is UsageViewTypeLocation -> elementKind()
|
||||
is UsageViewShortNameLocation, is UsageViewLongNameLocation -> namedElement.name
|
||||
is RefactoringDescriptionLocation -> {
|
||||
val kind = elementKind() ?: return null
|
||||
if (namedElement !is KtNamedDeclaration) return null
|
||||
val renderFqName = location.includeParent() &&
|
||||
namedElement !is KtTypeParameter &&
|
||||
namedElement !is KtParameter &&
|
||||
namedElement !is KtConstructor<*>
|
||||
val desc = when (namedElement) {
|
||||
is KtFunction -> {
|
||||
val baseText = buildString {
|
||||
append(namedElement.name ?: "")
|
||||
namedElement.valueParameters.joinTo(this, prefix = "(", postfix = ")") {
|
||||
(if (it.isVarArg) "vararg " else "") + (it.typeReference?.renderShort() ?: "")
|
||||
}
|
||||
namedElement.receiverTypeReference?.let { append(" on ").append(it.renderShort()) }
|
||||
}
|
||||
val parentFqName = if (renderFqName) namedElement.fqName().parent() else null
|
||||
if (parentFqName?.isRoot != false) baseText else "${parentFqName.asString()}.$baseText"
|
||||
}
|
||||
else -> (if (renderFqName) namedElement.fqName().asString() else namedElement.name) ?: ""
|
||||
}
|
||||
|
||||
"$kind ${CommonRefactoringUtil.htmlEmphasize(desc)}"
|
||||
}
|
||||
is HighlightUsagesDescriptionLocation -> {
|
||||
val kind = elementKind() ?: return null
|
||||
if (namedElement !is KtNamedDeclaration) return null
|
||||
"$kind ${namedElement.name}"
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
+7
-7
@@ -27,15 +27,15 @@ import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.ui.Messages
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.search.searches.OverridingMethodsSearch
|
||||
import org.jetbrains.kotlin.asJava.toLightMethods
|
||||
import org.jetbrains.kotlin.idea.asJava.LightClassProvider.Companion.providedToLightMethods
|
||||
import org.jetbrains.kotlin.asJava.unwrapped
|
||||
import org.jetbrains.kotlin.idea.KotlinBundle
|
||||
import org.jetbrains.kotlin.idea.core.isOverridable
|
||||
import org.jetbrains.kotlin.idea.KotlinBundleIndependent
|
||||
import org.jetbrains.kotlin.idea.findUsages.KotlinFindUsagesSupport.Companion.checkSuperMethods
|
||||
import org.jetbrains.kotlin.idea.search.KotlinSearchUsagesSupport.Companion.isOverridable
|
||||
import org.jetbrains.kotlin.idea.findUsages.handlers.DelegatingFindMemberUsagesHandler
|
||||
import org.jetbrains.kotlin.idea.findUsages.handlers.KotlinFindClassUsagesHandler
|
||||
import org.jetbrains.kotlin.idea.findUsages.handlers.KotlinFindMemberUsagesHandler
|
||||
import org.jetbrains.kotlin.idea.findUsages.handlers.KotlinTypeParameterFindUsagesHandler
|
||||
import org.jetbrains.kotlin.idea.refactoring.checkSuperMethods
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElementSelector
|
||||
@@ -85,14 +85,14 @@ class KotlinFindUsagesHandlerFactory(project: Project) : FindUsagesHandlerFactor
|
||||
val declarationsToSearch = checkSuperMethods(
|
||||
element,
|
||||
null,
|
||||
KotlinBundle.message("find.usages.action.text.find.usages.of")
|
||||
KotlinBundleIndependent.message("find.usages.action.text.find.usages.of")
|
||||
)
|
||||
|
||||
return handlerForMultiple(element, declarationsToSearch)
|
||||
}
|
||||
val function = element.ownerFunction
|
||||
if (function != null && function.isOverridable()) {
|
||||
val psiMethod = function.toLightMethods().singleOrNull()
|
||||
val psiMethod = function.providedToLightMethods().singleOrNull()
|
||||
if (psiMethod != null) {
|
||||
val hasOverridden = OverridingMethodsSearch.search(psiMethod).any()
|
||||
if (hasOverridden && askWhetherShouldSearchForParameterInOverridingMethods(element)) {
|
||||
@@ -122,7 +122,7 @@ class KotlinFindUsagesHandlerFactory(project: Project) : FindUsagesHandlerFactor
|
||||
val declarationsToSearch = checkSuperMethods(
|
||||
declaration,
|
||||
null,
|
||||
KotlinBundle.message("find.usages.action.text.find.usages.of")
|
||||
KotlinBundleIndependent.message("find.usages.action.text.find.usages.of")
|
||||
)
|
||||
|
||||
return handlerForMultiple(declaration, declarationsToSearch)
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.findUsages
|
||||
|
||||
import com.intellij.lang.cacheBuilder.WordsScanner
|
||||
import com.intellij.lang.findUsages.FindUsagesProvider
|
||||
import com.intellij.lang.java.JavaFindUsagesProvider
|
||||
import com.intellij.psi.*
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightElement
|
||||
import org.jetbrains.kotlin.idea.KotlinBundleIndependent
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isPropertyParameter
|
||||
|
||||
open class KotlinFindUsagesProviderBase : FindUsagesProvider {
|
||||
private val javaProvider by lazy { JavaFindUsagesProvider() }
|
||||
|
||||
override fun canFindUsagesFor(psiElement: PsiElement): Boolean =
|
||||
psiElement is KtNamedDeclaration
|
||||
|
||||
override fun getWordsScanner(): WordsScanner? = KotlinWordsScanner()
|
||||
|
||||
override fun getHelpId(psiElement: PsiElement): String? = null
|
||||
|
||||
override fun getType(element: PsiElement): String {
|
||||
return when (element) {
|
||||
is KtNamedFunction -> KotlinBundleIndependent.message("find.usages.function")
|
||||
is KtClass -> KotlinBundleIndependent.message("find.usages.class")
|
||||
is KtParameter -> KotlinBundleIndependent.message("find.usages.parameter")
|
||||
is KtProperty -> if (element.isLocal)
|
||||
KotlinBundleIndependent.message("find.usages.variable")
|
||||
else
|
||||
KotlinBundleIndependent.message("find.usages.property")
|
||||
is KtDestructuringDeclarationEntry -> KotlinBundleIndependent.message("find.usages.variable")
|
||||
is KtTypeParameter -> KotlinBundleIndependent.message("find.usages.type.parameter")
|
||||
is KtSecondaryConstructor -> KotlinBundleIndependent.message("find.usages.constructor")
|
||||
is KtObjectDeclaration -> KotlinBundleIndependent.message("find.usages.object")
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
|
||||
protected val KtDeclaration.containerDescription: String?
|
||||
get() {
|
||||
containingClassOrObject?.let { return getDescriptiveName(it) }
|
||||
(parent as? KtFile)?.parent?.let { return getDescriptiveName(it) }
|
||||
return null
|
||||
}
|
||||
|
||||
override fun getDescriptiveName(element: PsiElement): String {
|
||||
return when (element) {
|
||||
is PsiDirectory, is PsiPackage, is PsiFile -> javaProvider.getDescriptiveName(element)
|
||||
is KtClassOrObject -> {
|
||||
if (element is KtObjectDeclaration && element.isObjectLiteral()) return "<unnamed>"
|
||||
element.fqName?.asString() ?: element.name ?: "<unnamed>"
|
||||
}
|
||||
is KtProperty -> (element.name ?: "") + (element.containerDescription?.let { " of $it" } ?: "")
|
||||
is KtFunction -> {
|
||||
//TODO: Correct FIR implementation
|
||||
return element.name?.let { "$it(...)" } ?: ""
|
||||
}
|
||||
is KtLabeledExpression -> element.getLabelName() ?: ""
|
||||
is KtImportAlias -> element.name ?: ""
|
||||
is KtLightElement<*, *> -> element.kotlinOrigin?.let { getDescriptiveName(it) } ?: ""
|
||||
is KtParameter -> {
|
||||
if (element.isPropertyParameter()) {
|
||||
(element.name ?: "") + (element.containerDescription?.let { " of $it" } ?: "")
|
||||
} else {
|
||||
element.name ?: ""
|
||||
}
|
||||
}
|
||||
is PsiNamedElement -> element.name ?: ""
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
|
||||
override fun getNodeText(element: PsiElement, useFullName: Boolean): String =
|
||||
getDescriptiveName(element)
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.findUsages
|
||||
|
||||
import com.intellij.openapi.components.ServiceManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiReference
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.annotations.Nls
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
|
||||
interface KotlinFindUsagesSupport {
|
||||
|
||||
companion object {
|
||||
fun getInstance(project: Project): KotlinFindUsagesSupport {
|
||||
return ServiceManager.getService(project, KotlinFindUsagesSupport::class.java)
|
||||
}
|
||||
|
||||
val KtParameter.isDataClassComponentFunction: Boolean
|
||||
get() = getInstance(project).isDataClassComponentFunction(this)
|
||||
|
||||
fun KtElement.isCallReceiverRefersToCompanionObject(companionObject: KtObjectDeclaration): Boolean =
|
||||
getInstance(project).isCallReceiverRefersToCompanionObject(this, companionObject)
|
||||
|
||||
fun getTopMostOverriddenElementsToHighlight(target: PsiElement): List<PsiElement> =
|
||||
getInstance(target.project).getTopMostOverriddenElementsToHighlight(target)
|
||||
|
||||
fun tryRenderDeclarationCompactStyle(declaration: KtDeclaration): String? =
|
||||
getInstance(declaration.project).tryRenderDeclarationCompactStyle(declaration)
|
||||
|
||||
fun PsiReference.isConstructorUsage(ktClassOrObject: KtClassOrObject): Boolean =
|
||||
getInstance(ktClassOrObject.project).isConstructorUsage(this, ktClassOrObject)
|
||||
|
||||
fun checkSuperMethods(
|
||||
declaration: KtDeclaration,
|
||||
ignore: Collection<PsiElement>?,
|
||||
@Nls actionString: String
|
||||
): List<PsiElement> = getInstance(declaration.project).checkSuperMethods(declaration, ignore, actionString)
|
||||
|
||||
fun sourcesAndLibraries(delegate: GlobalSearchScope, project: Project): GlobalSearchScope =
|
||||
getInstance(project).sourcesAndLibraries(delegate, project)
|
||||
}
|
||||
|
||||
fun isCallReceiverRefersToCompanionObject(element: KtElement, companionObject: KtObjectDeclaration): Boolean
|
||||
|
||||
fun isDataClassComponentFunction(element: KtParameter): Boolean
|
||||
|
||||
fun getTopMostOverriddenElementsToHighlight(target: PsiElement): List<PsiElement>
|
||||
|
||||
fun tryRenderDeclarationCompactStyle(declaration: KtDeclaration): String?
|
||||
|
||||
fun isConstructorUsage(psiReference: PsiReference, ktClassOrObject: KtClassOrObject): Boolean
|
||||
|
||||
fun checkSuperMethods(
|
||||
declaration: KtDeclaration,
|
||||
ignore: Collection<PsiElement>?,
|
||||
@Nls actionString: String
|
||||
): List<PsiElement>
|
||||
|
||||
fun sourcesAndLibraries(delegate: GlobalSearchScope, project: Project): GlobalSearchScope
|
||||
}
|
||||
+13
-15
@@ -31,19 +31,17 @@ import com.intellij.ui.SimpleColoredComponent;
|
||||
import com.intellij.ui.StateRestoringCheckBox;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.idea.asJava.LightClassProvider;
|
||||
import org.jetbrains.kotlin.asJava.LightClassUtilsKt;
|
||||
import org.jetbrains.kotlin.idea.KotlinBundle;
|
||||
import org.jetbrains.kotlin.idea.core.PsiModificationUtilsKt;
|
||||
import org.jetbrains.kotlin.idea.KotlinBundleIndependent;
|
||||
import org.jetbrains.kotlin.idea.findUsages.KotlinClassFindUsagesOptions;
|
||||
import org.jetbrains.kotlin.idea.refactoring.RenderingUtilsKt;
|
||||
import org.jetbrains.kotlin.idea.search.KotlinSearchUsagesSupport;
|
||||
import org.jetbrains.kotlin.psi.KtClass;
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject;
|
||||
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
import static org.jetbrains.kotlin.asJava.LightClassUtilsKt.toLightClass;
|
||||
|
||||
public class KotlinFindClassUsagesDialog extends FindClassUsagesDialog {
|
||||
private StateRestoringCheckBox constructorUsages;
|
||||
private StateRestoringCheckBox derivedClasses;
|
||||
@@ -66,7 +64,7 @@ public class KotlinFindClassUsagesDialog extends FindClassUsagesDialog {
|
||||
|
||||
@NotNull
|
||||
private static PsiClass getRepresentingPsiClass(@NotNull KtClassOrObject classOrObject) {
|
||||
PsiClass lightClass = toLightClass(classOrObject);
|
||||
PsiClass lightClass = LightClassProvider.Companion.providedToLightClass(classOrObject);
|
||||
if (lightClass != null) return lightClass;
|
||||
|
||||
// TODO: Remove this code when light classes are generated for builtins
|
||||
@@ -74,7 +72,7 @@ public class KotlinFindClassUsagesDialog extends FindClassUsagesDialog {
|
||||
|
||||
String name = classOrObject.getName();
|
||||
if (name == null || name.isEmpty()) {
|
||||
name = KotlinBundle.message("find.usages.class.name.anonymous");
|
||||
name = KotlinBundleIndependent.message("find.usages.class.name.anonymous");
|
||||
}
|
||||
|
||||
PsiClass javaClass;
|
||||
@@ -93,7 +91,7 @@ public class KotlinFindClassUsagesDialog extends FindClassUsagesDialog {
|
||||
//noinspection ConstantConditions
|
||||
javaClass.getModifierList().setModifierProperty(
|
||||
PsiModifier.FINAL,
|
||||
!(classOrObject instanceof KtClass && PsiModificationUtilsKt.isInheritable((KtClass) classOrObject))
|
||||
!(classOrObject instanceof KtClass && KotlinSearchUsagesSupport.Companion.isInheritable((KtClass) classOrObject))
|
||||
);
|
||||
|
||||
javaClass.putUserData(ORIGINAL_CLASS, classOrObject);
|
||||
@@ -109,31 +107,31 @@ public class KotlinFindClassUsagesDialog extends FindClassUsagesDialog {
|
||||
Utils.renameCheckbox(
|
||||
findWhatPanel,
|
||||
FindBundle.message("find.what.methods.usages.checkbox"),
|
||||
KotlinBundle.message("find.declaration.functions.usages.checkbox")
|
||||
KotlinBundleIndependent.message("find.declaration.functions.usages.checkbox")
|
||||
);
|
||||
Utils.renameCheckbox(
|
||||
findWhatPanel,
|
||||
FindBundle.message("find.what.fields.usages.checkbox"),
|
||||
KotlinBundle.message("find.declaration.properties.usages.checkbox")
|
||||
KotlinBundleIndependent.message("find.declaration.properties.usages.checkbox")
|
||||
);
|
||||
Utils.removeCheckbox(findWhatPanel, FindBundle.message("find.what.implementing.classes.checkbox"));
|
||||
Utils.removeCheckbox(findWhatPanel, FindBundle.message("find.what.derived.interfaces.checkbox"));
|
||||
Utils.removeCheckbox(findWhatPanel, FindBundle.message("find.what.derived.classes.checkbox"));
|
||||
|
||||
derivedClasses = addCheckboxToPanel(
|
||||
KotlinBundle.message("find.declaration.derived.classes.checkbox"),
|
||||
KotlinBundleIndependent.message("find.declaration.derived.classes.checkbox"),
|
||||
getFindUsagesOptions().isDerivedClasses,
|
||||
findWhatPanel,
|
||||
true
|
||||
);
|
||||
derivedTraits = addCheckboxToPanel(
|
||||
KotlinBundle.message("find.declaration.derived.interfaces.checkbox"),
|
||||
KotlinBundleIndependent.message("find.declaration.derived.interfaces.checkbox"),
|
||||
getFindUsagesOptions().isDerivedInterfaces,
|
||||
findWhatPanel,
|
||||
true
|
||||
);
|
||||
constructorUsages = addCheckboxToPanel(
|
||||
KotlinBundle.message("find.declaration.constructor.usages.checkbox"),
|
||||
KotlinBundleIndependent.message("find.declaration.constructor.usages.checkbox"),
|
||||
getFindUsagesOptions().getSearchConstructorUsages(),
|
||||
findWhatPanel,
|
||||
true
|
||||
@@ -165,7 +163,7 @@ public class KotlinFindClassUsagesDialog extends FindClassUsagesDialog {
|
||||
KotlinClassFindUsagesOptions options = getFindUsagesOptions();
|
||||
if (isActual) {
|
||||
expectedUsages = addCheckboxToPanel(
|
||||
KotlinBundle.message("find.usages.checkbox.name.expected.classes"),
|
||||
KotlinBundleIndependent.message("find.usages.checkbox.name.expected.classes"),
|
||||
options.getSearchExpected(),
|
||||
optionsPanel,
|
||||
false
|
||||
@@ -177,7 +175,7 @@ public class KotlinFindClassUsagesDialog extends FindClassUsagesDialog {
|
||||
public void configureLabelComponent(@NotNull SimpleColoredComponent coloredComponent) {
|
||||
KtClassOrObject originalClass = getOriginalClass();
|
||||
if (originalClass != null) {
|
||||
coloredComponent.append(RenderingUtilsKt.formatClass(originalClass));
|
||||
coloredComponent.append(KotlinSearchUsagesSupport.Companion.formatClass(originalClass));
|
||||
}
|
||||
}
|
||||
|
||||
+8
-8
@@ -29,9 +29,9 @@ import com.intellij.ui.StateRestoringCheckBox;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.asJava.LightClassUtilsKt;
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethod;
|
||||
import org.jetbrains.kotlin.idea.KotlinBundle;
|
||||
import org.jetbrains.kotlin.idea.KotlinBundleIndependent;
|
||||
import org.jetbrains.kotlin.idea.findUsages.KotlinFunctionFindUsagesOptions;
|
||||
import org.jetbrains.kotlin.idea.refactoring.RenderingUtilsKt;
|
||||
import org.jetbrains.kotlin.idea.search.KotlinSearchUsagesSupport;
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration;
|
||||
import org.jetbrains.kotlin.psi.KtNamedDeclaration;
|
||||
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
|
||||
@@ -61,7 +61,7 @@ public class KotlinFindFunctionUsagesDialog extends FindMethodUsagesDialog {
|
||||
|
||||
@Override
|
||||
public void configureLabelComponent(@NotNull SimpleColoredComponent coloredComponent) {
|
||||
coloredComponent.append(RenderingUtilsKt.formatJavaOrLightMethod((PsiMethod) myPsiElement));
|
||||
coloredComponent.append(KotlinSearchUsagesSupport.Companion.formatJavaOrLightMethod((PsiMethod) myPsiElement));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -72,12 +72,12 @@ public class KotlinFindFunctionUsagesDialog extends FindMethodUsagesDialog {
|
||||
Utils.renameCheckbox(
|
||||
findWhatPanel,
|
||||
FindBundle.message("find.what.implementing.methods.checkbox"),
|
||||
KotlinBundle.message("find.declaration.implementing.methods.checkbox")
|
||||
KotlinBundleIndependent.message("find.declaration.implementing.methods.checkbox")
|
||||
);
|
||||
Utils.renameCheckbox(
|
||||
findWhatPanel,
|
||||
FindBundle.message("find.what.overriding.methods.checkbox"),
|
||||
KotlinBundle.message("find.declaration.overriding.methods.checkbox")
|
||||
KotlinBundleIndependent.message("find.declaration.overriding.methods.checkbox")
|
||||
);
|
||||
}
|
||||
|
||||
@@ -91,10 +91,10 @@ public class KotlinFindFunctionUsagesDialog extends FindMethodUsagesDialog {
|
||||
if (!Utils.renameCheckbox(
|
||||
optionsPanel,
|
||||
FindBundle.message("find.options.include.overloaded.methods.checkbox"),
|
||||
KotlinBundle.message("find.declaration.include.overloaded.methods.checkbox")
|
||||
KotlinBundleIndependent.message("find.declaration.include.overloaded.methods.checkbox")
|
||||
)) {
|
||||
addCheckboxToPanel(
|
||||
KotlinBundle.message("find.declaration.include.overloaded.methods.checkbox"),
|
||||
KotlinBundleIndependent.message("find.declaration.include.overloaded.methods.checkbox"),
|
||||
FindSettings.getInstance().isSearchOverloadedMethods(),
|
||||
optionsPanel,
|
||||
false
|
||||
@@ -110,7 +110,7 @@ public class KotlinFindFunctionUsagesDialog extends FindMethodUsagesDialog {
|
||||
KotlinFunctionFindUsagesOptions options = getFindUsagesOptions();
|
||||
if (isActual) {
|
||||
expectedUsages = addCheckboxToPanel(
|
||||
KotlinBundle.message("find.usages.checkbox.name.expected.functions"),
|
||||
KotlinBundleIndependent.message("find.usages.checkbox.name.expected.functions"),
|
||||
options.getSearchExpected(),
|
||||
optionsPanel,
|
||||
false
|
||||
+8
-8
@@ -27,7 +27,7 @@ import com.intellij.ui.IdeBorderFactory;
|
||||
import com.intellij.ui.SimpleColoredComponent;
|
||||
import com.intellij.ui.StateRestoringCheckBox;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.idea.KotlinBundle;
|
||||
import org.jetbrains.kotlin.idea.KotlinBundleIndependent;
|
||||
import org.jetbrains.kotlin.idea.findUsages.KotlinPropertyFindUsagesOptions;
|
||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
@@ -85,13 +85,13 @@ public class KotlinFindPropertyUsagesDialog extends JavaFindUsagesDialog<KotlinP
|
||||
KotlinPropertyFindUsagesOptions options = getFindUsagesOptions();
|
||||
|
||||
readAccesses = addCheckboxToPanel(
|
||||
KotlinBundle.message("find.declaration.property.readers.checkbox"),
|
||||
KotlinBundleIndependent.message("find.declaration.property.readers.checkbox"),
|
||||
options.isReadAccess,
|
||||
findWhatPanel,
|
||||
true
|
||||
);
|
||||
writeAccesses = addCheckboxToPanel(
|
||||
KotlinBundle.message("find.declaration.property.writers.checkbox"),
|
||||
KotlinBundleIndependent.message("find.declaration.property.writers.checkbox"),
|
||||
options.isWriteAccess,
|
||||
findWhatPanel,
|
||||
true
|
||||
@@ -116,8 +116,8 @@ public class KotlinFindPropertyUsagesDialog extends JavaFindUsagesDialog<KotlinP
|
||||
if (isOpen || isAbstract) {
|
||||
overrideUsages = addCheckboxToPanel(
|
||||
isAbstract
|
||||
? KotlinBundle.message("find.declaration.implementing.properties.checkbox")
|
||||
: KotlinBundle.message("find.declaration.overriding.properties.checkbox"),
|
||||
? KotlinBundleIndependent.message("find.declaration.implementing.properties.checkbox")
|
||||
: KotlinBundleIndependent.message("find.declaration.overriding.properties.checkbox"),
|
||||
FindSettings.getInstance().isSearchOverloadedMethods(),
|
||||
optionsPanel,
|
||||
false
|
||||
@@ -127,7 +127,7 @@ public class KotlinFindPropertyUsagesDialog extends JavaFindUsagesDialog<KotlinP
|
||||
KotlinPropertyFindUsagesOptions options = getFindUsagesOptions();
|
||||
if (isActual) {
|
||||
expectedUsages = addCheckboxToPanel(
|
||||
KotlinBundle.message("find.usages.checkbox.name.expected.properties"),
|
||||
KotlinBundleIndependent.message("find.usages.checkbox.name.expected.properties"),
|
||||
options.getSearchExpected(),
|
||||
optionsPanel,
|
||||
false
|
||||
@@ -136,8 +136,8 @@ public class KotlinFindPropertyUsagesDialog extends JavaFindUsagesDialog<KotlinP
|
||||
|
||||
if (isDataClassConstructorProperty(property)) {
|
||||
JCheckBox dataClassComponentCheckBox =
|
||||
new JCheckBox(KotlinBundle.message("find.usages.checkbox.text.fast.data.class.component.search"));
|
||||
dataClassComponentCheckBox.setToolTipText(KotlinBundle.message(
|
||||
new JCheckBox(KotlinBundleIndependent.message("find.usages.checkbox.text.fast.data.class.component.search"));
|
||||
dataClassComponentCheckBox.setToolTipText(KotlinBundleIndependent.message(
|
||||
"find.usages.tool.tip.text.disable.search.for.data.class.components.and.destruction.declarations.project.wide.setting"));
|
||||
Project project = property.getProject();
|
||||
dataClassComponentCheckBox.setSelected(getDisableComponentAndDestructionSearch(project));
|
||||
+4
-6
@@ -18,10 +18,8 @@ package org.jetbrains.kotlin.idea.findUsages.dialogs;
|
||||
|
||||
import com.intellij.ui.SimpleColoredComponent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.kotlin.idea.search.usagesSearch.UtilsKt;
|
||||
import org.jetbrains.kotlin.idea.findUsages.KotlinFindUsagesSupport;
|
||||
import org.jetbrains.kotlin.psi.KtNamedDeclaration;
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
@@ -34,9 +32,9 @@ class Utils {
|
||||
@NotNull SimpleColoredComponent coloredComponent,
|
||||
@NotNull KtNamedDeclaration declaration
|
||||
) {
|
||||
DeclarationDescriptor descriptor = UtilsKt.getDescriptor(declaration);
|
||||
if (descriptor != null) {
|
||||
coloredComponent.append(DescriptorRenderer.COMPACT.render(descriptor));
|
||||
String renderedDeclaration = KotlinFindUsagesSupport.Companion.tryRenderDeclarationCompactStyle(declaration);
|
||||
if (renderedDeclaration != null) {
|
||||
coloredComponent.append(renderedDeclaration);
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -27,8 +27,8 @@ import com.intellij.psi.search.searches.ReferencesSearch
|
||||
import com.intellij.usageView.UsageInfo
|
||||
import com.intellij.usages.UsageViewManager
|
||||
import com.intellij.util.Query
|
||||
import org.jetbrains.kotlin.asJava.toLightClass
|
||||
import org.jetbrains.kotlin.asJava.toLightElements
|
||||
import org.jetbrains.kotlin.idea.asJava.LightClassProvider.Companion.providedToLightClass
|
||||
import org.jetbrains.kotlin.idea.asJava.LightClassProvider.Companion.providedToLightElements
|
||||
import org.jetbrains.kotlin.idea.references.KtReference
|
||||
import org.jetbrains.kotlin.psi.KtConstructor
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
@@ -44,9 +44,9 @@ fun KtDeclaration.processAllExactUsages(
|
||||
if (reference is KtReference) return listOf(this)
|
||||
return SmartList<PsiElement>().also { list ->
|
||||
list += this
|
||||
list += toLightElements()
|
||||
list += providedToLightElements()
|
||||
if (this is KtConstructor<*>) {
|
||||
list.addIfNotNull(getContainingClassOrObject().toLightClass())
|
||||
list.addIfNotNull(getContainingClassOrObject().providedToLightClass())
|
||||
}
|
||||
}
|
||||
}
|
||||
+9
-20
@@ -28,28 +28,24 @@ import com.intellij.psi.search.searches.MethodReferencesSearch
|
||||
import com.intellij.psi.search.searches.ReferencesSearch
|
||||
import com.intellij.util.FilteredQuery
|
||||
import com.intellij.util.Processor
|
||||
import org.jetbrains.kotlin.idea.asJava.LightClassProvider.Companion.providedToLightClass
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||
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.KotlinFindUsagesSupport.Companion.isCallReceiverRefersToCompanionObject
|
||||
import org.jetbrains.kotlin.idea.findUsages.KotlinFindUsagesSupport.Companion.isConstructorUsage
|
||||
import org.jetbrains.kotlin.idea.findUsages.dialogs.KotlinFindClassUsagesDialog
|
||||
import org.jetbrains.kotlin.idea.search.declarationsSearch.HierarchySearchRequest
|
||||
import org.jetbrains.kotlin.idea.search.declarationsSearch.searchInheritors
|
||||
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchOptions
|
||||
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchParameters
|
||||
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.isImportUsage
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.anyDescendantOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.contains
|
||||
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.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
|
||||
import java.util.*
|
||||
|
||||
class KotlinFindClassUsagesHandler(
|
||||
@@ -97,7 +93,7 @@ class KotlinFindClassUsagesHandler(
|
||||
}
|
||||
|
||||
if (kotlinOptions.searchConstructorUsages) {
|
||||
classOrObject.toLightClass()?.constructors?.filterIsInstance<KtLightMethod>()?.forEach { constructor ->
|
||||
classOrObject.providedToLightClass()?.constructors?.filterIsInstance<KtLightMethod>()?.forEach { constructor ->
|
||||
val scope = constructor.useScope.intersectWith(options.searchScope)
|
||||
var query = MethodReferencesSearch.search(constructor, scope, true)
|
||||
if (kotlinOptions.isSkipImportStatements) {
|
||||
@@ -161,18 +157,11 @@ class KotlinFindClassUsagesHandler(
|
||||
|
||||
private fun processCompanionObjectInternalReferences(companionObject: KtObjectDeclaration): Boolean {
|
||||
val klass = companionObject.getStrictParentOfType<KtClass>() ?: return true
|
||||
val companionObjectDescriptor = companionObject.descriptor
|
||||
return !klass.anyDescendantOfType(fun(element: KtElement): Boolean {
|
||||
if (element == companionObject) return false // skip companion object itself
|
||||
|
||||
val bindingContext = element.analyze()
|
||||
val resolvedCall = bindingContext[BindingContext.CALL, element]?.getResolvedCall(bindingContext) ?: return false
|
||||
if ((resolvedCall.dispatchReceiver as? ImplicitClassReceiver)?.declarationDescriptor == companionObjectDescriptor
|
||||
|| (resolvedCall.extensionReceiver as? ImplicitClassReceiver)?.declarationDescriptor == companionObjectDescriptor
|
||||
) {
|
||||
return element.references.any { !referenceProcessor.process(it) }
|
||||
}
|
||||
return false
|
||||
return if (element.isCallReceiverRefersToCompanionObject(companionObject)) {
|
||||
element.references.any { !referenceProcessor.process(it) }
|
||||
} else false
|
||||
})
|
||||
}
|
||||
|
||||
@@ -190,7 +179,7 @@ class KotlinFindClassUsagesHandler(
|
||||
override fun getStringsToSearch(element: PsiElement): Collection<String> {
|
||||
val psiClass = when (element) {
|
||||
is PsiClass -> element
|
||||
is KtClassOrObject -> getElement().toLightClass()
|
||||
is KtClassOrObject -> getElement().providedToLightClass()
|
||||
else -> null
|
||||
} ?: return Collections.emptyList()
|
||||
|
||||
+14
-35
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.findUsages.handlers
|
||||
@@ -40,13 +29,12 @@ import com.intellij.psi.search.searches.MethodReferencesSearch
|
||||
import com.intellij.psi.search.searches.ReferencesSearch
|
||||
import com.intellij.util.*
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
import org.jetbrains.kotlin.asJava.toLightMethods
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ParameterDescriptor
|
||||
import org.jetbrains.kotlin.idea.KotlinBundle
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||
import org.jetbrains.kotlin.idea.debugger.readAction
|
||||
import org.jetbrains.kotlin.idea.asJava.LightClassProvider.Companion.providedToLightMethods
|
||||
import org.jetbrains.kotlin.idea.KotlinBundleIndependent
|
||||
import org.jetbrains.kotlin.idea.findUsages.*
|
||||
import org.jetbrains.kotlin.idea.findUsages.KotlinFindUsagesSupport.Companion.getTopMostOverriddenElementsToHighlight
|
||||
import org.jetbrains.kotlin.idea.findUsages.KotlinFindUsagesSupport.Companion.isDataClassComponentFunction
|
||||
import org.jetbrains.kotlin.idea.search.KotlinSearchUsagesSupport.Companion.filterDataClassComponentsIfDisabled
|
||||
import org.jetbrains.kotlin.idea.findUsages.dialogs.KotlinFindFunctionUsagesDialog
|
||||
import org.jetbrains.kotlin.idea.findUsages.dialogs.KotlinFindPropertyUsagesDialog
|
||||
import org.jetbrains.kotlin.idea.search.declarationsSearch.HierarchySearchRequest
|
||||
@@ -55,14 +43,10 @@ import org.jetbrains.kotlin.idea.search.excludeKotlinSources
|
||||
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.isImportUsage
|
||||
import org.jetbrains.kotlin.idea.search.isOnlyKotlinSearch
|
||||
import org.jetbrains.kotlin.idea.search.usagesSearch.dataClassComponentFunction
|
||||
import org.jetbrains.kotlin.idea.search.usagesSearch.filterDataClassComponentsIfDisabled
|
||||
import org.jetbrains.kotlin.idea.search.usagesSearch.isImportUsage
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.findOriginalTopMostOverriddenDescriptors
|
||||
import org.jetbrains.kotlin.resolve.source.getPsi
|
||||
import javax.swing.event.HyperlinkEvent
|
||||
import javax.swing.event.HyperlinkListener
|
||||
|
||||
@@ -86,7 +70,7 @@ abstract class KotlinFindMemberUsagesHandler<T : KtNamedDeclaration> protected c
|
||||
mustOpenInNewTab: Boolean
|
||||
): AbstractFindUsagesDialog {
|
||||
val options = factory.findFunctionOptions
|
||||
val lightMethod = getElement().toLightMethods().firstOrNull()
|
||||
val lightMethod = getElement().providedToLightMethods().firstOrNull()
|
||||
if (lightMethod != null) {
|
||||
return KotlinFindFunctionUsagesDialog(lightMethod, project, options, toShowInNewTab, mustOpenInNewTab, isSingleFile, this)
|
||||
}
|
||||
@@ -134,7 +118,7 @@ abstract class KotlinFindMemberUsagesHandler<T : KtNamedDeclaration> protected c
|
||||
}
|
||||
}
|
||||
|
||||
private val isPropertyOfDataClass = readAction {
|
||||
private val isPropertyOfDataClass = runReadAction {
|
||||
propertyDeclaration.parent is KtParameterList &&
|
||||
propertyDeclaration.parent.parent is KtPrimaryConstructor &&
|
||||
propertyDeclaration.parent.parent.parent.let { it is KtClass && it.isData() }
|
||||
@@ -238,12 +222,12 @@ abstract class KotlinFindMemberUsagesHandler<T : KtNamedDeclaration> protected c
|
||||
if (element is KtElement && !isOnlyKotlinSearch(options.searchScope)) {
|
||||
// TODO: very bad code!! ReferencesSearch does not work correctly for constructors and annotation parameters
|
||||
val psiMethodScopeSearch = when {
|
||||
element is KtParameter && element.dataClassComponentFunction() != null ->
|
||||
element is KtParameter && element.isDataClassComponentFunction ->
|
||||
options.searchScope.excludeKotlinSources()
|
||||
else -> options.searchScope
|
||||
}
|
||||
|
||||
for (psiMethod in element.toLightMethods().filterDataClassComponentsIfDisabled(kotlinSearchOptions)) {
|
||||
for (psiMethod in element.providedToLightMethods().filterDataClassComponentsIfDisabled(kotlinSearchOptions)) {
|
||||
addTask {
|
||||
applyQueryFilters(
|
||||
element,
|
||||
@@ -284,13 +268,8 @@ abstract class KotlinFindMemberUsagesHandler<T : KtNamedDeclaration> protected c
|
||||
!isSingleFile && psiElement !is KtParameter
|
||||
|
||||
override fun findReferencesToHighlight(target: PsiElement, searchScope: SearchScope): Collection<PsiReference> {
|
||||
val callableDescriptor = (target as? KtCallableDeclaration)?.resolveToDescriptorIfAny() as? CallableDescriptor
|
||||
val descriptorsToHighlight = if (callableDescriptor is ParameterDescriptor)
|
||||
listOf(callableDescriptor)
|
||||
else
|
||||
callableDescriptor?.findOriginalTopMostOverriddenDescriptors() ?: emptyList()
|
||||
|
||||
val baseDeclarations = descriptorsToHighlight.map { it.source.getPsi() }.filter { it != null && it != target }
|
||||
val baseDeclarations = getTopMostOverriddenElementsToHighlight(target)
|
||||
|
||||
return if (baseDeclarations.isNotEmpty()) {
|
||||
baseDeclarations.flatMap {
|
||||
@@ -311,7 +290,7 @@ abstract class KotlinFindMemberUsagesHandler<T : KtNamedDeclaration> protected c
|
||||
|
||||
private const val DISABLE_ONCE = "DISABLE_ONCE"
|
||||
private const val DISABLE = "DISABLE"
|
||||
private val DISABLE_COMPONENT_AND_DESTRUCTION_SEARCH_TEXT = KotlinBundle.message(
|
||||
private val DISABLE_COMPONENT_AND_DESTRUCTION_SEARCH_TEXT = KotlinBundleIndependent.message(
|
||||
"find.usages.text.find.usages.for.data.class.components.and.destruction.declarations",
|
||||
DISABLE_ONCE,
|
||||
DISABLE
|
||||
+1
-1
@@ -32,7 +32,7 @@ import org.jetbrains.kotlin.idea.findUsages.KotlinFindUsagesHandlerFactory
|
||||
import org.jetbrains.kotlin.idea.findUsages.KotlinReferencePreservingUsageInfo
|
||||
import org.jetbrains.kotlin.idea.findUsages.KotlinReferenceUsageInfo
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.idea.util.runReadActionInSmartMode
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadActionInSmartMode
|
||||
import java.util.*
|
||||
|
||||
abstract class KotlinFindUsagesHandler<T : PsiElement>(
|
||||
+152
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.search
|
||||
|
||||
import com.intellij.openapi.components.ServiceManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.psi.search.SearchScope
|
||||
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchOptions
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.ImportPath
|
||||
|
||||
interface KotlinSearchUsagesSupport {
|
||||
|
||||
companion object {
|
||||
fun getInstance(project: Project): KotlinSearchUsagesSupport {
|
||||
return ServiceManager.getService(project, KotlinSearchUsagesSupport::class.java)
|
||||
}
|
||||
|
||||
val KtParameter.dataClassComponentMethodName: String?
|
||||
get() = getInstance(project).dataClassComponentMethodName(this)
|
||||
|
||||
val KtExpression.hasType: Boolean
|
||||
get() = getInstance(project).hasType(this)
|
||||
|
||||
val PsiClass.isSamInterface: Boolean
|
||||
get() = getInstance(project).isSamInterface(this)
|
||||
|
||||
fun <T : PsiNamedElement> List<T>.filterDataClassComponentsIfDisabled(kotlinOptions: KotlinReferencesSearchOptions): List<T> =
|
||||
firstOrNull()?.let {
|
||||
getInstance(it.project).filterDataClassComponentsIfDisabled(this, kotlinOptions)
|
||||
} ?: this
|
||||
|
||||
fun PsiReference.isCallableOverrideUsage(declaration: KtNamedDeclaration): Boolean =
|
||||
getInstance(declaration.project).isCallableOverrideUsage(this, declaration)
|
||||
|
||||
fun PsiReference.isUsageInContainingDeclaration(declaration: KtNamedDeclaration): Boolean =
|
||||
getInstance(declaration.project).isUsageInContainingDeclaration(this, declaration)
|
||||
|
||||
fun PsiReference.isExtensionOfDeclarationClassUsage(declaration: KtNamedDeclaration): Boolean =
|
||||
getInstance(declaration.project).isExtensionOfDeclarationClassUsage(this, declaration)
|
||||
|
||||
fun PsiElement.getReceiverTypeSearcherInfo(isDestructionDeclarationSearch: Boolean): ReceiverTypeSearcherInfo? =
|
||||
getInstance(project).getReceiverTypeSearcherInfo(this, isDestructionDeclarationSearch)
|
||||
|
||||
fun KtFile.forceResolveReferences(elements: List<KtElement>) =
|
||||
getInstance(project).forceResolveReferences(this, elements)
|
||||
|
||||
fun PsiFile.scriptDefinitionExists(): Boolean =
|
||||
getInstance(project).scriptDefinitionExists(this)
|
||||
|
||||
fun KtFile.getDefaultImports(): List<ImportPath> =
|
||||
getInstance(project).getDefaultImports(this)
|
||||
|
||||
fun forEachKotlinOverride(
|
||||
ktClass: KtClass,
|
||||
members: List<KtNamedDeclaration>,
|
||||
scope: SearchScope,
|
||||
processor: (superMember: PsiElement, overridingMember: PsiElement) -> Boolean
|
||||
): Boolean = getInstance(ktClass.project).forEachKotlinOverride(ktClass, members, scope, processor)
|
||||
|
||||
fun PsiMethod.forEachOverridingMethod(
|
||||
scope: SearchScope = runReadAction { useScope },
|
||||
processor: (PsiMethod) -> Boolean
|
||||
): Boolean = getInstance(project).forEachOverridingMethod(this, scope, processor)
|
||||
|
||||
fun findDeepestSuperMethodsNoWrapping(method: PsiElement): List<PsiElement> =
|
||||
getInstance(method.project).findDeepestSuperMethodsNoWrapping(method)
|
||||
|
||||
fun findTypeAliasByShortName(shortName: String, project: Project, scope: GlobalSearchScope): Collection<KtTypeAlias> =
|
||||
getInstance(project).findTypeAliasByShortName(shortName, project, scope)
|
||||
|
||||
fun isInProjectSource(element: PsiElement, includeScriptsOutsideSourceRoots: Boolean = false): Boolean =
|
||||
getInstance(element.project).isInProjectSource(element, includeScriptsOutsideSourceRoots)
|
||||
|
||||
fun KtDeclaration.isOverridable(): Boolean =
|
||||
getInstance(project).isOverridable(this)
|
||||
|
||||
fun KtClass.isInheritable(): Boolean =
|
||||
getInstance(project).isInheritable(this)
|
||||
|
||||
fun formatJavaOrLightMethod(method: PsiMethod): String =
|
||||
getInstance(method.project).formatJavaOrLightMethod(method)
|
||||
|
||||
fun formatClass(classOrObject: KtClassOrObject): String =
|
||||
getInstance(classOrObject.project).formatClass(classOrObject)
|
||||
|
||||
fun KtDeclaration.expectedDeclarationIfAny(): KtDeclaration? =
|
||||
getInstance(project).expectedDeclarationIfAny(this)
|
||||
|
||||
fun KtDeclaration.isExpectDeclaration(): Boolean =
|
||||
getInstance(project).isExpectDeclaration(this)
|
||||
}
|
||||
|
||||
fun dataClassComponentMethodName(element: KtParameter): String?
|
||||
|
||||
fun hasType(element: KtExpression): Boolean
|
||||
|
||||
fun isSamInterface(psiClass: PsiClass): Boolean
|
||||
|
||||
fun <T : PsiNamedElement> filterDataClassComponentsIfDisabled(elements: List<T>, kotlinOptions: KotlinReferencesSearchOptions): List<T>
|
||||
|
||||
fun isCallableOverrideUsage(reference: PsiReference, declaration: KtNamedDeclaration): Boolean
|
||||
|
||||
fun isUsageInContainingDeclaration(reference: PsiReference, declaration: KtNamedDeclaration): Boolean
|
||||
|
||||
fun isExtensionOfDeclarationClassUsage(reference: PsiReference, declaration: KtNamedDeclaration): Boolean
|
||||
|
||||
fun getReceiverTypeSearcherInfo(psiElement: PsiElement, isDestructionDeclarationSearch: Boolean): ReceiverTypeSearcherInfo?
|
||||
|
||||
fun forceResolveReferences(file: KtFile, elements: List<KtElement>)
|
||||
|
||||
fun scriptDefinitionExists(file: PsiFile): Boolean
|
||||
|
||||
fun getDefaultImports(file: KtFile): List<ImportPath>
|
||||
|
||||
fun forEachKotlinOverride(
|
||||
ktClass: KtClass,
|
||||
members: List<KtNamedDeclaration>,
|
||||
scope: SearchScope,
|
||||
processor: (superMember: PsiElement, overridingMember: PsiElement) -> Boolean
|
||||
): Boolean
|
||||
|
||||
fun forEachOverridingMethod(
|
||||
method: PsiMethod,
|
||||
scope: SearchScope,
|
||||
processor: (PsiMethod) -> Boolean
|
||||
): Boolean
|
||||
|
||||
fun findDeepestSuperMethodsNoWrapping(method: PsiElement): List<PsiElement>
|
||||
|
||||
fun findTypeAliasByShortName(shortName: String, project: Project, scope: GlobalSearchScope): Collection<KtTypeAlias>
|
||||
|
||||
fun isInProjectSource(element: PsiElement, includeScriptsOutsideSourceRoots: Boolean = false): Boolean
|
||||
|
||||
fun isOverridable(declaration: KtDeclaration): Boolean
|
||||
|
||||
fun isInheritable(ktClass: KtClass): Boolean
|
||||
|
||||
fun formatJavaOrLightMethod(method: PsiMethod): String
|
||||
|
||||
fun formatClass(classOrObject: KtClassOrObject): String
|
||||
|
||||
fun expectedDeclarationIfAny(declaration: KtDeclaration): KtDeclaration?
|
||||
|
||||
fun isExpectDeclaration(declaration: KtDeclaration): Boolean
|
||||
}
|
||||
+5
-16
@@ -15,19 +15,15 @@ import com.intellij.psi.util.CachedValuesManager
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
import org.jetbrains.kotlin.asJava.ImpreciseResolveResult
|
||||
import org.jetbrains.kotlin.asJava.ImpreciseResolveResult.*
|
||||
import org.jetbrains.kotlin.idea.caches.project.getNullableModuleInfo
|
||||
import org.jetbrains.kotlin.idea.caches.trackers.KotlinCodeBlockModificationListener
|
||||
import org.jetbrains.kotlin.idea.compiler.IDELanguageSettingsProvider
|
||||
import org.jetbrains.kotlin.idea.project.TargetPlatformDetector
|
||||
import org.jetbrains.kotlin.idea.project.findAnalyzerServices
|
||||
import org.jetbrains.kotlin.idea.stubindex.KotlinTypeAliasShortNameIndex
|
||||
import org.jetbrains.kotlin.idea.search.KotlinSearchUsagesSupport.Companion.findTypeAliasByShortName
|
||||
import org.jetbrains.kotlin.idea.search.KotlinSearchUsagesSupport.Companion.getDefaultImports
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypeAndBranch
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||
import org.jetbrains.kotlin.resolve.ImportPath
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
/**
|
||||
@@ -35,6 +31,7 @@ import java.util.concurrent.atomic.AtomicInteger
|
||||
* with the given qualified name.
|
||||
*/
|
||||
class PsiBasedClassResolver @TestOnly constructor(private val targetClassFqName: String) {
|
||||
|
||||
private val targetShortName = targetClassFqName.substringAfterLast('.')
|
||||
private val targetPackage = targetClassFqName.substringBeforeLast('.', "")
|
||||
|
||||
@@ -125,7 +122,7 @@ class PsiBasedClassResolver @TestOnly constructor(private val targetClassFqName:
|
||||
}
|
||||
|
||||
private fun findPotentialTypeAliasConflicts(target: PsiClass) {
|
||||
val candidates = KotlinTypeAliasShortNameIndex.getInstance().get(targetShortName, target.project, target.project.allScope())
|
||||
val candidates = findTypeAliasByShortName(targetShortName, target.project, target.project.allScope())
|
||||
for (candidate in candidates) {
|
||||
packagesWithTypeAliases.add(candidate.containingKtFile.packageFqName.asString())
|
||||
}
|
||||
@@ -244,12 +241,4 @@ class PsiBasedClassResolver @TestOnly constructor(private val targetClassFqName:
|
||||
}
|
||||
return Result.Ambiguity
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtFile.getDefaultImports(): List<ImportPath> {
|
||||
val moduleInfo = getNullableModuleInfo() ?: return emptyList()
|
||||
return TargetPlatformDetector.getPlatform(this).findAnalyzerServices(project).getDefaultImports(
|
||||
IDELanguageSettingsProvider.getLanguageVersionSettings(moduleInfo, project),
|
||||
includeLowPriorityImports = true
|
||||
)
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -22,14 +22,14 @@ import com.intellij.psi.PsiModifier
|
||||
import com.intellij.psi.search.searches.ClassInheritorsSearch
|
||||
import com.intellij.util.EmptyQuery
|
||||
import com.intellij.util.Query
|
||||
import org.jetbrains.kotlin.asJava.toLightClassWithBuiltinMapping
|
||||
import org.jetbrains.kotlin.idea.caches.lightClasses.KtFakeLightClass
|
||||
import org.jetbrains.kotlin.idea.asJava.LightClassProvider.Companion.providedCreateKtFakeLightClass
|
||||
import org.jetbrains.kotlin.idea.asJava.LightClassProvider.Companion.providedToLightClassWithBuiltinMapping
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
|
||||
fun HierarchySearchRequest<*>.searchInheritors(): Query<PsiClass> {
|
||||
val psiClass: PsiClass = when (originalElement) {
|
||||
is KtClassOrObject -> runReadAction { originalElement.toLightClassWithBuiltinMapping() ?: KtFakeLightClass(originalElement) }
|
||||
is KtClassOrObject -> runReadAction { originalElement.providedToLightClassWithBuiltinMapping() ?: providedCreateKtFakeLightClass(originalElement) }
|
||||
is PsiClass -> originalElement
|
||||
else -> null
|
||||
} ?: return EmptyQuery.getEmptyQuery()
|
||||
+15
-86
@@ -18,27 +18,20 @@ import com.intellij.util.EmptyQuery
|
||||
import com.intellij.util.MergeQuery
|
||||
import com.intellij.util.Processor
|
||||
import com.intellij.util.Query
|
||||
import org.jetbrains.kotlin.asJava.getRepresentativeLightMethod
|
||||
import org.jetbrains.kotlin.asJava.toLightMethods
|
||||
import org.jetbrains.kotlin.asJava.unwrapped
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.isOverridable
|
||||
import org.jetbrains.kotlin.idea.caches.lightClasses.KtFakeLightClass
|
||||
import org.jetbrains.kotlin.idea.caches.lightClasses.KtFakeLightMethod
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor
|
||||
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
||||
import org.jetbrains.kotlin.idea.core.getDeepestSuperDeclarations
|
||||
import org.jetbrains.kotlin.idea.core.isOverridable
|
||||
import org.jetbrains.kotlin.asJava.*
|
||||
import org.jetbrains.kotlin.idea.asJava.LightClassProvider.Companion.providedCreateKtFakeLightMethod
|
||||
import org.jetbrains.kotlin.idea.asJava.LightClassProvider.Companion.providedGetRepresentativeLightMethod
|
||||
import org.jetbrains.kotlin.idea.asJava.LightClassProvider.Companion.providedIsKtFakeLightClass
|
||||
import org.jetbrains.kotlin.idea.asJava.LightClassProvider.Companion.providedToLightMethods
|
||||
import org.jetbrains.kotlin.idea.search.KotlinSearchUsagesSupport.Companion.findDeepestSuperMethodsNoWrapping
|
||||
import org.jetbrains.kotlin.idea.search.KotlinSearchUsagesSupport.Companion.forEachKotlinOverride
|
||||
import org.jetbrains.kotlin.idea.search.KotlinSearchUsagesSupport.Companion.forEachOverridingMethod
|
||||
import org.jetbrains.kotlin.idea.search.KotlinSearchUsagesSupport.Companion.isOverridable
|
||||
import org.jetbrains.kotlin.idea.search.allScope
|
||||
import org.jetbrains.kotlin.idea.search.excludeKotlinSources
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||
import org.jetbrains.kotlin.resolve.source.getPsi
|
||||
import org.jetbrains.kotlin.types.substitutions.getTypeSubstitutor
|
||||
import org.jetbrains.kotlin.util.findCallableMemberBySignature
|
||||
import java.util.*
|
||||
|
||||
fun PsiElement.isOverridableElement(): Boolean = when (this) {
|
||||
@@ -48,7 +41,7 @@ fun PsiElement.isOverridableElement(): Boolean = when (this) {
|
||||
}
|
||||
|
||||
fun HierarchySearchRequest<*>.searchOverriders(): Query<PsiMethod> {
|
||||
val psiMethods = runReadAction { originalElement.toLightMethods() }
|
||||
val psiMethods = runReadAction { originalElement.providedToLightMethods() }
|
||||
if (psiMethods.isEmpty()) return EmptyQuery.getEmptyQuery()
|
||||
|
||||
return psiMethods
|
||||
@@ -111,44 +104,10 @@ fun PsiElement.toPossiblyFakeLightMethods(): List<PsiMethod> {
|
||||
|
||||
val element = unwrapped ?: return emptyList()
|
||||
|
||||
val lightMethods = element.toLightMethods()
|
||||
val lightMethods = element.providedToLightMethods()
|
||||
if (lightMethods.isNotEmpty()) return lightMethods
|
||||
|
||||
return if (element is KtNamedDeclaration) listOfNotNull(KtFakeLightMethod.get(element)) else emptyList()
|
||||
}
|
||||
|
||||
private fun forEachKotlinOverride(
|
||||
ktClass: KtClass,
|
||||
members: List<KtNamedDeclaration>,
|
||||
scope: SearchScope,
|
||||
processor: (superMember: PsiElement, overridingMember: PsiElement) -> Boolean
|
||||
): Boolean {
|
||||
val baseClassDescriptor = runReadAction { ktClass.unsafeResolveToDescriptor() as ClassDescriptor }
|
||||
val baseDescriptors =
|
||||
runReadAction { members.mapNotNull { it.unsafeResolveToDescriptor() as? CallableMemberDescriptor }.filter { it.isOverridable } }
|
||||
if (baseDescriptors.isEmpty()) return true
|
||||
|
||||
HierarchySearchRequest(ktClass, scope, true).searchInheritors().forEach(Processor { psiClass ->
|
||||
val inheritor = psiClass.unwrapped as? KtClassOrObject ?: return@Processor true
|
||||
runReadAction {
|
||||
val inheritorDescriptor = inheritor.unsafeResolveToDescriptor() as ClassDescriptor
|
||||
val substitutor =
|
||||
getTypeSubstitutor(baseClassDescriptor.defaultType, inheritorDescriptor.defaultType) ?: return@runReadAction true
|
||||
baseDescriptors.forEach {
|
||||
val superMember = it.source.getPsi()!!
|
||||
val overridingDescriptor = (it.substitute(substitutor) as? CallableMemberDescriptor)?.let { memberDescriptor ->
|
||||
inheritorDescriptor.findCallableMemberBySignature(memberDescriptor)
|
||||
}
|
||||
val overridingMember = overridingDescriptor?.source?.getPsi()
|
||||
if (overridingMember != null) {
|
||||
if (!processor(superMember, overridingMember)) return@runReadAction false
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
})
|
||||
|
||||
return true
|
||||
return if (element is KtNamedDeclaration) listOfNotNull(providedCreateKtFakeLightMethod(element)) else emptyList()
|
||||
}
|
||||
|
||||
fun KtNamedDeclaration.forEachOverridingElement(
|
||||
@@ -157,29 +116,13 @@ fun KtNamedDeclaration.forEachOverridingElement(
|
||||
): Boolean {
|
||||
val ktClass = runReadAction { containingClassOrObject as? KtClass } ?: return true
|
||||
|
||||
toLightMethods().forEach { baseMethod ->
|
||||
providedToLightMethods().forEach { baseMethod ->
|
||||
if (!OverridingMethodsSearch.search(baseMethod, scope.excludeKotlinSources(), true).all { processor(baseMethod, it) }) return false
|
||||
}
|
||||
|
||||
return forEachKotlinOverride(ktClass, listOf(this), scope) { baseElement, overrider -> processor(baseElement, overrider) }
|
||||
}
|
||||
|
||||
fun PsiMethod.forEachOverridingMethod(
|
||||
scope: SearchScope = runReadAction { useScope },
|
||||
processor: (PsiMethod) -> Boolean
|
||||
): Boolean {
|
||||
if (this !is KtFakeLightMethod) {
|
||||
if (!OverridingMethodsSearch.search(this, scope.excludeKotlinSources(), true).forEach(processor)) return false
|
||||
}
|
||||
|
||||
val ktMember = this.unwrapped as? KtNamedDeclaration ?: return true
|
||||
val ktClass = runReadAction { ktMember.containingClassOrObject as? KtClass } ?: return true
|
||||
return forEachKotlinOverride(ktClass, listOf(ktMember), scope) { _, overrider ->
|
||||
val lightMethods = runReadAction { overrider.toPossiblyFakeLightMethods().distinctBy { it.unwrapped } }
|
||||
lightMethods.all { processor(it) }
|
||||
}
|
||||
}
|
||||
|
||||
fun PsiMethod.forEachImplementation(
|
||||
scope: SearchScope = runReadAction { useScope },
|
||||
processor: (PsiElement) -> Boolean
|
||||
@@ -191,7 +134,7 @@ fun PsiMethod.forEachImplementation(
|
||||
fun PsiClass.forEachDeclaredMemberOverride(processor: (superMember: PsiElement, overridingMember: PsiElement) -> Boolean) {
|
||||
val scope = runReadAction { useScope }
|
||||
|
||||
if (this !is KtFakeLightClass) {
|
||||
if (!providedIsKtFakeLightClass()) {
|
||||
AllOverridingMethodsSearch.search(this, scope.excludeKotlinSources()).all { processor(it.first, it.second) }
|
||||
}
|
||||
|
||||
@@ -201,19 +144,5 @@ fun PsiClass.forEachDeclaredMemberOverride(processor: (superMember: PsiElement,
|
||||
forEachKotlinOverride(ktClass, members, scope, processor)
|
||||
}
|
||||
|
||||
fun findDeepestSuperMethodsNoWrapping(method: PsiElement): List<PsiElement> {
|
||||
val element = method.unwrapped
|
||||
return when (element) {
|
||||
is PsiMethod -> element.findDeepestSuperMethods().toList()
|
||||
is KtCallableDeclaration -> {
|
||||
val descriptor = element.resolveToDescriptorIfAny() as? CallableMemberDescriptor ?: return emptyList()
|
||||
descriptor.getDeepestSuperDeclarations(false).mapNotNull {
|
||||
it.source.getPsi() ?: DescriptorToSourceUtilsIde.getAnyDeclaration(element.project, it)
|
||||
}
|
||||
}
|
||||
else -> emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
fun findDeepestSuperMethodsKotlinAware(method: PsiElement) =
|
||||
findDeepestSuperMethodsNoWrapping(method).mapNotNull { it.getRepresentativeLightMethod() }
|
||||
findDeepestSuperMethodsNoWrapping(method).mapNotNull { it.providedGetRepresentativeLightMethod() }
|
||||
+58
-45
@@ -25,33 +25,31 @@ import com.intellij.psi.search.searches.MethodReferencesSearch
|
||||
import com.intellij.psi.search.searches.ReferencesSearch
|
||||
import com.intellij.util.Processor
|
||||
import com.intellij.util.containers.nullize
|
||||
import org.jetbrains.kotlin.asJava.LightClassUtil
|
||||
import org.jetbrains.kotlin.idea.asJava.LightClassProvider.Companion.providedGetLightClassMethods
|
||||
import org.jetbrains.kotlin.idea.asJava.LightClassProvider.Companion.providedGetLightClassParameterDeclarations
|
||||
import org.jetbrains.kotlin.idea.asJava.LightClassProvider.Companion.providedGetLightClassPropertyDeclarations
|
||||
import org.jetbrains.kotlin.idea.asJava.LightClassProvider.Companion.providedGetLightFieldForCompanionObject
|
||||
import org.jetbrains.kotlin.idea.asJava.LightClassProvider.Companion.providedToLightClass
|
||||
import org.jetbrains.kotlin.idea.asJava.LightClassProvider.Companion.providedToLightElements
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightField
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightMember
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightParameter
|
||||
import org.jetbrains.kotlin.asJava.namedUnwrappedElement
|
||||
import org.jetbrains.kotlin.asJava.toLightClass
|
||||
import org.jetbrains.kotlin.asJava.toLightElements
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.idea.findUsages.KotlinFindUsagesSupport.Companion.sourcesAndLibraries
|
||||
import org.jetbrains.kotlin.idea.search.KotlinSearchUsagesSupport.Companion.dataClassComponentMethodName
|
||||
import org.jetbrains.kotlin.idea.search.KotlinSearchUsagesSupport.Companion.expectedDeclarationIfAny
|
||||
import org.jetbrains.kotlin.idea.search.KotlinSearchUsagesSupport.Companion.filterDataClassComponentsIfDisabled
|
||||
import org.jetbrains.kotlin.idea.search.KotlinSearchUsagesSupport.Companion.isExpectDeclaration
|
||||
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.idea.search.*
|
||||
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchOptions.Companion.Empty
|
||||
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchOptions.Companion.calculateEffectiveScope
|
||||
import org.jetbrains.kotlin.idea.search.usagesSearch.dataClassComponentFunction
|
||||
import org.jetbrains.kotlin.idea.search.usagesSearch.filterDataClassComponentsIfDisabled
|
||||
import org.jetbrains.kotlin.idea.search.usagesSearch.getClassNameForCompanionObject
|
||||
import org.jetbrains.kotlin.idea.search.usagesSearch.operators.OperatorReferenceSearcher
|
||||
import org.jetbrains.kotlin.idea.stubindex.KotlinSourceFilterScope
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.idea.util.expectedDeclarationIfAny
|
||||
import org.jetbrains.kotlin.idea.util.isExpectDeclaration
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElementSelector
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.hasActualModifier
|
||||
import org.jetbrains.kotlin.psi.psiUtil.parents
|
||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||
import java.util.*
|
||||
|
||||
data class KotlinReferencesSearchOptions(
|
||||
@@ -76,7 +74,7 @@ data class KotlinReferencesSearchOptions(
|
||||
): SearchScope {
|
||||
val kotlinOptions = (parameters as? KotlinAwareReferencesSearchParameters)?.kotlinOptions ?: Empty
|
||||
val elements = if (elementToSearch is KtDeclaration && !isOnlyKotlinSearch(parameters.scopeDeterminedByUser)) {
|
||||
elementToSearch.toLightElements().filterDataClassComponentsIfDisabled(kotlinOptions).nullize()
|
||||
elementToSearch.providedToLightElements().filterDataClassComponentsIfDisabled(kotlinOptions).nullize()
|
||||
} else {
|
||||
null
|
||||
} ?: listOf(elementToSearch)
|
||||
@@ -194,7 +192,6 @@ class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, ReferencesSearc
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
val classNameForCompanionObject = elementToSearch.getClassNameForCompanionObject()
|
||||
if (classNameForCompanionObject != null) {
|
||||
queryParameters.optimizer.searchWord(
|
||||
@@ -220,25 +217,14 @@ class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, ReferencesSearc
|
||||
}
|
||||
|
||||
if (kotlinOptions.searchForComponentConventions) {
|
||||
when (element) {
|
||||
is KtParameter -> {
|
||||
val componentFunctionDescriptor = element.dataClassComponentFunction()
|
||||
if (componentFunctionDescriptor != null) {
|
||||
val containingClass = element.getStrictParentOfType<KtClassOrObject>()?.toLightClass()
|
||||
searchDataClassComponentUsages(containingClass, componentFunctionDescriptor, kotlinOptions)
|
||||
}
|
||||
}
|
||||
|
||||
is KtLightParameter -> {
|
||||
val componentFunctionDescriptor = element.kotlinOrigin?.dataClassComponentFunction()
|
||||
if (componentFunctionDescriptor != null) {
|
||||
searchDataClassComponentUsages(element.method.containingClass, componentFunctionDescriptor, kotlinOptions)
|
||||
}
|
||||
}
|
||||
}
|
||||
searchForComponentConventions(element)
|
||||
}
|
||||
}
|
||||
|
||||
private fun PsiNamedElement.getClassNameForCompanionObject(): String? =
|
||||
(this is KtObjectDeclaration && this.isCompanion())
|
||||
.ifTrue { getNonStrictParentOfType<KtClass>()?.name }
|
||||
|
||||
private fun searchNamedArguments(parameter: KtParameter) {
|
||||
val parameterName = parameter.name ?: return
|
||||
val function = parameter.ownerFunction as? KtFunction ?: return
|
||||
@@ -247,7 +233,7 @@ class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, ReferencesSearc
|
||||
var namedArgsScope = function.useScope.intersectWith(queryParameters.scopeDeterminedByUser)
|
||||
|
||||
if (namedArgsScope is GlobalSearchScope) {
|
||||
namedArgsScope = KotlinSourceFilterScope.sourcesAndLibraries(namedArgsScope, project)
|
||||
namedArgsScope = sourcesAndLibraries(namedArgsScope, project)
|
||||
|
||||
val filesWithFunctionName = CacheManager.SERVICE.getInstance(project).getVirtualFilesWithWord(
|
||||
function.name!!, UsageSearchContext.IN_CODE, namedArgsScope, true
|
||||
@@ -275,7 +261,7 @@ class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, ReferencesSearc
|
||||
is KtNamedFunction, is KtSecondaryConstructor -> {
|
||||
val name = (element as KtFunction).name
|
||||
if (name != null) {
|
||||
val methods = LightClassUtil.getLightClassMethods(element)
|
||||
val methods = providedGetLightClassMethods(element)
|
||||
for (method in methods) {
|
||||
searchNamedElement(method)
|
||||
}
|
||||
@@ -285,8 +271,8 @@ class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, ReferencesSearc
|
||||
}
|
||||
|
||||
is KtProperty -> {
|
||||
val propertyMethods = LightClassUtil.getLightClassPropertyMethods(element)
|
||||
propertyMethods.allDeclarations.forEach { searchNamedElement(it) }
|
||||
val propertyDeclarations = providedGetLightClassPropertyDeclarations(element)
|
||||
propertyDeclarations.forEach { searchNamedElement(it) }
|
||||
processStaticsFromCompanionObject(element)
|
||||
}
|
||||
|
||||
@@ -294,8 +280,8 @@ class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, ReferencesSearc
|
||||
searchPropertyAccessorMethods(element)
|
||||
if (element.getStrictParentOfType<KtPrimaryConstructor>() != null) {
|
||||
// Simple parameters without val and var shouldn't be processed here because of local search scope
|
||||
val methods = LightClassUtil.getLightClassPropertyMethods(element)
|
||||
methods.allDeclarations.filterDataClassComponentsIfDisabled(kotlinOptions).forEach { searchNamedElement(it) }
|
||||
val parameterDeclarations = providedGetLightClassParameterDeclarations(element)
|
||||
parameterDeclarations.filterDataClassComponentsIfDisabled(kotlinOptions).forEach { searchNamedElement(it) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -323,19 +309,19 @@ class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, ReferencesSearc
|
||||
}
|
||||
|
||||
private fun searchPropertyAccessorMethods(origin: KtParameter) {
|
||||
origin.toLightElements().filterDataClassComponentsIfDisabled(kotlinOptions).forEach { searchNamedElement(it) }
|
||||
origin.providedToLightElements().filterDataClassComponentsIfDisabled(kotlinOptions).forEach { searchNamedElement(it) }
|
||||
}
|
||||
|
||||
private fun processKtClassOrObject(element: KtClassOrObject) {
|
||||
val className = element.name ?: return
|
||||
val lightClass = element.toLightClass() ?: return
|
||||
val lightClass = element.providedToLightClass() ?: return
|
||||
searchNamedElement(lightClass, className)
|
||||
|
||||
if (element is KtObjectDeclaration && element.isCompanion()) {
|
||||
LightClassUtil.getLightFieldForCompanionObject(element)?.let { searchNamedElement(it) }
|
||||
providedGetLightFieldForCompanionObject(element)?.let { searchNamedElement(it) }
|
||||
|
||||
if (kotlinOptions.acceptCompanionObjectMembers) {
|
||||
val originLightClass = element.getStrictParentOfType<KtClass>()?.toLightClass()
|
||||
val originLightClass = element.getStrictParentOfType<KtClass>()?.providedToLightClass()
|
||||
if (originLightClass != null) {
|
||||
val lightDeclarations: List<KtLightMember<*>?> =
|
||||
originLightClass.methods.map { it as? KtLightMethod } + originLightClass.fields.map { it as? KtLightField }
|
||||
@@ -350,13 +336,40 @@ class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, ReferencesSearc
|
||||
}
|
||||
}
|
||||
|
||||
private fun searchForComponentConventions(element: PsiElement) {
|
||||
when (element) {
|
||||
is KtParameter -> {
|
||||
val componentMethodName = element.dataClassComponentMethodName
|
||||
if (componentMethodName != null) {
|
||||
val containingClass = element.getStrictParentOfType<KtClassOrObject>()?.providedToLightClass()
|
||||
searchDataClassComponentUsages(
|
||||
containingClass = containingClass,
|
||||
componentMethodName = componentMethodName,
|
||||
kotlinOptions = kotlinOptions
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
is KtLightParameter -> {
|
||||
val componentMethodName = element.kotlinOrigin?.dataClassComponentMethodName
|
||||
if (componentMethodName != null) {
|
||||
searchDataClassComponentUsages(
|
||||
containingClass = element.method.containingClass,
|
||||
componentMethodName = componentMethodName,
|
||||
kotlinOptions = kotlinOptions
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun searchDataClassComponentUsages(
|
||||
containingClass: PsiClass?,
|
||||
componentFunctionDescriptor: FunctionDescriptor,
|
||||
componentMethodName: String,
|
||||
kotlinOptions: KotlinReferencesSearchOptions
|
||||
) {
|
||||
val componentFunction = containingClass?.methods?.firstOrNull {
|
||||
it.name == componentFunctionDescriptor.name.asString() && it.parameterList.parametersCount == 0
|
||||
it.name == componentMethodName && it.parameterList.parametersCount == 0
|
||||
}
|
||||
if (componentFunction != null) {
|
||||
searchNamedElement(componentFunction)
|
||||
@@ -378,7 +391,7 @@ class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, ReferencesSearc
|
||||
.firstOrNull() as? KtObjectDeclaration ?: return emptyList()
|
||||
if (!originObject.isCompanion()) return emptyList()
|
||||
val originClass = originObject.getStrictParentOfType<KtClass>()
|
||||
val originLightClass = originClass?.toLightClass() ?: return emptyList()
|
||||
val originLightClass = originClass?.providedToLightClass() ?: return emptyList()
|
||||
val allMethods = originLightClass.allMethods
|
||||
return allMethods.filter { it is KtLightMethod && it.kotlinOrigin == declaration }
|
||||
}
|
||||
+3
-3
@@ -23,10 +23,10 @@ import com.intellij.psi.PsiReferenceService
|
||||
import com.intellij.psi.ReferenceRange
|
||||
import com.intellij.psi.search.RequestResultProcessor
|
||||
import com.intellij.util.Processor
|
||||
import org.jetbrains.kotlin.idea.search.KotlinSearchUsagesSupport.Companion.isCallableOverrideUsage
|
||||
import org.jetbrains.kotlin.idea.search.KotlinSearchUsagesSupport.Companion.isExtensionOfDeclarationClassUsage
|
||||
import org.jetbrains.kotlin.idea.search.KotlinSearchUsagesSupport.Companion.isUsageInContainingDeclaration
|
||||
import org.jetbrains.kotlin.idea.references.KtDestructuringDeclarationReference
|
||||
import org.jetbrains.kotlin.idea.search.usagesSearch.isCallableOverrideUsage
|
||||
import org.jetbrains.kotlin.idea.search.usagesSearch.isExtensionOfDeclarationClassUsage
|
||||
import org.jetbrains.kotlin.idea.search.usagesSearch.isUsageInContainingDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtDestructuringDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
||||
|
||||
+30
-5
@@ -21,9 +21,7 @@ import com.intellij.openapi.fileTypes.FileTypeRegistry
|
||||
import com.intellij.openapi.progress.ProgressIndicator
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.PsiManager
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.impl.cache.impl.id.IdIndex
|
||||
import com.intellij.psi.impl.cache.impl.id.IdIndexEntry
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
@@ -33,12 +31,17 @@ import com.intellij.psi.search.SearchScope
|
||||
import com.intellij.psi.search.searches.ReferencesSearch
|
||||
import com.intellij.util.CommonProcessors
|
||||
import com.intellij.util.indexing.FileBasedIndex
|
||||
import org.jetbrains.kotlin.asJava.namedUnwrappedElement
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.idea.search.KotlinSearchUsagesSupport.Companion.scriptDefinitionExists
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtImportDirective
|
||||
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
||||
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
||||
import java.util.*
|
||||
|
||||
@@ -141,6 +144,28 @@ fun findScriptsWithUsages(declaration: KtNamedDeclaration): List<KtFile> {
|
||||
}
|
||||
return collector.results
|
||||
.mapNotNull { PsiManager.getInstance(project).findFile(it) as? KtFile }
|
||||
.filter { it.findScriptDefinition() != null }
|
||||
.filter { it.scriptDefinitionExists() }
|
||||
.toList()
|
||||
}
|
||||
|
||||
inline fun <T> Boolean.ifTrue(body: () -> T?): T? = if (this) body() else null
|
||||
|
||||
data class ReceiverTypeSearcherInfo(
|
||||
val psiClass: PsiClass?,
|
||||
val containsTypeOrDerivedInside: ((KtDeclaration) -> Boolean)
|
||||
)
|
||||
|
||||
fun PsiReference.isImportUsage(): Boolean =
|
||||
element.getNonStrictParentOfType<KtImportDirective>() != null
|
||||
|
||||
//TODO: Copied from fqNameUtil.kt
|
||||
fun PsiElement.getKotlinFqName(): FqName? = when (val element = namedUnwrappedElement) {
|
||||
is PsiPackage -> FqName(element.qualifiedName)
|
||||
is PsiClass -> element.qualifiedName?.let(::FqName)
|
||||
is PsiMember -> element.getName()?.let { name ->
|
||||
val prefix = element.containingClass?.qualifiedName
|
||||
FqName(if (prefix != null) "$prefix.$name" else name)
|
||||
}
|
||||
is KtNamedDeclaration -> element.fqName
|
||||
else -> null
|
||||
}
|
||||
+13
-28
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.idea.search.usagesSearch
|
||||
|
||||
import com.intellij.ide.highlighter.JavaFileType
|
||||
import com.intellij.ide.highlighter.XmlFileType
|
||||
import com.intellij.ide.projectView.impl.ProjectRootsUtil
|
||||
import com.intellij.lang.java.JavaLanguage
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
@@ -22,37 +23,30 @@ import com.intellij.psi.search.searches.ReferencesSearch
|
||||
import com.intellij.util.Processor
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
import org.jetbrains.kotlin.KtNodeTypes
|
||||
import org.jetbrains.kotlin.idea.asJava.LightClassProvider.Companion.providedToLightClass
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
||||
import org.jetbrains.kotlin.asJava.toLightClass
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.PsiDiagnosticUtils
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.util.getJavaMemberDescriptor
|
||||
import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName
|
||||
import org.jetbrains.kotlin.idea.search.KotlinSearchUsagesSupport.Companion.hasType
|
||||
import org.jetbrains.kotlin.idea.search.KotlinSearchUsagesSupport.Companion.isInProjectSource
|
||||
import org.jetbrains.kotlin.idea.search.KotlinSearchUsagesSupport.Companion.isSamInterface
|
||||
import org.jetbrains.kotlin.idea.references.KtDestructuringDeclarationReference
|
||||
import org.jetbrains.kotlin.idea.search.excludeFileTypes
|
||||
import org.jetbrains.kotlin.idea.search.getKotlinFqName
|
||||
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchOptions
|
||||
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchParameters
|
||||
import org.jetbrains.kotlin.idea.search.restrictToKotlinSources
|
||||
import org.jetbrains.kotlin.idea.util.FuzzyType
|
||||
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.kdoc.psi.impl.KDocName
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.resolve.sam.getSingleAbstractMethodOrNull
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import java.util.*
|
||||
|
||||
//TODO: check if smart search is too expensive
|
||||
|
||||
class ExpressionsOfTypeProcessor(
|
||||
private val typeToSearch: FuzzyType,
|
||||
private val containsTypeOrDerivedInside: (KtDeclaration) -> Boolean,
|
||||
private val classToSearch: PsiClass?,
|
||||
private val searchScope: SearchScope,
|
||||
private val project: Project,
|
||||
@@ -132,7 +126,7 @@ class ExpressionsOfTypeProcessor(
|
||||
}) return
|
||||
|
||||
// for class from library always use plain search because we cannot search usages in compiled code (we could though)
|
||||
if (!runReadAction { classToSearch.isValid && ProjectRootsUtil.isInProjectSource(classToSearch) }) {
|
||||
if (!runReadAction { classToSearch.isValid && isInProjectSource(classToSearch) }) {
|
||||
possibleMatchesInScopeHandler(searchScope)
|
||||
return
|
||||
}
|
||||
@@ -535,9 +529,7 @@ class ExpressionsOfTypeProcessor(
|
||||
|
||||
if (element.getStrictParentOfType<KtImportDirective>() != null) return true // ignore usage in import
|
||||
|
||||
val bindingContext = element.analyze(BodyResolveMode.PARTIAL)
|
||||
val hasType = bindingContext.getType(element) != null
|
||||
if (hasType) { // access to object or companion object
|
||||
if (element.hasType) { // access to object or companion object
|
||||
processSuspiciousExpression(element)
|
||||
return true
|
||||
}
|
||||
@@ -590,7 +582,7 @@ class ExpressionsOfTypeProcessor(
|
||||
val parent = typeRefParent.parent
|
||||
if (parent is KtSuperTypeCallEntry) {
|
||||
val classOrObject = (parent.parent as KtSuperTypeList).parent as KtClassOrObject
|
||||
val psiClass = classOrObject.toLightClass()
|
||||
val psiClass = classOrObject.providedToLightClass()
|
||||
psiClass?.let { addClassToProcess(it) }
|
||||
return true
|
||||
}
|
||||
@@ -599,7 +591,7 @@ class ExpressionsOfTypeProcessor(
|
||||
is KtSuperTypeListEntry -> { // super-interface name in the list of bases
|
||||
if (typeRef == typeRefParent.typeReference) {
|
||||
val classOrObject = (typeRefParent.parent as KtSuperTypeList).parent as KtClassOrObject
|
||||
val psiClass = classOrObject.toLightClass()
|
||||
val psiClass = classOrObject.providedToLightClass()
|
||||
psiClass?.let { addClassToProcess(it) }
|
||||
return true
|
||||
}
|
||||
@@ -762,8 +754,7 @@ class ExpressionsOfTypeProcessor(
|
||||
if (psiClass != null) {
|
||||
testLog { "Resolved java class to descriptor: ${psiClass.qualifiedName}" }
|
||||
|
||||
val classDescriptor = psiClass.getJavaMemberDescriptor() as? JavaClassDescriptor
|
||||
if (classDescriptor != null && getSingleAbstractMethodOrNull(classDescriptor) != null) {
|
||||
if (psiClass.isSamInterface) {
|
||||
addSamInterfaceToProcess(psiClass)
|
||||
return true
|
||||
}
|
||||
@@ -838,9 +829,7 @@ class ExpressionsOfTypeProcessor(
|
||||
|
||||
testLog { "Checked type of ${logPresentation(declaration)}" }
|
||||
|
||||
val descriptor = declaration.resolveToDescriptorIfAny() as? CallableDescriptor ?: return
|
||||
val type = descriptor.returnType
|
||||
if (type != null && type.containsTypeOrDerivedInside(typeToSearch)) {
|
||||
if (containsTypeOrDerivedInside(declaration)) {
|
||||
addCallableDeclarationOfOurType(declaration)
|
||||
}
|
||||
}
|
||||
@@ -907,10 +896,6 @@ class ExpressionsOfTypeProcessor(
|
||||
return true // we don't know
|
||||
}
|
||||
|
||||
private fun KotlinType.containsTypeOrDerivedInside(type: FuzzyType): Boolean {
|
||||
return type.checkIsSuperTypeOf(this) != null || arguments.any { !it.isStarProjection && it.type.containsTypeOrDerivedInside(type) }
|
||||
}
|
||||
|
||||
private fun isImplicitlyTyped(declaration: KtDeclaration): Boolean {
|
||||
return when (declaration) {
|
||||
is KtFunction -> !declaration.hasDeclaredReturnType()
|
||||
-11
@@ -22,10 +22,8 @@ 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.idea.search.ideaExtensions.KotlinReferencesSearchOptions
|
||||
import org.jetbrains.kotlin.idea.search.usagesSearch.dataClassComponentFunction
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
|
||||
|
||||
@@ -44,15 +42,6 @@ class DestructuringDeclarationReferenceSearcher(
|
||||
options,
|
||||
wordsToSearch = listOf("(")
|
||||
) {
|
||||
|
||||
override fun resolveTargetToDescriptor(): FunctionDescriptor? {
|
||||
return if (targetDeclaration is KtParameter) {
|
||||
targetDeclaration.dataClassComponentFunction()
|
||||
} else {
|
||||
super.resolveTargetToDescriptor()
|
||||
}
|
||||
}
|
||||
|
||||
override fun extractReference(element: KtElement): PsiReference? {
|
||||
val destructuringDeclaration = element as? KtDestructuringDeclaration ?: return null
|
||||
val entries = destructuringDeclaration.entries
|
||||
+12
-54
@@ -5,7 +5,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.search.usagesSearch.operators
|
||||
|
||||
import com.intellij.lang.java.JavaLanguage
|
||||
import com.intellij.openapi.progress.ProgressIndicatorProvider
|
||||
import com.intellij.openapi.progress.util.ProgressWrapper
|
||||
import com.intellij.psi.*
|
||||
@@ -13,36 +12,25 @@ 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.asJava.toLightClass
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.idea.KotlinIdeaAnalysisBundle
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.util.getJavaOrKotlinMemberDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.util.hasJavaResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
||||
import org.jetbrains.kotlin.idea.KotlinIdeaAnalysisBundleIndependent
|
||||
import org.jetbrains.kotlin.idea.search.KotlinSearchUsagesSupport.Companion.forceResolveReferences
|
||||
import org.jetbrains.kotlin.idea.search.KotlinSearchUsagesSupport.Companion.getReceiverTypeSearcherInfo
|
||||
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchOptions
|
||||
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinRequestResultProcessor
|
||||
import org.jetbrains.kotlin.idea.search.ifTrue
|
||||
import org.jetbrains.kotlin.idea.search.restrictToKotlinSources
|
||||
import org.jetbrains.kotlin.idea.search.usagesSearch.ExpressionsOfTypeProcessor
|
||||
import org.jetbrains.kotlin.idea.search.usagesSearch.ExpressionsOfTypeProcessor.Companion.logPresentation
|
||||
import org.jetbrains.kotlin.idea.search.usagesSearch.ExpressionsOfTypeProcessor.Companion.testLog
|
||||
import org.jetbrains.kotlin.idea.util.FuzzyType
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.idea.util.fuzzyExtensionReceiverType
|
||||
import org.jetbrains.kotlin.idea.util.toFuzzyType
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType
|
||||
import org.jetbrains.kotlin.resolve.DataClassDescriptorResolver
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.kotlin.util.isValidOperator
|
||||
import java.util.*
|
||||
|
||||
abstract class OperatorReferenceSearcher<TReferenceElement : KtElement>(
|
||||
@@ -89,10 +77,9 @@ abstract class OperatorReferenceSearcher<TReferenceElement : KtElement>(
|
||||
options: KotlinReferencesSearchOptions
|
||||
): OperatorReferenceSearcher<*>? {
|
||||
return runReadAction {
|
||||
if (declaration.isValid)
|
||||
declaration.isValid.ifTrue {
|
||||
createInReadAction(declaration, searchScope, consumer, optimizer, options)
|
||||
else
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,18 +190,10 @@ abstract class OperatorReferenceSearcher<TReferenceElement : KtElement>(
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun resolveTargetToDescriptor(): FunctionDescriptor? {
|
||||
return when {
|
||||
targetDeclaration is KtDeclaration -> targetDeclaration.resolveToDescriptorIfAny(BodyResolveMode.FULL)
|
||||
targetDeclaration is PsiMember && targetDeclaration.hasJavaResolutionFacade() ->
|
||||
targetDeclaration.getJavaOrKotlinMemberDescriptor()
|
||||
else -> null
|
||||
} as? FunctionDescriptor
|
||||
}
|
||||
|
||||
fun run() {
|
||||
val receiverType = runReadAction { extractReceiverType() } ?: return
|
||||
val psiClass = runReadAction { receiverType.toPsiClass() }
|
||||
|
||||
val (psiClass, containsTypeOrDerivedInside) =
|
||||
targetDeclaration.getReceiverTypeSearcherInfo(this is DestructuringDeclarationReferenceSearcher) ?: return
|
||||
|
||||
val inProgress = SearchesInProgress.get()
|
||||
if (psiClass != null) {
|
||||
@@ -235,7 +214,7 @@ abstract class OperatorReferenceSearcher<TReferenceElement : KtElement>(
|
||||
|
||||
try {
|
||||
ExpressionsOfTypeProcessor(
|
||||
receiverType,
|
||||
containsTypeOrDerivedInside,
|
||||
psiClass,
|
||||
searchScope,
|
||||
project,
|
||||
@@ -247,27 +226,6 @@ abstract class OperatorReferenceSearcher<TReferenceElement : KtElement>(
|
||||
}
|
||||
}
|
||||
|
||||
private fun FuzzyType.toPsiClass(): PsiClass? {
|
||||
val classDescriptor = type.constructor.declarationDescriptor ?: return null
|
||||
val classDeclaration = DescriptorToSourceUtilsIde.getAnyDeclaration(project, classDescriptor)
|
||||
return when (classDeclaration) {
|
||||
is PsiClass -> classDeclaration
|
||||
is KtClassOrObject -> classDeclaration.toLightClass()
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun extractReceiverType(): FuzzyType? {
|
||||
val descriptor = resolveTargetToDescriptor()?.takeIf { it.isValidOperator() } ?: return null
|
||||
|
||||
return if (descriptor.isExtension) {
|
||||
descriptor.fuzzyExtensionReceiverType()!!
|
||||
} else {
|
||||
val classDescriptor = descriptor.containingDeclaration as? ClassDescriptor ?: return null
|
||||
classDescriptor.defaultType.toFuzzyType(classDescriptor.typeConstructor.parameters)
|
||||
}
|
||||
}
|
||||
|
||||
private fun doPlainSearch(scope: SearchScope) {
|
||||
testLog { "Used plain search of ${logPresentation(targetDeclaration)} in ${scope.logPresentation()}" }
|
||||
|
||||
@@ -284,7 +242,7 @@ abstract class OperatorReferenceSearcher<TReferenceElement : KtElement>(
|
||||
}
|
||||
|
||||
// resolve all references at once
|
||||
(element.containingFile as KtFile).getResolutionFacade().analyze(elements, BodyResolveMode.PARTIAL)
|
||||
(element.containingFile as? KtFile)?.forceResolveReferences(elements)
|
||||
|
||||
refs
|
||||
.filter { it.isReferenceTo(targetDeclaration) }
|
||||
@@ -317,7 +275,7 @@ abstract class OperatorReferenceSearcher<TReferenceElement : KtElement>(
|
||||
// we must unwrap progress indicator because ProgressWrapper does not do anything on changing text and fraction
|
||||
val progress = ProgressWrapper.unwrap(ProgressIndicatorProvider.getGlobalProgressIndicator())
|
||||
progress?.pushState()
|
||||
progress?.text = KotlinIdeaAnalysisBundle.message("searching.for.implicit.usages")
|
||||
progress?.text = KotlinIdeaAnalysisBundleIndependent.message("searching.for.implicit.usages")
|
||||
|
||||
try {
|
||||
val files = runReadAction { FileTypeIndex.getFiles(KotlinFileType.INSTANCE, scope) }
|
||||
@@ -9,6 +9,7 @@ import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.command.CommandProcessor
|
||||
import com.intellij.openapi.components.ComponentManager
|
||||
import com.intellij.openapi.progress.impl.CancellationCheck
|
||||
import com.intellij.openapi.project.DumbService
|
||||
import com.intellij.openapi.project.Project
|
||||
|
||||
fun <T> runReadAction(action: () -> T): T {
|
||||
@@ -55,3 +56,8 @@ inline fun isUnitTestMode(): Boolean = ApplicationManager.getApplication().isUni
|
||||
|
||||
inline fun <reified T : Any> ComponentManager.getServiceSafe(): T =
|
||||
this.getService(T::class.java) ?: error("Unable to locate service ${T::class.java.name}")
|
||||
|
||||
fun <T> Project.runReadActionInSmartMode(action: () -> T): T {
|
||||
if (ApplicationManager.getApplication().isReadAccessAllowed) return action()
|
||||
return DumbService.getInstance(this).runReadActionInSmartMode<T>(action)
|
||||
}
|
||||
+6
@@ -10,6 +10,7 @@ import com.intellij.openapi.command.CommandProcessor
|
||||
import com.intellij.openapi.components.ComponentManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.annotations.Nls
|
||||
import com.intellij.openapi.project.DumbService
|
||||
|
||||
fun <T> runReadAction(action: () -> T): T {
|
||||
return ApplicationManager.getApplication().runReadAction<T>(action)
|
||||
@@ -46,3 +47,8 @@ inline fun isUnitTestMode(): Boolean = ApplicationManager.getApplication().isUni
|
||||
|
||||
inline fun <reified T : Any> ComponentManager.getServiceSafe(): T =
|
||||
this.getService(T::class.java) ?: error("Unable to locate service ${T::class.java.name}")
|
||||
|
||||
fun <T> Project.runReadActionInSmartMode(action: () -> T): T {
|
||||
if (ApplicationManager.getApplication().isReadAccessAllowed) return action()
|
||||
return DumbService.getInstance(this).runReadActionInSmartMode<T>(action)
|
||||
}
|
||||
+7
-1
@@ -24,6 +24,7 @@ import com.intellij.openapi.progress.ProgressIndicator
|
||||
import com.intellij.openapi.progress.ProgressIndicatorProvider
|
||||
import com.intellij.openapi.progress.ProgressManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.project.DumbService
|
||||
|
||||
fun <T> runReadAction(action: () -> T): T {
|
||||
return ApplicationManager.getApplication().runReadAction<T>(action)
|
||||
@@ -62,4 +63,9 @@ inline fun <reified T : Any> ComponentManager.getServiceSafe(): T =
|
||||
this.getService(T::class.java) ?: error("Unable to locate service ${T::class.java.name}")
|
||||
|
||||
fun <T> Project.getServiceIfCreated(serviceClass: Class<T>): T? =
|
||||
ServiceManager.getServiceIfCreated(this, serviceClass)
|
||||
ServiceManager.getServiceIfCreated(this, serviceClass)
|
||||
|
||||
fun <T> Project.runReadActionInSmartMode(action: () -> T): T {
|
||||
if (ApplicationManager.getApplication().isReadAccessAllowed) return action()
|
||||
return DumbService.getInstance(this).runReadActionInSmartMode<T>(action)
|
||||
}
|
||||
+1
-1
@@ -21,7 +21,7 @@ import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.idea.debugger.DebuggerClassNameProvider.Companion.getRelevantElement
|
||||
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches
|
||||
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches.ComputedClassNames
|
||||
import org.jetbrains.kotlin.idea.search.usagesSearch.isImportUsage
|
||||
import org.jetbrains.kotlin.idea.search.isImportUsage
|
||||
import org.jetbrains.kotlin.idea.stubindex.KotlinSourceFilterScope
|
||||
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
|
||||
@@ -214,19 +214,6 @@ override.declaration.choose.to.delete=Choose the ones you want to be deleted.
|
||||
override.declaration.member=Member
|
||||
override.declaration.delete.multiple.parameters={0} is a part of method hierarchy. Do you want to delete multiple parameters?
|
||||
|
||||
find.declaration.implementing.methods.checkbox=&Implementing functions
|
||||
find.declaration.overriding.methods.checkbox=Over&riding functions
|
||||
find.declaration.implementing.properties.checkbox=&Implementing properties
|
||||
find.declaration.overriding.properties.checkbox=Over&riding properties
|
||||
find.declaration.property.readers.checkbox=Readers
|
||||
find.declaration.property.writers.checkbox=Writers
|
||||
find.declaration.include.overloaded.methods.checkbox=Include o&verloaded functions and extensions
|
||||
find.declaration.functions.usages.checkbox=Usages of &functions
|
||||
find.declaration.properties.usages.checkbox=Usages of &properties
|
||||
find.declaration.constructor.usages.checkbox=Usages of &constructor
|
||||
find.declaration.derived.classes.checkbox=&Derived classes
|
||||
find.declaration.derived.interfaces.checkbox=Derived &interfaces
|
||||
|
||||
hierarchy.legend.member.is.defined.in.class=Member is defined in the class
|
||||
hierarchy.legend.member.defined.in.superclass=Member is not defined in the class but defined in superclass
|
||||
hierarchy.legend.member.should.be.defined=Member should be defined since the class is not abstract
|
||||
@@ -457,33 +444,6 @@ filters.text.inline.function.body=inline function body
|
||||
filters.text.inline.function.call.site=inline function call site
|
||||
filters.title.navigate.to=Navigate to
|
||||
|
||||
find.usages.class=class
|
||||
find.usages.companion.object=companion object
|
||||
find.usages.constructor=constructor
|
||||
find.usages.facade.class=facade class
|
||||
find.usages.for.property={0} for property
|
||||
find.usages.function=function
|
||||
find.usages.getter=getter
|
||||
find.usages.import.alias=import alias
|
||||
find.usages.interface=interface
|
||||
find.usages.label=label
|
||||
find.usages.lambda=lambda
|
||||
find.usages.object=object
|
||||
find.usages.parameter=parameter
|
||||
find.usages.property.accessor=property accessor
|
||||
find.usages.property=property
|
||||
find.usages.setter=setter
|
||||
find.usages.type.alias=type alias
|
||||
find.usages.type.parameter=type parameter
|
||||
find.usages.variable=variable
|
||||
find.usages.checkbox.name.expected.classes=Expected classes
|
||||
find.usages.class.name.anonymous=Anonymous
|
||||
find.usages.checkbox.name.expected.functions=Expected functions
|
||||
find.usages.text.find.usages.for.data.class.components.and.destruction.declarations=<p>Find usages for data class components and destructuring declarations<br/>could be <a href="{0}">disabled once</a> or <a href="{1}">disabled for a project</a>.</p>
|
||||
find.usages.tool.tip.text.disable.search.for.data.class.components.and.destruction.declarations.project.wide.setting=Disable search for data class components and destructuring declarations. (Project wide setting)
|
||||
find.usages.checkbox.text.fast.data.class.component.search=Fast data class component search
|
||||
find.usages.checkbox.name.expected.properties=Expected properties
|
||||
find.usages.action.text.find.usages.of=find usages of
|
||||
find.usages.type.named.argument=Named argument
|
||||
find.usages.type.type.alias=Type alias
|
||||
find.usages.type.callable.reference=Callable reference
|
||||
|
||||
@@ -192,6 +192,12 @@ The Kotlin FIR plugin provides language support in IntelliJ IDEA and Android Stu
|
||||
|
||||
<highlightingPassFactory implementation="org.jetbrains.kotlin.idea.highlighter.KotlinBeforeResolveHighlightingPass$Registrar"/>
|
||||
|
||||
<elementDescriptionProvider
|
||||
implementation="org.jetbrains.kotlin.idea.findUsages.KotlinElementDescriptionProviderBase"
|
||||
order="first"/>
|
||||
|
||||
<lang.findUsagesProvider language="kotlin" implementationClass="org.jetbrains.kotlin.idea.findUsages.KotlinFindUsagesProviderBase"/>
|
||||
|
||||
<fileType name="Kotlin"
|
||||
implementationClass="org.jetbrains.kotlin.idea.KotlinFileType"
|
||||
fieldName="INSTANCE"
|
||||
|
||||
@@ -211,6 +211,9 @@
|
||||
<projectService serviceInterface="org.jetbrains.kotlin.asJava.KotlinAsJavaSupport"
|
||||
serviceImplementation="org.jetbrains.kotlin.idea.caches.resolve.IDEKotlinAsJavaSupport"/>
|
||||
|
||||
<projectService serviceInterface="org.jetbrains.kotlin.idea.asJava.LightClassProvider"
|
||||
serviceImplementation="org.jetbrains.kotlin.idea.asJava.LightClassProviderImpl"/>
|
||||
|
||||
<projectService serviceInterface="org.jetbrains.kotlin.psi.KtFileClassProvider"
|
||||
serviceImplementation="org.jetbrains.kotlin.idea.caches.resolve.KtFileClassProviderImpl"/>
|
||||
|
||||
@@ -281,6 +284,12 @@
|
||||
<projectService serviceInterface="org.jetbrains.kotlin.idea.debugger.coroutine.DebuggerListener"
|
||||
serviceImplementation="org.jetbrains.kotlin.idea.debugger.coroutine.CoroutineDebuggerListener"/>
|
||||
|
||||
<projectService serviceInterface="org.jetbrains.kotlin.idea.findUsages.KotlinFindUsagesSupport"
|
||||
serviceImplementation="org.jetbrains.kotlin.idea.findUsages.KotlinFindUsagesSupportImpl"/>
|
||||
|
||||
<projectService serviceInterface="org.jetbrains.kotlin.idea.search.KotlinSearchUsagesSupport"
|
||||
serviceImplementation="org.jetbrains.kotlin.idea.search.KotlinSearchUsagesSupportImpl"/>
|
||||
|
||||
<errorHandler implementation="org.jetbrains.kotlin.idea.reporter.KotlinReportSubmitter"/>
|
||||
|
||||
<registryKey
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.asJava
|
||||
|
||||
import com.intellij.psi.*
|
||||
import org.jetbrains.kotlin.asJava.*
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
||||
import org.jetbrains.kotlin.idea.caches.lightClasses.KtFakeLightClass
|
||||
import org.jetbrains.kotlin.idea.caches.lightClasses.KtFakeLightMethod
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
|
||||
class LightClassProviderImpl : LightClassProvider {
|
||||
override fun getLightFieldForCompanionObject(companionObject: KtClassOrObject): PsiField? =
|
||||
LightClassUtil.getLightFieldForCompanionObject(companionObject)
|
||||
|
||||
override fun getLightClassMethods(function: KtFunction): List<PsiMethod> =
|
||||
LightClassUtil.getLightClassMethods(function)
|
||||
|
||||
override fun getLightClassParameterDeclarations(parameter: KtParameter): List<PsiNamedElement> =
|
||||
LightClassUtil.getLightClassPropertyMethods(parameter).allDeclarations
|
||||
|
||||
override fun getLightClassPropertyDeclarations(property: KtProperty): List<PsiNamedElement> =
|
||||
LightClassUtil.getLightClassPropertyMethods(property).allDeclarations
|
||||
|
||||
override fun toLightClassWithBuiltinMapping(classOrObject: KtClassOrObject): PsiClass? =
|
||||
classOrObject.toLightClassWithBuiltinMapping()
|
||||
|
||||
override fun toLightMethods(psiElement: PsiElement): List<PsiMethod> =
|
||||
psiElement.toLightMethods()
|
||||
|
||||
override fun toLightClass(classOrObject: KtClassOrObject): KtLightClass? =
|
||||
classOrObject.toLightClass()
|
||||
|
||||
override fun toLightElements(ktElement: KtElement): List<PsiNamedElement> =
|
||||
ktElement.toLightElements()
|
||||
|
||||
override fun createKtFakeLightClass(kotlinOrigin: KtClassOrObject): PsiClass =
|
||||
KtFakeLightClass(kotlinOrigin)
|
||||
|
||||
override fun getRepresentativeLightMethod(psiElement: PsiElement): PsiMethod? =
|
||||
psiElement.getRepresentativeLightMethod()
|
||||
|
||||
override fun isKtFakeLightClass(psiClass: PsiClass): Boolean =
|
||||
psiClass is KtFakeLightClass
|
||||
|
||||
override fun createKtFakeLightMethod(ktDeclaration: KtNamedDeclaration): PsiMethod? =
|
||||
KtFakeLightMethod.get(ktDeclaration)
|
||||
}
|
||||
@@ -16,190 +16,15 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.findUsages
|
||||
|
||||
import com.intellij.codeInsight.highlighting.HighlightUsagesDescriptionLocation
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.psi.ElementDescriptionLocation
|
||||
import com.intellij.psi.ElementDescriptionProvider
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiNamedElement
|
||||
import com.intellij.refactoring.util.CommonRefactoringUtil
|
||||
import com.intellij.refactoring.util.RefactoringDescriptionLocation
|
||||
import com.intellij.usageView.UsageViewLongNameLocation
|
||||
import com.intellij.usageView.UsageViewShortNameLocation
|
||||
import com.intellij.usageView.UsageViewTypeLocation
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
|
||||
import org.jetbrains.kotlin.asJava.unwrapped
|
||||
import org.jetbrains.kotlin.idea.KotlinBundle
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||
import org.jetbrains.kotlin.idea.refactoring.rename.RenameJavaSyntheticPropertyHandler
|
||||
import org.jetbrains.kotlin.idea.refactoring.rename.RenameKotlinPropertyProcessor
|
||||
import org.jetbrains.kotlin.idea.util.string.collapseSpaces
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||
|
||||
class KotlinElementDescriptionProvider : ElementDescriptionProvider {
|
||||
private tailrec fun KtNamedDeclaration.parentForFqName(): KtNamedDeclaration? {
|
||||
val parent = getStrictParentOfType<KtNamedDeclaration>() ?: return null
|
||||
if (parent is KtProperty && parent.isLocal) return parent.parentForFqName()
|
||||
return parent
|
||||
}
|
||||
class KotlinElementDescriptionProvider : KotlinElementDescriptionProviderBase() {
|
||||
|
||||
private fun KtNamedDeclaration.name() = nameAsName ?: Name.special("<no name provided>")
|
||||
override val PsiElement.isRenameJavaSyntheticPropertyHandler: Boolean
|
||||
get() = this is RenameJavaSyntheticPropertyHandler.SyntheticPropertyWrapper
|
||||
|
||||
private fun KtNamedDeclaration.fqName(): FqNameUnsafe {
|
||||
containingClassOrObject?.let {
|
||||
if (it is KtObjectDeclaration && it.isCompanion()) {
|
||||
return it.fqName().child(name())
|
||||
}
|
||||
return FqNameUnsafe("${it.name()}.${name()}")
|
||||
}
|
||||
|
||||
val internalSegments = generateSequence(this) { it.parentForFqName() }
|
||||
.filterIsInstance<KtNamedDeclaration>()
|
||||
.map { it.name ?: "<no name provided>" }
|
||||
.toList()
|
||||
.asReversed()
|
||||
val packageSegments = containingKtFile.packageFqName.pathSegments()
|
||||
return FqNameUnsafe((packageSegments + internalSegments).joinToString("."))
|
||||
}
|
||||
|
||||
private fun KtTypeReference.renderShort(): String {
|
||||
return accept(
|
||||
object : KtVisitor<String, Unit>() {
|
||||
private val visitor get() = this
|
||||
|
||||
override fun visitTypeReference(typeReference: KtTypeReference, data: Unit): String {
|
||||
val typeText = typeReference.typeElement?.accept(this, data) ?: "???"
|
||||
return if (typeReference.hasParentheses()) "($typeText)" else typeText
|
||||
}
|
||||
|
||||
override fun visitDynamicType(type: KtDynamicType, data: Unit) = type.text
|
||||
|
||||
override fun visitFunctionType(type: KtFunctionType, data: Unit): String {
|
||||
return buildString {
|
||||
type.receiverTypeReference?.let { append(it.accept(visitor, data)).append('.') }
|
||||
type.parameters.joinTo(this, prefix = "(", postfix = ")") { it.accept(visitor, data) }
|
||||
append(" -> ")
|
||||
append(type.returnTypeReference?.accept(visitor, data) ?: "???")
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitNullableType(nullableType: KtNullableType, data: Unit): String {
|
||||
val innerTypeText = nullableType.innerType?.accept(this, data) ?: return "???"
|
||||
return "$innerTypeText?"
|
||||
}
|
||||
|
||||
override fun visitSelfType(type: KtSelfType, data: Unit) = type.text
|
||||
|
||||
override fun visitUserType(type: KtUserType, data: Unit): String {
|
||||
return buildString {
|
||||
append(type.referencedName ?: "???")
|
||||
|
||||
val arguments = type.typeArguments
|
||||
if (arguments.isNotEmpty()) {
|
||||
arguments.joinTo(this, prefix = "<", postfix = ">") {
|
||||
it.typeReference?.accept(visitor, data) ?: it.text
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitParameter(parameter: KtParameter, data: Unit) = parameter.typeReference?.accept(this, data) ?: "???"
|
||||
},
|
||||
Unit
|
||||
)
|
||||
}
|
||||
|
||||
override fun getElementDescription(element: PsiElement, location: ElementDescriptionLocation): String? {
|
||||
val shouldUnwrap = location !is UsageViewShortNameLocation && location !is UsageViewLongNameLocation
|
||||
val targetElement = if (shouldUnwrap) element.unwrapped ?: element else element
|
||||
|
||||
fun elementKind() = when (targetElement) {
|
||||
is KtClass -> if (targetElement.isInterface())
|
||||
KotlinBundle.message("find.usages.interface")
|
||||
else
|
||||
KotlinBundle.message("find.usages.class")
|
||||
is KtObjectDeclaration -> if (targetElement.isCompanion())
|
||||
KotlinBundle.message("find.usages.companion.object")
|
||||
else
|
||||
KotlinBundle.message("find.usages.object")
|
||||
is KtNamedFunction -> KotlinBundle.message("find.usages.function")
|
||||
is KtPropertyAccessor -> KotlinBundle.message(
|
||||
"find.usages.for.property",
|
||||
(if (targetElement.isGetter)
|
||||
KotlinBundle.message("find.usages.getter")
|
||||
else
|
||||
KotlinBundle.message("find.usages.setter"))
|
||||
) + " "
|
||||
is KtFunctionLiteral -> KotlinBundle.message("find.usages.lambda")
|
||||
is KtPrimaryConstructor, is KtSecondaryConstructor -> KotlinBundle.message("find.usages.constructor")
|
||||
is KtProperty -> if (targetElement.isLocal)
|
||||
KotlinBundle.message("find.usages.variable")
|
||||
else
|
||||
KotlinBundle.message("find.usages.property")
|
||||
is KtTypeParameter -> KotlinBundle.message("find.usages.type.parameter")
|
||||
is KtParameter -> KotlinBundle.message("find.usages.parameter")
|
||||
is KtDestructuringDeclarationEntry -> KotlinBundle.message("find.usages.variable")
|
||||
is KtTypeAlias -> KotlinBundle.message("find.usages.type.alias")
|
||||
is KtLabeledExpression -> KotlinBundle.message("find.usages.label")
|
||||
is KtImportAlias -> KotlinBundle.message("find.usages.import.alias")
|
||||
is RenameJavaSyntheticPropertyHandler.SyntheticPropertyWrapper -> KotlinBundle.message("find.usages.property")
|
||||
is KtLightClassForFacade -> KotlinBundle.message("find.usages.facade.class")
|
||||
is RenameKotlinPropertyProcessor.PropertyMethodWrapper -> KotlinBundle.message("find.usages.property.accessor")
|
||||
else -> null
|
||||
}
|
||||
|
||||
val namedElement = if (targetElement is KtPropertyAccessor) {
|
||||
targetElement.parent as? KtProperty
|
||||
} else targetElement as? PsiNamedElement
|
||||
|
||||
@Suppress("FoldInitializerAndIfToElvis")
|
||||
if (namedElement == null) {
|
||||
return if (targetElement is KtElement) "'" + StringUtil.shortenTextWithEllipsis(
|
||||
targetElement.text.collapseSpaces(),
|
||||
53,
|
||||
0
|
||||
) + "'" else null
|
||||
}
|
||||
|
||||
if (namedElement.language != KotlinLanguage.INSTANCE) return null
|
||||
|
||||
return when (location) {
|
||||
is UsageViewTypeLocation -> elementKind()
|
||||
is UsageViewShortNameLocation, is UsageViewLongNameLocation -> namedElement.name
|
||||
is RefactoringDescriptionLocation -> {
|
||||
val kind = elementKind() ?: return null
|
||||
if (namedElement !is KtNamedDeclaration) return null
|
||||
val renderFqName = location.includeParent() &&
|
||||
namedElement !is KtTypeParameter &&
|
||||
namedElement !is KtParameter &&
|
||||
namedElement !is KtConstructor<*>
|
||||
val desc = when (namedElement) {
|
||||
is KtFunction -> {
|
||||
val baseText = buildString {
|
||||
append(namedElement.name ?: "")
|
||||
namedElement.valueParameters.joinTo(this, prefix = "(", postfix = ")") {
|
||||
(if (it.isVarArg) "vararg " else "") + (it.typeReference?.renderShort() ?: "")
|
||||
}
|
||||
namedElement.receiverTypeReference?.let { append(" on ").append(it.renderShort()) }
|
||||
}
|
||||
val parentFqName = if (renderFqName) namedElement.fqName().parent() else null
|
||||
if (parentFqName?.isRoot != false) baseText else "${parentFqName.asString()}.$baseText"
|
||||
}
|
||||
else -> (if (renderFqName) namedElement.fqName().asString() else namedElement.name) ?: ""
|
||||
}
|
||||
|
||||
"$kind ${CommonRefactoringUtil.htmlEmphasize(desc)}"
|
||||
}
|
||||
is HighlightUsagesDescriptionLocation -> {
|
||||
val kind = elementKind() ?: return null
|
||||
if (namedElement !is KtNamedDeclaration) return null
|
||||
"$kind ${namedElement.name}"
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
override val PsiElement.isRenameKotlinPropertyProcessor: Boolean
|
||||
get() = this is RenameKotlinPropertyProcessor.PropertyMethodWrapper
|
||||
}
|
||||
|
||||
@@ -19,72 +19,21 @@ import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isPropertyParameter
|
||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||
|
||||
class KotlinFindUsagesProvider : FindUsagesProvider {
|
||||
private val javaProvider by lazy { JavaFindUsagesProvider() }
|
||||
|
||||
override fun canFindUsagesFor(psiElement: PsiElement): Boolean =
|
||||
psiElement is KtNamedDeclaration
|
||||
|
||||
override fun getWordsScanner(): WordsScanner? = KotlinWordsScanner()
|
||||
|
||||
override fun getHelpId(psiElement: PsiElement): String? = null
|
||||
|
||||
override fun getType(element: PsiElement): String {
|
||||
return when (element) {
|
||||
is KtNamedFunction -> KotlinBundle.message("find.usages.function")
|
||||
is KtClass -> KotlinBundle.message("find.usages.class")
|
||||
is KtParameter -> KotlinBundle.message("find.usages.parameter")
|
||||
is KtProperty -> if (element.isLocal)
|
||||
KotlinBundle.message("find.usages.variable")
|
||||
else
|
||||
KotlinBundle.message("find.usages.property")
|
||||
is KtDestructuringDeclarationEntry -> KotlinBundle.message("find.usages.variable")
|
||||
is KtTypeParameter -> KotlinBundle.message("find.usages.type.parameter")
|
||||
is KtSecondaryConstructor -> KotlinBundle.message("find.usages.constructor")
|
||||
is KtObjectDeclaration -> KotlinBundle.message("find.usages.object")
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
|
||||
private val KtDeclaration.containerDescription: String?
|
||||
get() {
|
||||
containingClassOrObject?.let { return getDescriptiveName(it) }
|
||||
(parent as? KtFile)?.parent?.let { return getDescriptiveName(it) }
|
||||
return null
|
||||
}
|
||||
class KotlinFindUsagesProvider : KotlinFindUsagesProviderBase() {
|
||||
|
||||
override fun getDescriptiveName(element: PsiElement): String {
|
||||
return when (element) {
|
||||
is PsiDirectory, is PsiPackage, is PsiFile -> javaProvider.getDescriptiveName(element)
|
||||
is KtClassOrObject -> {
|
||||
if (element is KtObjectDeclaration && element.isObjectLiteral()) return "<unnamed>"
|
||||
element.fqName?.asString() ?: element.name ?: "<unnamed>"
|
||||
}
|
||||
is KtProperty -> (element.name ?: "") + (element.containerDescription?.let { " of $it" } ?: "")
|
||||
is KtFunction -> {
|
||||
val name = element.name ?: ""
|
||||
val descriptor = element.unsafeResolveToDescriptor() as FunctionDescriptor
|
||||
val renderer = IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_NO_ANNOTATIONS
|
||||
val paramsDescription =
|
||||
descriptor.valueParameters.joinToString(prefix = "(", postfix = ")") { renderer.renderType(it.type) }
|
||||
val returnType = descriptor.returnType
|
||||
val returnTypeDescription = if (returnType != null && !returnType.isUnit()) renderer.renderType(returnType) else null
|
||||
val funDescription = "$name$paramsDescription" + (returnTypeDescription?.let { ": $it" } ?: "")
|
||||
return funDescription + (element.containerDescription?.let { " of $it" } ?: "")
|
||||
}
|
||||
is KtLabeledExpression -> element.getLabelName() ?: ""
|
||||
is KtImportAlias -> element.name ?: ""
|
||||
is KtLightElement<*, *> -> element.kotlinOrigin?.let { getDescriptiveName(it) } ?: ""
|
||||
is KtParameter -> {
|
||||
if (element.isPropertyParameter()) {
|
||||
(element.name ?: "") + (element.containerDescription?.let { " of $it" } ?: "")
|
||||
} else {
|
||||
element.name ?: ""
|
||||
}
|
||||
}
|
||||
is PsiNamedElement -> element.name ?: ""
|
||||
else -> ""
|
||||
}
|
||||
|
||||
if (element !is KtFunction) return super.getDescriptiveName(element)
|
||||
|
||||
val name = element.name ?: ""
|
||||
val descriptor = element.unsafeResolveToDescriptor() as FunctionDescriptor
|
||||
val renderer = IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_NO_ANNOTATIONS
|
||||
val paramsDescription =
|
||||
descriptor.valueParameters.joinToString(prefix = "(", postfix = ")") { renderer.renderType(it.type) }
|
||||
val returnType = descriptor.returnType
|
||||
val returnTypeDescription = if (returnType != null && !returnType.isUnit()) renderer.renderType(returnType) else null
|
||||
val funDescription = "$name$paramsDescription" + (returnTypeDescription?.let { ": $it" } ?: "")
|
||||
return funDescription + (element.containerDescription?.let { " of $it" } ?: "")
|
||||
}
|
||||
|
||||
override fun getNodeText(element: PsiElement, useFullName: Boolean): String =
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.findUsages
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiReference
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.idea.search.usagesSearch.dataClassComponentFunction
|
||||
import org.jetbrains.kotlin.idea.search.usagesSearch.isConstructorUsage
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
|
||||
class KotlinFindUsagesSupportImpl : KotlinFindUsagesSupport {
|
||||
override fun isCallReceiverRefersToCompanionObject(element: KtElement, companionObject: KtObjectDeclaration): Boolean =
|
||||
org.jetbrains.kotlin.idea.search.usagesSearch.isCallReceiverRefersToCompanionObject(element, companionObject)
|
||||
|
||||
override fun isDataClassComponentFunction(element: KtParameter): Boolean =
|
||||
element.dataClassComponentFunction() != null
|
||||
|
||||
override fun getTopMostOverriddenElementsToHighlight(target: PsiElement): List<PsiElement> =
|
||||
org.jetbrains.kotlin.idea.search.usagesSearch.getTopMostOverriddenElementsToHighlight(target)
|
||||
|
||||
override fun tryRenderDeclarationCompactStyle(declaration: KtDeclaration): String? =
|
||||
org.jetbrains.kotlin.idea.search.usagesSearch.tryRenderDeclarationCompactStyle(declaration)
|
||||
|
||||
override fun isConstructorUsage(psiReference: PsiReference, ktClassOrObject: KtClassOrObject): Boolean =
|
||||
psiReference.isConstructorUsage(ktClassOrObject)
|
||||
|
||||
override fun checkSuperMethods(declaration: KtDeclaration, ignore: Collection<PsiElement>?, actionString: String): List<PsiElement> =
|
||||
org.jetbrains.kotlin.idea.refactoring.checkSuperMethods(declaration, ignore, actionString)
|
||||
|
||||
override fun sourcesAndLibraries(delegate: GlobalSearchScope, project: Project): GlobalSearchScope =
|
||||
org.jetbrains.kotlin.idea.stubindex.KotlinSourceFilterScope.sourcesAndLibraries(delegate, project)
|
||||
}
|
||||
+1
-1
@@ -46,7 +46,7 @@ import java.util.*
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.ClassKind as IdeaClassKind
|
||||
|
||||
enum class ClassKind(@NonNls val keyword: String, @Nls val description: String) {
|
||||
PLAIN_CLASS("class", KotlinBundle.message("find.usages.class")),
|
||||
PLAIN_CLASS("class", KotlinBundle.message("text.class")),
|
||||
ENUM_CLASS("enum class", KotlinBundle.message("text.enum")),
|
||||
ENUM_ENTRY("", KotlinBundle.message("text.enum.constant")),
|
||||
ANNOTATION_CLASS("annotation class", KotlinBundle.message("text.annotation")),
|
||||
|
||||
+2
-2
@@ -26,7 +26,7 @@ import org.jetbrains.kotlin.idea.references.findPsiDeclarations
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.idea.references.resolveMainReferenceToDescriptors
|
||||
import org.jetbrains.kotlin.idea.search.fileScope
|
||||
import org.jetbrains.kotlin.idea.search.usagesSearch.isImportUsage
|
||||
import org.jetbrains.kotlin.idea.search.isImportUsage
|
||||
import org.jetbrains.kotlin.idea.util.ImportInsertHelperImpl
|
||||
import org.jetbrains.kotlin.idea.util.getAllAccessibleFunctions
|
||||
import org.jetbrains.kotlin.idea.util.getAllAccessibleVariables
|
||||
@@ -136,7 +136,7 @@ private fun invokeRename(
|
||||
private fun replaceUsages(usages: List<UsageContext>, newName: String) {
|
||||
// case: inner element
|
||||
for (usage in usages.asReversed()) {
|
||||
val reference = usage.pointer.element?.safeAs<KtElement>()?.mainReference?.takeUnless(KtReference::isImportUsage) ?: continue
|
||||
val reference = usage.pointer.element?.safeAs<KtElement>()?.mainReference?.takeUnless { it.isImportUsage() } ?: continue
|
||||
val newExpression = reference.handleElementRename(newName) as? KtNameReferenceExpression ?: continue
|
||||
if (usage.isExtension) {
|
||||
newExpression.getQualifiedElementSelector()?.replace(newExpression)
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.search
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.psi.search.SearchScope
|
||||
import org.jetbrains.kotlin.idea.core.isInheritable
|
||||
import org.jetbrains.kotlin.idea.core.isOverridable
|
||||
import org.jetbrains.kotlin.idea.search.declarationsSearch.forEachOverridingMethod
|
||||
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchOptions
|
||||
import org.jetbrains.kotlin.idea.search.usagesSearch.*
|
||||
import org.jetbrains.kotlin.idea.stubindex.KotlinTypeAliasShortNameIndex
|
||||
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
|
||||
import org.jetbrains.kotlin.idea.util.expectedDeclarationIfAny
|
||||
import org.jetbrains.kotlin.idea.util.isExpectDeclaration
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.ImportPath
|
||||
|
||||
class KotlinSearchUsagesSupportImpl : KotlinSearchUsagesSupport {
|
||||
|
||||
override fun dataClassComponentMethodName(element: KtParameter): String? =
|
||||
element.dataClassComponentFunction()?.name?.asString()
|
||||
|
||||
override fun hasType(element: KtExpression): Boolean =
|
||||
org.jetbrains.kotlin.idea.search.usagesSearch.hasType(element)
|
||||
|
||||
override fun isSamInterface(psiClass: PsiClass): Boolean =
|
||||
org.jetbrains.kotlin.idea.search.usagesSearch.isSamInterface(psiClass)
|
||||
|
||||
override fun <T : PsiNamedElement> filterDataClassComponentsIfDisabled(
|
||||
elements: List<T>,
|
||||
kotlinOptions: KotlinReferencesSearchOptions
|
||||
): List<T> =
|
||||
elements.filterDataClassComponentsIfDisabled(kotlinOptions)
|
||||
|
||||
override fun isCallableOverrideUsage(reference: PsiReference, declaration: KtNamedDeclaration): Boolean =
|
||||
reference.isCallableOverrideUsage(declaration)
|
||||
|
||||
override fun isUsageInContainingDeclaration(reference: PsiReference, declaration: KtNamedDeclaration): Boolean =
|
||||
reference.isUsageInContainingDeclaration(declaration)
|
||||
|
||||
override fun isExtensionOfDeclarationClassUsage(reference: PsiReference, declaration: KtNamedDeclaration): Boolean =
|
||||
reference.isExtensionOfDeclarationClassUsage(declaration)
|
||||
|
||||
override fun getReceiverTypeSearcherInfo(psiElement: PsiElement, isDestructionDeclarationSearch: Boolean): ReceiverTypeSearcherInfo? =
|
||||
psiElement.getReceiverTypeSearcherInfo(isDestructionDeclarationSearch)
|
||||
|
||||
override fun forceResolveReferences(file: KtFile, elements: List<KtElement>) =
|
||||
file.forceResolveReferences(elements)
|
||||
|
||||
override fun scriptDefinitionExists(file: PsiFile): Boolean =
|
||||
file.scriptDefinitionExists()
|
||||
|
||||
override fun getDefaultImports(file: KtFile): List<ImportPath> =
|
||||
file.getDefaultImports()
|
||||
|
||||
override fun forEachKotlinOverride(
|
||||
ktClass: KtClass,
|
||||
members: List<KtNamedDeclaration>,
|
||||
scope: SearchScope,
|
||||
processor: (superMember: PsiElement, overridingMember: PsiElement) -> Boolean
|
||||
): Boolean =
|
||||
org.jetbrains.kotlin.idea.search.declarationsSearch.forEachKotlinOverride(
|
||||
ktClass,
|
||||
members,
|
||||
scope,
|
||||
processor
|
||||
)
|
||||
|
||||
override fun forEachOverridingMethod(method: PsiMethod, scope: SearchScope, processor: (PsiMethod) -> Boolean): Boolean =
|
||||
method.forEachOverridingMethod(scope, processor)
|
||||
|
||||
override fun findDeepestSuperMethodsNoWrapping(method: PsiElement): List<PsiElement> =
|
||||
org.jetbrains.kotlin.idea.search.declarationsSearch.findDeepestSuperMethodsNoWrapping(method)
|
||||
|
||||
override fun findTypeAliasByShortName(shortName: String, project: Project, scope: GlobalSearchScope): Collection<KtTypeAlias> =
|
||||
KotlinTypeAliasShortNameIndex.getInstance().get(shortName, project, scope)
|
||||
|
||||
override fun isInProjectSource(element: PsiElement, includeScriptsOutsideSourceRoots: Boolean): Boolean =
|
||||
ProjectRootsUtil.isInProjectSource(element, includeScriptsOutsideSourceRoots)
|
||||
|
||||
override fun isOverridable(declaration: KtDeclaration): Boolean =
|
||||
declaration.isOverridable()
|
||||
|
||||
override fun isInheritable(ktClass: KtClass): Boolean =
|
||||
ktClass.isInheritable()
|
||||
|
||||
override fun formatJavaOrLightMethod(method: PsiMethod): String =
|
||||
org.jetbrains.kotlin.idea.refactoring.formatJavaOrLightMethod(method)
|
||||
|
||||
override fun formatClass(classOrObject: KtClassOrObject): String =
|
||||
org.jetbrains.kotlin.idea.refactoring.formatClass(classOrObject)
|
||||
|
||||
override fun expectedDeclarationIfAny(declaration: KtDeclaration): KtDeclaration? =
|
||||
declaration.expectedDeclarationIfAny()
|
||||
|
||||
override fun isExpectDeclaration(declaration: KtDeclaration): Boolean =
|
||||
declaration.isExpectDeclaration()
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2000-2017 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.search.declarationsSearch
|
||||
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.search.SearchScope
|
||||
import com.intellij.psi.search.searches.OverridingMethodsSearch
|
||||
import com.intellij.util.Processor
|
||||
import org.jetbrains.kotlin.asJava.*
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.isOverridable
|
||||
import org.jetbrains.kotlin.idea.caches.lightClasses.KtFakeLightMethod
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor
|
||||
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
||||
import org.jetbrains.kotlin.idea.core.getDeepestSuperDeclarations
|
||||
import org.jetbrains.kotlin.idea.search.excludeKotlinSources
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||
import org.jetbrains.kotlin.resolve.source.getPsi
|
||||
import org.jetbrains.kotlin.types.substitutions.getTypeSubstitutor
|
||||
import org.jetbrains.kotlin.util.findCallableMemberBySignature
|
||||
import java.util.*
|
||||
|
||||
fun forEachKotlinOverride(
|
||||
ktClass: KtClass,
|
||||
members: List<KtNamedDeclaration>,
|
||||
scope: SearchScope,
|
||||
processor: (superMember: PsiElement, overridingMember: PsiElement) -> Boolean
|
||||
): Boolean {
|
||||
val baseClassDescriptor = runReadAction { ktClass.unsafeResolveToDescriptor() as ClassDescriptor }
|
||||
val baseDescriptors =
|
||||
runReadAction { members.mapNotNull { it.unsafeResolveToDescriptor() as? CallableMemberDescriptor }.filter { it.isOverridable } }
|
||||
if (baseDescriptors.isEmpty()) return true
|
||||
|
||||
HierarchySearchRequest(ktClass, scope, true).searchInheritors().forEach(Processor { psiClass ->
|
||||
val inheritor = psiClass.unwrapped as? KtClassOrObject ?: return@Processor true
|
||||
runReadAction {
|
||||
val inheritorDescriptor = inheritor.unsafeResolveToDescriptor() as ClassDescriptor
|
||||
val substitutor =
|
||||
getTypeSubstitutor(baseClassDescriptor.defaultType, inheritorDescriptor.defaultType) ?: return@runReadAction true
|
||||
baseDescriptors.forEach {
|
||||
val superMember = it.source.getPsi()!!
|
||||
val overridingDescriptor = (it.substitute(substitutor) as? CallableMemberDescriptor)?.let { memberDescriptor ->
|
||||
inheritorDescriptor.findCallableMemberBySignature(memberDescriptor)
|
||||
}
|
||||
val overridingMember = overridingDescriptor?.source?.getPsi()
|
||||
if (overridingMember != null) {
|
||||
if (!processor(superMember, overridingMember)) return@runReadAction false
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
})
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
fun PsiMethod.forEachOverridingMethod(
|
||||
scope: SearchScope = runReadAction { useScope },
|
||||
processor: (PsiMethod) -> Boolean
|
||||
): Boolean {
|
||||
if (this !is KtFakeLightMethod) {
|
||||
if (!OverridingMethodsSearch.search(this, scope.excludeKotlinSources(), true).forEach(processor)) return false
|
||||
}
|
||||
|
||||
val ktMember = this.unwrapped as? KtNamedDeclaration ?: return true
|
||||
val ktClass = runReadAction { ktMember.containingClassOrObject as? KtClass } ?: return true
|
||||
return forEachKotlinOverride(ktClass, listOf(ktMember), scope) { _, overrider ->
|
||||
val lightMethods = runReadAction { overrider.toPossiblyFakeLightMethods().distinctBy { it.unwrapped } }
|
||||
lightMethods.all { processor(it) }
|
||||
}
|
||||
}
|
||||
|
||||
fun findDeepestSuperMethodsNoWrapping(method: PsiElement): List<PsiElement> {
|
||||
val element = method.unwrapped
|
||||
return when (element) {
|
||||
is PsiMethod -> element.findDeepestSuperMethods().toList()
|
||||
is KtCallableDeclaration -> {
|
||||
val descriptor = element.resolveToDescriptorIfAny() as? CallableMemberDescriptor ?: return emptyList()
|
||||
descriptor.getDeepestSuperDeclarations(false).mapNotNull {
|
||||
it.source.getPsi() ?: DescriptorToSourceUtilsIde.getAnyDeclaration(element.project, it)
|
||||
}
|
||||
}
|
||||
else -> emptyList()
|
||||
}
|
||||
}
|
||||
+102
-9
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.idea.search.usagesSearch
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.search.SearchScope
|
||||
import com.intellij.psi.search.searches.MethodReferencesSearch
|
||||
@@ -26,29 +27,59 @@ import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
||||
import org.jetbrains.kotlin.asJava.classes.lazyPub
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightElement
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||
import org.jetbrains.kotlin.asJava.toLightClass
|
||||
import org.jetbrains.kotlin.asJava.toLightMethods
|
||||
import org.jetbrains.kotlin.asJava.unwrapped
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.idea.caches.project.NotUnderContentRootModuleInfo.project
|
||||
import org.jetbrains.kotlin.idea.caches.project.getNullableModuleInfo
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToParameterDescriptorIfAny
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.util.getJavaMemberDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.util.getJavaMethodDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.util.getJavaOrKotlinMemberDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.util.hasJavaResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
||||
import org.jetbrains.kotlin.idea.compiler.IDELanguageSettingsProvider
|
||||
import org.jetbrains.kotlin.idea.project.TargetPlatformDetector
|
||||
import org.jetbrains.kotlin.idea.project.findAnalyzerServices
|
||||
import org.jetbrains.kotlin.idea.references.unwrappedTargets
|
||||
import org.jetbrains.kotlin.idea.search.ReceiverTypeSearcherInfo
|
||||
import org.jetbrains.kotlin.idea.search.declarationsSearch.HierarchySearchRequest
|
||||
import org.jetbrains.kotlin.idea.search.declarationsSearch.searchInheritors
|
||||
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchOptions
|
||||
import org.jetbrains.kotlin.idea.util.FuzzyType
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.idea.util.fuzzyExtensionReceiverType
|
||||
import org.jetbrains.kotlin.idea.util.toFuzzyType
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.contains
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isTypeRefinementEnabled
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.resolve.sam.getSingleAbstractMethodOrNull
|
||||
import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.util.isValidOperator
|
||||
|
||||
val KtDeclaration.descriptor: DeclarationDescriptor?
|
||||
get() = if (this is KtParameter) this.descriptor else this.resolveToDescriptorIfAny(BodyResolveMode.FULL)
|
||||
fun tryRenderDeclarationCompactStyle(declaration: KtDeclaration): String? =
|
||||
declaration.descriptor?.let { DescriptorRenderer.COMPACT.render(it) }
|
||||
|
||||
fun isSamInterface(psiClass: PsiClass): Boolean {
|
||||
val classDescriptor = psiClass.getJavaMemberDescriptor() as? JavaClassDescriptor
|
||||
return classDescriptor != null && getSingleAbstractMethodOrNull(classDescriptor) != null
|
||||
}
|
||||
|
||||
fun hasType(element: KtExpression): Boolean =
|
||||
element.analyze(BodyResolveMode.PARTIAL).getType(element) != null
|
||||
|
||||
val KtDeclaration.constructor: ConstructorDescriptor?
|
||||
get() {
|
||||
@@ -60,9 +91,6 @@ val KtDeclaration.constructor: ConstructorDescriptor?
|
||||
}
|
||||
}
|
||||
|
||||
val KtParameter.descriptor: ValueParameterDescriptor?
|
||||
get() = this.resolveToParameterDescriptorIfAny(BodyResolveMode.FULL)
|
||||
|
||||
val KtParameter.propertyDescriptor: PropertyDescriptor?
|
||||
get() = this.resolveToDescriptorIfAny(BodyResolveMode.FULL) as? PropertyDescriptor
|
||||
|
||||
@@ -79,9 +107,6 @@ fun PsiReference.checkUsageVsOriginalDescriptor(
|
||||
}
|
||||
}
|
||||
|
||||
fun PsiReference.isImportUsage(): Boolean =
|
||||
element.getNonStrictParentOfType<KtImportDirective>() != null
|
||||
|
||||
fun PsiReference.isConstructorUsage(ktClassOrObject: KtClassOrObject): Boolean = with(element) {
|
||||
fun checkJavaUsage(): Boolean {
|
||||
val call = getNonStrictParentOfType<PsiConstructorCall>()
|
||||
@@ -306,4 +331,72 @@ fun <T : PsiNamedElement> List<T>.filterDataClassComponentsIfDisabled(kotlinOpti
|
||||
}
|
||||
|
||||
return filter { !it.isComponentElement() }
|
||||
}
|
||||
}
|
||||
|
||||
fun KtFile.forceResolveReferences(elements: List<KtElement>) {
|
||||
getResolutionFacade().analyze(elements, BodyResolveMode.PARTIAL)
|
||||
}
|
||||
|
||||
private fun PsiElement.resolveTargetToDescriptor(isDestructionDeclarationSearch: Boolean): FunctionDescriptor? {
|
||||
|
||||
if (isDestructionDeclarationSearch && this is KtParameter) {
|
||||
return dataClassComponentFunction()
|
||||
}
|
||||
|
||||
return when {
|
||||
this is KtDeclaration -> resolveToDescriptorIfAny(BodyResolveMode.FULL)
|
||||
this is PsiMember && hasJavaResolutionFacade() ->
|
||||
this.getJavaOrKotlinMemberDescriptor()
|
||||
else -> null
|
||||
} as? FunctionDescriptor
|
||||
}
|
||||
|
||||
private fun containsTypeOrDerivedInside(declaration: KtDeclaration, typeToSearch: FuzzyType): Boolean {
|
||||
|
||||
fun KotlinType.containsTypeOrDerivedInside(type: FuzzyType): Boolean {
|
||||
return type.checkIsSuperTypeOf(this) != null || arguments.any { !it.isStarProjection && it.type.containsTypeOrDerivedInside(type) }
|
||||
}
|
||||
|
||||
val descriptor = declaration.resolveToDescriptorIfAny() as? CallableDescriptor
|
||||
val type = descriptor?.returnType
|
||||
return type != null && type.containsTypeOrDerivedInside(typeToSearch)
|
||||
}
|
||||
|
||||
private fun FuzzyType.toPsiClass(project: Project): PsiClass? {
|
||||
val classDescriptor = type.constructor.declarationDescriptor ?: return null
|
||||
val classDeclaration = DescriptorToSourceUtilsIde.getAnyDeclaration(project, classDescriptor)
|
||||
return when (classDeclaration) {
|
||||
is PsiClass -> classDeclaration
|
||||
is KtClassOrObject -> classDeclaration.toLightClass()
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun PsiElement.extractReceiverType(isDestructionDeclarationSearch: Boolean): FuzzyType? {
|
||||
val descriptor = resolveTargetToDescriptor(isDestructionDeclarationSearch)?.takeIf { it.isValidOperator() } ?: return null
|
||||
|
||||
return if (descriptor.isExtension) {
|
||||
descriptor.fuzzyExtensionReceiverType()!!
|
||||
} else {
|
||||
val classDescriptor = descriptor.containingDeclaration as? ClassDescriptor ?: return null
|
||||
classDescriptor.defaultType.toFuzzyType(classDescriptor.typeConstructor.parameters)
|
||||
}
|
||||
}
|
||||
|
||||
fun PsiElement.getReceiverTypeSearcherInfo(isDestructionDeclarationSearch: Boolean): ReceiverTypeSearcherInfo? {
|
||||
val receiverType = runReadAction { extractReceiverType(isDestructionDeclarationSearch) } ?: return null
|
||||
val psiClass = runReadAction { receiverType.toPsiClass(project) }
|
||||
return ReceiverTypeSearcherInfo(psiClass) {
|
||||
containsTypeOrDerivedInside(it, receiverType)
|
||||
}
|
||||
}
|
||||
|
||||
fun KtFile.getDefaultImports(): List<ImportPath> {
|
||||
val moduleInfo = getNullableModuleInfo() ?: return emptyList()
|
||||
return TargetPlatformDetector.getPlatform(this).findAnalyzerServices(project).getDefaultImports(
|
||||
IDELanguageSettingsProvider.getLanguageVersionSettings(moduleInfo, project),
|
||||
includeLowPriorityImports = true
|
||||
)
|
||||
}
|
||||
|
||||
fun PsiFile.scriptDefinitionExists(): Boolean = findScriptDefinition() != null
|
||||
@@ -11,7 +11,7 @@ import com.intellij.psi.PsiEnumConstant
|
||||
import com.intellij.psi.PsiMethod
|
||||
import com.intellij.psi.PsiModifierListOwner
|
||||
import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName
|
||||
import org.jetbrains.kotlin.idea.search.declarationsSearch.findDeepestSuperMethodsNoWrapping
|
||||
import org.jetbrains.kotlin.idea.search.KotlinSearchUsagesSupport.Companion.findDeepestSuperMethodsNoWrapping
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
import org.jetbrains.kotlin.nj2k.isObjectOrCompanionObject
|
||||
import org.jetbrains.kotlin.nj2k.psi
|
||||
|
||||
Reference in New Issue
Block a user