Avoid loading psi for compiled kotlin file if it's possible to get declaration by name from stubs
This commit is contained in:
+32
-2
@@ -28,7 +28,9 @@ 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.KtClassOrObject
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtDeclarationContainer
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind
|
||||
@@ -51,7 +53,7 @@ data class LightMemberOriginForCompiledField(val psiField: PsiField, val file: K
|
||||
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))
|
||||
findDeclarationInCompiledFile(file, psiField, signature)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,10 +65,38 @@ data class LightMemberOriginForCompiledMethod(val psiMethod: PsiMethod, val 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))
|
||||
findDeclarationInCompiledFile(file, psiMethod, signature)
|
||||
}
|
||||
}
|
||||
|
||||
private fun findDeclarationInCompiledFile(file: KtClsFile, member: PsiMember, signature: MemberSignature): KtDeclaration? {
|
||||
val relativeClassName = member.relativeClassName()
|
||||
val key = ClassNameAndSignature(relativeClassName, signature)
|
||||
|
||||
val memberName = member.name
|
||||
|
||||
if (memberName != null && !file.isContentsLoaded && file.hasDeclarationWithKey(ByJvmSignatureIndexer, key)) {
|
||||
val container: KtDeclarationContainer? = if (relativeClassName.isEmpty())
|
||||
file
|
||||
else {
|
||||
val topClassOrObject = file.declarations.singleOrNull() as? KtClassOrObject
|
||||
relativeClassName.fold<Name, KtClassOrObject?>(topClassOrObject) { classOrObject, name ->
|
||||
classOrObject?.declarations?.singleOrNull { it.name == name.asString() } as? KtClassOrObject
|
||||
}
|
||||
}
|
||||
|
||||
val declaration = container?.declarations?.singleOrNull {
|
||||
it.name == memberName
|
||||
}
|
||||
|
||||
if (declaration != null) {
|
||||
return declaration
|
||||
}
|
||||
}
|
||||
|
||||
return file.getDeclaration(ByJvmSignatureIndexer, key)
|
||||
}
|
||||
|
||||
// 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)
|
||||
|
||||
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
package test;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import test.kotlin.A.B.C.C;
|
||||
|
||||
public class FunctionInNestedClassInDataFlowInspection {
|
||||
void other(@NotNull Object some) {
|
||||
Object foo = new C().foo(some);
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
package test.kotlin
|
||||
|
||||
class A {
|
||||
class B {
|
||||
class C {
|
||||
class C {
|
||||
fun foo(a: Any): Any = a
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
// TOOL: DataFlowInspection
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package test;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import test.kotlin.*;
|
||||
|
||||
public class TopLevelFunctionWithNameSimilarToClassInDataFlowInspection {
|
||||
void other(@NotNull Object some) {
|
||||
Object foo = TopLevelFunctionWithNameSimilarToClassInDataFlowInspectionKt.foo(some);
|
||||
}
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
package test.kotlin
|
||||
|
||||
class foo
|
||||
fun foo(a: Any): Any = a
|
||||
+1
@@ -0,0 +1 @@
|
||||
// TOOL: DataFlowInspection
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package test;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import test.kotlin.*;
|
||||
|
||||
public class TopLevelFunctionWithNameSimilarToPropertyInDataFlowInspection {
|
||||
void other(@NotNull Object some) {
|
||||
Object foo = (new Test()).foo(some);
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package test.kotlin
|
||||
|
||||
class Test {
|
||||
val foo: Int = 12
|
||||
fun foo(a: Any): Any = a
|
||||
}
|
||||
|
||||
// ALLOW_AST_ACCESS
|
||||
+1
@@ -0,0 +1 @@
|
||||
// TOOL: DataFlowInspection
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package test;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import test.kotlin.*;
|
||||
|
||||
public class TopLevelOverloadedFunctionInDataFlowInspection {
|
||||
void other(@NotNull Object some) {
|
||||
Object foo = TopLevelOverloadedFunctionInDataFlowInspectionKt.foo(some);
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package test.kotlin
|
||||
|
||||
fun foo(a: Any?, b: Any): Any? = a
|
||||
fun foo(a: Any): Any = a
|
||||
|
||||
|
||||
// ALLOW_AST_ACCESS
|
||||
+1
@@ -0,0 +1 @@
|
||||
// TOOL: DataFlowInspection
|
||||
+11
@@ -17,10 +17,14 @@
|
||||
package org.jetbrains.kotlin.checkers
|
||||
|
||||
import com.intellij.openapi.roots.ModuleRootModificationUtil
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.util.io.FileUtilRt
|
||||
import org.jetbrains.kotlin.idea.test.AstAccessControl
|
||||
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
|
||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
import org.jetbrains.kotlin.test.MockLibraryUtil
|
||||
import java.io.File
|
||||
|
||||
abstract class AbstractJavaAgainstKotlinBinariesCheckerTest : AbstractJavaAgainstKotlinCheckerTest() {
|
||||
override fun setUp() {
|
||||
@@ -39,6 +43,13 @@ abstract class AbstractJavaAgainstKotlinBinariesCheckerTest : AbstractJavaAgains
|
||||
}
|
||||
|
||||
fun doTest(path: String) {
|
||||
val ktFileText = FileUtil.loadFile(File(path), true)
|
||||
val allowAstForCompiledFile = InTextDirectivesUtils.isDirectiveDefined(ktFileText, AstAccessControl.ALLOW_AST_ACCESS_DIRECTIVE)
|
||||
|
||||
if (allowAstForCompiledFile) {
|
||||
allowTreeAccessForAllFiles()
|
||||
}
|
||||
|
||||
doTest(true, true, path.replace(".kt", ".java"))
|
||||
}
|
||||
}
|
||||
+24
@@ -72,6 +72,12 @@ public class JavaAgainstKotlinBinariesCheckerTestGenerated extends AbstractJavaA
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("FunctionInNestedClassInDataFlowInspection.kt")
|
||||
public void testFunctionInNestedClassInDataFlowInspection() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/FunctionInNestedClassInDataFlowInspection.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ImplementedMethodsFromTraits.kt")
|
||||
public void testImplementedMethodsFromTraits() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/ImplementedMethodsFromTraits.kt");
|
||||
@@ -120,6 +126,24 @@ public class JavaAgainstKotlinBinariesCheckerTestGenerated extends AbstractJavaA
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("TopLevelFunctionWithNameSimilarToClassInDataFlowInspection.kt")
|
||||
public void testTopLevelFunctionWithNameSimilarToClassInDataFlowInspection() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/TopLevelFunctionWithNameSimilarToClassInDataFlowInspection.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("TopLevelFunctionWithNameSimilarToPropertyInDataFlowInspection.kt")
|
||||
public void testTopLevelFunctionWithNameSimilarToPropertyInDataFlowInspection() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/TopLevelFunctionWithNameSimilarToPropertyInDataFlowInspection.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("TopLevelOverloadedFunctionInDataFlowInspection.kt")
|
||||
public void testTopLevelOverloadedFunctionInDataFlowInspection() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/TopLevelOverloadedFunctionInDataFlowInspection.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("UseKotlinConstInSwitch.kt")
|
||||
public void testUseKotlinConstInSwitch() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/UseKotlinConstInSwitch.kt");
|
||||
|
||||
+24
@@ -74,6 +74,12 @@ public class JavaAgainstKotlinSourceCheckerTestGenerated extends AbstractJavaAga
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("FunctionInNestedClassInDataFlowInspection.kt")
|
||||
public void testFunctionInNestedClassInDataFlowInspection() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/FunctionInNestedClassInDataFlowInspection.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ImplementedMethodsFromTraits.kt")
|
||||
public void testImplementedMethodsFromTraits() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/ImplementedMethodsFromTraits.kt");
|
||||
@@ -122,6 +128,24 @@ public class JavaAgainstKotlinSourceCheckerTestGenerated extends AbstractJavaAga
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("TopLevelFunctionWithNameSimilarToClassInDataFlowInspection.kt")
|
||||
public void testTopLevelFunctionWithNameSimilarToClassInDataFlowInspection() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/TopLevelFunctionWithNameSimilarToClassInDataFlowInspection.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("TopLevelFunctionWithNameSimilarToPropertyInDataFlowInspection.kt")
|
||||
public void testTopLevelFunctionWithNameSimilarToPropertyInDataFlowInspection() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/TopLevelFunctionWithNameSimilarToPropertyInDataFlowInspection.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("TopLevelOverloadedFunctionInDataFlowInspection.kt")
|
||||
public void testTopLevelOverloadedFunctionInDataFlowInspection() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/TopLevelOverloadedFunctionInDataFlowInspection.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("UseKotlinConstInSwitch.kt")
|
||||
public void testUseKotlinConstInSwitch() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/UseKotlinConstInSwitch.kt");
|
||||
|
||||
Reference in New Issue
Block a user