From f69df70a75c0c011c8cbf712946f8a70039603ce Mon Sep 17 00:00:00 2001 From: Dmitry Gridin Date: Fri, 22 Oct 2021 20:13:08 +0700 Subject: [PATCH] [cri] fix hierarchy navigation for classes that are not used directly from java For such classes, `NameEnumerator` returns the identifier 0, which makes it impossible to search subclasses in other languages ^KTIJ-16709 GitOrigin-RevId: bed282c2a965387e046b079ed98d908ce9c98fc9 --- .../backwardRefs/DirectInheritorProvider.kt | 11 +- ...vaBackwardReferenceIndexReaderFactory.java | 5 +- .../compiler/backwardRefs/SearchId.java | 20 +--- .../kotlinInterfaceImplThroughDelegate.0.kt | 3 +- .../kotlinInterfaceNoImplThroughDelegate.0.kt | 3 +- .../idea/search/refIndex/FqNameWrapper.kt | 2 +- .../JavaCompilerClassRefWithSearchId.kt | 55 +++++++++ .../refIndex/KotlinCompilerRefHelper.kt | 112 +++++++++--------- .../CustomKotlinCompilerReferenceTest.kt | 30 +++++ .../testNonPresentedClass/Hierarchy.java | 60 ++++++++++ .../testNonPresentedClass/KotlinOnlyClass.kt | 23 ++++ .../testNonPresentedClass/Parameter.java | 60 ++++++++++ .../Hierarchy.java | 39 ++++++ .../KotlinOnlyClass.kt | 43 +++++++ .../Parameter.java | 39 ++++++ 15 files changed, 426 insertions(+), 79 deletions(-) create mode 100644 plugins/kotlin/refIndex/src/org/jetbrains/kotlin/idea/search/refIndex/JavaCompilerClassRefWithSearchId.kt create mode 100644 plugins/kotlin/refIndex/tests/testData/customCompilerIndexData/testNonPresentedClass/Hierarchy.java create mode 100644 plugins/kotlin/refIndex/tests/testData/customCompilerIndexData/testNonPresentedClass/KotlinOnlyClass.kt create mode 100644 plugins/kotlin/refIndex/tests/testData/customCompilerIndexData/testNonPresentedClass/Parameter.java create mode 100644 plugins/kotlin/refIndex/tests/testData/customCompilerIndexData/testNonPresentedClassWithCompanion/Hierarchy.java create mode 100644 plugins/kotlin/refIndex/tests/testData/customCompilerIndexData/testNonPresentedClassWithCompanion/KotlinOnlyClass.kt create mode 100644 plugins/kotlin/refIndex/tests/testData/customCompilerIndexData/testNonPresentedClassWithCompanion/Parameter.java diff --git a/java/compiler/impl/src/com/intellij/compiler/backwardRefs/DirectInheritorProvider.kt b/java/compiler/impl/src/com/intellij/compiler/backwardRefs/DirectInheritorProvider.kt index 5059a31d0cbe..e8c583509b1e 100644 --- a/java/compiler/impl/src/com/intellij/compiler/backwardRefs/DirectInheritorProvider.kt +++ b/java/compiler/impl/src/com/intellij/compiler/backwardRefs/DirectInheritorProvider.kt @@ -13,8 +13,17 @@ import org.jetbrains.jps.backwardRefs.NameEnumerator interface DirectInheritorProvider { companion object { @JvmField - val EP_NAME = ExtensionPointName.create("com.intellij.languageCompilerRefAdapter.directInheritorProvider"); + val EP_NAME = ExtensionPointName.create("com.intellij.languageCompilerRefAdapter.directInheritorProvider") } fun findDirectInheritors(searchId: SearchId, nameEnumerator: NameEnumerator): Collection +} + +/** + * An interface provides missing information to [JavaBackwardReferenceIndexReaderFactory.BackwardReferenceReader.getHierarchy] for finding + * classes not involved in Java compilation + */ +@IntellijInternalApi +interface SearchIdHolder { + val searchId: SearchId } \ No newline at end of file diff --git a/java/compiler/impl/src/com/intellij/compiler/backwardRefs/JavaBackwardReferenceIndexReaderFactory.java b/java/compiler/impl/src/com/intellij/compiler/backwardRefs/JavaBackwardReferenceIndexReaderFactory.java index 1d95100ff4f5..8738298b9f50 100644 --- a/java/compiler/impl/src/com/intellij/compiler/backwardRefs/JavaBackwardReferenceIndexReaderFactory.java +++ b/java/compiler/impl/src/com/intellij/compiler/backwardRefs/JavaBackwardReferenceIndexReaderFactory.java @@ -265,7 +265,10 @@ public final class JavaBackwardReferenceIndexReaderFactory implements CompilerRe return true; }); try { - SearchId searchId = CompilerHierarchySearchType.DIRECT_INHERITOR.convertToId(curClass, myIndex.getByteSeqEum()); + SearchId searchId = curClass instanceof SearchIdHolder + ? ((SearchIdHolder)curClass).getSearchId() + : CompilerHierarchySearchType.DIRECT_INHERITOR.convertToId(curClass, myIndex.getByteSeqEum()); + for (DirectInheritorProvider provider : directInheritorProviders) { q.addAll(provider.findDirectInheritors(searchId, myIndex.getByteSeqEum())); } diff --git a/java/compiler/impl/src/com/intellij/compiler/backwardRefs/SearchId.java b/java/compiler/impl/src/com/intellij/compiler/backwardRefs/SearchId.java index 93fc74848ade..0459c46fc77b 100644 --- a/java/compiler/impl/src/com/intellij/compiler/backwardRefs/SearchId.java +++ b/java/compiler/impl/src/com/intellij/compiler/backwardRefs/SearchId.java @@ -1,20 +1,7 @@ -/* - * Copyright 2000-2017 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 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.compiler.backwardRefs; +import com.intellij.openapi.util.IntellijInternalApi; import org.jetbrains.annotations.Nullable; public class SearchId { @@ -26,7 +13,8 @@ public class SearchId { myId = id; } - SearchId(@Nullable String deserializedName) { + @IntellijInternalApi + public SearchId(@Nullable String deserializedName) { this(deserializedName, -1); } diff --git a/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findFunctionUsages/kotlinInterfaceImplThroughDelegate.0.kt b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findFunctionUsages/kotlinInterfaceImplThroughDelegate.0.kt index 8de484b18794..63ca634951c2 100644 --- a/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findFunctionUsages/kotlinInterfaceImplThroughDelegate.0.kt +++ b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findFunctionUsages/kotlinInterfaceImplThroughDelegate.0.kt @@ -10,5 +10,4 @@ public class InterfaceWithDelegatedWithImpl(f: InterfaceWithImpl) : InterfaceWit fun test(twdwi: InterfaceWithDelegatedWithImpl) = twdwi.foo() -// FIR_COMPARISON -// CRI_IGNORE \ No newline at end of file +// FIR_COMPARISON \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findFunctionUsages/kotlinInterfaceNoImplThroughDelegate.0.kt b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findFunctionUsages/kotlinInterfaceNoImplThroughDelegate.0.kt index e7198aec703a..7ccc1e488caf 100644 --- a/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findFunctionUsages/kotlinInterfaceNoImplThroughDelegate.0.kt +++ b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findFunctionUsages/kotlinInterfaceNoImplThroughDelegate.0.kt @@ -10,5 +10,4 @@ public class InterfaceWithDelegatedNoImpl(f: InterfaceNoImpl) : InterfaceNoImpl fun test(twdni: InterfaceWithDelegatedNoImpl) = twdni.foo() -// FIR_COMPARISON -// CRI_IGNORE \ No newline at end of file +// FIR_COMPARISON \ No newline at end of file diff --git a/plugins/kotlin/refIndex/src/org/jetbrains/kotlin/idea/search/refIndex/FqNameWrapper.kt b/plugins/kotlin/refIndex/src/org/jetbrains/kotlin/idea/search/refIndex/FqNameWrapper.kt index d6886e3932ac..a720be0d987e 100644 --- a/plugins/kotlin/refIndex/src/org/jetbrains/kotlin/idea/search/refIndex/FqNameWrapper.kt +++ b/plugins/kotlin/refIndex/src/org/jetbrains/kotlin/idea/search/refIndex/FqNameWrapper.kt @@ -48,4 +48,4 @@ private class JvmFqNameBasedWrapper(override val jvmFqName: String) : FqNameWrap } fun FqNameWrapper.asJavaCompilerClassRef(nameEnumerator: NameEnumerator): CompilerRef.JavaCompilerClassRef = - CompilerRef.JavaCompilerClassRef(nameEnumerator.tryEnumerate(jvmFqName)) + JavaCompilerClassRefWithSearchId.create(jvmFqName, nameEnumerator) diff --git a/plugins/kotlin/refIndex/src/org/jetbrains/kotlin/idea/search/refIndex/JavaCompilerClassRefWithSearchId.kt b/plugins/kotlin/refIndex/src/org/jetbrains/kotlin/idea/search/refIndex/JavaCompilerClassRefWithSearchId.kt new file mode 100644 index 000000000000..b785020ac585 --- /dev/null +++ b/plugins/kotlin/refIndex/src/org/jetbrains/kotlin/idea/search/refIndex/JavaCompilerClassRefWithSearchId.kt @@ -0,0 +1,55 @@ +// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package org.jetbrains.kotlin.idea.search.refIndex + +import com.intellij.compiler.backwardRefs.SearchId +import com.intellij.compiler.backwardRefs.SearchIdHolder +import org.jetbrains.jps.backwardRefs.CompilerRef +import org.jetbrains.jps.backwardRefs.NameEnumerator +import org.jetbrains.kotlin.idea.util.jvmFqName +import org.jetbrains.kotlin.psi.KtClassOrObject + +class JavaCompilerClassRefWithSearchId private constructor( + override val jvmClassName: String, + qualifierId: Int, +) : CompilerRef.JavaCompilerClassRef(qualifierId), CompilerClassHierarchyElementDefWithSearchId { + override val searchId: SearchId get() = SearchId(jvmClassName) + + override fun createMethod(name: Int, parameterCount: Int): CompilerRef.CompilerMember = JavaCompilerMethodRefWithSearchIdOwner( + owner = this, + name = name, + parameterCount = parameterCount, + ) + + override fun createField(name: Int): CompilerRef.CompilerMember = JavaCompilerFieldRefWithSearchIdOwner(owner = this, name = name) + + companion object { + fun create(classOrObject: KtClassOrObject, names: NameEnumerator): JavaCompilerClassRefWithSearchId? { + val qualifier = classOrObject.jvmFqName ?: return null + return JavaCompilerClassRefWithSearchId(qualifier, names.tryEnumerate(qualifier)) + } + + fun create(jvmClassName: String, names: NameEnumerator): JavaCompilerClassRefWithSearchId = + JavaCompilerClassRefWithSearchId(jvmClassName, names.tryEnumerate(jvmClassName)) + } +} + +private class JavaCompilerFieldRefWithSearchIdOwner( + private val owner: CompilerClassHierarchyElementDefWithSearchId, + name: Int, +) : CompilerRef.JavaCompilerFieldRef(owner.name, name) { + override fun getOwner(): CompilerRef.CompilerClassHierarchyElementDef = owner +} + +private class JavaCompilerMethodRefWithSearchIdOwner( + private val owner: CompilerClassHierarchyElementDefWithSearchId, + name: Int, + parameterCount: Int, +) : CompilerRef.JavaCompilerMethodRef(owner.name, name, parameterCount) { + override fun getOwner(): CompilerRef.CompilerClassHierarchyElementDef = owner +} + +interface CompilerClassHierarchyElementDefWithSearchId : CompilerRef.CompilerClassHierarchyElementDef, SearchIdHolder { + fun createMethod(name: Int, parameterCount: Int): CompilerRef.CompilerMember + fun createField(name: Int): CompilerRef.CompilerMember + val jvmClassName: String +} \ No newline at end of file diff --git a/plugins/kotlin/refIndex/src/org/jetbrains/kotlin/idea/search/refIndex/KotlinCompilerRefHelper.kt b/plugins/kotlin/refIndex/src/org/jetbrains/kotlin/idea/search/refIndex/KotlinCompilerRefHelper.kt index 8586d9c784d0..6814b24f2a0f 100644 --- a/plugins/kotlin/refIndex/src/org/jetbrains/kotlin/idea/search/refIndex/KotlinCompilerRefHelper.kt +++ b/plugins/kotlin/refIndex/src/org/jetbrains/kotlin/idea/search/refIndex/KotlinCompilerRefHelper.kt @@ -102,26 +102,28 @@ private fun KtCallableDeclaration.asObjectMemberCompilerRefs( } private fun KtCallableDeclaration.asTopLevelCompilerRefs(names: NameEnumerator): List? = - containingKtFile.javaFileFacadeFqName.asString().let(names::tryEnumerate).let { qualifierId -> + containingKtFile.javaFileFacadeFqName.asString().asClassCompilerRef(names).let { owner -> when (this) { - is KtNamedFunction -> asFunctionCompilerRefs(qualifierId, names) - is KtProperty -> asPropertyCompilerRefs(qualifierId, names) + is KtNamedFunction -> asFunctionCompilerRefs(owner, names) + is KtProperty -> asPropertyCompilerRefs(owner, names) else -> null } } -private fun KtClassOrObject.asClassCompilerRef(names: NameEnumerator): CompilerRef.CompilerClassHierarchyElementDef? = - qualifierId(names)?.let(CompilerRef::JavaCompilerClassRef) +private fun String.asClassCompilerRef( + names: NameEnumerator, +): CompilerClassHierarchyElementDefWithSearchId = JavaCompilerClassRefWithSearchId.create(this, names) -private fun KtClassOrObject.qualifier(): String? = jvmFqName -private fun KtClassOrObject.qualifierId(names: NameEnumerator): Int? = qualifier()?.let(names::tryEnumerate) +private fun KtClassOrObject.asClassCompilerRef( + names: NameEnumerator, +): CompilerClassHierarchyElementDefWithSearchId? = JavaCompilerClassRefWithSearchId.create(this, names) private fun KtObjectDeclaration.asObjectCompilerRefs(names: NameEnumerator): List? { val classCompilerRef = asClassCompilerRef(names) ?: return null val instanceField = if (isCompanion()) { asCompanionCompilerRef(names) } else { - CompilerRef.JavaCompilerFieldRef(classCompilerRef.name, names.tryEnumerate("INSTANCE")) + classCompilerRef.createField(names.tryEnumerate("INSTANCE")) } return listOfNotNull(classCompilerRef, instanceField) @@ -129,23 +131,23 @@ private fun KtObjectDeclaration.asObjectCompilerRefs(names: NameEnumerator): Lis private fun KtObjectDeclaration.asCompanionCompilerRef(names: NameEnumerator): CompilerRef.NamedCompilerRef? { val name = name ?: return null - val qualifierId = containingClassOrObject?.qualifierId(names) ?: return null - return CompilerRef.JavaCompilerFieldRef(qualifierId, names.tryEnumerate(name)) + val owner = containingClassOrObject?.asClassCompilerRef(names) ?: return null + return owner.createField(names.tryEnumerate(name)) } private fun KtConstructor<*>.asConstructorCompilerRef(names: NameEnumerator): List? { - val qualifierId = getContainingClassOrObject().qualifierId(names) ?: return null + val owner = getContainingClassOrObject().asClassCompilerRef(names) ?: return null val nameId = names.tryEnumerate("") - return asCompilerRefsWithJvmOverloads(qualifierId, nameId) + return asCompilerRefsWithJvmOverloads(owner, nameId) } private fun KtNamedFunction.asFunctionCompilerRefs( - qualifierId: Int, + owner: CompilerClassHierarchyElementDefWithSearchId, names: NameEnumerator, isDefaultImplsMember: Boolean = false, ): List { val nameId = names.tryEnumerate(jvmName ?: name) - return asCompilerRefsWithJvmOverloads(qualifierId, nameId, isDefaultImplsMember) + return asCompilerRefsWithJvmOverloads(owner, nameId, isDefaultImplsMember) } private fun KtNamedFunction.asClassMemberFunctionCompilerRefs( @@ -154,8 +156,8 @@ private fun KtNamedFunction.asClassMemberFunctionCompilerRefs( ): List? = asClassMemberCompilerRefs( containingClass = containingClass, names = names, - methodHandler = { qualifierId -> asFunctionCompilerRefs(qualifierId, names) }, - defaultMethodHandler = { qualifierId -> asFunctionCompilerRefs(qualifierId, names, isDefaultImplsMember = true) }, + methodHandler = { owner -> asFunctionCompilerRefs(owner, names) }, + defaultMethodHandler = { owner -> asFunctionCompilerRefs(owner, names, isDefaultImplsMember = true) }, ) private fun KtProperty.asClassMemberPropertyCompilerRefs( @@ -164,22 +166,22 @@ private fun KtProperty.asClassMemberPropertyCompilerRefs( ): List? = asClassMemberCompilerRefs( containingClass = containingClass, names = names, - methodHandler = { qualifierId -> asPropertyCompilerRefs(qualifierId, names) }, - defaultMethodHandler = { qualifierId -> asPropertyCompilerRefs(qualifierId, names, fieldOwnerId = null, isDefaultImplsMember = true) }, + methodHandler = { owner -> asPropertyCompilerRefs(owner, names) }, + defaultMethodHandler = { owner -> asPropertyCompilerRefs(owner, names, fieldOwner = null, isDefaultImplsMember = true) }, ) private fun KtCallableDeclaration.asClassMemberCompilerRefs( containingClass: KtClass, names: NameEnumerator, - methodHandler: (qualifierId: Int) -> List?, - defaultMethodHandler: (qualifierId: Int) -> List? = methodHandler, + methodHandler: (owner: CompilerClassHierarchyElementDefWithSearchId) -> List?, + defaultMethodHandler: (owner: CompilerClassHierarchyElementDefWithSearchId) -> List? = methodHandler, ): List? { - val qualifier = containingClass.qualifier() ?: return null - val compilerMembers = methodHandler(names.tryEnumerate(qualifier)) + val owner = containingClass.asClassCompilerRef(names) ?: return null + val compilerMembers = methodHandler(owner) if (!containingClass.isInterface() || !hasBody()) return compilerMembers - val defaultImplQualifier = qualifier + JvmAbi.DEFAULT_IMPLS_SUFFIX - val defaultImplMembers = defaultMethodHandler(names.tryEnumerate(defaultImplQualifier)) + val defaultImplQualifier = owner.jvmClassName + JvmAbi.DEFAULT_IMPLS_SUFFIX + val defaultImplMembers = defaultMethodHandler(defaultImplQualifier.asClassCompilerRef(names)) ?: return compilerMembers return compilerMembers?.plus(defaultImplMembers) ?: defaultImplMembers @@ -189,33 +191,33 @@ private fun KtNamedFunction.asObjectMemberFunctionCompilerRefs( containingObject: KtObjectDeclaration, names: NameEnumerator, ): List? { - val qualifierId = containingObject.qualifierId(names) ?: return null - val compilerMembers = asFunctionCompilerRefs(qualifierId, names) - val additionalQualifierId = containingObject.takeIf { hasJvmStaticAnnotation() } + val owner = containingObject.asClassCompilerRef(names) ?: return null + val compilerMembers = asFunctionCompilerRefs(owner, names) + val additionalOwner = containingObject.takeIf { hasJvmStaticAnnotation() } ?.containingClassOrObject - ?.qualifierId(names) + ?.asClassCompilerRef(names) ?: return compilerMembers - return compilerMembers + asFunctionCompilerRefs(additionalQualifierId, names) + return compilerMembers + asFunctionCompilerRefs(additionalOwner, names) } private fun KtFunction.asCompilerRefsWithJvmOverloads( - qualifierId: Int, + owner: CompilerClassHierarchyElementDefWithSearchId, nameId: Int, isDefaultImplsMember: Boolean = false, ): List { val numberOfArguments = numberOfArguments(countReceiver = true) + (1.takeIf { isDefaultImplsMember } ?: 0) if (!hasJvmOverloadsAnnotation()) { - val mainMethodRef = CompilerRef.JavaCompilerMethodRef(qualifierId, nameId, numberOfArguments) + val mainMethodRef = owner.createMethod(nameId, numberOfArguments) return if (this is KtPrimaryConstructor && valueParameters.all(KtParameter::hasDefaultValue)) { - listOf(mainMethodRef, CompilerRef.JavaCompilerMethodRef(qualifierId, nameId, 0)) + listOf(mainMethodRef, owner.createMethod(nameId, 0)) } else { listOf(mainMethodRef) } } return numberOfArguments.minus(valueParameters.count(KtParameter::hasDefaultValue)).rangeTo(numberOfArguments).map { - CompilerRef.JavaCompilerMethodRef(qualifierId, nameId, it) + owner.createMethod(nameId, it) } } @@ -223,25 +225,25 @@ private fun KtProperty.asObjectMemberPropertyCompilerRefs( containingObject: KtObjectDeclaration, names: NameEnumerator, ): List? { - val qualifierId = containingObject.qualifierId(names) ?: return null + val owner = containingObject.asClassCompilerRef(names) ?: return null if (!containingObject.isCompanion()) { - return asPropertyCompilerRefs(qualifierId, names) + return asPropertyCompilerRefs(owner, names) } - val fieldOwnerId = containingObject.containingClassOrObject?.qualifierId(names) - val compilerMembers = asPropertyCompilerRefs(qualifierId, names, fieldOwnerId) - if (!hasJvmStaticAnnotation() || fieldOwnerId == null) return compilerMembers + val fieldOwner = containingObject.containingClassOrObject?.asClassCompilerRef(names) + val compilerMembers = asPropertyCompilerRefs(owner, names, fieldOwner) + if (!hasJvmStaticAnnotation() || fieldOwner == null) return compilerMembers - val staticMembers = asPropertyCompilerRefs(fieldOwnerId, names, fieldOwnerId = null) ?: return compilerMembers + val staticMembers = asPropertyCompilerRefs(fieldOwner, names, fieldOwner = null) ?: return compilerMembers return compilerMembers?.plus(staticMembers) ?: staticMembers } private fun KtProperty.asPropertyCompilerRefs( - qualifierId: Int, + owner: CompilerClassHierarchyElementDefWithSearchId, names: NameEnumerator, - fieldOwnerId: Int? = qualifierId, + fieldOwner: CompilerClassHierarchyElementDefWithSearchId? = owner, isDefaultImplsMember: Boolean = false, -): List? = asPropertyOrParameterCompilerRefs(qualifierId, names, isVar, fieldOwnerId, isDefaultImplsMember) +): List? = asPropertyOrParameterCompilerRefs(owner, names, isVar, fieldOwner, isDefaultImplsMember) private fun KtParameter.asParameterCompilerRefs( containingClass: KtClass, @@ -249,48 +251,46 @@ private fun KtParameter.asParameterCompilerRefs( ): List? { if (!hasValOrVar()) return null - val qualifierId = containingClass.qualifierId(names) ?: return null + val owner = containingClass.asClassCompilerRef(names) ?: return null if (containingClassOrObject?.isAnnotation() == true) { val name = name ?: return null - return listOf(CompilerRef.JavaCompilerMethodRef(qualifierId, names.tryEnumerate(name), 0)) + return listOf(owner.createMethod(names.tryEnumerate(name), 0)) } - val compilerMembers = asPropertyOrParameterCompilerRefs(qualifierId, names, isMutable) + val compilerMembers = asPropertyOrParameterCompilerRefs(owner, names, isMutable) val componentFunctionMember = asComponentFunctionName?.let { - CompilerRef.JavaCompilerMethodRef(qualifierId, names.tryEnumerate(it), 0) + owner.createMethod(names.tryEnumerate(it), 0) } ?: return compilerMembers return compilerMembers?.plus(componentFunctionMember) ?: listOf(componentFunctionMember) } private fun T.asPropertyOrParameterCompilerRefs( - qualifierId: Int, + owner: CompilerClassHierarchyElementDefWithSearchId, names: NameEnumerator, isMutable: Boolean, - fieldOwnerId: Int? = qualifierId, + fieldOwner: CompilerClassHierarchyElementDefWithSearchId? = owner, isDefaultImplsMember: Boolean = false, ): List? where T : KtCallableDeclaration, T : KtValVarKeywordOwner { val name = name ?: return null - if (fieldOwnerId != null && (hasModifier(KtTokens.CONST_KEYWORD) || hasJvmFieldAnnotation())) { - return listOf(CompilerRef.JavaCompilerFieldRef(fieldOwnerId, names.tryEnumerate(name))) + if (fieldOwner != null && (hasModifier(KtTokens.CONST_KEYWORD) || hasJvmFieldAnnotation())) { + return listOf(fieldOwner.createField(names.tryEnumerate(name))) } - val field = if (fieldOwnerId != null && hasModifier(KtTokens.LATEINIT_KEYWORD)) { - CompilerRef.JavaCompilerFieldRef(fieldOwnerId, names.tryEnumerate(name)) + val field = if (fieldOwner != null && hasModifier(KtTokens.LATEINIT_KEYWORD)) { + fieldOwner.createField(names.tryEnumerate(name)) } else { null } val numberOfArguments = numberOfArguments(countReceiver = true) + (1.takeIf { isDefaultImplsMember } ?: 0) - val getter = CompilerRef.JavaCompilerMethodRef( - qualifierId, + val getter = owner.createMethod( names.tryEnumerate(jvmGetterName ?: JvmAbi.getterName(name)), numberOfArguments, ) val setter = if (isMutable) - CompilerRef.JavaCompilerMethodRef( - qualifierId, + owner.createMethod( names.tryEnumerate(jvmSetterName ?: JvmAbi.setterName(name)), numberOfArguments + 1, ) diff --git a/plugins/kotlin/refIndex/tests/test/org/jetbrains/kotlin/idea/search/refIndex/CustomKotlinCompilerReferenceTest.kt b/plugins/kotlin/refIndex/tests/test/org/jetbrains/kotlin/idea/search/refIndex/CustomKotlinCompilerReferenceTest.kt index 89d83cb05574..b76250ff9b51 100644 --- a/plugins/kotlin/refIndex/tests/test/org/jetbrains/kotlin/idea/search/refIndex/CustomKotlinCompilerReferenceTest.kt +++ b/plugins/kotlin/refIndex/tests/test/org/jetbrains/kotlin/idea/search/refIndex/CustomKotlinCompilerReferenceTest.kt @@ -12,9 +12,13 @@ import com.intellij.testFramework.SkipSlowTestLocally import junit.framework.AssertionFailedError import junit.framework.TestCase import org.jetbrains.jps.backwardRefs.CompilerRef +import org.jetbrains.kotlin.asJava.unwrapped import org.jetbrains.kotlin.idea.highlighter.markers.OVERRIDDEN_FUNCTION import org.jetbrains.kotlin.idea.highlighter.markers.SUBCLASSED_CLASS import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName +import org.jetbrains.kotlin.psi.KtClass +import org.jetbrains.kotlin.psi.KtDeclaration +import org.jetbrains.kotlin.psi.KtObjectDeclaration import org.jetbrains.kotlin.test.KotlinRoot import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull import kotlin.io.path.Path @@ -309,4 +313,30 @@ class CustomKotlinCompilerReferenceTest : KotlinCompilerReferenceTestBase() { .findAll() .map { it.getKotlinFqName().toString() } .sorted() + + fun testNonPresentedClass(): Unit = doTestNonPresentedClass(7) + + fun testNonPresentedClassWithCompanion(): Unit = doTestNonPresentedClass(13) + + private fun doTestNonPresentedClass(declarationsCount: Int) { + myFixture.configureByFiles( + "Hierarchy.java", + "KotlinOnlyClass.kt", + "Parameter.java", + ) + + val kotlinOnlyClass = myFixture.findClass("one.KotlinOnlyClass").unwrapped as KtClass + val declarations = kotlinOnlyClass.declarations.fold(mutableListOf()) { list, declaration -> + if (declaration is KtObjectDeclaration) list += declaration.declarations else list += declaration + list + } + + assertEquals(declarationsCount, declarations.size) + rebuildProject() + for (declaration in declarations) { + val referentFiles = getReferentFiles(declaration, withJavaIndex = true) ?: error("${declaration.name}: file is not found") + assertTrue(declaration.name, "Hierarchy.java" in referentFiles) + assertTrue(declaration.name, "Parameter.java" in referentFiles) + } + } } diff --git a/plugins/kotlin/refIndex/tests/testData/customCompilerIndexData/testNonPresentedClass/Hierarchy.java b/plugins/kotlin/refIndex/tests/testData/customCompilerIndexData/testNonPresentedClass/Hierarchy.java new file mode 100644 index 000000000000..6c64dc2cf90f --- /dev/null +++ b/plugins/kotlin/refIndex/tests/testData/customCompilerIndexData/testNonPresentedClass/Hierarchy.java @@ -0,0 +1,60 @@ +package one; + + +public class Hierarchy extends Proxy { + void classMembers() { + this.getProperty(); + + int fieldProperty = this.fieldProperty; + + this.getVariable(); + this.setVariable(42); + + this.fieldVariable = 4; + int fieldVariable = this.fieldVariable; + + Custom lateinitVariable = this.lateinitVariable; + this.lateinitVariable = new Custom(); + this.setLateinitVariable(lateinitVariable); + this.getLateinitVariable(); + + this.simpleFunction(42); + + this.extension("awd"); + } + + //void companionMembers() { + // Companion.getCompanionproperty(); + // + // int companionfieldProperty1 = companionfieldProperty; + // + // getCompanionstaticProperty(); + // + // int companionconstProperty1 = companionconstProperty; + // + // Companion.getCompanionvariable(); + // Companion.setCompanionvariable(4); + // + // int companionfieldVariable1 = companionfieldVariable; + // companionfieldVariable = 4; + // + // getCompanionstaticVariable(); + // setCompanionstaticVariable(4); + // + // Custom companionlateinitVariable = KotlinOnlyClass.companionlateinitVariable; + // Companion.getCompanionlateinitVariable(); + // Companion.setCompanionlateinitVariable(companionlateinitVariable); + // + // Custom companionlateinitStaticVariable = KotlinOnlyClass.companionlateinitStaticVariable; + // getCompanionlateinitStaticVariable(); + // setCompanionlateinitStaticVariable(companionlateinitStaticVariable); + // + // Companion.companionsimpleFunction(4); + // + // companionstaticFunction(4); + // + // Companion.companionextension(""); + // + // companionstaticExtension("42"); + //} +} diff --git a/plugins/kotlin/refIndex/tests/testData/customCompilerIndexData/testNonPresentedClass/KotlinOnlyClass.kt b/plugins/kotlin/refIndex/tests/testData/customCompilerIndexData/testNonPresentedClass/KotlinOnlyClass.kt new file mode 100644 index 000000000000..558c93acf6f6 --- /dev/null +++ b/plugins/kotlin/refIndex/tests/testData/customCompilerIndexData/testNonPresentedClass/KotlinOnlyClass.kt @@ -0,0 +1,23 @@ +package one + +open class KotlinOnlyClass { + val property: Int = 4 + + @JvmField + val fieldProperty: Int = 4 + + var variable: Int? = 4 + + @JvmField + var fieldVariable: Int = 4 + + lateinit var lateinitVariable: Custom + + fun simpleFunction(i: Int) {} + + fun String.extension() {} +} + +class Custom + +open class Proxy : KotlinOnlyClass() \ No newline at end of file diff --git a/plugins/kotlin/refIndex/tests/testData/customCompilerIndexData/testNonPresentedClass/Parameter.java b/plugins/kotlin/refIndex/tests/testData/customCompilerIndexData/testNonPresentedClass/Parameter.java new file mode 100644 index 000000000000..eb0a8a8d9d17 --- /dev/null +++ b/plugins/kotlin/refIndex/tests/testData/customCompilerIndexData/testNonPresentedClass/Parameter.java @@ -0,0 +1,60 @@ +package one; + + +public class Parameter { + void classMembers(Proxy proxy) { + proxy.getProperty(); + + int fieldProperty = proxy.fieldProperty; + + proxy.getVariable(); + proxy.setVariable(42); + + proxy.fieldVariable = 4; + int fieldVariable = proxy.fieldVariable; + + Custom lateinitVariable = proxy.lateinitVariable; + proxy.lateinitVariable = new Custom(); + proxy.setLateinitVariable(lateinitVariable); + proxy.getLateinitVariable(); + + proxy.simpleFunction(42); + + proxy.extension("awd"); + } + + //void companionMembers(Proxy proxy) { + // proxy.Companion.getCompanionproperty(); + // + // int companionfieldProperty1 = proxy.companionfieldProperty; + // + // proxy.getCompanionstaticProperty(); + // + // int companionconstProperty1 = proxy.companionconstProperty; + // + // proxy.Companion.getCompanionvariable(); + // proxy.Companion.setCompanionvariable(4); + // + // int companionfieldVariable1 = proxy.companionfieldVariable; + // proxy.companionfieldVariable = 4; + // + // proxy.getCompanionstaticVariable(); + // proxy.setCompanionstaticVariable(4); + // + // Custom companionlateinitVariable = KotlinOnlyClass.companionlateinitVariable; + // proxy.Companion.getCompanionlateinitVariable(); + // proxy.Companion.setCompanionlateinitVariable(companionlateinitVariable); + // + // Custom companionlateinitStaticVariable = KotlinOnlyClass.companionlateinitStaticVariable; + // proxy.getCompanionlateinitStaticVariable(); + // proxy.setCompanionlateinitStaticVariable(companionlateinitStaticVariable); + // + // proxy.Companion.companionsimpleFunction(4); + // + // proxy.companionstaticFunction(4); + // + // proxy.Companion.companionextension(""); + // + // proxy.companionstaticExtension("42"); + //} +} diff --git a/plugins/kotlin/refIndex/tests/testData/customCompilerIndexData/testNonPresentedClassWithCompanion/Hierarchy.java b/plugins/kotlin/refIndex/tests/testData/customCompilerIndexData/testNonPresentedClassWithCompanion/Hierarchy.java new file mode 100644 index 000000000000..0fd4888545b3 --- /dev/null +++ b/plugins/kotlin/refIndex/tests/testData/customCompilerIndexData/testNonPresentedClassWithCompanion/Hierarchy.java @@ -0,0 +1,39 @@ +package one; + + +public class Hierarchy extends Proxy { + void companionMembers() { + Companion.getCompanionproperty(); + + int companionfieldProperty1 = companionfieldProperty; + + getCompanionstaticProperty(); + + int companionconstProperty1 = companionconstProperty; + + Companion.getCompanionvariable(); + Companion.setCompanionvariable(4); + + int companionfieldVariable1 = companionfieldVariable; + companionfieldVariable = 4; + + getCompanionstaticVariable(); + setCompanionstaticVariable(4); + + Custom companionlateinitVariable = KotlinOnlyClass.companionlateinitVariable; + Companion.getCompanionlateinitVariable(); + Companion.setCompanionlateinitVariable(companionlateinitVariable); + + Custom companionlateinitStaticVariable = KotlinOnlyClass.companionlateinitStaticVariable; + getCompanionlateinitStaticVariable(); + setCompanionlateinitStaticVariable(companionlateinitStaticVariable); + + Companion.companionsimpleFunction(4); + + companionstaticFunction(4); + + Companion.companionextension(""); + + companionstaticExtension("42"); + } +} diff --git a/plugins/kotlin/refIndex/tests/testData/customCompilerIndexData/testNonPresentedClassWithCompanion/KotlinOnlyClass.kt b/plugins/kotlin/refIndex/tests/testData/customCompilerIndexData/testNonPresentedClassWithCompanion/KotlinOnlyClass.kt new file mode 100644 index 000000000000..e707116f202e --- /dev/null +++ b/plugins/kotlin/refIndex/tests/testData/customCompilerIndexData/testNonPresentedClassWithCompanion/KotlinOnlyClass.kt @@ -0,0 +1,43 @@ +package one + +open class KotlinOnlyClass { + companion object { + val companionproperty: Int = 4 + + @JvmField + val companionfieldProperty: Int = 4 + + @JvmStatic + val companionstaticProperty: Int = 4 + + const val companionconstProperty: Int = 4 + + var companionvariable: Int? = 4 + + @JvmField + var companionfieldVariable: Int = 4 + + @JvmStatic + var companionstaticVariable: Int = 4 + + lateinit var companionlateinitVariable: Custom + + @JvmStatic + lateinit var companionlateinitStaticVariable: Custom + + fun companionsimpleFunction(i: Int) {} + + @JvmStatic + fun companionstaticFunction(i: Int) { + } + + fun String.companionextension() {} + + @JvmStatic + fun String.companionstaticExtension() {} + } +} + +class Custom + +open class Proxy : KotlinOnlyClass() \ No newline at end of file diff --git a/plugins/kotlin/refIndex/tests/testData/customCompilerIndexData/testNonPresentedClassWithCompanion/Parameter.java b/plugins/kotlin/refIndex/tests/testData/customCompilerIndexData/testNonPresentedClassWithCompanion/Parameter.java new file mode 100644 index 000000000000..2e4fdbbd7ef0 --- /dev/null +++ b/plugins/kotlin/refIndex/tests/testData/customCompilerIndexData/testNonPresentedClassWithCompanion/Parameter.java @@ -0,0 +1,39 @@ +package one; + + +public class Parameter { + void companionMembers(Proxy proxy) { + proxy.Companion.getCompanionproperty(); + + int companionfieldProperty1 = proxy.companionfieldProperty; + + proxy.getCompanionstaticProperty(); + + int companionconstProperty1 = proxy.companionconstProperty; + + proxy.Companion.getCompanionvariable(); + proxy.Companion.setCompanionvariable(4); + + int companionfieldVariable1 = proxy.companionfieldVariable; + proxy.companionfieldVariable = 4; + + proxy.getCompanionstaticVariable(); + proxy.setCompanionstaticVariable(4); + + Custom companionlateinitVariable = KotlinOnlyClass.companionlateinitVariable; + proxy.Companion.getCompanionlateinitVariable(); + proxy.Companion.setCompanionlateinitVariable(companionlateinitVariable); + + Custom companionlateinitStaticVariable = KotlinOnlyClass.companionlateinitStaticVariable; + proxy.getCompanionlateinitStaticVariable(); + proxy.setCompanionlateinitStaticVariable(companionlateinitStaticVariable); + + proxy.Companion.companionsimpleFunction(4); + + proxy.companionstaticFunction(4); + + proxy.Companion.companionextension(""); + + proxy.companionstaticExtension("42"); + } +}