From e19cc04c63e05aef10fd6cbdfac4494cfac7d5c6 Mon Sep 17 00:00:00 2001 From: "Pavel V. Talanov" Date: Tue, 29 Mar 2016 19:32:58 +0300 Subject: [PATCH] KT-11678 Support navigation from Java source to Kotlin binaries Introduce LightMemberOriginForCompiledElement which holds logic for finding corresponding decompiled declaration ByJvmSignatureIndexer stores the required information while building decompiled text Some are unsolved in this commit: - constructors - @Jvm* and other unregular generated members - annotation methods #KT-11678 Fixed --- .../kotlin/load/kotlin/MemberSignature.kt | 4 +- .../KtLightClassForDecompiledDeclaration.kt | 12 ++ .../LightMemberOriginForCompiledElement.kt | 144 ++++++++++++++++++ .../idea/caches/resolve/MapPsiToAsmDesc.kt | 85 +++++++++++ .../classFile/KotlinClassFileDecompiler.kt | 20 ++- .../LibraryCompanionObjectUsages.results.txt | 3 +- .../LibraryMemberFunctionUsages.results.txt | 1 + .../binaryAndSource/Field.java | 8 + .../binaryAndSource/FileFacade.java | 2 +- .../binaryAndSource/MethodOfDeeplyNested.java | 8 + .../binaryAndSource/MethodWithParameters.java | 8 + .../dependency/dependencies.kt | 20 +++ .../ReferenceResolveInJavaTestGenerated.java | 18 +++ ...piledKotlinResolveInJavaTestGenerated.java | 18 +++ 14 files changed, 339 insertions(+), 12 deletions(-) create mode 100644 idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/LightMemberOriginForCompiledElement.kt create mode 100644 idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/MapPsiToAsmDesc.kt create mode 100644 idea/testData/resolve/referenceInJava/binaryAndSource/Field.java create mode 100644 idea/testData/resolve/referenceInJava/binaryAndSource/MethodOfDeeplyNested.java create mode 100644 idea/testData/resolve/referenceInJava/binaryAndSource/MethodWithParameters.java diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/MemberSignature.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/MemberSignature.kt index 63361009177..565986bb99d 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/MemberSignature.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/MemberSignature.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2015 JetBrains s.r.o. + * 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. @@ -21,7 +21,7 @@ import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf // The purpose of this class is to hold a unique signature of either a method or a field, so that annotations on a member can be put // into a map indexed by these signatures -internal data class MemberSignature private constructor(internal val signature: String) { +data class MemberSignature private constructor(internal val signature: String) { companion object { @JvmStatic fun fromMethod(nameResolver: NameResolver, signature: JvmProtoBuf.JvmMethodSignature): MemberSignature { diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/KtLightClassForDecompiledDeclaration.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/KtLightClassForDecompiledDeclaration.kt index 4e768fdfadb..04c0bcb9cb5 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/KtLightClassForDecompiledDeclaration.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/KtLightClassForDecompiledDeclaration.kt @@ -17,7 +17,11 @@ package org.jetbrains.kotlin.idea.caches.resolve import com.intellij.psi.PsiClass +import com.intellij.psi.PsiField +import com.intellij.psi.PsiMethod import com.intellij.psi.impl.compiled.ClsClassImpl +import org.jetbrains.kotlin.asJava.KtLightFieldImpl +import org.jetbrains.kotlin.asJava.KtLightMethodImpl import org.jetbrains.kotlin.asJava.KtWrappingLightClass import org.jetbrains.kotlin.idea.decompiler.classFile.KtClsFile import org.jetbrains.kotlin.name.FqName @@ -40,6 +44,14 @@ class KtLightClassForDecompiledDeclaration( } } + override fun getOwnFields(): List { + return clsDelegate.ownFields.map { KtLightFieldImpl.create(LightMemberOriginForCompiledField(it, file), it, this) } + } + + override fun getOwnMethods(): List { + return clsDelegate.ownMethods.map { KtLightMethodImpl.create(it, LightMemberOriginForCompiledMethod(it, file), this) } + } + override fun getNavigationElement() = kotlinOrigin?.navigationElement ?: file override fun getFqName() = fqName diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/LightMemberOriginForCompiledElement.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/LightMemberOriginForCompiledElement.kt new file mode 100644 index 00000000000..4202bbce85f --- /dev/null +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/LightMemberOriginForCompiledElement.kt @@ -0,0 +1,144 @@ +/* + * 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.caches.resolve + +import com.intellij.psi.PsiField +import com.intellij.psi.PsiMember +import com.intellij.psi.PsiMethod +import org.jetbrains.kotlin.asJava.LightMemberOrigin +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.idea.decompiler.classFile.KtClsFile +import org.jetbrains.kotlin.idea.decompiler.textBuilder.DecompiledTextIndexer +import org.jetbrains.kotlin.load.java.JvmAbi +import org.jetbrains.kotlin.load.kotlin.MemberSignature +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.KtDeclaration +import org.jetbrains.kotlin.resolve.descriptorUtil.classId +import org.jetbrains.kotlin.resolve.jvm.JvmClassName +import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind +import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor +import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor +import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf +import org.jetbrains.kotlin.serialization.jvm.JvmProtoBufUtil + +interface LightMemberOriginForCompiledElement : LightMemberOrigin { + override val originKind: JvmDeclarationOriginKind + get() = JvmDeclarationOriginKind.OTHER +} + + +data class LightMemberOriginForCompiledField(val psiField: PsiField, val file: KtClsFile) : LightMemberOriginForCompiledElement { + override fun copy(): LightMemberOrigin { + return LightMemberOriginForCompiledField(psiField.copy() as PsiField, file) + } + + override val originalElement: KtDeclaration? by lazy(LazyThreadSafetyMode.PUBLICATION) { + val desc = MapPsiToAsmDesc.typeDesc(psiField.type) + val signature = MemberSignature.fromFieldNameAndDesc(psiField.name!!, desc) + file.getDeclaration(ByJvmSignatureIndexer, ClassNameAndSignature(psiField.relativeClassName(), signature)) + } +} + +data class LightMemberOriginForCompiledMethod(val psiMethod: PsiMethod, val file: KtClsFile) : LightMemberOriginForCompiledElement { + override fun copy(): LightMemberOrigin { + return LightMemberOriginForCompiledMethod(psiMethod.copy() as PsiMethod, file) + } + + override val originalElement: KtDeclaration? by lazy(LazyThreadSafetyMode.PUBLICATION) { + val desc = MapPsiToAsmDesc.methodDesc(psiMethod) + val signature = MemberSignature.fromMethodNameAndDesc(psiMethod.name, desc) + file.getDeclaration(ByJvmSignatureIndexer, ClassNameAndSignature(psiMethod.relativeClassName(), signature)) + } +} + +// this is convenient data structure for this purpose and is not supposed to be used outside this file +// every member is represented by its jvm signature and relative class name (which is easy to obtain from descriptors or cls psi) + +// relative class name is a path containing inner/nested class names from top level class to the class containing this member (excluding top level class name) +// Examples: for top level function or function in a top level class relativeClassName is empty +// For: class TopLevel { class A { class B { fun f() } } } +// relativeClassName for function 'f' will be [A, B] +private data class ClassNameAndSignature(val relativeClassName: List, val memberSignature: MemberSignature) + +private fun PsiMember.relativeClassName(): List { + return generateSequence(this.containingClass) { it.containingClass }.toList().dropLast(1).reversed().map { Name.identifier(it.name!!) } +} + +private fun ClassDescriptor.relativeClassName(): List { + return classId.relativeClassName.pathSegments().drop(1).orEmpty() +} + +private fun ClassDescriptor.desc(): String = "L" + JvmClassName.byClassId(classId).internalName + ";" + +private object ByJvmSignatureIndexer : DecompiledTextIndexer { + override fun indexDescriptor(descriptor: DeclarationDescriptor): Collection { + val signatures = arrayListOf() + + fun save(id: List, signature: MemberSignature) { + signatures.add(ClassNameAndSignature(id, signature)) + } + + if (descriptor is ClassDescriptor) { + @Suppress("NON_EXHAUSTIVE_WHEN") + when (descriptor.kind) { + ClassKind.ENUM_ENTRY -> { + val enumClass = descriptor.containingDeclaration as ClassDescriptor + val signature = MemberSignature.fromFieldNameAndDesc(descriptor.name.asString(), enumClass.desc()) + save(enumClass.relativeClassName(), signature) + } + ClassKind.OBJECT -> { + val instanceFieldSignature = MemberSignature.fromFieldNameAndDesc(JvmAbi.INSTANCE_FIELD, descriptor.desc()) + save(descriptor.relativeClassName(), instanceFieldSignature) + if (descriptor.isCompanionObject) { + val signature = MemberSignature.fromFieldNameAndDesc(descriptor.name.asString(), descriptor.desc()) + save((descriptor.containingDeclaration as? ClassDescriptor)?.relativeClassName().orEmpty(), signature) + } + } + } + } + + if (descriptor is DeserializedSimpleFunctionDescriptor) { + JvmProtoBufUtil.getJvmMethodSignature(descriptor.proto, descriptor.nameResolver, descriptor.typeTable)?.let { + val signature = MemberSignature.fromMethodNameAndDesc(it) + save((descriptor.containingDeclaration as? ClassDescriptor)?.relativeClassName().orEmpty(), signature) + } + } + if (descriptor is DeserializedPropertyDescriptor) { + val proto = descriptor.proto + val className = (descriptor.containingDeclaration as? ClassDescriptor)?.relativeClassName().orEmpty() + if (proto.hasExtension(JvmProtoBuf.propertySignature)) { + val signature = proto.getExtension(JvmProtoBuf.propertySignature) + val fieldSignature = JvmProtoBufUtil.getJvmFieldSignature(proto, descriptor.nameResolver, descriptor.typeTable) + if (fieldSignature != null) { + save(className, MemberSignature.fromFieldNameAndDesc(fieldSignature.name, fieldSignature.desc)) + } + if (signature.hasGetter()) { + save(className, MemberSignature.fromMethod(descriptor.nameResolver, signature.getter)) + } + if (signature.hasSetter()) { + save(className, MemberSignature.fromMethod(descriptor.nameResolver, signature.setter)) + } + } + } + return signatures + } +} + +// expose with different type +val BySignatureIndexer: DecompiledTextIndexer<*> = ByJvmSignatureIndexer diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/MapPsiToAsmDesc.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/MapPsiToAsmDesc.kt new file mode 100644 index 00000000000..993758aa39d --- /dev/null +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/MapPsiToAsmDesc.kt @@ -0,0 +1,85 @@ +/* + * 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.caches.resolve + +import com.intellij.openapi.diagnostic.Logger +import com.intellij.psi.* +import org.jetbrains.org.objectweb.asm.Type +import org.jetbrains.org.objectweb.asm.Type.* + +object MapPsiToAsmDesc { + fun typeDesc(type: PsiType): String = when (type) { + PsiType.VOID -> primitive(VOID_TYPE) + + PsiType.BOOLEAN -> primitive(BOOLEAN_TYPE) + + PsiType.CHAR -> primitive(CHAR_TYPE) + PsiType.INT -> primitive(INT_TYPE) + PsiType.BYTE -> primitive(BYTE_TYPE) + PsiType.SHORT -> primitive(SHORT_TYPE) + PsiType.LONG -> primitive(LONG_TYPE) + + PsiType.FLOAT -> primitive(FLOAT_TYPE) + PsiType.DOUBLE -> primitive(DOUBLE_TYPE) + + is PsiArrayType -> "[" + typeDesc(type.componentType) + + is PsiClassType -> { + val resolved = type.resolve() + when (resolved) { + is PsiTypeParameter -> resolved.superTypes.firstOrNull()?.let { typeDesc(it) } ?: "Ljava/lang/Object;" + is PsiClass -> classDesc(resolved) + null -> unknownSignature() + else -> error("Resolved to unexpected $resolved of class ${resolved.javaClass}" ) + } + + } + else -> error("Unexpected type $type of class ${type.javaClass}") + } + + private fun classDesc(psiClass: PsiClass) = buildString { + append("L") + val classes = generateSequence(psiClass) { it.containingClass }.toList().reversed() + append(classes.first().qualifiedName!!.replace(".", "/")) + classes.drop(1).forEach { + append("$") + append(it.name!!) + } + append(";") + } + + fun methodDesc(psiMethod: PsiMethod): String = buildString { + append("(") + psiMethod.parameterList.parameters.forEach { + append(typeDesc(it.type)) + } + append(")") + psiMethod.returnType?.let { + append(typeDesc(it)) + } + ?: return unknownSignature() // TODO: support constructors, there seems to be additional logic in java that doesn't work correctly for compiled kotlin + } + + private fun unknownSignature() = "" + private fun error(message: String): String { + LOG.error(message) + return unknownSignature() + } + private fun primitive(asmType: Type) = asmType.descriptor + + private val LOG = Logger.getInstance(javaClass) +} \ No newline at end of file diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/KotlinClassFileDecompiler.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/KotlinClassFileDecompiler.kt index 58b91c4c2bf..195304f6d1e 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/KotlinClassFileDecompiler.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/KotlinClassFileDecompiler.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2015 JetBrains s.r.o. + * 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. @@ -21,10 +21,13 @@ import com.intellij.openapi.roots.FileIndexFacade import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.PsiManager import com.intellij.psi.compiled.ClassFileDecompilers +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.idea.caches.IDEKotlinBinaryClassCache +import org.jetbrains.kotlin.idea.caches.resolve.BySignatureIndexer import org.jetbrains.kotlin.idea.decompiler.KotlinDecompiledFileViewProvider import org.jetbrains.kotlin.idea.decompiler.KtDecompiledFile import org.jetbrains.kotlin.idea.decompiler.common.createIncompatibleAbiVersionDecompiledText +import org.jetbrains.kotlin.idea.decompiler.navigation.ByDescriptorIndexer import org.jetbrains.kotlin.idea.decompiler.textBuilder.DecompiledText import org.jetbrains.kotlin.idea.decompiler.textBuilder.ResolverForDecompiler import org.jetbrains.kotlin.idea.decompiler.textBuilder.buildDecompiledText @@ -34,7 +37,6 @@ import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.types.flexibility import org.jetbrains.kotlin.types.isFlexible -import java.util.* class KotlinClassFileDecompiler : ClassFileDecompilers.Full() { private val stubBuilder = KotlinClsStubBuilder() @@ -75,19 +77,21 @@ fun buildDecompiledTextForClassFile( return createIncompatibleAbiVersionDecompiledText(JvmMetadataVersion.INSTANCE, classHeader.metadataVersion) } + fun buildText(declarations: List) = + buildDecompiledText(classId.packageFqName, declarations, decompilerRendererForClassFiles, listOf(ByDescriptorIndexer, BySignatureIndexer)) + return when (classHeader.kind) { KotlinClassHeader.Kind.FILE_FACADE -> - buildDecompiledText(classId.packageFqName, ArrayList(resolver.resolveDeclarationsInFacade(classId.asSingleFqName())), - decompilerRendererForClassFiles) - KotlinClassHeader.Kind.CLASS -> - buildDecompiledText(classId.packageFqName, listOfNotNull(resolver.resolveTopLevelClass(classId)), - decompilerRendererForClassFiles) + buildText(resolver.resolveDeclarationsInFacade(classId.asSingleFqName())) + KotlinClassHeader.Kind.CLASS -> { + buildText(listOfNotNull(resolver.resolveTopLevelClass(classId))) + } KotlinClassHeader.Kind.MULTIFILE_CLASS -> { val partClasses = findMultifileClassParts(classFile, classId, classHeader) val partMembers = partClasses.flatMap { partClass -> resolver.resolveDeclarationsInFacade(partClass.classId.asSingleFqName()) } - buildDecompiledText(classId.packageFqName, partMembers, decompilerRendererForClassFiles) + buildText(partMembers) } else -> throw UnsupportedOperationException("Unknown header kind: $classHeader, class $classId") diff --git a/idea/testData/findUsages/libraryUsages/kotlinLibrary/LibraryCompanionObjectUsages.results.txt b/idea/testData/findUsages/libraryUsages/kotlinLibrary/LibraryCompanionObjectUsages.results.txt index 2f87b6c5d67..e49ece3b8f2 100644 --- a/idea/testData/findUsages/libraryUsages/kotlinLibrary/LibraryCompanionObjectUsages.results.txt +++ b/idea/testData/findUsages/libraryUsages/kotlinLibrary/LibraryCompanionObjectUsages.results.txt @@ -1,2 +1,3 @@ [LibraryCompanionObjectUsages.0.kt] Companion object (10: 15) val a = A.Companion -[LibraryCompanionObjectUsages.1.java] Local variable declaration (7: 11) A.Companion o = A.Companion; \ No newline at end of file +[LibraryCompanionObjectUsages.1.java] Local variable declaration (7: 11) A.Companion o = A.Companion; +[LibraryCompanionObjectUsages.1.java] Unclassified usage (7: 27) A.Companion o = A.Companion; \ No newline at end of file diff --git a/idea/testData/findUsages/libraryUsages/kotlinLibrary/LibraryMemberFunctionUsages.results.txt b/idea/testData/findUsages/libraryUsages/kotlinLibrary/LibraryMemberFunctionUsages.results.txt index cfb08cc8338..4886eb99dfe 100644 --- a/idea/testData/findUsages/libraryUsages/kotlinLibrary/LibraryMemberFunctionUsages.results.txt +++ b/idea/testData/findUsages/libraryUsages/kotlinLibrary/LibraryMemberFunctionUsages.results.txt @@ -1,4 +1,5 @@ [LibraryMemberFunctionUsages.0.kt] Callable reference (10: 16) val f = A::foo [LibraryMemberFunctionUsages.0.kt] Function call (11: 9) A().foo(1) +[LibraryMemberFunctionUsages.1.java] Unclassified usage (11: 17) new A().foo(1); [library.kt] Callable reference (61: 17) val ff = A::foo [library.kt] Function call (60: 7) a.foo(2) \ No newline at end of file diff --git a/idea/testData/resolve/referenceInJava/binaryAndSource/Field.java b/idea/testData/resolve/referenceInJava/binaryAndSource/Field.java new file mode 100644 index 00000000000..7ceb94301de --- /dev/null +++ b/idea/testData/resolve/referenceInJava/binaryAndSource/Field.java @@ -0,0 +1,8 @@ +public class Field { + public static void foo() { + (new k.Class()).prop; + } +} + +// REF: (in k.Class).prop +// CLS_REF: (in k.Class).prop diff --git a/idea/testData/resolve/referenceInJava/binaryAndSource/FileFacade.java b/idea/testData/resolve/referenceInJava/binaryAndSource/FileFacade.java index c0258684ff5..f17f2b8afa5 100644 --- a/idea/testData/resolve/referenceInJava/binaryAndSource/FileFacade.java +++ b/idea/testData/resolve/referenceInJava/binaryAndSource/FileFacade.java @@ -5,4 +5,4 @@ public class PackageFacade { } // REF: /src//resolve/referenceInJava/dependency.dependencies.kt -// CLS_REF: (k).DependenciesKt \ No newline at end of file +// CLS_REF: !/k.DependenciesKt.class \ No newline at end of file diff --git a/idea/testData/resolve/referenceInJava/binaryAndSource/MethodOfDeeplyNested.java b/idea/testData/resolve/referenceInJava/binaryAndSource/MethodOfDeeplyNested.java new file mode 100644 index 00000000000..0c175e0a87d --- /dev/null +++ b/idea/testData/resolve/referenceInJava/binaryAndSource/MethodOfDeeplyNested.java @@ -0,0 +1,8 @@ +public class MethodOfDeeplyNested { + public static void foo() { + (new k.Class.F.F()).function(); + } +} + +// REF: (in k.Class.F.F).function() +// CLS_REF: (in k.Class.F.F).function() diff --git a/idea/testData/resolve/referenceInJava/binaryAndSource/MethodWithParameters.java b/idea/testData/resolve/referenceInJava/binaryAndSource/MethodWithParameters.java new file mode 100644 index 00000000000..deceebdc503 --- /dev/null +++ b/idea/testData/resolve/referenceInJava/binaryAndSource/MethodWithParameters.java @@ -0,0 +1,8 @@ +public class MethodWithParameters { + public static void foo() { + (new k.Class()).function2(); + } +} + +// REF: (in k.Class).function2(Byte, Char, Short, Int, Long, Boolean, Float, Double, ByteArray, CharArray, IntArray, LongArray, BooleanArray, FloatArray, DoubleArray, Array, Array, Array>, T, G, String, Class.F, Class.G, Class.F.F) +// CLS_REF: (in k.Class).function2(kotlin.Byte, kotlin.Char, kotlin.Short, kotlin.Int, kotlin.Long, kotlin.Boolean, kotlin.Float, kotlin.Double, kotlin.ByteArray, kotlin.CharArray, kotlin.IntArray, kotlin.LongArray, kotlin.BooleanArray, kotlin.FloatArray, kotlin.DoubleArray, kotlin.Array, kotlin.Array, kotlin.Array>, T, G, kotlin.String, k.Class.F, k.Class.G, k.Class.F.F) diff --git a/idea/testData/resolve/referenceInJava/dependency/dependencies.kt b/idea/testData/resolve/referenceInJava/dependency/dependencies.kt index 5dd2a544400..58aaf43f0de 100644 --- a/idea/testData/resolve/referenceInJava/dependency/dependencies.kt +++ b/idea/testData/resolve/referenceInJava/dependency/dependencies.kt @@ -3,6 +3,26 @@ package k public class Class() { public val prop: Int = 0 fun function() = 1 + + fun function2( + b: Byte, c: Char, s: Short, i: Int, l: Long, bool: Boolean, f: Float, d: Double, + ba: ByteArray, ca: CharArray, ia: IntArray, la: LongArray, boola: BooleanArray, fa: FloatArray, da: DoubleArray, sa: Array, + baa: Array, saa: Array>, + t: T, g: G, str: String, nestedClass: Class.F, innerClass: Class.G, nestedNested: Class.F.F + ) { + } + + class F { + fun function() = 1 + + class F { + fun function() = 1 + } + } + + inner class G { + fun function() = 5 + } } public enum class EnumClass { diff --git a/idea/tests/org/jetbrains/kotlin/idea/resolve/ReferenceResolveInJavaTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/resolve/ReferenceResolveInJavaTestGenerated.java index b834de3a461..d5737248089 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/resolve/ReferenceResolveInJavaTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/resolve/ReferenceResolveInJavaTestGenerated.java @@ -61,6 +61,12 @@ public class ReferenceResolveInJavaTestGenerated extends AbstractReferenceResolv doTest(fileName); } + @TestMetadata("Field.java") + public void testField() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/resolve/referenceInJava/binaryAndSource/Field.java"); + doTest(fileName); + } + @TestMetadata("FileFacade.java") public void testFileFacade() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/resolve/referenceInJava/binaryAndSource/FileFacade.java"); @@ -79,6 +85,18 @@ public class ReferenceResolveInJavaTestGenerated extends AbstractReferenceResolv doTest(fileName); } + @TestMetadata("MethodOfDeeplyNested.java") + public void testMethodOfDeeplyNested() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/resolve/referenceInJava/binaryAndSource/MethodOfDeeplyNested.java"); + doTest(fileName); + } + + @TestMetadata("MethodWithParameters.java") + public void testMethodWithParameters() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/resolve/referenceInJava/binaryAndSource/MethodWithParameters.java"); + doTest(fileName); + } + @TestMetadata("ObjectInstance.java") public void testObjectInstance() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/resolve/referenceInJava/binaryAndSource/ObjectInstance.java"); diff --git a/idea/tests/org/jetbrains/kotlin/idea/resolve/ReferenceToCompiledKotlinResolveInJavaTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/resolve/ReferenceToCompiledKotlinResolveInJavaTestGenerated.java index 6519ee98be1..af4be26bbf8 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/resolve/ReferenceToCompiledKotlinResolveInJavaTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/resolve/ReferenceToCompiledKotlinResolveInJavaTestGenerated.java @@ -59,6 +59,12 @@ public class ReferenceToCompiledKotlinResolveInJavaTestGenerated extends Abstrac doTest(fileName); } + @TestMetadata("Field.java") + public void testField() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/resolve/referenceInJava/binaryAndSource/Field.java"); + doTest(fileName); + } + @TestMetadata("FileFacade.java") public void testFileFacade() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/resolve/referenceInJava/binaryAndSource/FileFacade.java"); @@ -77,6 +83,18 @@ public class ReferenceToCompiledKotlinResolveInJavaTestGenerated extends Abstrac doTest(fileName); } + @TestMetadata("MethodOfDeeplyNested.java") + public void testMethodOfDeeplyNested() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/resolve/referenceInJava/binaryAndSource/MethodOfDeeplyNested.java"); + doTest(fileName); + } + + @TestMetadata("MethodWithParameters.java") + public void testMethodWithParameters() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/resolve/referenceInJava/binaryAndSource/MethodWithParameters.java"); + doTest(fileName); + } + @TestMetadata("ObjectInstance.java") public void testObjectInstance() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/resolve/referenceInJava/binaryAndSource/ObjectInstance.java");