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.java.JvmAbi
|
||||||
import org.jetbrains.kotlin.load.kotlin.MemberSignature
|
import org.jetbrains.kotlin.load.kotlin.MemberSignature
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
|
import org.jetbrains.kotlin.psi.KtDeclarationContainer
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind
|
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) {
|
override val originalElement: KtDeclaration? by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||||
val desc = MapPsiToAsmDesc.typeDesc(psiField.type)
|
val desc = MapPsiToAsmDesc.typeDesc(psiField.type)
|
||||||
val signature = MemberSignature.fromFieldNameAndDesc(psiField.name!!, desc)
|
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) {
|
override val originalElement: KtDeclaration? by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||||
val desc = MapPsiToAsmDesc.methodDesc(psiMethod)
|
val desc = MapPsiToAsmDesc.methodDesc(psiMethod)
|
||||||
val signature = MemberSignature.fromMethodNameAndDesc(psiMethod.name, desc)
|
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
|
// 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)
|
// 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
|
package org.jetbrains.kotlin.checkers
|
||||||
|
|
||||||
import com.intellij.openapi.roots.ModuleRootModificationUtil
|
import com.intellij.openapi.roots.ModuleRootModificationUtil
|
||||||
|
import com.intellij.openapi.util.io.FileUtil
|
||||||
import com.intellij.openapi.util.io.FileUtilRt
|
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.idea.test.PluginTestCaseBase
|
||||||
|
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
||||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||||
import org.jetbrains.kotlin.test.MockLibraryUtil
|
import org.jetbrains.kotlin.test.MockLibraryUtil
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
abstract class AbstractJavaAgainstKotlinBinariesCheckerTest : AbstractJavaAgainstKotlinCheckerTest() {
|
abstract class AbstractJavaAgainstKotlinBinariesCheckerTest : AbstractJavaAgainstKotlinCheckerTest() {
|
||||||
override fun setUp() {
|
override fun setUp() {
|
||||||
@@ -39,6 +43,13 @@ abstract class AbstractJavaAgainstKotlinBinariesCheckerTest : AbstractJavaAgains
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun doTest(path: String) {
|
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"))
|
doTest(true, true, path.replace(".kt", ".java"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+24
@@ -72,6 +72,12 @@ public class JavaAgainstKotlinBinariesCheckerTestGenerated extends AbstractJavaA
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("ImplementedMethodsFromTraits.kt")
|
||||||
public void testImplementedMethodsFromTraits() throws Exception {
|
public void testImplementedMethodsFromTraits() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/ImplementedMethodsFromTraits.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/ImplementedMethodsFromTraits.kt");
|
||||||
@@ -120,6 +126,24 @@ public class JavaAgainstKotlinBinariesCheckerTestGenerated extends AbstractJavaA
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("UseKotlinConstInSwitch.kt")
|
||||||
public void testUseKotlinConstInSwitch() throws Exception {
|
public void testUseKotlinConstInSwitch() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/UseKotlinConstInSwitch.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/UseKotlinConstInSwitch.kt");
|
||||||
|
|||||||
+24
@@ -74,6 +74,12 @@ public class JavaAgainstKotlinSourceCheckerTestGenerated extends AbstractJavaAga
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("ImplementedMethodsFromTraits.kt")
|
||||||
public void testImplementedMethodsFromTraits() throws Exception {
|
public void testImplementedMethodsFromTraits() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/ImplementedMethodsFromTraits.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/ImplementedMethodsFromTraits.kt");
|
||||||
@@ -122,6 +128,24 @@ public class JavaAgainstKotlinSourceCheckerTestGenerated extends AbstractJavaAga
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("UseKotlinConstInSwitch.kt")
|
||||||
public void testUseKotlinConstInSwitch() throws Exception {
|
public void testUseKotlinConstInSwitch() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/UseKotlinConstInSwitch.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/kotlinAndJavaChecker/javaAgainstKotlin/UseKotlinConstInSwitch.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user