diff --git a/idea/idea-analysis/resources/messages/KotlinIdeaAnalysisBundle.properties b/idea/idea-analysis/resources/messages/KotlinIdeaAnalysisBundle.properties index ad3a5bf26dd..9507a1ed3be 100644 --- a/idea/idea-analysis/resources/messages/KotlinIdeaAnalysisBundle.properties +++ b/idea/idea-analysis/resources/messages/KotlinIdeaAnalysisBundle.properties @@ -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= object.0=object{0} show.non.public=Show non-public diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/searchHelpers.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/searchHelpers.kt index 09e6a359996..86a5a71bf17 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/searchHelpers.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/searchHelpers.kt @@ -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 { @@ -87,3 +92,26 @@ fun KtParameter.isDataClassProperty(): Boolean { return this.containingClassOrObject?.hasModifier(KtTokens.DATA_KEYWORD) ?: false } +fun getTopMostOverriddenElementsToHighlight(target: PsiElement): List { + 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 +} diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/KotlinIndicesHelper.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/KotlinIndicesHelper.kt index 4cc0f7fdcea..7154c8d4b1c 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/KotlinIndicesHelper.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/KotlinIndicesHelper.kt @@ -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 diff --git a/idea/idea-frontend-independent/build.gradle.kts b/idea/idea-frontend-independent/build.gradle.kts index 0cb4fe9427d..62f34e40882 100644 --- a/idea/idea-frontend-independent/build.gradle.kts +++ b/idea/idea-frontend-independent/build.gradle.kts @@ -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() diff --git a/idea/idea-frontend-independent/resources-en/messages/KotlinBundleIndependent.properties b/idea/idea-frontend-independent/resources-en/messages/KotlinBundleIndependent.properties new file mode 100644 index 00000000000..90259c526e0 --- /dev/null +++ b/idea/idea-frontend-independent/resources-en/messages/KotlinBundleIndependent.properties @@ -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=

Find usages for data class components and destructuring declarations
could be disabled once or disabled for a project.

+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 diff --git a/idea/idea-frontend-independent/resources-en/messages/KotlinIdeaAnalysisBundleIndependent.properties b/idea/idea-frontend-independent/resources-en/messages/KotlinIdeaAnalysisBundleIndependent.properties new file mode 100644 index 00000000000..d8c2a4229d5 --- /dev/null +++ b/idea/idea-frontend-independent/resources-en/messages/KotlinIdeaAnalysisBundleIndependent.properties @@ -0,0 +1 @@ +searching.for.implicit.usages=Searching for implicit usages... \ No newline at end of file diff --git a/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/AbstractKotlinBundleIndependent.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/AbstractKotlinBundleIndependent.kt new file mode 100644 index 00000000000..cab9eeb4830 --- /dev/null +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/AbstractKotlinBundleIndependent.kt @@ -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 = "$this" +} \ No newline at end of file diff --git a/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/AbstractKotlinBundleIndependent.kt.193 b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/AbstractKotlinBundleIndependent.kt.193 new file mode 100644 index 00000000000..520bae7804c --- /dev/null +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/AbstractKotlinBundleIndependent.kt.193 @@ -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 = "$this" +} \ No newline at end of file diff --git a/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/KotlinBundleIndependent.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/KotlinBundleIndependent.kt new file mode 100644 index 00000000000..b8f1bad9d04 --- /dev/null +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/KotlinBundleIndependent.kt @@ -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) } +} \ No newline at end of file diff --git a/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/KotlinIdeaAnalysisBundleIndependent.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/KotlinIdeaAnalysisBundleIndependent.kt new file mode 100644 index 00000000000..ea61fe4df25 --- /dev/null +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/KotlinIdeaAnalysisBundleIndependent.kt @@ -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) } +} \ No newline at end of file diff --git a/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/asJava/LightClassProvider.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/asJava/LightClassProvider.kt new file mode 100644 index 00000000000..cb1f970ff9a --- /dev/null +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/asJava/LightClassProvider.kt @@ -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 + + //getLightClassPropertyMethods.allDeclarations + fun getLightClassParameterDeclarations(parameter: KtParameter): List + + //getLightClassPropertyMethods.allDeclarations + fun getLightClassPropertyDeclarations(property: KtProperty): List + + fun toLightClassWithBuiltinMapping(classOrObject: KtClassOrObject): PsiClass? + + fun toLightMethods(psiElement: PsiElement): List + + fun toLightClass(classOrObject: KtClassOrObject): KtLightClass? + + fun toLightElements(ktElement: KtElement): List + + 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 = + getInstance(function.project).getLightClassMethods(function) + + //getLightClassPropertyMethods.allDeclarations + fun providedGetLightClassParameterDeclarations(parameter: KtParameter): List = + getInstance(parameter.project).getLightClassParameterDeclarations(parameter) + + //getLightClassPropertyMethods.allDeclarations + fun providedGetLightClassPropertyDeclarations(property: KtProperty): List = + getInstance(property.project).getLightClassPropertyDeclarations(property) + + fun KtClassOrObject.providedToLightClassWithBuiltinMapping(): PsiClass? = + getInstance(project).toLightClassWithBuiltinMapping(this) + + fun PsiElement.providedToLightMethods(): List = + getInstance(project).toLightMethods(this) + + fun KtClassOrObject.providedToLightClass(): KtLightClass? = + getInstance(project).toLightClass(this) + + fun KtElement.providedToLightElements(): List = + 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) + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/findUsages/KotlinDeclarationGroupRuleProvider.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/KotlinDeclarationGroupRuleProvider.kt similarity index 100% rename from idea/src/org/jetbrains/kotlin/idea/findUsages/KotlinDeclarationGroupRuleProvider.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/KotlinDeclarationGroupRuleProvider.kt diff --git a/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/KotlinElementDescriptionProvider.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/KotlinElementDescriptionProvider.kt new file mode 100644 index 00000000000..40ad4604321 --- /dev/null +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/KotlinElementDescriptionProvider.kt @@ -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() ?: return null + if (parent is KtProperty && parent.isLocal) return parent.parentForFqName() + return parent + } + + private fun KtNamedDeclaration.name() = nameAsName ?: Name.special("") + + 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() + .map { it.name ?: "" } + .toList() + .asReversed() + val packageSegments = containingKtFile.packageFqName.pathSegments() + return FqNameUnsafe((packageSegments + internalSegments).joinToString(".")) + } + + private fun KtTypeReference.renderShort(): String { + return accept( + object : KtVisitor() { + 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 + } + } +} diff --git a/idea/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesHandlerFactory.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesHandlerFactory.kt similarity index 92% rename from idea/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesHandlerFactory.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesHandlerFactory.kt index edcc4bb264c..ca74f4d6b79 100644 --- a/idea/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesHandlerFactory.kt +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesHandlerFactory.kt @@ -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) diff --git a/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesProvider.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesProvider.kt new file mode 100644 index 00000000000..0e4a92cb584 --- /dev/null +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesProvider.kt @@ -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 "" + element.fqName?.asString() ?: element.name ?: "" + } + 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) +} diff --git a/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesSupport.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesSupport.kt new file mode 100644 index 00000000000..a84aa02b976 --- /dev/null +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesSupport.kt @@ -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 = + 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?, + @Nls actionString: String + ): List = 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 + + fun tryRenderDeclarationCompactStyle(declaration: KtDeclaration): String? + + fun isConstructorUsage(psiReference: PsiReference, ktClassOrObject: KtClassOrObject): Boolean + + fun checkSuperMethods( + declaration: KtDeclaration, + ignore: Collection?, + @Nls actionString: String + ): List + + fun sourcesAndLibraries(delegate: GlobalSearchScope, project: Project): GlobalSearchScope +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/findUsages/KotlinImportFilteringRule.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/KotlinImportFilteringRule.kt similarity index 100% rename from idea/src/org/jetbrains/kotlin/idea/findUsages/KotlinImportFilteringRule.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/KotlinImportFilteringRule.kt diff --git a/idea/src/org/jetbrains/kotlin/idea/findUsages/KotlinNonCodeSearchElementDescriptionProvider.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/KotlinNonCodeSearchElementDescriptionProvider.kt similarity index 100% rename from idea/src/org/jetbrains/kotlin/idea/findUsages/KotlinNonCodeSearchElementDescriptionProvider.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/KotlinNonCodeSearchElementDescriptionProvider.kt diff --git a/idea/src/org/jetbrains/kotlin/idea/findUsages/KotlinReferenceUsageInfo.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/KotlinReferenceUsageInfo.kt similarity index 100% rename from idea/src/org/jetbrains/kotlin/idea/findUsages/KotlinReferenceUsageInfo.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/KotlinReferenceUsageInfo.kt diff --git a/idea/src/org/jetbrains/kotlin/idea/findUsages/KotlinWordsScanner.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/KotlinWordsScanner.kt similarity index 100% rename from idea/src/org/jetbrains/kotlin/idea/findUsages/KotlinWordsScanner.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/KotlinWordsScanner.kt diff --git a/idea/src/org/jetbrains/kotlin/idea/findUsages/dialogs/KotlinFindClassUsagesDialog.java b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/dialogs/KotlinFindClassUsagesDialog.java similarity index 85% rename from idea/src/org/jetbrains/kotlin/idea/findUsages/dialogs/KotlinFindClassUsagesDialog.java rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/dialogs/KotlinFindClassUsagesDialog.java index 263c3f9a553..9315cdf411f 100644 --- a/idea/src/org/jetbrains/kotlin/idea/findUsages/dialogs/KotlinFindClassUsagesDialog.java +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/dialogs/KotlinFindClassUsagesDialog.java @@ -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)); } } diff --git a/idea/src/org/jetbrains/kotlin/idea/findUsages/dialogs/KotlinFindFunctionUsagesDialog.java b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/dialogs/KotlinFindFunctionUsagesDialog.java similarity index 85% rename from idea/src/org/jetbrains/kotlin/idea/findUsages/dialogs/KotlinFindFunctionUsagesDialog.java rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/dialogs/KotlinFindFunctionUsagesDialog.java index 290eed109ab..d55cfca0634 100644 --- a/idea/src/org/jetbrains/kotlin/idea/findUsages/dialogs/KotlinFindFunctionUsagesDialog.java +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/dialogs/KotlinFindFunctionUsagesDialog.java @@ -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 diff --git a/idea/src/org/jetbrains/kotlin/idea/findUsages/dialogs/KotlinFindPropertyUsagesDialog.java b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/dialogs/KotlinFindPropertyUsagesDialog.java similarity index 90% rename from idea/src/org/jetbrains/kotlin/idea/findUsages/dialogs/KotlinFindPropertyUsagesDialog.java rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/dialogs/KotlinFindPropertyUsagesDialog.java index cb0742860e8..e2351b8e7f3 100644 --- a/idea/src/org/jetbrains/kotlin/idea/findUsages/dialogs/KotlinFindPropertyUsagesDialog.java +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/dialogs/KotlinFindPropertyUsagesDialog.java @@ -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().also { list -> list += this - list += toLightElements() + list += providedToLightElements() if (this is KtConstructor<*>) { - list.addIfNotNull(getContainingClassOrObject().toLightClass()) + list.addIfNotNull(getContainingClassOrObject().providedToLightClass()) } } } diff --git a/idea/src/org/jetbrains/kotlin/idea/findUsages/findUsagesOptions.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/findUsagesOptions.kt similarity index 100% rename from idea/src/org/jetbrains/kotlin/idea/findUsages/findUsagesOptions.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/findUsagesOptions.kt diff --git a/idea/src/org/jetbrains/kotlin/idea/findUsages/handlers/DelegatingFindMemberUsagesHandler.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/handlers/DelegatingFindMemberUsagesHandler.kt similarity index 100% rename from idea/src/org/jetbrains/kotlin/idea/findUsages/handlers/DelegatingFindMemberUsagesHandler.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/handlers/DelegatingFindMemberUsagesHandler.kt diff --git a/idea/src/org/jetbrains/kotlin/idea/findUsages/handlers/KotlinFindClassUsagesHandler.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/handlers/KotlinFindClassUsagesHandler.kt similarity index 85% rename from idea/src/org/jetbrains/kotlin/idea/findUsages/handlers/KotlinFindClassUsagesHandler.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/handlers/KotlinFindClassUsagesHandler.kt index e75782feec2..c1e1a068a61 100644 --- a/idea/src/org/jetbrains/kotlin/idea/findUsages/handlers/KotlinFindClassUsagesHandler.kt +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/handlers/KotlinFindClassUsagesHandler.kt @@ -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()?.forEach { constructor -> + classOrObject.providedToLightClass()?.constructors?.filterIsInstance()?.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() ?: 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 { val psiClass = when (element) { is PsiClass -> element - is KtClassOrObject -> getElement().toLightClass() + is KtClassOrObject -> getElement().providedToLightClass() else -> null } ?: return Collections.emptyList() diff --git a/idea/src/org/jetbrains/kotlin/idea/findUsages/handlers/KotlinFindMemberUsagesHandler.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/handlers/KotlinFindMemberUsagesHandler.kt similarity index 87% rename from idea/src/org/jetbrains/kotlin/idea/findUsages/handlers/KotlinFindMemberUsagesHandler.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/handlers/KotlinFindMemberUsagesHandler.kt index ffbe09c5d24..3aa8cf235df 100644 --- a/idea/src/org/jetbrains/kotlin/idea/findUsages/handlers/KotlinFindMemberUsagesHandler.kt +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/handlers/KotlinFindMemberUsagesHandler.kt @@ -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 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 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 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 protected c !isSingleFile && psiElement !is KtParameter override fun findReferencesToHighlight(target: PsiElement, searchScope: SearchScope): Collection { - 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 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 diff --git a/idea/src/org/jetbrains/kotlin/idea/findUsages/handlers/KotlinFindUsagesHandler.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/handlers/KotlinFindUsagesHandler.kt similarity index 98% rename from idea/src/org/jetbrains/kotlin/idea/findUsages/handlers/KotlinFindUsagesHandler.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/handlers/KotlinFindUsagesHandler.kt index 7863587bd1e..48691589d79 100644 --- a/idea/src/org/jetbrains/kotlin/idea/findUsages/handlers/KotlinFindUsagesHandler.kt +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/handlers/KotlinFindUsagesHandler.kt @@ -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( diff --git a/idea/src/org/jetbrains/kotlin/idea/findUsages/handlers/KotlinTypeParameterFindUsagesHandler.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/handlers/KotlinTypeParameterFindUsagesHandler.kt similarity index 100% rename from idea/src/org/jetbrains/kotlin/idea/findUsages/handlers/KotlinTypeParameterFindUsagesHandler.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/handlers/KotlinTypeParameterFindUsagesHandler.kt diff --git a/idea/src/org/jetbrains/kotlin/idea/findUsages/handlers/compat.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/handlers/compat.kt similarity index 100% rename from idea/src/org/jetbrains/kotlin/idea/findUsages/handlers/compat.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/handlers/compat.kt diff --git a/idea/src/org/jetbrains/kotlin/idea/findUsages/handlers/compat.kt.193 b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/handlers/compat.kt.193 similarity index 100% rename from idea/src/org/jetbrains/kotlin/idea/findUsages/handlers/compat.kt.193 rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/findUsages/handlers/compat.kt.193 diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/IndexPatternBuilderAdapter.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/IndexPatternBuilderAdapter.kt similarity index 100% rename from idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/IndexPatternBuilderAdapter.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/IndexPatternBuilderAdapter.kt diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/KotlinIndexPatternBuilder.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/KotlinIndexPatternBuilder.kt similarity index 100% rename from idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/KotlinIndexPatternBuilder.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/KotlinIndexPatternBuilder.kt diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/KotlinIndexers.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/KotlinIndexers.kt similarity index 100% rename from idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/KotlinIndexers.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/KotlinIndexers.kt diff --git a/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/KotlinSearchSupport.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/KotlinSearchSupport.kt new file mode 100644 index 00000000000..c4cc0a682e0 --- /dev/null +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/KotlinSearchSupport.kt @@ -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 List.filterDataClassComponentsIfDisabled(kotlinOptions: KotlinReferencesSearchOptions): List = + 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) = + getInstance(project).forceResolveReferences(this, elements) + + fun PsiFile.scriptDefinitionExists(): Boolean = + getInstance(project).scriptDefinitionExists(this) + + fun KtFile.getDefaultImports(): List = + getInstance(project).getDefaultImports(this) + + fun forEachKotlinOverride( + ktClass: KtClass, + members: List, + 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 = + getInstance(method.project).findDeepestSuperMethodsNoWrapping(method) + + fun findTypeAliasByShortName(shortName: String, project: Project, scope: GlobalSearchScope): Collection = + 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 filterDataClassComponentsIfDisabled(elements: List, kotlinOptions: KotlinReferencesSearchOptions): List + + 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) + + fun scriptDefinitionExists(file: PsiFile): Boolean + + fun getDefaultImports(file: KtFile): List + + fun forEachKotlinOverride( + ktClass: KtClass, + members: List, + scope: SearchScope, + processor: (superMember: PsiElement, overridingMember: PsiElement) -> Boolean + ): Boolean + + fun forEachOverridingMethod( + method: PsiMethod, + scope: SearchScope, + processor: (PsiMethod) -> Boolean + ): Boolean + + fun findDeepestSuperMethodsNoWrapping(method: PsiElement): List + + fun findTypeAliasByShortName(shortName: String, project: Project, scope: GlobalSearchScope): Collection + + 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 +} \ No newline at end of file diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/PsiBasedClassResolver.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/PsiBasedClassResolver.kt similarity index 92% rename from idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/PsiBasedClassResolver.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/PsiBasedClassResolver.kt index ebc7080e373..5a7ae764db4 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/PsiBasedClassResolver.kt +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/PsiBasedClassResolver.kt @@ -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 { - val moduleInfo = getNullableModuleInfo() ?: return emptyList() - return TargetPlatformDetector.getPlatform(this).findAnalyzerServices(project).getDefaultImports( - IDELanguageSettingsProvider.getLanguageVersionSettings(moduleInfo, project), - includeLowPriorityImports = true - ) -} +} \ No newline at end of file diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/declarationsSearch/classInheritorsSearch.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/declarationsSearch/classInheritorsSearch.kt similarity index 80% rename from idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/declarationsSearch/classInheritorsSearch.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/declarationsSearch/classInheritorsSearch.kt index 55c29b1ba76..36fefee43ea 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/declarationsSearch/classInheritorsSearch.kt +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/declarationsSearch/classInheritorsSearch.kt @@ -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 { 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() diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/declarationsSearch/declarationSearchUtil.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/declarationsSearch/declarationSearchUtil.kt similarity index 100% rename from idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/declarationsSearch/declarationSearchUtil.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/declarationsSearch/declarationSearchUtil.kt diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/declarationsSearch/overridersSearch.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/declarationsSearch/overridersSearch.kt similarity index 57% rename from idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/declarationsSearch/overridersSearch.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/declarationsSearch/overridersSearch.kt index 6ff05997d46..a3aa14099af 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/declarationsSearch/overridersSearch.kt +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/declarationsSearch/overridersSearch.kt @@ -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 { - 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 { 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, - 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 { - 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() } \ No newline at end of file + findDeepestSuperMethodsNoWrapping(method).mapNotNull { it.providedGetRepresentativeLightMethod() } \ No newline at end of file diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinImportAliasGotoDeclarationHandler.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinImportAliasGotoDeclarationHandler.kt similarity index 100% rename from idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinImportAliasGotoDeclarationHandler.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinImportAliasGotoDeclarationHandler.kt diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinReadWriteAccessDetector.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinReadWriteAccessDetector.kt similarity index 100% rename from idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinReadWriteAccessDetector.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinReadWriteAccessDetector.kt diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinReferenceScopeOptimizer.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinReferenceScopeOptimizer.kt similarity index 100% rename from idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinReferenceScopeOptimizer.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinReferenceScopeOptimizer.kt diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinReferenceScopeOptimizer.kt.193 b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinReferenceScopeOptimizer.kt.193 similarity index 100% rename from idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinReferenceScopeOptimizer.kt.193 rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinReferenceScopeOptimizer.kt.193 diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinReferencesSearcher.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinReferencesSearcher.kt similarity index 81% rename from idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinReferencesSearcher.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinReferencesSearcher.kt index 170e2644d09..04e34bf8c5b 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinReferencesSearcher.kt +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinReferencesSearcher.kt @@ -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 { - val componentFunctionDescriptor = element.dataClassComponentFunction() - if (componentFunctionDescriptor != null) { - val containingClass = element.getStrictParentOfType()?.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()?.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 { 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 { - 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() != 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()?.toLightClass() + val originLightClass = element.getStrictParentOfType()?.providedToLightClass() if (originLightClass != null) { val lightDeclarations: List?> = originLightClass.methods.map { it as? KtLightMethod } + originLightClass.fields.map { it as? KtLightField } @@ -350,13 +336,40 @@ class KotlinReferencesSearcher : QueryExecutorBase { + val componentMethodName = element.dataClassComponentMethodName + if (componentMethodName != null) { + val containingClass = element.getStrictParentOfType()?.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() - 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 } } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinRequestResultProcessor.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinRequestResultProcessor.kt similarity index 91% rename from idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinRequestResultProcessor.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinRequestResultProcessor.kt index 969b31373a7..cf287a9ba98 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinRequestResultProcessor.kt +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinRequestResultProcessor.kt @@ -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 diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/searchUtil.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/searchUtil.kt similarity index 82% rename from idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/searchUtil.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/searchUtil.kt index 77902521844..be92150fc07 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/searchUtil.kt +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/searchUtil.kt @@ -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 { } return collector.results .mapNotNull { PsiManager.getInstance(project).findFile(it) as? KtFile } - .filter { it.findScriptDefinition() != null } + .filter { it.scriptDefinitionExists() } .toList() } + +inline fun 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() != 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 +} \ No newline at end of file diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/ExpressionsOfTypeProcessor.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/usagesSearch/ExpressionsOfTypeProcessor.kt similarity index 95% rename from idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/ExpressionsOfTypeProcessor.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/usagesSearch/ExpressionsOfTypeProcessor.kt index a1a5b39ef1c..b2acb8e8c97 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/ExpressionsOfTypeProcessor.kt +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/usagesSearch/ExpressionsOfTypeProcessor.kt @@ -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() != 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() diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/BinaryOperatorReferenceSearcher.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/BinaryOperatorReferenceSearcher.kt similarity index 100% rename from idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/BinaryOperatorReferenceSearcher.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/BinaryOperatorReferenceSearcher.kt diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/ContainsOperatorReferenceSearcher.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/ContainsOperatorReferenceSearcher.kt similarity index 100% rename from idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/ContainsOperatorReferenceSearcher.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/ContainsOperatorReferenceSearcher.kt diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/DestructuringDeclarationReferenceSearcher.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/DestructuringDeclarationReferenceSearcher.kt similarity index 87% rename from idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/DestructuringDeclarationReferenceSearcher.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/DestructuringDeclarationReferenceSearcher.kt index d7315c9e62b..a742b9f83a5 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/DestructuringDeclarationReferenceSearcher.kt +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/DestructuringDeclarationReferenceSearcher.kt @@ -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 diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/IndexingOperatorReferenceSearcher.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/IndexingOperatorReferenceSearcher.kt similarity index 100% rename from idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/IndexingOperatorReferenceSearcher.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/IndexingOperatorReferenceSearcher.kt diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/InvokeOperatorReferenceSearcher.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/InvokeOperatorReferenceSearcher.kt similarity index 100% rename from idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/InvokeOperatorReferenceSearcher.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/InvokeOperatorReferenceSearcher.kt diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/IteratorOperatorReferenceSearcher.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/IteratorOperatorReferenceSearcher.kt similarity index 100% rename from idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/IteratorOperatorReferenceSearcher.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/IteratorOperatorReferenceSearcher.kt diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/OperatorReferenceSearcher.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/OperatorReferenceSearcher.kt similarity index 83% rename from idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/OperatorReferenceSearcher.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/OperatorReferenceSearcher.kt index 429c78dede2..0ada1b9c1ba 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/OperatorReferenceSearcher.kt +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/OperatorReferenceSearcher.kt @@ -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( @@ -89,10 +77,9 @@ abstract class OperatorReferenceSearcher( 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( } } - 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( try { ExpressionsOfTypeProcessor( - receiverType, + containsTypeOrDerivedInside, psiClass, searchScope, project, @@ -247,27 +226,6 @@ abstract class OperatorReferenceSearcher( } } - 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( } // 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( // 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) } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/PropertyDelegationOperatorReferenceSearcher.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/PropertyDelegationOperatorReferenceSearcher.kt similarity index 100% rename from idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/PropertyDelegationOperatorReferenceSearcher.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/PropertyDelegationOperatorReferenceSearcher.kt diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/UnaryOperatorReferenceSearcher.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/UnaryOperatorReferenceSearcher.kt similarity index 100% rename from idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/UnaryOperatorReferenceSearcher.kt rename to idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/search/usagesSearch/operators/UnaryOperatorReferenceSearcher.kt diff --git a/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/util/ApplicationUtils.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/util/ApplicationUtils.kt index de5923fb4d8..77f9eb8dfc5 100644 --- a/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/util/ApplicationUtils.kt +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/util/ApplicationUtils.kt @@ -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 runReadAction(action: () -> T): T { @@ -55,3 +56,8 @@ inline fun isUnitTestMode(): Boolean = ApplicationManager.getApplication().isUni inline fun ComponentManager.getServiceSafe(): T = this.getService(T::class.java) ?: error("Unable to locate service ${T::class.java.name}") + +fun Project.runReadActionInSmartMode(action: () -> T): T { + if (ApplicationManager.getApplication().isReadAccessAllowed) return action() + return DumbService.getInstance(this).runReadActionInSmartMode(action) +} \ No newline at end of file diff --git a/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/util/ApplicationUtils.kt.193 b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/util/ApplicationUtils.kt.193 index de743788afd..39e98ebdfad 100644 --- a/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/util/ApplicationUtils.kt.193 +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/util/ApplicationUtils.kt.193 @@ -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 runReadAction(action: () -> T): T { return ApplicationManager.getApplication().runReadAction(action) @@ -46,3 +47,8 @@ inline fun isUnitTestMode(): Boolean = ApplicationManager.getApplication().isUni inline fun ComponentManager.getServiceSafe(): T = this.getService(T::class.java) ?: error("Unable to locate service ${T::class.java.name}") + +fun Project.runReadActionInSmartMode(action: () -> T): T { + if (ApplicationManager.getApplication().isReadAccessAllowed) return action() + return DumbService.getInstance(this).runReadActionInSmartMode(action) +} \ No newline at end of file diff --git a/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/util/ApplicationUtils.kt.as40 b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/util/ApplicationUtils.kt.as40 index 7e79539378d..aebd7211d12 100644 --- a/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/util/ApplicationUtils.kt.as40 +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/util/ApplicationUtils.kt.as40 @@ -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 runReadAction(action: () -> T): T { return ApplicationManager.getApplication().runReadAction(action) @@ -62,4 +63,9 @@ inline fun ComponentManager.getServiceSafe(): T = this.getService(T::class.java) ?: error("Unable to locate service ${T::class.java.name}") fun Project.getServiceIfCreated(serviceClass: Class): T? = - ServiceManager.getServiceIfCreated(this, serviceClass) \ No newline at end of file + ServiceManager.getServiceIfCreated(this, serviceClass) + +fun Project.runReadActionInSmartMode(action: () -> T): T { + if (ApplicationManager.getApplication().isReadAccessAllowed) return action() + return DumbService.getInstance(this).runReadActionInSmartMode(action) +} \ No newline at end of file diff --git a/idea/jvm-debugger/jvm-debugger-core/src/org/jetbrains/kotlin/idea/debugger/InlineCallableUsagesSearcher.kt b/idea/jvm-debugger/jvm-debugger-core/src/org/jetbrains/kotlin/idea/debugger/InlineCallableUsagesSearcher.kt index 7adb2f651db..088cdd42e08 100644 --- a/idea/jvm-debugger/jvm-debugger-core/src/org/jetbrains/kotlin/idea/debugger/InlineCallableUsagesSearcher.kt +++ b/idea/jvm-debugger/jvm-debugger-core/src/org/jetbrains/kotlin/idea/debugger/InlineCallableUsagesSearcher.kt @@ -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 diff --git a/idea/resources-en/messages/KotlinBundle.properties b/idea/resources-en/messages/KotlinBundle.properties index 5360f43ae9f..dc5601a7e7a 100644 --- a/idea/resources-en/messages/KotlinBundle.properties +++ b/idea/resources-en/messages/KotlinBundle.properties @@ -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=

