diff --git a/compiler/util/src/org/jetbrains/kotlin/type/MapPsiToAsmDesc.kt b/compiler/util/src/org/jetbrains/kotlin/type/MapPsiToAsmDesc.kt index 6d21c1d8359..a324581cfc7 100644 --- a/compiler/util/src/org/jetbrains/kotlin/type/MapPsiToAsmDesc.kt +++ b/compiler/util/src/org/jetbrains/kotlin/type/MapPsiToAsmDesc.kt @@ -57,10 +57,7 @@ object MapPsiToAsmDesc { 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 + append(psiMethod.returnType?.let { typeDesc(it) } ?: "V") } private fun unknownSignature() = "" diff --git a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt index 97ca7ffc395..338dbaef712 100644 --- a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt +++ b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt @@ -64,6 +64,7 @@ import org.jetbrains.kotlin.idea.debugger.test.AbstractFileRankingTest import org.jetbrains.kotlin.idea.decompiler.navigation.AbstractNavigateToDecompiledLibraryTest import org.jetbrains.kotlin.idea.decompiler.navigation.AbstractNavigateToLibrarySourceTest import org.jetbrains.kotlin.idea.decompiler.navigation.AbstractNavigateToLibrarySourceTestWithJS +import org.jetbrains.kotlin.idea.decompiler.navigation.AbstractNavigateJavaToLibrarySourceTest import org.jetbrains.kotlin.idea.decompiler.stubBuilder.AbstractClsStubBuilderTest import org.jetbrains.kotlin.idea.decompiler.stubBuilder.AbstractLoadJavaClsStubTest import org.jetbrains.kotlin.idea.decompiler.textBuilder.AbstractCommonDecompiledTextFromJsMetadataTest @@ -332,6 +333,10 @@ fun main(args: Array) { model("decompiler/navigation/usercode") } + testClass(annotations = listOf(muteExtraSuffix(".libsrc"))) { + model("decompiler/navigation/userJavaCode", pattern = "^(.+)\\.java$") + } + testClass(annotations = listOf(muteExtraSuffix(".libsrcjs"))) { model("decompiler/navigation/usercode", testClassName = "UsercodeWithJSModule") } diff --git a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as35 b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as35 index b7153861e4a..70ccd40e075 100644 --- a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as35 +++ b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as35 @@ -70,6 +70,7 @@ import org.jetbrains.kotlin.idea.debugger.test.AbstractFileRankingTest import org.jetbrains.kotlin.idea.decompiler.navigation.AbstractNavigateToDecompiledLibraryTest import org.jetbrains.kotlin.idea.decompiler.navigation.AbstractNavigateToLibrarySourceTest import org.jetbrains.kotlin.idea.decompiler.navigation.AbstractNavigateToLibrarySourceTestWithJS +import org.jetbrains.kotlin.idea.decompiler.navigation.AbstractNavigateJavaToLibrarySourceTest import org.jetbrains.kotlin.idea.decompiler.stubBuilder.AbstractClsStubBuilderTest import org.jetbrains.kotlin.idea.decompiler.stubBuilder.AbstractLoadJavaClsStubTest import org.jetbrains.kotlin.idea.decompiler.textBuilder.AbstractCommonDecompiledTextFromJsMetadataTest @@ -318,6 +319,10 @@ fun main(args: Array) { model("decompiler/navigation/usercode") } + testClass(annotations = listOf(muteExtraSuffix(".libsrc"))) { + model("decompiler/navigation/userJavaCode", pattern = "^(.+)\\.java$") + } + testClass(annotations = listOf(muteExtraSuffix(".libsrcjs"))) { model("decompiler/navigation/usercode", testClassName ="UsercodeWithJSModule") } diff --git a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as36 b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as36 index b7153861e4a..70ccd40e075 100644 --- a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as36 +++ b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as36 @@ -70,6 +70,7 @@ import org.jetbrains.kotlin.idea.debugger.test.AbstractFileRankingTest import org.jetbrains.kotlin.idea.decompiler.navigation.AbstractNavigateToDecompiledLibraryTest import org.jetbrains.kotlin.idea.decompiler.navigation.AbstractNavigateToLibrarySourceTest import org.jetbrains.kotlin.idea.decompiler.navigation.AbstractNavigateToLibrarySourceTestWithJS +import org.jetbrains.kotlin.idea.decompiler.navigation.AbstractNavigateJavaToLibrarySourceTest import org.jetbrains.kotlin.idea.decompiler.stubBuilder.AbstractClsStubBuilderTest import org.jetbrains.kotlin.idea.decompiler.stubBuilder.AbstractLoadJavaClsStubTest import org.jetbrains.kotlin.idea.decompiler.textBuilder.AbstractCommonDecompiledTextFromJsMetadataTest @@ -318,6 +319,10 @@ fun main(args: Array) { model("decompiler/navigation/usercode") } + testClass(annotations = listOf(muteExtraSuffix(".libsrc"))) { + model("decompiler/navigation/userJavaCode", pattern = "^(.+)\\.java$") + } + testClass(annotations = listOf(muteExtraSuffix(".libsrcjs"))) { model("decompiler/navigation/usercode", testClassName ="UsercodeWithJSModule") } diff --git a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as40 b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as40 index b7153861e4a..70ccd40e075 100644 --- a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as40 +++ b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as40 @@ -70,6 +70,7 @@ import org.jetbrains.kotlin.idea.debugger.test.AbstractFileRankingTest import org.jetbrains.kotlin.idea.decompiler.navigation.AbstractNavigateToDecompiledLibraryTest import org.jetbrains.kotlin.idea.decompiler.navigation.AbstractNavigateToLibrarySourceTest import org.jetbrains.kotlin.idea.decompiler.navigation.AbstractNavigateToLibrarySourceTestWithJS +import org.jetbrains.kotlin.idea.decompiler.navigation.AbstractNavigateJavaToLibrarySourceTest import org.jetbrains.kotlin.idea.decompiler.stubBuilder.AbstractClsStubBuilderTest import org.jetbrains.kotlin.idea.decompiler.stubBuilder.AbstractLoadJavaClsStubTest import org.jetbrains.kotlin.idea.decompiler.textBuilder.AbstractCommonDecompiledTextFromJsMetadataTest @@ -318,6 +319,10 @@ fun main(args: Array) { model("decompiler/navigation/usercode") } + testClass(annotations = listOf(muteExtraSuffix(".libsrc"))) { + model("decompiler/navigation/userJavaCode", pattern = "^(.+)\\.java$") + } + testClass(annotations = listOf(muteExtraSuffix(".libsrcjs"))) { model("decompiler/navigation/usercode", testClassName ="UsercodeWithJSModule") } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/lightClasses/LightMemberOriginForCompiledElement.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/lightClasses/LightMemberOriginForCompiledElement.kt index 59f3d47d99d..dddf0e49a1d 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/lightClasses/LightMemberOriginForCompiledElement.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/lightClasses/LightMemberOriginForCompiledElement.kt @@ -1,17 +1,6 @@ /* - * Copyright 2010-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 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.caches.lightClasses @@ -20,6 +9,8 @@ import com.intellij.psi.PsiElement import com.intellij.psi.PsiField import com.intellij.psi.PsiMember import com.intellij.psi.PsiMethod +import com.intellij.psi.impl.compiled.SignatureParsing +import com.intellij.util.cls.ClsFormatException import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin import org.jetbrains.kotlin.asJava.classes.lazyPub import org.jetbrains.kotlin.descriptors.ClassDescriptor @@ -36,12 +27,18 @@ import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclarationContainer +import org.jetbrains.kotlin.resolve.calls.components.hasDefaultValue import org.jetbrains.kotlin.resolve.descriptorUtil.classId +import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension import org.jetbrains.kotlin.resolve.jvm.JvmClassName +import org.jetbrains.kotlin.resolve.jvm.annotations.findJvmOverloadsAnnotation import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind +import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassConstructorDescriptor import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor import org.jetbrains.kotlin.type.MapPsiToAsmDesc +import java.text.CharacterIterator +import java.text.StringCharacterIterator interface LightMemberOriginForCompiledElement : LightMemberOrigin { val member: T @@ -98,7 +95,8 @@ data class LightMemberOriginForCompiledMethod(val psiMethod: PsiMethod, val file override val originalElement: KtDeclaration? by lazyPub { val desc = MapPsiToAsmDesc.methodDesc(psiMethod) - val signature = MemberSignature.fromMethodNameAndDesc(psiMethod.name, desc) + val name = if (psiMethod.isConstructor) "" else psiMethod.name + val signature = MemberSignature.fromMethodNameAndDesc(name, desc) findDeclarationInCompiledFile(file, psiMethod, signature) } } @@ -148,58 +146,138 @@ private fun ClassDescriptor.relativeClassName(): List { return classId!!.relativeClassName.pathSegments().drop(1) } +private fun excludeParametersFromDescriptor(descriptor: String, omittedParameters: List): String? { + + fun tryParseParametersAndReturnType(): Pair, String>? { + val iterator = StringCharacterIterator(descriptor) + + fun parseTypeString(): String? { + val begin = iterator.index + try { + SignatureParsing.parseTypeString(iterator) { it } + } catch (e: ClsFormatException) { + return null + } + val end = iterator.index + return descriptor.substring(begin, end) + } + + if (iterator.current() != '(') return null + iterator.next() + + if (iterator.current() == ')') { + iterator.next() + val returnType = parseTypeString() ?: return null + return emptyList() to returnType + } + + val parameterTypes = mutableListOf() + while (iterator.current() != ')' && iterator.current() != CharacterIterator.DONE) { + parameterTypes += parseTypeString() ?: return null + } + + if (iterator.current() != ')') return null + iterator.next() + + val returnType = parseTypeString() ?: return null + return parameterTypes to returnType + } + + val (parameterTypes, returnType) = tryParseParametersAndReturnType() ?: return null + + val parametersList = parameterTypes + .filterIndexed { index, _ -> index !in omittedParameters } + .joinToString("") + + return "($parametersList)$returnType" +} + 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) { + fun ClassDescriptor.apply() { + when (kind) { ClassKind.ENUM_ENTRY -> { - val enumClass = descriptor.containingDeclaration as ClassDescriptor - val signature = MemberSignature.fromFieldNameAndDesc(descriptor.name.asString(), enumClass.desc()) + val enumClass = containingDeclaration as ClassDescriptor + val signature = MemberSignature.fromFieldNameAndDesc(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) + val instanceFieldSignature = MemberSignature.fromFieldNameAndDesc(JvmAbi.INSTANCE_FIELD, desc()) + save(relativeClassName(), instanceFieldSignature) + if (isCompanionObject) { + val signature = MemberSignature.fromFieldNameAndDesc(name.asString(), desc()) + save((containingDeclaration as? ClassDescriptor)?.relativeClassName().orEmpty(), signature) + } + } + else -> { + } + } + } + + fun DeserializedClassConstructorDescriptor.apply() { + JvmProtoBufUtil.getJvmConstructorSignature(proto, nameResolver, typeTable)?.let { + val id = (containingDeclaration as? ClassDescriptor)?.relativeClassName().orEmpty() + val signature = MemberSignature.fromJvmMemberSignature(it) + save(id, signature) + } + } + + fun DeserializedSimpleFunctionDescriptor.apply() { + JvmProtoBufUtil.getJvmMethodSignature(proto, nameResolver, typeTable)?.let { + val id = (containingDeclaration as? ClassDescriptor)?.relativeClassName().orEmpty() + + val signature = MemberSignature.fromJvmMemberSignature(it) + save(id, signature) + + if (findJvmOverloadsAnnotation() == null) return + + val extensionShift = if (isExtension) 1 else 0 + + val omittedList = mutableListOf() + valueParameters.asReversed().forEach { parameter -> + if (parameter.hasDefaultValue()) { + omittedList.add(parameter.index + extensionShift) + val newDescriptor = excludeParametersFromDescriptor(it.desc, omittedList) + if (newDescriptor != null) { + val overloadedSignature = MemberSignature.fromMethodNameAndDesc(it.name, newDescriptor) + save(id, overloadedSignature) + } } } } } - if (descriptor is DeserializedSimpleFunctionDescriptor) { - JvmProtoBufUtil.getJvmMethodSignature(descriptor.proto, descriptor.nameResolver, descriptor.typeTable)?.let { it -> - val signature = MemberSignature.fromJvmMemberSignature(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() + fun DeserializedPropertyDescriptor.apply() { + val className = (containingDeclaration as? ClassDescriptor)?.relativeClassName().orEmpty() val signature = proto.getExtensionOrNull(JvmProtoBuf.propertySignature) if (signature != null) { - val fieldSignature = JvmProtoBufUtil.getJvmFieldSignature(proto, descriptor.nameResolver, descriptor.typeTable) + val fieldSignature = JvmProtoBufUtil.getJvmFieldSignature(proto, nameResolver, typeTable) if (fieldSignature != null) { save(className, MemberSignature.fromJvmMemberSignature(fieldSignature)) } if (signature.hasGetter()) { - save(className, MemberSignature.fromMethod(descriptor.nameResolver, signature.getter)) + save(className, MemberSignature.fromMethod(nameResolver, signature.getter)) } if (signature.hasSetter()) { - save(className, MemberSignature.fromMethod(descriptor.nameResolver, signature.setter)) + save(className, MemberSignature.fromMethod(nameResolver, signature.setter)) } } } + + when (descriptor) { + is ClassDescriptor -> descriptor.apply() + is DeserializedClassConstructorDescriptor -> descriptor.apply() + is DeserializedSimpleFunctionDescriptor -> descriptor.apply() + is DeserializedPropertyDescriptor -> descriptor.apply() + } + return signatures } } diff --git a/idea/testData/decompiler/navigation/fromJavaSource/classAndConstructors.kt b/idea/testData/decompiler/navigation/fromJavaSource/classAndConstructors.kt new file mode 100644 index 00000000000..27017a1bb1b --- /dev/null +++ b/idea/testData/decompiler/navigation/fromJavaSource/classAndConstructors.kt @@ -0,0 +1,8 @@ +package testData.libraries + +class SomeClassWithConstructors(private val arg: String) { + constructor(x: Int) : this("Hello") + fun check() { + TODO() + } +} \ No newline at end of file diff --git a/idea/testData/decompiler/navigation/fromJavaSource/overloadedFun.kt b/idea/testData/decompiler/navigation/fromJavaSource/overloadedFun.kt new file mode 100644 index 00000000000..f378bc9df9e --- /dev/null +++ b/idea/testData/decompiler/navigation/fromJavaSource/overloadedFun.kt @@ -0,0 +1,6 @@ +package testData.libraries + +@JvmOverloads +fun String.overloadedFun(vararg specs: String, allowExisting: Boolean = false, x: Int, y: Int = 2, z: T): String { + TODO() +} \ No newline at end of file diff --git a/idea/testData/decompiler/navigation/fromJavaSource/renamedElements.kt b/idea/testData/decompiler/navigation/fromJavaSource/renamedElements.kt new file mode 100644 index 00000000000..52658eab15d --- /dev/null +++ b/idea/testData/decompiler/navigation/fromJavaSource/renamedElements.kt @@ -0,0 +1,6 @@ +package testData.libraries + +@JvmName("renamedFun") +fun funToRename(x: Int) { + +} \ No newline at end of file diff --git a/idea/testData/decompiler/navigation/userJavaCode/ClassAndConstuctors.java b/idea/testData/decompiler/navigation/userJavaCode/ClassAndConstuctors.java new file mode 100644 index 00000000000..5d073d2a456 --- /dev/null +++ b/idea/testData/decompiler/navigation/userJavaCode/ClassAndConstuctors.java @@ -0,0 +1,10 @@ +import testData.libraries.*; + +class TestClassAndConstructors { + void foo() { + + SomeClassWithConstructors inst = new SomeClassWithConstructors("arg"); + + SomeClassWithConstructors inst2 = new SomeClassWithConstructors(2); + } +} \ No newline at end of file diff --git a/idea/testData/decompiler/navigation/userJavaCode/ClassAndConstuctors.java.libsrc.fail.192 b/idea/testData/decompiler/navigation/userJavaCode/ClassAndConstuctors.java.libsrc.fail.192 new file mode 100644 index 00000000000..cd8c8240431 --- /dev/null +++ b/idea/testData/decompiler/navigation/userJavaCode/ClassAndConstuctors.java.libsrc.fail.192 @@ -0,0 +1,5 @@ +Actual data differs from file content: ClassAndConstuctors.source.expected expected:< [SomeClassWithConstructors.class +public final class <1><2><3><4>SomeClassWithConstructors public constructor(arg: kotlin.String)] { +> but was:< [classAndConstructors.kt +class <1><2><3><4>SomeClassWithConstructors(private val arg: String) ] { +> \ No newline at end of file diff --git a/idea/testData/decompiler/navigation/userJavaCode/ClassAndConstuctors.source.expected b/idea/testData/decompiler/navigation/userJavaCode/ClassAndConstuctors.source.expected new file mode 100644 index 00000000000..9e940d9e1d8 --- /dev/null +++ b/idea/testData/decompiler/navigation/userJavaCode/ClassAndConstuctors.source.expected @@ -0,0 +1,2 @@ + SomeClassWithConstructors.class +public final class <1><2><3><4>SomeClassWithConstructors public constructor(arg: kotlin.String) { diff --git a/idea/testData/decompiler/navigation/userJavaCode/OverloadedFun.java b/idea/testData/decompiler/navigation/userJavaCode/OverloadedFun.java new file mode 100644 index 00000000000..12283aab333 --- /dev/null +++ b/idea/testData/decompiler/navigation/userJavaCode/OverloadedFun.java @@ -0,0 +1,11 @@ +import testData.libraries.*; + +class TestOverload { + void foo() { + OverloadedFunKt.overloadedFun("", null, 2, null); + + OverloadedFunKt.overloadedFun("", null, true, 2, null); + + OverloadedFunKt.overloadedFun("", null, true, 2, 3, null); + } +} \ No newline at end of file diff --git a/idea/testData/decompiler/navigation/userJavaCode/OverloadedFun.java.libsrc.fail.192 b/idea/testData/decompiler/navigation/userJavaCode/OverloadedFun.java.libsrc.fail.192 new file mode 100644 index 00000000000..07fe0e9c91b --- /dev/null +++ b/idea/testData/decompiler/navigation/userJavaCode/OverloadedFun.java.libsrc.fail.192 @@ -0,0 +1,10 @@ +Actual data differs from file content: OverloadedFun.source.expected expected:<...d from a class file +[// Implementation of methods is not available + +package testData.libraries + +@kotlin.jvm.JvmOverloads public fun kotlin.String.<2><4><6>overloadedFun(vararg specs: kotlin.String, allowExisting: kotlin.Boolean /* = compiled code */, x: kotlin.Int, y: kotlin.Int /* = compiled code */, z: T): kotlin.String { /* compiled code */ }] +> but was:<...d from a class file +[ overloadedFun.kt +fun String.<2><4><6>overloadedFun(vararg specs: String, allowExisting: Boolean = false, x: Int, y: Int = 2, z: T): String {] +> \ No newline at end of file diff --git a/idea/testData/decompiler/navigation/userJavaCode/OverloadedFun.source.expected b/idea/testData/decompiler/navigation/userJavaCode/OverloadedFun.source.expected new file mode 100644 index 00000000000..1720bf7ddaa --- /dev/null +++ b/idea/testData/decompiler/navigation/userJavaCode/OverloadedFun.source.expected @@ -0,0 +1,7 @@ + OverloadedFunKt.class +<1><3><5>// IntelliJ API Decompiler stub source generated from a class file +// Implementation of methods is not available + +package testData.libraries + +@kotlin.jvm.JvmOverloads public fun kotlin.String.<2><4><6>overloadedFun(vararg specs: kotlin.String, allowExisting: kotlin.Boolean /* = compiled code */, x: kotlin.Int, y: kotlin.Int /* = compiled code */, z: T): kotlin.String { /* compiled code */ } diff --git a/idea/testData/decompiler/navigation/userJavaCode/RenamedElements.java b/idea/testData/decompiler/navigation/userJavaCode/RenamedElements.java new file mode 100644 index 00000000000..6ef2a82f2d4 --- /dev/null +++ b/idea/testData/decompiler/navigation/userJavaCode/RenamedElements.java @@ -0,0 +1,7 @@ +import testData.libraries.*; + +class TestRenamedElements { + void foo() { + RenamedElementsKt.renamedFun(2); + } +} \ No newline at end of file diff --git a/idea/testData/decompiler/navigation/userJavaCode/RenamedElements.java.libsrc.fail.192 b/idea/testData/decompiler/navigation/userJavaCode/RenamedElements.java.libsrc.fail.192 new file mode 100644 index 00000000000..4c177094b04 --- /dev/null +++ b/idea/testData/decompiler/navigation/userJavaCode/RenamedElements.java.libsrc.fail.192 @@ -0,0 +1,12 @@ +Actual data differs from file content: RenamedElements.source.expected expected:<[RenamedElementsKt.class +<1>// IntelliJ API Decompiler stub source generated from a class file +// Implementation of methods is not available + +package testData.libraries + +@kotlin.jvm.JvmName public fun <2>funToRename(x: kotlin.Int): kotlin.Unit { /* compiled code */ }] +> but was:<[ RenamedElementsKt.class +<1>// IntelliJ API Decompiler stub source generated from a class file + renamedElements.kt +fun <2>funToRename(x: Int) {] +> \ No newline at end of file diff --git a/idea/testData/decompiler/navigation/userJavaCode/RenamedElements.source.expected b/idea/testData/decompiler/navigation/userJavaCode/RenamedElements.source.expected new file mode 100644 index 00000000000..2eb83aa872b --- /dev/null +++ b/idea/testData/decompiler/navigation/userJavaCode/RenamedElements.source.expected @@ -0,0 +1,7 @@ +RenamedElementsKt.class +<1>// IntelliJ API Decompiler stub source generated from a class file +// Implementation of methods is not available + +package testData.libraries + +@kotlin.jvm.JvmName public fun <2>funToRename(x: kotlin.Int): kotlin.Unit { /* compiled code */ } diff --git a/idea/testData/findUsages/libraryUsages/kotlinLibrary/LibraryNestedClassSecondaryConstructorUsages.0.kt.fail.192 b/idea/testData/findUsages/libraryUsages/kotlinLibrary/LibraryNestedClassSecondaryConstructorUsages.0.kt.fail.192 new file mode 100644 index 00000000000..80a0350d0f4 --- /dev/null +++ b/idea/testData/findUsages/libraryUsages/kotlinLibrary/LibraryNestedClassSecondaryConstructorUsages.0.kt.fail.192 @@ -0,0 +1,9 @@ +Actual data differs from file content: LibraryNestedClassSecondaryConstructorUsages.results.txt expected:<...3 class Y(): A.T() +[[LibraryNestedClassSecondaryConstructorUsages.1.java] New instance creation 14 A.T a = new A.T(); +[LibraryNestedClassSecondaryConstructorUsages.1.java] Unclassified usage 10 super(); +[LibraryNestedClassSecondaryConstructorUsages.1.java] Unclassified usage 6 public J() { +[library.kt] New instance creation 64 val tt = A.T() +[library.kt] Supertype 40 class VV(): A.T() +]> but was:<...3 class Y(): A.T() +[[library.kt] New instance creation 64 val tt = A.T() +[library.kt] Supertype 40 class VV(): A.T()]> \ No newline at end of file diff --git a/idea/testData/findUsages/libraryUsages/kotlinLibrary/LibraryNestedClassSecondaryConstructorUsages.1.java b/idea/testData/findUsages/libraryUsages/kotlinLibrary/LibraryNestedClassSecondaryConstructorUsages.1.java index 76e5e14e4de..89aa3df0f18 100644 --- a/idea/testData/findUsages/libraryUsages/kotlinLibrary/LibraryNestedClassSecondaryConstructorUsages.1.java +++ b/idea/testData/findUsages/libraryUsages/kotlinLibrary/LibraryNestedClassSecondaryConstructorUsages.1.java @@ -1,6 +1,6 @@ -package usages +package usages; -import library.* +import library.*; class J extends A.T { public J() { diff --git a/idea/testData/findUsages/libraryUsages/kotlinLibrary/LibraryNestedClassSecondaryConstructorUsages.results.txt b/idea/testData/findUsages/libraryUsages/kotlinLibrary/LibraryNestedClassSecondaryConstructorUsages.results.txt index b5be9d81980..55a4ff92488 100644 --- a/idea/testData/findUsages/libraryUsages/kotlinLibrary/LibraryNestedClassSecondaryConstructorUsages.results.txt +++ b/idea/testData/findUsages/libraryUsages/kotlinLibrary/LibraryNestedClassSecondaryConstructorUsages.results.txt @@ -1,4 +1,7 @@ [LibraryNestedClassSecondaryConstructorUsages.0.kt] New instance creation 16 val a: A.T = A.T() [LibraryNestedClassSecondaryConstructorUsages.0.kt] Supertype 13 class Y(): A.T() +[LibraryNestedClassSecondaryConstructorUsages.1.java] New instance creation 14 A.T a = new A.T(); +[LibraryNestedClassSecondaryConstructorUsages.1.java] Unclassified usage 10 super(); +[LibraryNestedClassSecondaryConstructorUsages.1.java] Unclassified usage 6 public J() { [library.kt] New instance creation 64 val tt = A.T() [library.kt] Supertype 40 class VV(): A.T() diff --git a/idea/testData/findUsages/libraryUsages/kotlinLibrary/LibrarySecondaryConstructorUsages.0.kt.fail.192 b/idea/testData/findUsages/libraryUsages/kotlinLibrary/LibrarySecondaryConstructorUsages.0.kt.fail.192 new file mode 100644 index 00000000000..80394f51d40 --- /dev/null +++ b/idea/testData/findUsages/libraryUsages/kotlinLibrary/LibrarySecondaryConstructorUsages.0.kt.fail.192 @@ -0,0 +1,6 @@ +Actual data differs from file content: LibrarySecondaryConstructorUsages.results.txt expected:<... 13 class Y(): A() +[[LibrarySecondaryConstructorUsages.1.java] New instance creation 14 A a = new A(); +[LibrarySecondaryConstructorUsages.1.java] Unclassified usage 10 super(); +[LibrarySecondaryConstructorUsages.1.java] Unclassified usage 6 public J() { +[]library.kt] New inst...> but was:<... 13 class Y(): A() +[[]library.kt] New inst...> \ No newline at end of file diff --git a/idea/testData/findUsages/libraryUsages/kotlinLibrary/LibrarySecondaryConstructorUsages.1.java b/idea/testData/findUsages/libraryUsages/kotlinLibrary/LibrarySecondaryConstructorUsages.1.java index 91a17a8f8cf..8b8b8b526da 100644 --- a/idea/testData/findUsages/libraryUsages/kotlinLibrary/LibrarySecondaryConstructorUsages.1.java +++ b/idea/testData/findUsages/libraryUsages/kotlinLibrary/LibrarySecondaryConstructorUsages.1.java @@ -1,6 +1,6 @@ -package usages +package usages; -import library.* +import library.*; class J extends A { public J() { diff --git a/idea/testData/findUsages/libraryUsages/kotlinLibrary/LibrarySecondaryConstructorUsages.results.txt b/idea/testData/findUsages/libraryUsages/kotlinLibrary/LibrarySecondaryConstructorUsages.results.txt index 6b9061b2bfa..6e66d93e269 100644 --- a/idea/testData/findUsages/libraryUsages/kotlinLibrary/LibrarySecondaryConstructorUsages.results.txt +++ b/idea/testData/findUsages/libraryUsages/kotlinLibrary/LibrarySecondaryConstructorUsages.results.txt @@ -1,4 +1,7 @@ [LibrarySecondaryConstructorUsages.0.kt] New instance creation 16 val a: A = A() [LibrarySecondaryConstructorUsages.0.kt] Supertype 13 class Y(): A() +[LibrarySecondaryConstructorUsages.1.java] New instance creation 14 A a = new A(); +[LibrarySecondaryConstructorUsages.1.java] Unclassified usage 10 super(); +[LibrarySecondaryConstructorUsages.1.java] Unclassified usage 6 public J() { [library.kt] New instance creation 58 val aa = A() -[library.kt] Supertype 39 class CC(): A() { +[library.kt] Supertype 39 class CC(): A() { \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/decompiler/navigation/AbstractNavigateToLibraryTest.kt b/idea/tests/org/jetbrains/kotlin/idea/decompiler/navigation/AbstractNavigateToLibraryTest.kt index e79810a3550..6ad160216a6 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/decompiler/navigation/AbstractNavigateToLibraryTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/decompiler/navigation/AbstractNavigateToLibraryTest.kt @@ -5,8 +5,7 @@ package org.jetbrains.kotlin.idea.decompiler.navigation -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiFile +import com.intellij.psi.* import com.intellij.psi.impl.source.resolve.reference.impl.PsiMultiReference import junit.framework.TestCase import org.jetbrains.kotlin.idea.navigation.NavigationTestUtils @@ -22,7 +21,8 @@ abstract class AbstractNavigateToLibraryTest : KotlinLightCodeInsightFixtureTest protected fun doTest(path: String) { myFixture.configureByFile(fileName()) - NavigationChecker.checkAnnotatedCode(file, File(path.replace(".kt", expectedFileExt))) + val pathOfExpect = path.replace(Regex("\\.kt|\\.java"), expectedFileExt) + NavigationChecker.checkAnnotatedCode(file, File(pathOfExpect)) } override fun tearDown() { @@ -55,6 +55,18 @@ abstract class AbstractNavigateToLibrarySourceTest : AbstractNavigateToLibraryTe } } +abstract class AbstractNavigateJavaToLibrarySourceTest : AbstractNavigateToLibraryTest() { + override val expectedFileExt: String get() = ".source.expected" + + override fun getProjectDescriptor(): KotlinLightProjectDescriptor = PROJECT_DESCRIPTOR + + protected companion object { + val PROJECT_DESCRIPTOR = SdkAndMockLibraryProjectDescriptor( + PluginTestCaseBase.getTestDataPathBase() + "/decompiler/navigation/fromJavaSource", true + ) + } +} + abstract class AbstractNavigateToLibrarySourceTestWithJS : AbstractNavigateToLibrarySourceTest() { override fun getProjectDescriptor(): KotlinLightProjectDescriptor = KotlinMultiModuleProjectDescriptor( "AbstractNavigateToLibrarySourceTestWithJS", @@ -74,13 +86,13 @@ class NavigationChecker(val file: PsiFile, val referenceTargetChecker: (PsiEleme target!!.navigationElement } - private fun collectInterestingReferences(): Collection { - val referenceContainersToReferences = LinkedHashMap() + private fun collectInterestingReferences(): Collection { + val referenceContainersToReferences = LinkedHashMap() for (offset in 0 until file.textLength) { val refs = when (val ref = file.findReferenceAt(offset)) { - is KtReference -> listOf(ref) + is KtReference, is PsiReferenceExpression, is PsiJavaCodeReferenceElement -> listOf(ref) is PsiMultiReference -> ref.references.filterIsInstance() - else -> emptyList() + else -> emptyList() } refs.forEach { referenceContainersToReferences.addReference(it) } @@ -88,7 +100,7 @@ class NavigationChecker(val file: PsiFile, val referenceTargetChecker: (PsiEleme return referenceContainersToReferences.values } - private fun MutableMap.addReference(ref: KtReference) { + private fun MutableMap.addReference(ref: PsiReference) { if (containsKey(ref.element)) return val target = ref.resolve() ?: return diff --git a/idea/tests/org/jetbrains/kotlin/idea/decompiler/navigation/NavigateJavaToLibrarySourceTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/decompiler/navigation/NavigateJavaToLibrarySourceTestGenerated.java new file mode 100644 index 00000000000..3b692be914d --- /dev/null +++ b/idea/tests/org/jetbrains/kotlin/idea/decompiler/navigation/NavigateJavaToLibrarySourceTestGenerated.java @@ -0,0 +1,47 @@ +/* + * 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.decompiler.navigation; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.JUnit3RunnerWithInners; +import org.jetbrains.kotlin.test.KotlinTestUtils; +import org.jetbrains.kotlin.test.MuteExtraSuffix; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.runner.RunWith; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("idea/testData/decompiler/navigation/userJavaCode") +@TestDataPath("$PROJECT_ROOT") +@MuteExtraSuffix(".libsrc") +@RunWith(JUnit3RunnerWithInners.class) +public class NavigateJavaToLibrarySourceTestGenerated extends AbstractNavigateJavaToLibrarySourceTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInUserJavaCode() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/decompiler/navigation/userJavaCode"), Pattern.compile("^(.+)\\.java$"), null, true); + } + + @TestMetadata("ClassAndConstuctors.java") + public void testClassAndConstuctors() throws Exception { + runTest("idea/testData/decompiler/navigation/userJavaCode/ClassAndConstuctors.java"); + } + + @TestMetadata("OverloadedFun.java") + public void testOverloadedFun() throws Exception { + runTest("idea/testData/decompiler/navigation/userJavaCode/OverloadedFun.java"); + } + + @TestMetadata("RenamedElements.java") + public void testRenamedElements() throws Exception { + runTest("idea/testData/decompiler/navigation/userJavaCode/RenamedElements.java"); + } +} diff --git a/tests/mute-platform.csv.192 b/tests/mute-platform.csv.192 index 27fcabcc901..55d81c4b51e 100644 --- a/tests/mute-platform.csv.192 +++ b/tests/mute-platform.csv.192 @@ -19,4 +19,9 @@ org.jetbrains.kotlin.idea.completion.test.JvmBasicCompletionTestGenerated.Java.S org.jetbrains.kotlin.idea.completion.test.JvmBasicCompletionTestGenerated.Java.SyntheticExtensions.testSmartCast2, KT-32919 org.jetbrains.kotlin.idea.completion.test.JvmBasicCompletionTestGenerated.Java.SyntheticExtensions.testSyntheticExtensions1, KT-32919 org.jetbrains.kotlin.idea.completion.test.weighers.BasicCompletionWeigherTestGenerated.testPreferFromJdk, KT-35709 Class from JDK is not prioritized -org.jetbrains.kotlin.idea.quickfix.QuickFixMultiFileTestGenerated.AutoImports.testAmbiguousNamePreferFromJdk, KT-35709 Class from JDK is not prioritized \ No newline at end of file +org.jetbrains.kotlin.idea.quickfix.QuickFixMultiFileTestGenerated.AutoImports.testAmbiguousNamePreferFromJdk, KT-35709 Class from JDK is not prioritized +org.jetbrains.kotlin.findUsages.KotlinFindUsagesWithLibraryTestGenerated.KotlinLibrary.testLibrarySecondaryConstructorUsages, KT-34542, FAIL +org.jetbrains.kotlin.findUsages.KotlinFindUsagesWithLibraryTestGenerated.KotlinLibrary.testLibraryNestedClassSecondaryConstructorUsages, KT-34542, FAIL +org.jetbrains.kotlin.idea.decompiler.navigation.NavigateJavaToLibrarySourceTestGenerated.testClassAndConstuctors, KT-34542, FAIL +org.jetbrains.kotlin.idea.decompiler.navigation.NavigateJavaToLibrarySourceTestGenerated.testOverloadedFun, KT-34542, FAIL +org.jetbrains.kotlin.idea.decompiler.navigation.NavigateJavaToLibrarySourceTestGenerated.testRenamedElements, KT-34542, FAIL \ No newline at end of file