Improved kotlin decompiler range indexes

Fixed #KT-30628
This commit is contained in:
Igor Yakovlev
2020-01-22 03:50:05 +03:00
parent cb1c0344b8
commit 48db96b66d
27 changed files with 326 additions and 55 deletions
@@ -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() = ""
@@ -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<String>) {
model("decompiler/navigation/usercode")
}
testClass<AbstractNavigateJavaToLibrarySourceTest>(annotations = listOf(muteExtraSuffix(".libsrc"))) {
model("decompiler/navigation/userJavaCode", pattern = "^(.+)\\.java$")
}
testClass<AbstractNavigateToLibrarySourceTestWithJS>(annotations = listOf(muteExtraSuffix(".libsrcjs"))) {
model("decompiler/navigation/usercode", testClassName = "UsercodeWithJSModule")
}
@@ -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<String>) {
model("decompiler/navigation/usercode")
}
testClass<AbstractNavigateJavaToLibrarySourceTest>(annotations = listOf(muteExtraSuffix(".libsrc"))) {
model("decompiler/navigation/userJavaCode", pattern = "^(.+)\\.java$")
}
testClass<AbstractNavigateToLibrarySourceTestWithJS>(annotations = listOf(muteExtraSuffix(".libsrcjs"))) {
model("decompiler/navigation/usercode", testClassName ="UsercodeWithJSModule")
}
@@ -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<String>) {
model("decompiler/navigation/usercode")
}
testClass<AbstractNavigateJavaToLibrarySourceTest>(annotations = listOf(muteExtraSuffix(".libsrc"))) {
model("decompiler/navigation/userJavaCode", pattern = "^(.+)\\.java$")
}
testClass<AbstractNavigateToLibrarySourceTestWithJS>(annotations = listOf(muteExtraSuffix(".libsrcjs"))) {
model("decompiler/navigation/usercode", testClassName ="UsercodeWithJSModule")
}
@@ -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<String>) {
model("decompiler/navigation/usercode")
}
testClass<AbstractNavigateJavaToLibrarySourceTest>(annotations = listOf(muteExtraSuffix(".libsrc"))) {
model("decompiler/navigation/userJavaCode", pattern = "^(.+)\\.java$")
}
testClass<AbstractNavigateToLibrarySourceTestWithJS>(annotations = listOf(muteExtraSuffix(".libsrcjs"))) {
model("decompiler/navigation/usercode", testClassName ="UsercodeWithJSModule")
}
@@ -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<T : PsiMember> : 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) "<init>" else psiMethod.name
val signature = MemberSignature.fromMethodNameAndDesc(name, desc)
findDeclarationInCompiledFile(file, psiMethod, signature)
}
}
@@ -148,58 +146,138 @@ private fun ClassDescriptor.relativeClassName(): List<Name> {
return classId!!.relativeClassName.pathSegments().drop(1)
}
private fun excludeParametersFromDescriptor(descriptor: String, omittedParameters: List<Int>): String? {
fun tryParseParametersAndReturnType(): Pair<List<String>, 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<String>() to returnType
}
val parameterTypes = mutableListOf<String>()
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<ClassNameAndSignature> {
override fun indexDescriptor(descriptor: DeclarationDescriptor): Collection<ClassNameAndSignature> {
val signatures = arrayListOf<ClassNameAndSignature>()
fun save(id: List<Name>, 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<Int>()
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
}
}
@@ -0,0 +1,8 @@
package testData.libraries
class SomeClassWithConstructors(private val arg: String) {
constructor(x: Int) : this("Hello")
fun check() {
TODO()
}
}
@@ -0,0 +1,6 @@
package testData.libraries
@JvmOverloads
fun <T> String.overloadedFun(vararg specs: String, allowExisting: Boolean = false, x: Int, y: Int = 2, z: T): String {
TODO()
}
@@ -0,0 +1,6 @@
package testData.libraries
@JvmName("renamedFun")
fun funToRename(x: Int) {
}
@@ -0,0 +1,10 @@
import testData.libraries.*;
class TestClassAndConstructors {
void foo() {
SomeClassWithConstructors inst = new SomeClassWithConstructors("arg");
SomeClassWithConstructors inst2 = new SomeClassWithConstructors(2);
}
}
@@ -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) ] {
>
@@ -0,0 +1,2 @@
SomeClassWithConstructors.class
public final class <1><2><3><4>SomeClassWithConstructors public constructor(arg: kotlin.String) {
@@ -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);
}
}
@@ -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 <T> 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 <T> String.<2><4><6>overloadedFun(vararg specs: String, allowExisting: Boolean = false, x: Int, y: Int = 2, z: T): String {]
>
@@ -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 <T> 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 */ }
@@ -0,0 +1,7 @@
import testData.libraries.*;
class TestRenamedElements {
void foo() {
RenamedElementsKt.renamedFun(2);
}
}
@@ -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) {]
>
@@ -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 */ }
@@ -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()]>
@@ -1,6 +1,6 @@
package usages
package usages;
import library.*
import library.*;
class J extends A.T {
public J() {
@@ -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()
@@ -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...>
@@ -1,6 +1,6 @@
package usages
package usages;
import library.*
import library.*;
class J extends A {
public J() {
@@ -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() {
@@ -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<KtReference> {
val referenceContainersToReferences = LinkedHashMap<PsiElement, KtReference>()
private fun collectInterestingReferences(): Collection<PsiReference> {
val referenceContainersToReferences = LinkedHashMap<PsiElement, PsiReference>()
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<KtReference>()
else -> emptyList<KtReference>()
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<PsiElement, KtReference>.addReference(ref: KtReference) {
private fun MutableMap<PsiElement, PsiReference>.addReference(ref: PsiReference) {
if (containsKey(ref.element)) return
val target = ref.resolve() ?: return
@@ -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");
}
}
+6 -1
View File
@@ -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
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