Find usages for data class components and destructuring declarations
could be disabled once or disabled for a project.

-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 diff --git a/idea/resources-fir/META-INF/plugin.xml b/idea/resources-fir/META-INF/plugin.xml index c62c7bf5f59..284f85d6903 100644 --- a/idea/resources-fir/META-INF/plugin.xml +++ b/idea/resources-fir/META-INF/plugin.xml @@ -192,6 +192,12 @@ The Kotlin FIR plugin provides language support in IntelliJ IDEA and Android Stu + + + + + + @@ -281,6 +284,12 @@ + + + + = + LightClassUtil.getLightClassMethods(function) + + override fun getLightClassParameterDeclarations(parameter: KtParameter): List = + LightClassUtil.getLightClassPropertyMethods(parameter).allDeclarations + + override fun getLightClassPropertyDeclarations(property: KtProperty): List = + LightClassUtil.getLightClassPropertyMethods(property).allDeclarations + + override fun toLightClassWithBuiltinMapping(classOrObject: KtClassOrObject): PsiClass? = + classOrObject.toLightClassWithBuiltinMapping() + + override fun toLightMethods(psiElement: PsiElement): List = + psiElement.toLightMethods() + + override fun toLightClass(classOrObject: KtClassOrObject): KtLightClass? = + classOrObject.toLightClass() + + override fun toLightElements(ktElement: KtElement): List = + 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) +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/findUsages/KotlinElementDescriptionProvider.kt b/idea/src/org/jetbrains/kotlin/idea/findUsages/KotlinElementDescriptionProvider.kt index 08b7252300d..0056531e841 100644 --- a/idea/src/org/jetbrains/kotlin/idea/findUsages/KotlinElementDescriptionProvider.kt +++ b/idea/src/org/jetbrains/kotlin/idea/findUsages/KotlinElementDescriptionProvider.kt @@ -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() ?: return null - if (parent is KtProperty && parent.isLocal) return parent.parentForFqName() - return parent - } +class KotlinElementDescriptionProvider : KotlinElementDescriptionProviderBase() { - private fun KtNamedDeclaration.name() = nameAsName ?: Name.special("") + 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() - .map { it.name ?: "" } - .toList() - .asReversed() - val packageSegments = containingKtFile.packageFqName.pathSegments() - return FqNameUnsafe((packageSegments + internalSegments).joinToString(".")) - } - - private fun KtTypeReference.renderShort(): String { - return accept( - object : KtVisitor() { - 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 } diff --git a/idea/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesProvider.kt b/idea/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesProvider.kt index c205744cce7..449fe7ed043 100644 --- a/idea/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesProvider.kt +++ b/idea/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesProvider.kt @@ -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 "" - element.fqName?.asString() ?: element.name ?: "" - } - 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 = diff --git a/idea/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesSupportImpl.kt b/idea/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesSupportImpl.kt new file mode 100644 index 00000000000..152f831ad57 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesSupportImpl.kt @@ -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 = + 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?, actionString: String): List = + 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) +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createClass/CreateClassFromUsageFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createClass/CreateClassFromUsageFix.kt index 74c0fe95a0a..24e2f864c92 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createClass/CreateClassFromUsageFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createClass/CreateClassFromUsageFix.kt @@ -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")), diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceImportAlias/KotlinIntroduceImportAliasHandler.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceImportAlias/KotlinIntroduceImportAliasHandler.kt index 6f1026b7b77..050c8da9bda 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceImportAlias/KotlinIntroduceImportAliasHandler.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceImportAlias/KotlinIntroduceImportAliasHandler.kt @@ -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, newName: String) { // case: inner element for (usage in usages.asReversed()) { - val reference = usage.pointer.element?.safeAs()?.mainReference?.takeUnless(KtReference::isImportUsage) ?: continue + val reference = usage.pointer.element?.safeAs()?.mainReference?.takeUnless { it.isImportUsage() } ?: continue val newExpression = reference.handleElementRename(newName) as? KtNameReferenceExpression ?: continue if (usage.isExtension) { newExpression.getQualifiedElementSelector()?.replace(newExpression) diff --git a/idea/src/org/jetbrains/kotlin/idea/search/KotlinSearchUsagesSupportImpl.kt b/idea/src/org/jetbrains/kotlin/idea/search/KotlinSearchUsagesSupportImpl.kt new file mode 100644 index 00000000000..3d0ee2842b8 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/search/KotlinSearchUsagesSupportImpl.kt @@ -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 filterDataClassComponentsIfDisabled( + elements: List, + kotlinOptions: KotlinReferencesSearchOptions + ): List = + 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) = + file.forceResolveReferences(elements) + + override fun scriptDefinitionExists(file: PsiFile): Boolean = + file.scriptDefinitionExists() + + override fun getDefaultImports(file: KtFile): List = + file.getDefaultImports() + + override fun forEachKotlinOverride( + ktClass: KtClass, + members: List, + 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 = + org.jetbrains.kotlin.idea.search.declarationsSearch.findDeepestSuperMethodsNoWrapping(method) + + override fun findTypeAliasByShortName(shortName: String, project: Project, scope: GlobalSearchScope): Collection = + 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() +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/search/declarationsSearch/overridersSearchUtils.kt b/idea/src/org/jetbrains/kotlin/idea/search/declarationsSearch/overridersSearchUtils.kt new file mode 100644 index 00000000000..a079732fea7 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/search/declarationsSearch/overridersSearchUtils.kt @@ -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, + 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 { + 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() + } +} \ No newline at end of file diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/utils.kt b/idea/src/org/jetbrains/kotlin/idea/search/usagesSearch/utils.kt similarity index 72% rename from idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/utils.kt rename to idea/src/org/jetbrains/kotlin/idea/search/usagesSearch/utils.kt index f2fa5f9a692..493af3a5edc 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/usagesSearch/utils.kt +++ b/idea/src/org/jetbrains/kotlin/idea/search/usagesSearch/utils.kt @@ -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() != null - fun PsiReference.isConstructorUsage(ktClassOrObject: KtClassOrObject): Boolean = with(element) { fun checkJavaUsage(): Boolean { val call = getNonStrictParentOfType() @@ -306,4 +331,72 @@ fun List.filterDataClassComponentsIfDisabled(kotlinOpti } return filter { !it.isComponentElement() } -} \ No newline at end of file +} + +fun KtFile.forceResolveReferences(elements: List) { + 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 { + val moduleInfo = getNullableModuleInfo() ?: return emptyList() + return TargetPlatformDetector.getPlatform(this).findAnalyzerServices(project).getDefaultImports( + IDELanguageSettingsProvider.getLanguageVersionSettings(moduleInfo, project), + includeLowPriorityImports = true + ) +} + +fun PsiFile.scriptDefinitionExists(): Boolean = findScriptDefinition() != null \ No newline at end of file diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/symbols/utils.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/symbols/utils.kt index 4f34c033984..631e7ab0724 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/symbols/utils.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/symbols/utils.kt @@ -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